diff --git a/arch/src/aarch64/fdt.rs b/arch/src/aarch64/fdt.rs index 6e626070d..6d3aab95e 100644 --- a/arch/src/aarch64/fdt.rs +++ b/arch/src/aarch64/fdt.rs @@ -114,7 +114,7 @@ pub fn create_fdt, guest_mem: &GuestMemoryMmap) -> Result<()> { // Write FDT to memory. - let fdt_address = GuestAddress(get_fdt_addr(&guest_mem)); + let fdt_address = GuestAddress(get_fdt_addr()); guest_mem .write_slice(fdt_final.as_slice(), fdt_address) .map_err(Error::WriteFdtToMemory)?; diff --git a/arch/src/aarch64/layout.rs b/arch/src/aarch64/layout.rs index 2f16f5c6a..ae0c325e2 100644 --- a/arch/src/aarch64/layout.rs +++ b/arch/src/aarch64/layout.rs @@ -36,7 +36,7 @@ // | | // 144 M +---------------------------------------------------------------| // | Reserved (now GIC is here) | -// 128 M +---------------------------------------------------------------+ +// 64 M +---------------------------------------------------------------+ // | | // | UEFI space | // | | @@ -46,10 +46,10 @@ use vm_memory::GuestAddress; -/// 0x0 ~ 0x800_0000 is reserved to uefi +/// 0x0 ~ 0x400_0000 is reserved to uefi pub const UEFI_START: u64 = 0x0; pub const MEM_UEFI_START: GuestAddress = GuestAddress(0); -pub const UEFI_SIZE: u64 = 0x0800_0000; +pub const UEFI_SIZE: u64 = 0x0400_0000; /// Below this address will reside the GIC, above this address will reside the MMIO devices. pub const MAPPED_IO_START: u64 = 0x0900_0000; @@ -59,13 +59,10 @@ pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000; pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000; pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000; -/// Space 0x0902_0000 ~ 0x903_0000 is reserved for pcie io address -pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0902_0000); +/// Space 0x0905_0000 ~ 0x906_0000 is reserved for pcie io address +pub const MEM_PCI_IO_START: GuestAddress = GuestAddress(0x0905_0000); pub const MEM_PCI_IO_SIZE: u64 = 0x10000; -/// Legacy space will be allocated at once whiling setting up legacy devices. -pub const LEGACY_DEVICES_MAPPED_IO_SIZE: u64 = 0x0700_0000; - /// Starting from 0x1000_0000 (256MiB) to 0x3000_0000 (768MiB) is used for PCIE MMIO pub const MEM_32BIT_DEVICES_START: GuestAddress = GuestAddress(0x1000_0000); pub const MEM_32BIT_DEVICES_SIZE: u64 = 0x2000_0000; @@ -81,13 +78,19 @@ pub const RAM_64BIT_START: u64 = 0x4000_0000; /// As per `arch/arm64/include/uapi/asm/setup.h`. pub const CMDLINE_MAX_SIZE: usize = 2048; +/// FDT is at the beginning of RAM. /// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt. +pub const FDT_START: u64 = RAM_64BIT_START; pub const FDT_MAX_SIZE: usize = 0x20_0000; /// Put ACPI table above dtb pub const ACPI_START: u64 = RAM_64BIT_START + FDT_MAX_SIZE as u64; +pub const ACPI_MAX_SIZE: usize = 0x20_0000; pub const RSDP_POINTER: GuestAddress = GuestAddress(ACPI_START); +/// Kernel start after FDT and ACPI +pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64; + // As per virt/kvm/arm/vgic/vgic-kvm-device.c we need // the number of interrupts our GIC will support to be: // * bigger than 32 diff --git a/arch/src/aarch64/mod.rs b/arch/src/aarch64/mod.rs index 36719dde2..49a78fd7a 100644 --- a/arch/src/aarch64/mod.rs +++ b/arch/src/aarch64/mod.rs @@ -82,28 +82,49 @@ pub fn configure_vcpu( } pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> { + // Normally UEFI should be loaded to a flash area at the beginning of memory. + // But now flash memory type is not supported. + // As a workaround, we take 64 MiB memory from the main RAM for UEFI. + // As a result, the RAM that the guest can see is less than what has been + // assigned in command line, when ACPI and UEFI is enabled. + let ram_deduction = if cfg!(feature = "acpi") { + layout::UEFI_SIZE + } else { + 0 + }; + vec![ - // 0 ~ 256 MiB: Reserved + // 0 ~ 64 MiB: Reserved for UEFI space + #[cfg(feature = "acpi")] + (GuestAddress(0), layout::UEFI_SIZE as usize, RegionType::Ram), + #[cfg(not(feature = "acpi"))] ( GuestAddress(0), - layout::MEM_32BIT_DEVICES_START.0 as usize, + layout::UEFI_SIZE as usize, RegionType::Reserved, ), - // 256 MiB ~ 1 G: MMIO space + // 64 MiB ~ 256 MiB: Gic and legacy devices + ( + GuestAddress(layout::UEFI_SIZE), + (layout::MEM_32BIT_DEVICES_START.0 - layout::UEFI_SIZE) as usize, + RegionType::Reserved, + ), + // 256 MiB ~ 768 MiB: MMIO space ( layout::MEM_32BIT_DEVICES_START, layout::MEM_32BIT_DEVICES_SIZE as usize, RegionType::SubRegion, ), - // 1G ~ 2G: reserved. The leading 256M for PCIe MMCONFIG space + // 768 MiB ~ 1 GiB: reserved. The leading 256M for PCIe MMCONFIG space ( layout::PCI_MMCONFIG_START, - (layout::RAM_64BIT_START - layout::PCI_MMCONFIG_START.0) as usize, + layout::PCI_MMCONFIG_SIZE as usize, RegionType::Reserved, ), + // 1 GiB ~ : Ram ( GuestAddress(layout::RAM_64BIT_START), - size as usize, + (size - ram_deduction) as usize, RegionType::Ram, ), ] @@ -150,8 +171,9 @@ pub fn initramfs_load_addr( initramfs_size: usize, ) -> super::Result { let round_to_pagesize = |size| (size + (super::PAGE_SIZE - 1)) & !(super::PAGE_SIZE - 1); - match GuestAddress(get_fdt_addr(&guest_mem)) - .checked_sub(round_to_pagesize(initramfs_size) as u64) + match guest_mem + .last_addr() + .checked_sub(round_to_pagesize(initramfs_size) as u64 - 1) { Some(offset) => { if guest_mem.address_in_range(offset) { @@ -166,22 +188,12 @@ pub fn initramfs_load_addr( /// Returns the memory address where the kernel could be loaded. pub fn get_kernel_start() -> u64 { - layout::RAM_64BIT_START + layout::KERNEL_START } // Auxiliary function to get the address where the device tree blob is loaded. -fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 { - // If the memory allocated is smaller than the size allocated for the FDT, - // we return the start of the DRAM so that - // we allow the code to try and load the FDT. - - if let Some(addr) = mem.last_addr().checked_sub(layout::FDT_MAX_SIZE as u64 - 1) { - if mem.address_in_range(addr) { - return addr.raw_value(); - } - } - - layout::RAM_64BIT_START +fn get_fdt_addr() -> u64 { + layout::FDT_START } pub fn get_host_cpu_phys_bits() -> u8 { @@ -210,38 +222,9 @@ mod tests { #[test] fn test_arch_memory_regions_dram() { let regions = arch_memory_regions((1usize << 32) as u64); //4GB - assert_eq!(4, regions.len()); - assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[3].0); - assert_eq!(1usize << 32, regions[3].1); - assert_eq!(RegionType::Ram, regions[3].2); - } - - #[test] - fn test_get_fdt_addr() { - let mut regions = Vec::new(); - - regions.push(( - GuestAddress(layout::RAM_64BIT_START), - (layout::FDT_MAX_SIZE - 0x1000) as usize, - )); - let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); - assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START); - regions.clear(); - - regions.push(( - GuestAddress(layout::RAM_64BIT_START), - (layout::FDT_MAX_SIZE) as usize, - )); - let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); - assert_eq!(get_fdt_addr(&mem), layout::RAM_64BIT_START); - regions.clear(); - - regions.push(( - GuestAddress(layout::RAM_64BIT_START), - (layout::FDT_MAX_SIZE + 0x1000) as usize, - )); - let mem = GuestMemoryMmap::from_ranges(®ions).expect("Cannot initialize memory"); - assert_eq!(get_fdt_addr(&mem), 0x1000 + layout::RAM_64BIT_START); - regions.clear(); + assert_eq!(5, regions.len()); + assert_eq!(GuestAddress(layout::RAM_64BIT_START), regions[4].0); + assert_eq!(1usize << 32, regions[4].1); + assert_eq!(RegionType::Ram, regions[4].2); } } diff --git a/arch/src/aarch64/regs.rs b/arch/src/aarch64/regs.rs index 279e87b2a..6838b0e0c 100644 --- a/arch/src/aarch64/regs.rs +++ b/arch/src/aarch64/regs.rs @@ -47,7 +47,7 @@ pub fn setup_regs( vcpu: &Arc, cpu_id: u8, boot_ip: u64, - mem: &GuestMemoryMmap, + _mem: &GuestMemoryMmap, ) -> Result<()> { let kreg_off = offset__of!(kvm_regs, regs); @@ -73,7 +73,7 @@ pub fn setup_regs( let regs0 = offset__of!(user_pt_regs, regs) + kreg_off; vcpu.set_reg( arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0), - get_fdt_addr(mem) as u64, + get_fdt_addr() as u64, ) .map_err(Error::SetCoreRegister)?; } diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 89cf2979d..4abd7f3bf 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -112,16 +112,7 @@ pub fn create_acpi_tables( memory_manager: &Arc>, numa_nodes: &NumaNodes, ) -> GuestAddress { - #[cfg(target_arch = "x86_64")] - // RSDP is at the EBDA let rsdp_offset = arch::layout::RSDP_POINTER; - #[cfg(target_arch = "aarch64")] - // TODO: For aarch64 place the ACPI tables in the last MiB of guest RAM - let rsdp_offset = { - use vm_memory::GuestMemory; - guest_mem.last_addr().checked_sub(1 << 20).unwrap() - }; - let mut tables: Vec = Vec::new(); // DSDT