mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-01 22:50:54 +00:00
Merge pull request #13063 from RainaYL/rainax/acpi_pr
dragonball: Add basic ACPI implementation for TDX boot
This commit is contained in:
121
src/dragonball/dbs_acpi/src/fadt.rs
Normal file
121
src/dragonball/dbs_acpi/src/fadt.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2026 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use crate::sdt::{GenericAddress, Sdt};
|
||||
use vm_memory::ByteValued;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct FadtBody {
|
||||
pub FirmwareCtrl: u32,
|
||||
pub Dsdt: u32,
|
||||
pub Reserved: u8,
|
||||
pub PreferredPowerManagementProfile: u8,
|
||||
pub SCI_Interrupt: u16,
|
||||
pub SMI_CommandPort: u32,
|
||||
pub AcpiEnable: u8,
|
||||
pub AcpiDisable: u8,
|
||||
pub S4BIOS_REQ: u8,
|
||||
pub PSTATE_Control: u8,
|
||||
pub PM1aEventBlock: u32,
|
||||
pub PM1bEventBlock: u32,
|
||||
pub PM1aControlBlock: u32,
|
||||
pub PM1bControlBlock: u32,
|
||||
pub PM2ControlBlock: u32,
|
||||
pub PMTimerBlock: u32,
|
||||
pub GPE0Block: u32,
|
||||
pub GPE1Block: u32,
|
||||
pub PM1EventLength: u8,
|
||||
pub PM1ControlLength: u8,
|
||||
pub PM2ControlLength: u8,
|
||||
pub PMTimerLength: u8,
|
||||
pub GPE0Length: u8,
|
||||
pub GPE1Length: u8,
|
||||
pub GPE1Base: u8,
|
||||
pub CStateControl: u8,
|
||||
pub WorstC2Latency: u16,
|
||||
pub WorstC3Latency: u16,
|
||||
pub FlushSize: u16,
|
||||
pub FlushStride: u16,
|
||||
pub DutyOffset: u8,
|
||||
pub DutyWidth: u8,
|
||||
pub DayAlarm: u8,
|
||||
pub MonthAlarm: u8,
|
||||
pub Century: u8,
|
||||
pub BootArchitectureFlags: u16,
|
||||
pub Reserved2: u8,
|
||||
pub Flags: u32,
|
||||
pub ResetReg: GenericAddress,
|
||||
pub ResetValue: u8,
|
||||
pub ArmBootArch: u16,
|
||||
pub FadtMinorVersion: u8,
|
||||
pub X_FirmwareControl: u64,
|
||||
pub X_Dsdt: u64,
|
||||
pub X_PM1aEventBlock: GenericAddress,
|
||||
pub X_PM1bEventBlock: GenericAddress,
|
||||
pub X_PM1aControlBlock: GenericAddress,
|
||||
pub X_PM1bControlBlock: GenericAddress,
|
||||
pub X_PM2ControlBlock: GenericAddress,
|
||||
pub X_PMTimerBlock: GenericAddress,
|
||||
pub X_GPE0Block: GenericAddress,
|
||||
pub X_GPE1Block: GenericAddress,
|
||||
pub SleepControlReg: GenericAddress,
|
||||
pub SleepStatusReg: GenericAddress,
|
||||
pub HypervisorVendorIdentity: u64,
|
||||
}
|
||||
|
||||
unsafe impl ByteValued for FadtBody {}
|
||||
|
||||
impl FadtBody {
|
||||
pub fn new() -> Self {
|
||||
FadtBody {
|
||||
SCI_Interrupt: 9,
|
||||
|
||||
PM1aEventBlock: 0xb000,
|
||||
PM1aControlBlock: 0xb004,
|
||||
PMTimerBlock: 0xb008,
|
||||
GPE0Block: 0xb020,
|
||||
|
||||
PM1EventLength: 4,
|
||||
PM1ControlLength: 2,
|
||||
PMTimerLength: 4,
|
||||
GPE0Length: 2,
|
||||
|
||||
BootArchitectureFlags: 1,
|
||||
Flags: (1 << 0) | (1 << 8) | (1 << 9) | (1 << 10),
|
||||
|
||||
X_PM1aEventBlock: GenericAddress {
|
||||
address_space_id: 1,
|
||||
register_bit_width: 32,
|
||||
register_bit_offset: 0,
|
||||
access_size: 3,
|
||||
address: 0xb000,
|
||||
},
|
||||
X_PM1aControlBlock: GenericAddress {
|
||||
address_space_id: 1,
|
||||
register_bit_width: 16,
|
||||
register_bit_offset: 0,
|
||||
access_size: 2,
|
||||
address: 0xb004,
|
||||
},
|
||||
X_PMTimerBlock: GenericAddress {
|
||||
address_space_id: 1,
|
||||
register_bit_width: 32,
|
||||
register_bit_offset: 0,
|
||||
access_size: 3,
|
||||
address: 0xb008,
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_fadt_table() -> Sdt {
|
||||
let mut fadt = Sdt::new(*b"FACP", 36, 6);
|
||||
fadt.append_slice(FadtBody::new().as_slice());
|
||||
|
||||
fadt
|
||||
}
|
||||
@@ -2,9 +2,22 @@
|
||||
// Copyright (c) 2023 Alibaba Cloud
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Please refer to the official ACPI 6.0 documentation:
|
||||
// https://uefi.org/sites/default/files/resources/ACPI_6.0.pdf
|
||||
// for specification of ACPI tables.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
pub mod fadt;
|
||||
pub mod madt;
|
||||
pub mod rsdp;
|
||||
pub mod sdt;
|
||||
|
||||
pub use fadt::create_fadt_table;
|
||||
pub use madt::create_madt_table;
|
||||
pub use sdt::create_dsdt_table;
|
||||
|
||||
fn generate_checksum(data: &[u8]) -> u8 {
|
||||
(255 - data.iter().fold(0u8, |acc, x| acc.wrapping_add(*x))).wrapping_add(1)
|
||||
}
|
||||
|
||||
164
src/dragonball/dbs_acpi/src/madt.rs
Normal file
164
src/dragonball/dbs_acpi/src/madt.rs
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2026 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use crate::sdt::Sdt;
|
||||
use vm_memory::ByteValued;
|
||||
|
||||
const IOAPIC_START: u32 = 0xfec0_0000;
|
||||
const APIC_START: u32 = 0xfee0_0000;
|
||||
|
||||
const MADT_CPU_ENABLE_FLAG: usize = 0;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub enum MadtEntryType {
|
||||
#[default]
|
||||
LocalApic,
|
||||
Ioapic,
|
||||
InterruptSourceOverride,
|
||||
LocalX2Apic = 9,
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct MadtBody {
|
||||
pub apic_address: u32,
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
impl MadtBody {
|
||||
pub fn new(apic_address: u32, flags: u32) -> Self {
|
||||
Self {
|
||||
apic_address,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct MadtEntryLocalApic {
|
||||
pub r#type: MadtEntryType,
|
||||
pub length: u8,
|
||||
pub processor_id: u8,
|
||||
pub apic_id: u8,
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
impl MadtEntryLocalApic {
|
||||
pub fn new(processor_id: u8, flags: u32) -> Self {
|
||||
Self {
|
||||
r#type: MadtEntryType::LocalApic,
|
||||
length: 8,
|
||||
processor_id,
|
||||
apic_id: processor_id,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct MadtEntryIoapic {
|
||||
pub r#type: MadtEntryType,
|
||||
pub length: u8,
|
||||
pub ioapic_id: u8,
|
||||
pub reserved: u8,
|
||||
pub ioapic_address: u32,
|
||||
pub gsi_base: u32,
|
||||
}
|
||||
|
||||
impl MadtEntryIoapic {
|
||||
pub fn new(ioapic_id: u8, ioapic_address: u32, gsi_base: u32) -> Self {
|
||||
Self {
|
||||
r#type: MadtEntryType::Ioapic,
|
||||
length: 12,
|
||||
ioapic_id,
|
||||
reserved: 0,
|
||||
ioapic_address,
|
||||
gsi_base,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct MadtEntryIntrSrcOverride {
|
||||
pub r#type: MadtEntryType,
|
||||
pub length: u8,
|
||||
pub bus_source: u8,
|
||||
pub irq_source: u8,
|
||||
pub gsi: u32,
|
||||
pub flags: u16,
|
||||
}
|
||||
|
||||
impl MadtEntryIntrSrcOverride {
|
||||
pub fn new(bus_source: u8, irq_source: u8, gsi: u32, flags: u16) -> Self {
|
||||
Self {
|
||||
r#type: MadtEntryType::InterruptSourceOverride,
|
||||
length: 10,
|
||||
bus_source,
|
||||
irq_source,
|
||||
gsi,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct MadtEntryLocalX2Apic {
|
||||
r#type: MadtEntryType,
|
||||
length: u8,
|
||||
reserved: u16,
|
||||
x2apic_id: u32,
|
||||
flags: u32,
|
||||
processor_id: u32,
|
||||
}
|
||||
|
||||
impl MadtEntryLocalX2Apic {
|
||||
pub fn new(processor_id: u32, flags: u32) -> Self {
|
||||
Self {
|
||||
r#type: MadtEntryType::LocalX2Apic,
|
||||
length: 16,
|
||||
reserved: 0,
|
||||
// TODO: Calculate x2apic id from processor id
|
||||
x2apic_id: processor_id,
|
||||
flags,
|
||||
processor_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl ByteValued for MadtBody {}
|
||||
unsafe impl ByteValued for MadtEntryLocalApic {}
|
||||
unsafe impl ByteValued for MadtEntryIoapic {}
|
||||
unsafe impl ByteValued for MadtEntryIntrSrcOverride {}
|
||||
unsafe impl ByteValued for MadtEntryLocalX2Apic {}
|
||||
|
||||
pub fn create_madt_table(max_vcpus: u8, boot_vcpus: u8) -> Sdt {
|
||||
let mut madt = Sdt::new(*b"APIC", 36, 5);
|
||||
madt.append_slice(MadtBody::new(APIC_START, 0).as_slice());
|
||||
|
||||
for cpu_id in 0..max_vcpus {
|
||||
madt.append_slice(
|
||||
MadtEntryLocalApic::new(
|
||||
cpu_id,
|
||||
if cpu_id < boot_vcpus {
|
||||
1 << MADT_CPU_ENABLE_FLAG
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
.as_slice(),
|
||||
);
|
||||
}
|
||||
|
||||
madt.append_slice(MadtEntryIoapic::new(0, IOAPIC_START, 0).as_slice());
|
||||
|
||||
madt.append_slice(MadtEntryIntrSrcOverride::new(0, 2, 2, 0).as_slice());
|
||||
|
||||
madt
|
||||
}
|
||||
@@ -2,7 +2,11 @@
|
||||
// Copyright (c) 2023 Alibaba Cloud
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#[repr(Rust, packed)]
|
||||
|
||||
use vm_memory::ByteValued;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct GenericAddress {
|
||||
pub address_space_id: u8,
|
||||
pub register_bit_width: u8,
|
||||
@@ -33,6 +37,8 @@ impl GenericAddress {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl ByteValued for GenericAddress {}
|
||||
|
||||
pub struct Sdt {
|
||||
data: Vec<u8>,
|
||||
}
|
||||
@@ -116,6 +122,11 @@ impl Sdt {
|
||||
self.data.len()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_dsdt_table() -> Sdt {
|
||||
Sdt::new(*b"DSDT", 36, 2)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Sdt;
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::ops::Deref;
|
||||
|
||||
use dbs_acpi::sdt::Sdt;
|
||||
use dbs_acpi::*;
|
||||
use dbs_address_space::{AddressSpace, AddressSpaceRegionType};
|
||||
use dbs_boot::{
|
||||
add_e820_entry, bootparam, layout, mptable, tdshim::*, BootParamsWrapper, FirmwareType,
|
||||
@@ -215,8 +215,11 @@ impl Vm {
|
||||
.cloned()
|
||||
.ok_or(StartMicroVmError::GuestMemoryNotInitialized)?;
|
||||
let mut hob_address = 0;
|
||||
// TODO: Fill the empty list with ACPI table content
|
||||
let acpi_tables: Vec<Sdt> = Vec::new();
|
||||
let acpi_tables: Vec<sdt::Sdt> = vec![
|
||||
create_madt_table(self.vm_config.max_vcpu_count, self.vm_config.vcpu_count),
|
||||
create_fadt_table(),
|
||||
create_dsdt_table(),
|
||||
];
|
||||
|
||||
self.load_kernel_with_tdshim(
|
||||
§ions,
|
||||
@@ -383,7 +386,7 @@ impl Vm {
|
||||
vm_memory: &GuestMemoryImpl,
|
||||
address_space: AddressSpace,
|
||||
hob_address: &mut u64,
|
||||
acpi_tables: &Vec<Sdt>,
|
||||
acpi_tables: &Vec<sdt::Sdt>,
|
||||
) -> std::result::Result<(), StartMicroVmError> {
|
||||
let mut required_sections = vec!["Bfv", "TdHob", "PayloadParam"];
|
||||
|
||||
@@ -461,7 +464,7 @@ impl Vm {
|
||||
vm_memory: &GuestMemoryImpl,
|
||||
address_space: AddressSpace,
|
||||
payload_info: PayloadInfo,
|
||||
acpi_tables: &Vec<Sdt>,
|
||||
acpi_tables: &Vec<sdt::Sdt>,
|
||||
) -> std::result::Result<(), StartMicroVmError> {
|
||||
let mut hob = TdHob::start(hob_address);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user