arch: x86_64: Generate basic ACPI tables

Generate very basic ACPI tables for HW reduced ACPI.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2019-08-14 17:14:34 +01:00 committed by Samuel Ortiz
parent eea6f1dc9e
commit ee83c2d44e
5 changed files with 77 additions and 0 deletions

1
Cargo.lock generated
View File

@ -32,6 +32,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "arch" name = "arch"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"acpi_tables 0.1.0",
"arch_gen 0.1.0", "arch_gen 0.1.0",
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "kvm-bindings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -9,6 +9,7 @@ kvm-bindings = "0.1.1"
kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "master" } kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "master" }
libc = "0.2.60" libc = "0.2.60"
acpi_tables = { path ="../acpi_tables" }
arch_gen = { path = "../arch_gen" } arch_gen = { path = "../arch_gen" }
[dependencies.vm-memory] [dependencies.vm-memory]

View File

@ -13,6 +13,7 @@ extern crate byteorder;
extern crate kvm_bindings; extern crate kvm_bindings;
extern crate libc; extern crate libc;
extern crate acpi_tables;
extern crate arch_gen; extern crate arch_gen;
extern crate kvm_ioctls; extern crate kvm_ioctls;
extern crate linux_loader; extern crate linux_loader;

70
arch/src/x86_64/acpi.rs Normal file
View File

@ -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<u64> = 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
}

View File

@ -5,6 +5,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file. // found in the LICENSE-BSD-3-Clause file.
mod acpi;
mod gdt; mod gdt;
pub mod interrupts; pub mod interrupts;
pub mod layout; 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; let zero_page_addr = layout::ZERO_PAGE_START;
guest_mem guest_mem
.checked_offset(zero_page_addr, mem::size_of::<boot_params>()) .checked_offset(zero_page_addr, mem::size_of::<boot_params>())