diff --git a/Cargo.lock b/Cargo.lock index 9adea4216..aa09d281c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "arch" version = "0.1.0" dependencies = [ + "acpi_tables 0.1.0", "arch_gen 0.1.0", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvm-bindings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/arch/Cargo.toml b/arch/Cargo.toml index a7a16a674..e873725b8 100644 --- a/arch/Cargo.toml +++ b/arch/Cargo.toml @@ -9,6 +9,7 @@ kvm-bindings = "0.1.1" kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "master" } libc = "0.2.60" +acpi_tables = { path ="../acpi_tables" } arch_gen = { path = "../arch_gen" } [dependencies.vm-memory] diff --git a/arch/src/lib.rs b/arch/src/lib.rs index ea01c3d1f..5005dcde5 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -13,6 +13,7 @@ extern crate byteorder; extern crate kvm_bindings; extern crate libc; +extern crate acpi_tables; extern crate arch_gen; extern crate kvm_ioctls; extern crate linux_loader; diff --git a/arch/src/x86_64/acpi.rs b/arch/src/x86_64/acpi.rs new file mode 100644 index 000000000..8cc538294 --- /dev/null +++ b/arch/src/x86_64/acpi.rs @@ -0,0 +1,70 @@ +// Copyright © 2019 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 +// +use acpi_tables::{rsdp::RSDP, sdt::SDT}; +use vm_memory::{GuestAddress, GuestMemoryMmap}; + +use vm_memory::{Address, ByteValued, Bytes}; + +pub fn create_acpi_tables(guest_mem: &GuestMemoryMmap) -> GuestAddress { + // RSDP is at the EBDA + let rsdp_offset = super::EBDA_START; + let mut tables: Vec = Vec::new(); + + // DSDT + let mut dsdt = SDT::new(*b"DSDT", 36, 6, *b"CLOUDH", *b"CHDSDT ", 1); + dsdt.update_checksum(); + let dsdt_offset = rsdp_offset.checked_add(RSDP::len() as u64).unwrap(); + guest_mem + .write_slice(dsdt.as_slice(), dsdt_offset) + .expect("Error writing DSDT table"); + + // FACP aka FADT + // Revision 6 of the ACPI FADT table is 276 bytes long + let mut facp = SDT::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1); + + let fadt_flags: u32 = 1 << 20; // HW_REDUCED_ACPI + facp.write(112, fadt_flags); + + // TODO: RESET_REG/RESET_VALUE @ offset 116/128 + + facp.write(131, 3u8); // FADT minor version + facp.write(140, dsdt_offset.0); // X_DSDT + + // TODO: SLEEP_CONTROL_REG/SLEEP_STATUS_REG @ offset 244/256 + + facp.write(268, b"CLOUDHYP"); // Hypervisor Vendor Identity + + facp.update_checksum(); + let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap(); + guest_mem + .write_slice(facp.as_slice(), facp_offset) + .expect("Error writing FACP table"); + tables.push(facp_offset.0); + + // XSDT + let mut xsdt = SDT::new( + *b"XSDT", + 36 + 8 * tables.len() as u32, + 1, + *b"CLOUDH", + *b"CHXSDT ", + 1, + ); + xsdt.write(36, tables[0]); + xsdt.update_checksum(); + + let xsdt_offset = facp_offset.checked_add(facp.len() as u64).unwrap(); + guest_mem + .write_slice(xsdt.as_slice(), xsdt_offset) + .expect("Error writing XSDT table"); + + // RSDP + let rsdp = RSDP::new(*b"CLOUDH", xsdt_offset.0); + guest_mem + .write_slice(rsdp.as_slice(), rsdp_offset) + .expect("Error writing RSDP"); + + rsdp_offset +} diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 48ccdbaf1..3e58da672 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -5,6 +5,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-BSD-3-Clause file. +mod acpi; mod gdt; pub mod interrupts; pub mod layout; @@ -181,6 +182,9 @@ pub fn configure_system( } } + let rsdp_addr = acpi::create_acpi_tables(guest_mem); + params.0.acpi_rsdp_addr = rsdp_addr.0; + let zero_page_addr = layout::ZERO_PAGE_START; guest_mem .checked_offset(zero_page_addr, mem::size_of::())