diff --git a/arch/src/x86_64/acpi.rs b/arch/src/x86_64/acpi.rs index 7147937ef..8148fc6b9 100644 --- a/arch/src/x86_64/acpi.rs +++ b/arch/src/x86_64/acpi.rs @@ -51,7 +51,11 @@ struct PCIRangeEntry { _reserved: u32, } -pub fn create_dsdt_table(serial_enabled: bool) -> SDT { +pub fn create_dsdt_table( + serial_enabled: bool, + start_of_device_area: GuestAddress, + end_of_device_area: GuestAddress, +) -> SDT { /* The hex tables in this file are generated from the ASL below with: "iasl -tc " @@ -126,7 +130,7 @@ pub fn create_dsdt_table(serial_enabled: bool) -> SDT { }) } */ - let pci_dsdt_data = [ + let mut pci_dsdt_data = [ 0x5Bu8, 0x82, 0x36, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x50, 0x43, 0x49, 0x30, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x08, 0x08, 0x5F, 0x43, 0x49, 0x44, 0x0C, 0x41, 0xD0, 0x0A, 0x03, 0x08, 0x5F, 0x41, 0x44, 0x52, 0x00, 0x08, 0x5F, 0x53, 0x45, 0x47, 0x00, 0x08, @@ -145,6 +149,13 @@ pub fn create_dsdt_table(serial_enabled: bool) -> SDT { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x79, 0x00, ]; + // Patch the Range Minimum/Range Maximum/Length for the the 64-bit device area + pci_dsdt_data[200..208].copy_from_slice(&(start_of_device_area.0).to_le_bytes()); + pci_dsdt_data[208..216].copy_from_slice(&end_of_device_area.0.to_le_bytes()); + pci_dsdt_data[224..232].copy_from_slice( + &(end_of_device_area.unchecked_offset_from(start_of_device_area)).to_le_bytes(), + ); + /* Device (_SB.COM1) { @@ -194,13 +205,15 @@ pub fn create_acpi_tables( guest_mem: &GuestMemoryMmap, num_cpus: u8, serial_enabled: bool, + start_of_device_area: GuestAddress, + end_of_device_area: GuestAddress, ) -> GuestAddress { // RSDP is at the EBDA let rsdp_offset = super::EBDA_START; let mut tables: Vec = Vec::new(); // DSDT - let dsdt = create_dsdt_table(serial_enabled); + let dsdt = create_dsdt_table(serial_enabled, start_of_device_area, end_of_device_area); let dsdt_offset = rsdp_offset.checked_add(RSDP::len() as u64).unwrap(); guest_mem .write_slice(dsdt.as_slice(), dsdt_offset) diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 8baf1fd24..c2ee5295f 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -130,6 +130,7 @@ pub fn configure_system( num_cpus: u8, setup_hdr: Option, _serial_enabled: bool, + _end_of_range: GuestAddress, ) -> super::Result<()> { const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55; const KERNEL_HDR_MAGIC: u32 = 0x53726448; @@ -187,7 +188,18 @@ pub fn configure_system( #[cfg(feature = "acpi")] { - let rsdp_addr = acpi::create_acpi_tables(guest_mem, num_cpus, _serial_enabled); + let start_of_device_area = if mem_end < end_32bit_gap_start { + first_addr_past_32bits + } else { + guest_mem.end_addr().unchecked_add(1) + }; + let rsdp_addr = acpi::create_acpi_tables( + guest_mem, + num_cpus, + _serial_enabled, + start_of_device_area, + _end_of_range, + ); params.0.acpi_rsdp_addr = rsdp_addr.0; } @@ -257,7 +269,15 @@ mod tests { fn test_system_configuration() { let no_vcpus = 4; let gm = GuestMemoryMmap::new(&vec![(GuestAddress(0), 0x10000)]).unwrap(); - let config_err = configure_system(&gm, GuestAddress(0), 0, 1, None, false); + let config_err = configure_system( + &gm, + GuestAddress(0), + 0, + 1, + None, + false, + GuestAddress((1 << 36) - 1), + ); assert!(config_err.is_err()); assert_eq!( config_err.unwrap_err(), @@ -275,7 +295,16 @@ mod tests { .map(|r| (r.0, r.1)) .collect(); let gm = GuestMemoryMmap::new(&ram_regions).unwrap(); - configure_system(&gm, GuestAddress(0), 0, no_vcpus, None, false).unwrap(); + configure_system( + &gm, + GuestAddress(0), + 0, + no_vcpus, + None, + false, + GuestAddress((1 << 36) - 1), + ) + .unwrap(); // Now assigning some memory that is equal to the start of the 32bit memory hole. let mem_size = 3328 << 20; @@ -286,7 +315,16 @@ mod tests { .map(|r| (r.0, r.1)) .collect(); let gm = GuestMemoryMmap::new(&ram_regions).unwrap(); - configure_system(&gm, GuestAddress(0), 0, no_vcpus, None, false).unwrap(); + configure_system( + &gm, + GuestAddress(0), + 0, + no_vcpus, + None, + false, + GuestAddress((1 << 36) - 1), + ) + .unwrap(); // Now assigning some memory that falls after the 32bit memory hole. let mem_size = 3330 << 20; @@ -297,7 +335,16 @@ mod tests { .map(|r| (r.0, r.1)) .collect(); let gm = GuestMemoryMmap::new(&ram_regions).unwrap(); - configure_system(&gm, GuestAddress(0), 0, no_vcpus, None, false).unwrap(); + configure_system( + &gm, + GuestAddress(0), + 0, + no_vcpus, + None, + false, + GuestAddress((1 << 36) - 1), + ) + .unwrap(); } #[test] diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index dfd58a826..d600c4fd1 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -787,7 +787,7 @@ impl<'a> Vm<'a> { .map_err(|_| Error::CmdLine)?; let vcpu_count = u8::from(&self.config.cpus); - + let end_of_range = GuestAddress((1 << 36) - 1); match entry_addr.setup_header { Some(hdr) => { arch::configure_system( @@ -797,6 +797,7 @@ impl<'a> Vm<'a> { vcpu_count, Some(hdr), self.config.serial.mode != ConsoleOutputMode::Off, + end_of_range, ) .map_err(|_| Error::CmdLine)?; @@ -816,6 +817,7 @@ impl<'a> Vm<'a> { vcpu_count, None, self.config.serial.mode != ConsoleOutputMode::Off, + end_of_range, ) .map_err(|_| Error::CmdLine)?;