2019-08-14 16:14:34 +00:00
|
|
|
// Copyright © 2019 Intel Corporation
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
//
|
2019-08-29 13:58:25 +00:00
|
|
|
use acpi_tables::{
|
2019-10-23 10:36:48 +00:00
|
|
|
aml::Aml,
|
2019-08-29 13:58:25 +00:00
|
|
|
rsdp::RSDP,
|
|
|
|
sdt::{GenericAddress, SDT},
|
|
|
|
};
|
2019-08-14 16:14:34 +00:00
|
|
|
use vm_memory::{GuestAddress, GuestMemoryMmap};
|
|
|
|
|
|
|
|
use vm_memory::{Address, ByteValued, Bytes};
|
|
|
|
|
2019-12-06 15:25:57 +00:00
|
|
|
use std::sync::{Arc, Mutex};
|
2019-10-02 06:56:37 +00:00
|
|
|
|
2019-12-06 15:25:57 +00:00
|
|
|
use crate::cpu::CpuManager;
|
2019-12-06 16:14:32 +00:00
|
|
|
use crate::device_manager::DeviceManager;
|
2020-01-10 16:11:32 +00:00
|
|
|
use crate::memory_manager::MemoryManager;
|
2019-11-06 17:20:55 +00:00
|
|
|
use arch::layout;
|
2019-09-27 13:11:50 +00:00
|
|
|
|
2019-08-20 06:31:44 +00:00
|
|
|
#[repr(packed)]
|
|
|
|
#[derive(Default)]
|
|
|
|
struct PCIRangeEntry {
|
|
|
|
pub base_address: u64,
|
|
|
|
pub segment: u16,
|
|
|
|
pub start: u8,
|
|
|
|
pub end: u8,
|
2019-09-03 13:54:06 +00:00
|
|
|
_reserved: u32,
|
2019-08-20 06:31:44 +00:00
|
|
|
}
|
|
|
|
|
2019-10-02 06:56:37 +00:00
|
|
|
#[repr(packed)]
|
|
|
|
#[derive(Default)]
|
|
|
|
struct IortParavirtIommuNode {
|
|
|
|
pub type_: u8,
|
|
|
|
pub length: u16,
|
|
|
|
pub revision: u8,
|
|
|
|
_reserved1: u32,
|
|
|
|
pub num_id_mappings: u32,
|
|
|
|
pub ref_id_mappings: u32,
|
|
|
|
pub device_id: u32,
|
|
|
|
_reserved2: [u32; 3],
|
|
|
|
pub model: u32,
|
|
|
|
pub flags: u32,
|
|
|
|
_reserved3: [u32; 4],
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(packed)]
|
|
|
|
#[derive(Default)]
|
|
|
|
struct IortPciRootComplexNode {
|
|
|
|
pub type_: u8,
|
|
|
|
pub length: u16,
|
|
|
|
pub revision: u8,
|
|
|
|
_reserved1: u32,
|
|
|
|
pub num_id_mappings: u32,
|
|
|
|
pub ref_id_mappings: u32,
|
|
|
|
pub mem_access_props: IortMemoryAccessProperties,
|
|
|
|
pub ats_attr: u32,
|
|
|
|
pub pci_seg_num: u32,
|
|
|
|
pub mem_addr_size_limit: u8,
|
|
|
|
_reserved2: [u8; 3],
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(packed)]
|
|
|
|
#[derive(Default)]
|
|
|
|
struct IortMemoryAccessProperties {
|
|
|
|
pub cca: u32,
|
|
|
|
pub ah: u8,
|
|
|
|
_reserved: u16,
|
|
|
|
pub maf: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(packed)]
|
|
|
|
#[derive(Default)]
|
|
|
|
struct IortIdMapping {
|
|
|
|
pub input_base: u32,
|
|
|
|
pub num_of_ids: u32,
|
|
|
|
pub ouput_base: u32,
|
|
|
|
pub output_ref: u32,
|
|
|
|
pub flags: u32,
|
|
|
|
}
|
|
|
|
|
2019-09-18 14:11:56 +00:00
|
|
|
pub fn create_dsdt_table(
|
2020-02-27 09:29:03 +00:00
|
|
|
device_manager: &Arc<Mutex<DeviceManager>>,
|
2019-12-06 15:25:57 +00:00
|
|
|
cpu_manager: &Arc<Mutex<CpuManager>>,
|
2020-01-10 16:11:32 +00:00
|
|
|
memory_manager: &Arc<Mutex<MemoryManager>>,
|
2019-09-18 14:11:56 +00:00
|
|
|
) -> SDT {
|
2019-08-21 11:12:24 +00:00
|
|
|
// DSDT
|
|
|
|
let mut dsdt = SDT::new(*b"DSDT", 36, 6, *b"CLOUDH", *b"CHDSDT ", 1);
|
2019-12-06 16:14:32 +00:00
|
|
|
|
2020-02-27 09:29:03 +00:00
|
|
|
dsdt.append_slice(device_manager.lock().unwrap().to_aml_bytes().as_slice());
|
2019-12-06 15:25:57 +00:00
|
|
|
dsdt.append_slice(cpu_manager.lock().unwrap().to_aml_bytes().as_slice());
|
2020-01-10 16:11:32 +00:00
|
|
|
dsdt.append_slice(memory_manager.lock().unwrap().to_aml_bytes().as_slice());
|
2019-08-21 11:12:24 +00:00
|
|
|
|
|
|
|
dsdt
|
|
|
|
}
|
2019-11-25 15:13:46 +00:00
|
|
|
|
2019-08-22 10:18:48 +00:00
|
|
|
pub fn create_acpi_tables(
|
|
|
|
guest_mem: &GuestMemoryMmap,
|
2020-02-27 09:29:03 +00:00
|
|
|
device_manager: &Arc<Mutex<DeviceManager>>,
|
2019-12-06 15:25:57 +00:00
|
|
|
cpu_manager: &Arc<Mutex<CpuManager>>,
|
2020-01-10 16:11:32 +00:00
|
|
|
memory_manager: &Arc<Mutex<MemoryManager>>,
|
2019-08-22 10:18:48 +00:00
|
|
|
) -> GuestAddress {
|
2019-08-14 16:14:34 +00:00
|
|
|
// RSDP is at the EBDA
|
2019-09-27 13:11:50 +00:00
|
|
|
let rsdp_offset = layout::RSDP_POINTER;
|
2019-08-14 16:14:34 +00:00
|
|
|
let mut tables: Vec<u64> = Vec::new();
|
|
|
|
|
|
|
|
// DSDT
|
2020-01-10 16:11:32 +00:00
|
|
|
let dsdt = create_dsdt_table(device_manager, cpu_manager, memory_manager);
|
2019-08-14 16:14:34 +00:00
|
|
|
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);
|
|
|
|
|
2019-08-29 13:58:25 +00:00
|
|
|
// HW_REDUCED_ACPI and RESET_REG_SUP
|
|
|
|
let fadt_flags: u32 = 1 << 20 | 1 << 10;
|
2019-08-14 16:14:34 +00:00
|
|
|
facp.write(112, fadt_flags);
|
|
|
|
|
2019-08-29 13:58:25 +00:00
|
|
|
// RESET_REG
|
|
|
|
facp.write(116, GenericAddress::io_port_address(0x3c0));
|
|
|
|
// RESET_VALUE
|
|
|
|
facp.write(128, 1u8);
|
2019-08-14 16:14:34 +00:00
|
|
|
|
|
|
|
facp.write(131, 3u8); // FADT minor version
|
|
|
|
facp.write(140, dsdt_offset.0); // X_DSDT
|
|
|
|
|
2019-08-29 13:58:25 +00:00
|
|
|
// SLEEP_CONTROL_REG
|
|
|
|
facp.write(244, GenericAddress::io_port_address(0x3c0));
|
|
|
|
// SLEEP_STATUS_REG
|
|
|
|
facp.write(256, GenericAddress::io_port_address(0x3c0));
|
2019-08-14 16:14:34 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2019-08-19 16:28:35 +00:00
|
|
|
// MADT
|
2019-12-06 15:25:57 +00:00
|
|
|
let madt = cpu_manager.lock().unwrap().create_madt();
|
2019-08-19 16:28:35 +00:00
|
|
|
let madt_offset = facp_offset.checked_add(facp.len() as u64).unwrap();
|
|
|
|
guest_mem
|
|
|
|
.write_slice(madt.as_slice(), madt_offset)
|
|
|
|
.expect("Error writing MADT table");
|
|
|
|
tables.push(madt_offset.0);
|
|
|
|
|
2019-08-20 06:31:44 +00:00
|
|
|
// MCFG
|
2019-09-16 16:51:30 +00:00
|
|
|
let mut mcfg = SDT::new(*b"MCFG", 36, 1, *b"CLOUDH", *b"CHMCFG ", 1);
|
|
|
|
|
|
|
|
// MCFG reserved 8 bytes
|
|
|
|
mcfg.append(0u64);
|
2019-08-20 06:31:44 +00:00
|
|
|
|
|
|
|
// 32-bit PCI enhanced configuration mechanism
|
|
|
|
mcfg.append(PCIRangeEntry {
|
2019-09-30 13:12:36 +00:00
|
|
|
base_address: layout::PCI_MMCONFIG_START.0,
|
2019-08-20 06:31:44 +00:00
|
|
|
segment: 0,
|
|
|
|
start: 0,
|
|
|
|
end: 0xff,
|
|
|
|
..Default::default()
|
|
|
|
});
|
|
|
|
|
|
|
|
let mcfg_offset = madt_offset.checked_add(madt.len() as u64).unwrap();
|
|
|
|
guest_mem
|
|
|
|
.write_slice(mcfg.as_slice(), mcfg_offset)
|
|
|
|
.expect("Error writing MCFG table");
|
|
|
|
tables.push(mcfg_offset.0);
|
|
|
|
|
2019-08-14 16:14:34 +00:00
|
|
|
// XSDT
|
2019-08-19 16:28:35 +00:00
|
|
|
let mut xsdt = SDT::new(*b"XSDT", 36, 1, *b"CLOUDH", *b"CHXSDT ", 1);
|
|
|
|
for table in tables {
|
|
|
|
xsdt.append(table);
|
|
|
|
}
|
2019-08-14 16:14:34 +00:00
|
|
|
xsdt.update_checksum();
|
|
|
|
|
2020-01-29 08:45:05 +00:00
|
|
|
let xsdt_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
|
2019-08-14 16:14:34 +00:00
|
|
|
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
|
|
|
|
}
|