xref: /aosp_15_r20/external/crosvm/x86_64/src/acpi.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::CpuidResult;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::__cpuid;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::__cpuid_count;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::aml;
12*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::facs::FACS;
13*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::rsdp::RSDP;
14*bb4ee6a4SAndroid Build Coastguard Worker use acpi_tables::sdt::SDT;
15*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuSet;
16*bb4ee6a4SAndroid Build Coastguard Worker use arch::VcpuAffinity;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
19*bb4ee6a4SAndroid Build Coastguard Worker use devices::ACPIPMResource;
20*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciAddress;
21*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciInterruptPin;
22*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciRoot;
23*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
24*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
25*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
26*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
27*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
28*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker pub struct AcpiDevResource {
31*bb4ee6a4SAndroid Build Coastguard Worker     pub amls: Vec<u8>,
32*bb4ee6a4SAndroid Build Coastguard Worker     pub pm_iobase: u64,
33*bb4ee6a4SAndroid Build Coastguard Worker     pub pm: Arc<Mutex<ACPIPMResource>>,
34*bb4ee6a4SAndroid Build Coastguard Worker     /// Additional system descriptor tables.
35*bb4ee6a4SAndroid Build Coastguard Worker     pub sdts: Vec<SDT>,
36*bb4ee6a4SAndroid Build Coastguard Worker }
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
39*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, FromZeroes, FromBytes, AsBytes)]
40*bb4ee6a4SAndroid Build Coastguard Worker struct GenericAddress {
41*bb4ee6a4SAndroid Build Coastguard Worker     _space_id: u8,
42*bb4ee6a4SAndroid Build Coastguard Worker     _bit_width: u8,
43*bb4ee6a4SAndroid Build Coastguard Worker     _bit_offset: u8,
44*bb4ee6a4SAndroid Build Coastguard Worker     _access_width: u8,
45*bb4ee6a4SAndroid Build Coastguard Worker     _address: u64,
46*bb4ee6a4SAndroid Build Coastguard Worker }
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
49*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, AsBytes)]
50*bb4ee6a4SAndroid Build Coastguard Worker struct LocalApic {
51*bb4ee6a4SAndroid Build Coastguard Worker     _type: u8,
52*bb4ee6a4SAndroid Build Coastguard Worker     _length: u8,
53*bb4ee6a4SAndroid Build Coastguard Worker     _processor_id: u8,
54*bb4ee6a4SAndroid Build Coastguard Worker     _apic_id: u8,
55*bb4ee6a4SAndroid Build Coastguard Worker     _flags: u32,
56*bb4ee6a4SAndroid Build Coastguard Worker }
57*bb4ee6a4SAndroid Build Coastguard Worker 
58*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
59*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, FromZeroes, FromBytes, AsBytes)]
60*bb4ee6a4SAndroid Build Coastguard Worker struct Ioapic {
61*bb4ee6a4SAndroid Build Coastguard Worker     _type: u8,
62*bb4ee6a4SAndroid Build Coastguard Worker     _length: u8,
63*bb4ee6a4SAndroid Build Coastguard Worker     _ioapic_id: u8,
64*bb4ee6a4SAndroid Build Coastguard Worker     _reserved: u8,
65*bb4ee6a4SAndroid Build Coastguard Worker     _apic_address: u32,
66*bb4ee6a4SAndroid Build Coastguard Worker     _gsi_base: u32,
67*bb4ee6a4SAndroid Build Coastguard Worker }
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C, packed)]
70*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, FromZeroes, FromBytes, AsBytes)]
71*bb4ee6a4SAndroid Build Coastguard Worker struct IoapicInterruptSourceOverride {
72*bb4ee6a4SAndroid Build Coastguard Worker     _type: u8,
73*bb4ee6a4SAndroid Build Coastguard Worker     _length: u8,
74*bb4ee6a4SAndroid Build Coastguard Worker     _bus: u8,
75*bb4ee6a4SAndroid Build Coastguard Worker     _source: u8,
76*bb4ee6a4SAndroid Build Coastguard Worker     _gsi: u32,
77*bb4ee6a4SAndroid Build Coastguard Worker     _flags: u16,
78*bb4ee6a4SAndroid Build Coastguard Worker }
79*bb4ee6a4SAndroid Build Coastguard Worker 
80*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
81*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Default, FromZeroes, FromBytes, AsBytes)]
82*bb4ee6a4SAndroid Build Coastguard Worker struct Localx2Apic {
83*bb4ee6a4SAndroid Build Coastguard Worker     _type: u8,
84*bb4ee6a4SAndroid Build Coastguard Worker     _length: u8,
85*bb4ee6a4SAndroid Build Coastguard Worker     _reserved: u16,
86*bb4ee6a4SAndroid Build Coastguard Worker     _x2apic_id: u32,
87*bb4ee6a4SAndroid Build Coastguard Worker     _flags: u32,
88*bb4ee6a4SAndroid Build Coastguard Worker     _processor_id: u32,
89*bb4ee6a4SAndroid Build Coastguard Worker }
90*bb4ee6a4SAndroid Build Coastguard Worker 
91*bb4ee6a4SAndroid Build Coastguard Worker // Space ID for GenericAddress
92*bb4ee6a4SAndroid Build Coastguard Worker const ADR_SPACE_SYSTEM_IO: u8 = 1;
93*bb4ee6a4SAndroid Build Coastguard Worker 
94*bb4ee6a4SAndroid Build Coastguard Worker const OEM_REVISION: u32 = 1;
95*bb4ee6a4SAndroid Build Coastguard Worker //DSDT
96*bb4ee6a4SAndroid Build Coastguard Worker const DSDT_REVISION: u8 = 6;
97*bb4ee6a4SAndroid Build Coastguard Worker // FADT
98*bb4ee6a4SAndroid Build Coastguard Worker const FADT_LEN: u32 = 276;
99*bb4ee6a4SAndroid Build Coastguard Worker const FADT_REVISION: u8 = 6;
100*bb4ee6a4SAndroid Build Coastguard Worker const FADT_MINOR_REVISION: u8 = 3;
101*bb4ee6a4SAndroid Build Coastguard Worker // FADT flags
102*bb4ee6a4SAndroid Build Coastguard Worker const FADT_POWER_BUTTON: u32 = 1 << 4;
103*bb4ee6a4SAndroid Build Coastguard Worker const _FADT_SLEEP_BUTTON: u32 = 1 << 5;
104*bb4ee6a4SAndroid Build Coastguard Worker const FADT_RESET_REGISTER: u32 = 1 << 10;
105*bb4ee6a4SAndroid Build Coastguard Worker const FADT_LOW_POWER_S2IDLE: u32 = 1 << 21;
106*bb4ee6a4SAndroid Build Coastguard Worker // FADT fields offset
107*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_FACS_ADDR32: usize = 36;
108*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_DSDT_ADDR32: usize = 40;
109*bb4ee6a4SAndroid Build Coastguard Worker pub const FADT_FIELD_SCI_INTERRUPT: usize = 46;
110*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_SMI_COMMAND: usize = 48;
111*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM1A_EVENT_BLK_ADDR: usize = 56;
112*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM1B_EVENT_BLK_ADDR: usize = 60;
113*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM1A_CONTROL_BLK_ADDR: usize = 64;
114*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM1B_CONTROL_BLK_ADDR: usize = 68;
115*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM2_CONTROL_BLK_ADDR: usize = 72;
116*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM_TMR_BLK_ADDR: usize = 76;
117*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_GPE0_BLK_ADDR: usize = 80;
118*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_GPE1_BLK_ADDR: usize = 84;
119*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM1A_EVENT_BLK_LEN: usize = 88;
120*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM1A_CONTROL_BLK_LEN: usize = 89;
121*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM2_CONTROL_BLK_LEN: usize = 90;
122*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_PM_TMR_LEN: usize = 91;
123*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_GPE0_BLK_LEN: usize = 92;
124*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_GPE1_BLK_LEN: usize = 93;
125*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_GPE1_BASE: usize = 94;
126*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_RTC_DAY_ALARM: usize = 106;
127*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_RTC_MONTH_ALARM: usize = 107;
128*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_RTC_CENTURY: usize = 108;
129*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_FLAGS: usize = 112;
130*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_RESET_REGISTER: usize = 116;
131*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_RESET_VALUE: usize = 128;
132*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_MINOR_REVISION: usize = 131;
133*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_FACS_ADDR: usize = 132;
134*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_DSDT_ADDR: usize = 140;
135*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_PM1A_EVENT_BLK_ADDR: usize = 148;
136*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_PM1B_EVENT_BLK_ADDR: usize = 160;
137*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_PM1A_CONTROL_BLK_ADDR: usize = 172;
138*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_PM1B_CONTROL_BLK_ADDR: usize = 184;
139*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_PM2_CONTROL_BLK_ADDR: usize = 196;
140*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_PM_TMR_BLK_ADDR: usize = 208;
141*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_GPE0_BLK_ADDR: usize = 220;
142*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_X_GPE1_BLK_ADDR: usize = 232;
143*bb4ee6a4SAndroid Build Coastguard Worker const FADT_FIELD_HYPERVISOR_ID: usize = 268;
144*bb4ee6a4SAndroid Build Coastguard Worker // MADT
145*bb4ee6a4SAndroid Build Coastguard Worker const MADT_LEN: u32 = 44;
146*bb4ee6a4SAndroid Build Coastguard Worker const MADT_REVISION: u8 = 5;
147*bb4ee6a4SAndroid Build Coastguard Worker // MADT fields offset
148*bb4ee6a4SAndroid Build Coastguard Worker const MADT_FIELD_LAPIC_ADDR: usize = 36;
149*bb4ee6a4SAndroid Build Coastguard Worker const MADT_FIELD_FLAGS: usize = 40;
150*bb4ee6a4SAndroid Build Coastguard Worker // MADT flags
151*bb4ee6a4SAndroid Build Coastguard Worker const MADT_FLAG_PCAT_COMPAT: u32 = 1 << 0;
152*bb4ee6a4SAndroid Build Coastguard Worker // MADT structure offsets
153*bb4ee6a4SAndroid Build Coastguard Worker const MADT_STRUCTURE_TYPE: usize = 0;
154*bb4ee6a4SAndroid Build Coastguard Worker const MADT_STRUCTURE_LEN: usize = 1;
155*bb4ee6a4SAndroid Build Coastguard Worker // MADT types
156*bb4ee6a4SAndroid Build Coastguard Worker const MADT_TYPE_LOCAL_APIC: u8 = 0;
157*bb4ee6a4SAndroid Build Coastguard Worker const MADT_TYPE_IO_APIC: u8 = 1;
158*bb4ee6a4SAndroid Build Coastguard Worker const MADT_TYPE_INTERRUPT_SOURCE_OVERRIDE: u8 = 2;
159*bb4ee6a4SAndroid Build Coastguard Worker const MADT_TYPE_LOCAL_X2APIC: u8 = 9;
160*bb4ee6a4SAndroid Build Coastguard Worker // MADT flags
161*bb4ee6a4SAndroid Build Coastguard Worker const MADT_ENABLED: u32 = 1;
162*bb4ee6a4SAndroid Build Coastguard Worker const MADT_INT_POLARITY_ACTIVE_LOW: u16 = 0b11;
163*bb4ee6a4SAndroid Build Coastguard Worker const MADT_INT_TRIGGER_LEVEL: u16 = 0b11 << 2;
164*bb4ee6a4SAndroid Build Coastguard Worker // MADT compatibility
165*bb4ee6a4SAndroid Build Coastguard Worker const MADT_MIN_LOCAL_APIC_ID: u32 = 255;
166*bb4ee6a4SAndroid Build Coastguard Worker // XSDT
167*bb4ee6a4SAndroid Build Coastguard Worker const XSDT_REVISION: u8 = 1;
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker const CPUID_LEAF0_EBX_CPUID_SHIFT: u32 = 24; // Offset of initial apic id.
170*bb4ee6a4SAndroid Build Coastguard Worker 
171*bb4ee6a4SAndroid Build Coastguard Worker // MCFG
172*bb4ee6a4SAndroid Build Coastguard Worker const MCFG_LEN: u32 = 60;
173*bb4ee6a4SAndroid Build Coastguard Worker const MCFG_REVISION: u8 = 1;
174*bb4ee6a4SAndroid Build Coastguard Worker const MCFG_FIELD_BASE_ADDRESS: usize = 44;
175*bb4ee6a4SAndroid Build Coastguard Worker const MCFG_FIELD_START_BUS_NUMBER: usize = 54;
176*bb4ee6a4SAndroid Build Coastguard Worker const MCFG_FIELD_END_BUS_NUMBER: usize = 55;
177*bb4ee6a4SAndroid Build Coastguard Worker 
178*bb4ee6a4SAndroid Build Coastguard Worker const SSDT_REVISION: u8 = 2;
create_customize_ssdt( pci_root: Arc<Mutex<PciRoot>>, amls: BTreeMap<PciAddress, Vec<u8>>, gpe_scope_amls: BTreeMap<PciAddress, Vec<u8>>, ) -> Option<SDT>179*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_customize_ssdt(
180*bb4ee6a4SAndroid Build Coastguard Worker     pci_root: Arc<Mutex<PciRoot>>,
181*bb4ee6a4SAndroid Build Coastguard Worker     amls: BTreeMap<PciAddress, Vec<u8>>,
182*bb4ee6a4SAndroid Build Coastguard Worker     gpe_scope_amls: BTreeMap<PciAddress, Vec<u8>>,
183*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<SDT> {
184*bb4ee6a4SAndroid Build Coastguard Worker     if amls.is_empty() {
185*bb4ee6a4SAndroid Build Coastguard Worker         return None;
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker     let mut ssdt = SDT::new(
189*bb4ee6a4SAndroid Build Coastguard Worker         *b"SSDT",
190*bb4ee6a4SAndroid Build Coastguard Worker         acpi_tables::HEADER_LEN,
191*bb4ee6a4SAndroid Build Coastguard Worker         SSDT_REVISION,
192*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVM",
193*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVMDT",
194*bb4ee6a4SAndroid Build Coastguard Worker         OEM_REVISION,
195*bb4ee6a4SAndroid Build Coastguard Worker     );
196*bb4ee6a4SAndroid Build Coastguard Worker 
197*bb4ee6a4SAndroid Build Coastguard Worker     for (address, children) in amls {
198*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(path) = pci_root.lock().acpi_path(&address) {
199*bb4ee6a4SAndroid Build Coastguard Worker             ssdt.append_slice(&aml::Scope::raw((*path).into(), children));
200*bb4ee6a4SAndroid Build Coastguard Worker         }
201*bb4ee6a4SAndroid Build Coastguard Worker     }
202*bb4ee6a4SAndroid Build Coastguard Worker 
203*bb4ee6a4SAndroid Build Coastguard Worker     for children in gpe_scope_amls.values() {
204*bb4ee6a4SAndroid Build Coastguard Worker         ssdt.append_slice(children);
205*bb4ee6a4SAndroid Build Coastguard Worker     }
206*bb4ee6a4SAndroid Build Coastguard Worker 
207*bb4ee6a4SAndroid Build Coastguard Worker     Some(ssdt)
208*bb4ee6a4SAndroid Build Coastguard Worker }
209*bb4ee6a4SAndroid Build Coastguard Worker 
create_dsdt_table(amls: &[u8]) -> SDT210*bb4ee6a4SAndroid Build Coastguard Worker fn create_dsdt_table(amls: &[u8]) -> SDT {
211*bb4ee6a4SAndroid Build Coastguard Worker     let mut dsdt = SDT::new(
212*bb4ee6a4SAndroid Build Coastguard Worker         *b"DSDT",
213*bb4ee6a4SAndroid Build Coastguard Worker         acpi_tables::HEADER_LEN,
214*bb4ee6a4SAndroid Build Coastguard Worker         DSDT_REVISION,
215*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVM",
216*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVMDT",
217*bb4ee6a4SAndroid Build Coastguard Worker         OEM_REVISION,
218*bb4ee6a4SAndroid Build Coastguard Worker     );
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker     if !amls.is_empty() {
221*bb4ee6a4SAndroid Build Coastguard Worker         dsdt.append_slice(amls);
222*bb4ee6a4SAndroid Build Coastguard Worker     }
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker     dsdt
225*bb4ee6a4SAndroid Build Coastguard Worker }
226*bb4ee6a4SAndroid Build Coastguard Worker 
create_facp_table(sci_irq: u16, force_s2idle: bool) -> SDT227*bb4ee6a4SAndroid Build Coastguard Worker fn create_facp_table(sci_irq: u16, force_s2idle: bool) -> SDT {
228*bb4ee6a4SAndroid Build Coastguard Worker     let mut facp = SDT::new(
229*bb4ee6a4SAndroid Build Coastguard Worker         *b"FACP",
230*bb4ee6a4SAndroid Build Coastguard Worker         FADT_LEN,
231*bb4ee6a4SAndroid Build Coastguard Worker         FADT_REVISION,
232*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVM",
233*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVMDT",
234*bb4ee6a4SAndroid Build Coastguard Worker         OEM_REVISION,
235*bb4ee6a4SAndroid Build Coastguard Worker     );
236*bb4ee6a4SAndroid Build Coastguard Worker 
237*bb4ee6a4SAndroid Build Coastguard Worker     let mut fadt_flags: u32 = 0;
238*bb4ee6a4SAndroid Build Coastguard Worker 
239*bb4ee6a4SAndroid Build Coastguard Worker     if force_s2idle {
240*bb4ee6a4SAndroid Build Coastguard Worker         fadt_flags |= FADT_LOW_POWER_S2IDLE;
241*bb4ee6a4SAndroid Build Coastguard Worker     }
242*bb4ee6a4SAndroid Build Coastguard Worker 
243*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_FLAGS, fadt_flags);
244*bb4ee6a4SAndroid Build Coastguard Worker 
245*bb4ee6a4SAndroid Build Coastguard Worker     // SCI Interrupt
246*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_SCI_INTERRUPT, sci_irq);
247*bb4ee6a4SAndroid Build Coastguard Worker 
248*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_MINOR_REVISION, FADT_MINOR_REVISION); // FADT minor version
249*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_HYPERVISOR_ID, *b"CROSVM"); // Hypervisor Vendor Identity
250*bb4ee6a4SAndroid Build Coastguard Worker 
251*bb4ee6a4SAndroid Build Coastguard Worker     facp.write::<u8>(FADT_FIELD_RTC_CENTURY, devices::cmos::RTC_REG_CENTURY);
252*bb4ee6a4SAndroid Build Coastguard Worker     facp.write::<u8>(FADT_FIELD_RTC_DAY_ALARM, devices::cmos::RTC_REG_ALARM_DAY);
253*bb4ee6a4SAndroid Build Coastguard Worker     facp.write::<u8>(
254*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_RTC_MONTH_ALARM,
255*bb4ee6a4SAndroid Build Coastguard Worker         devices::cmos::RTC_REG_ALARM_MONTH,
256*bb4ee6a4SAndroid Build Coastguard Worker     );
257*bb4ee6a4SAndroid Build Coastguard Worker 
258*bb4ee6a4SAndroid Build Coastguard Worker     facp
259*bb4ee6a4SAndroid Build Coastguard Worker }
260*bb4ee6a4SAndroid Build Coastguard Worker 
261*bb4ee6a4SAndroid Build Coastguard Worker // Write virtualized FADT fields
write_facp_overrides( facp: &mut SDT, facs_offset: GuestAddress, dsdt_offset: GuestAddress, pm_iobase: u32, reset_port: u32, reset_value: u8, )262*bb4ee6a4SAndroid Build Coastguard Worker fn write_facp_overrides(
263*bb4ee6a4SAndroid Build Coastguard Worker     facp: &mut SDT,
264*bb4ee6a4SAndroid Build Coastguard Worker     facs_offset: GuestAddress,
265*bb4ee6a4SAndroid Build Coastguard Worker     dsdt_offset: GuestAddress,
266*bb4ee6a4SAndroid Build Coastguard Worker     pm_iobase: u32,
267*bb4ee6a4SAndroid Build Coastguard Worker     reset_port: u32,
268*bb4ee6a4SAndroid Build Coastguard Worker     reset_value: u8,
269*bb4ee6a4SAndroid Build Coastguard Worker ) {
270*bb4ee6a4SAndroid Build Coastguard Worker     let fadt_flags: u32 = facp.read(FADT_FIELD_FLAGS);
271*bb4ee6a4SAndroid Build Coastguard Worker     // indicate we support FADT RESET_REG
272*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_FLAGS, fadt_flags | FADT_RESET_REGISTER);
273*bb4ee6a4SAndroid Build Coastguard Worker 
274*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_SMI_COMMAND, 0u32);
275*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_FACS_ADDR32, 0u32);
276*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_DSDT_ADDR32, 0u32);
277*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_FACS_ADDR, facs_offset.0);
278*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_DSDT_ADDR, dsdt_offset.0);
279*bb4ee6a4SAndroid Build Coastguard Worker 
280*bb4ee6a4SAndroid Build Coastguard Worker     // PM1A Event Block Address
281*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM1A_EVENT_BLK_ADDR, pm_iobase);
282*bb4ee6a4SAndroid Build Coastguard Worker 
283*bb4ee6a4SAndroid Build Coastguard Worker     // PM1B Event Block Address (not supported)
284*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM1B_EVENT_BLK_ADDR, 0u32);
285*bb4ee6a4SAndroid Build Coastguard Worker 
286*bb4ee6a4SAndroid Build Coastguard Worker     // PM1A Control Block Address
287*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
288*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_PM1A_CONTROL_BLK_ADDR,
289*bb4ee6a4SAndroid Build Coastguard Worker         pm_iobase + devices::acpi::ACPIPM_RESOURCE_EVENTBLK_LEN as u32,
290*bb4ee6a4SAndroid Build Coastguard Worker     );
291*bb4ee6a4SAndroid Build Coastguard Worker 
292*bb4ee6a4SAndroid Build Coastguard Worker     // PM1B Control Block Address (not supported)
293*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM1B_CONTROL_BLK_ADDR, 0u32);
294*bb4ee6a4SAndroid Build Coastguard Worker 
295*bb4ee6a4SAndroid Build Coastguard Worker     // PM2 Control Block Address (not supported)
296*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM2_CONTROL_BLK_ADDR, 0u32);
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker     // PM Timer Control Block Address (not supported)
299*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM_TMR_BLK_ADDR, 0u32);
300*bb4ee6a4SAndroid Build Coastguard Worker 
301*bb4ee6a4SAndroid Build Coastguard Worker     // GPE0 Block Address
302*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
303*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_GPE0_BLK_ADDR,
304*bb4ee6a4SAndroid Build Coastguard Worker         pm_iobase + devices::acpi::ACPIPM_RESOURCE_EVENTBLK_LEN as u32 + 4,
305*bb4ee6a4SAndroid Build Coastguard Worker     );
306*bb4ee6a4SAndroid Build Coastguard Worker 
307*bb4ee6a4SAndroid Build Coastguard Worker     // GPE1 Block Address (not supported)
308*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_GPE1_BLK_ADDR, 0u32);
309*bb4ee6a4SAndroid Build Coastguard Worker 
310*bb4ee6a4SAndroid Build Coastguard Worker     // PM1 Event Block Length
311*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
312*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_PM1A_EVENT_BLK_LEN,
313*bb4ee6a4SAndroid Build Coastguard Worker         devices::acpi::ACPIPM_RESOURCE_EVENTBLK_LEN,
314*bb4ee6a4SAndroid Build Coastguard Worker     );
315*bb4ee6a4SAndroid Build Coastguard Worker 
316*bb4ee6a4SAndroid Build Coastguard Worker     // PM1 Control Block Length
317*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
318*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_PM1A_CONTROL_BLK_LEN,
319*bb4ee6a4SAndroid Build Coastguard Worker         devices::acpi::ACPIPM_RESOURCE_CONTROLBLK_LEN,
320*bb4ee6a4SAndroid Build Coastguard Worker     );
321*bb4ee6a4SAndroid Build Coastguard Worker 
322*bb4ee6a4SAndroid Build Coastguard Worker     // PM2 Control Block Length (not supported)
323*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM2_CONTROL_BLK_LEN, 0u8);
324*bb4ee6a4SAndroid Build Coastguard Worker 
325*bb4ee6a4SAndroid Build Coastguard Worker     // PM Timer Control Block Length (not supported)
326*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_PM_TMR_LEN, 0u8);
327*bb4ee6a4SAndroid Build Coastguard Worker 
328*bb4ee6a4SAndroid Build Coastguard Worker     // GPE0 Block Length
329*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
330*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_GPE0_BLK_LEN,
331*bb4ee6a4SAndroid Build Coastguard Worker         devices::acpi::ACPIPM_RESOURCE_GPE0_BLK_LEN,
332*bb4ee6a4SAndroid Build Coastguard Worker     );
333*bb4ee6a4SAndroid Build Coastguard Worker 
334*bb4ee6a4SAndroid Build Coastguard Worker     // GPE1 Block Length (not supported)
335*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_GPE1_BLK_LEN, 0u8);
336*bb4ee6a4SAndroid Build Coastguard Worker 
337*bb4ee6a4SAndroid Build Coastguard Worker     // GPE1 Base (not supported)
338*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_GPE1_BASE, 0u8);
339*bb4ee6a4SAndroid Build Coastguard Worker 
340*bb4ee6a4SAndroid Build Coastguard Worker     // PM1A Extended Event Block Address (not supported)
341*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
342*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_PM1A_EVENT_BLK_ADDR,
343*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
344*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
345*bb4ee6a4SAndroid Build Coastguard Worker         },
346*bb4ee6a4SAndroid Build Coastguard Worker     );
347*bb4ee6a4SAndroid Build Coastguard Worker 
348*bb4ee6a4SAndroid Build Coastguard Worker     // PM1B Extended Event Block Address (not supported)
349*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
350*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_PM1B_EVENT_BLK_ADDR,
351*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
352*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
353*bb4ee6a4SAndroid Build Coastguard Worker         },
354*bb4ee6a4SAndroid Build Coastguard Worker     );
355*bb4ee6a4SAndroid Build Coastguard Worker 
356*bb4ee6a4SAndroid Build Coastguard Worker     // PM1A Extended Control Block Address (not supported)
357*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
358*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_PM1A_CONTROL_BLK_ADDR,
359*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
360*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
361*bb4ee6a4SAndroid Build Coastguard Worker         },
362*bb4ee6a4SAndroid Build Coastguard Worker     );
363*bb4ee6a4SAndroid Build Coastguard Worker 
364*bb4ee6a4SAndroid Build Coastguard Worker     // PM1B Extended Control Block Address (not supported)
365*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
366*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_PM1B_CONTROL_BLK_ADDR,
367*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
368*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
369*bb4ee6a4SAndroid Build Coastguard Worker         },
370*bb4ee6a4SAndroid Build Coastguard Worker     );
371*bb4ee6a4SAndroid Build Coastguard Worker 
372*bb4ee6a4SAndroid Build Coastguard Worker     // PM2 Extended Control Block Address (not supported)
373*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
374*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_PM2_CONTROL_BLK_ADDR,
375*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
376*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
377*bb4ee6a4SAndroid Build Coastguard Worker         },
378*bb4ee6a4SAndroid Build Coastguard Worker     );
379*bb4ee6a4SAndroid Build Coastguard Worker 
380*bb4ee6a4SAndroid Build Coastguard Worker     // PM Timer Extended Control Block Address (not supported)
381*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
382*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_PM_TMR_BLK_ADDR,
383*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
384*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
385*bb4ee6a4SAndroid Build Coastguard Worker         },
386*bb4ee6a4SAndroid Build Coastguard Worker     );
387*bb4ee6a4SAndroid Build Coastguard Worker 
388*bb4ee6a4SAndroid Build Coastguard Worker     // GPE0 Extended Address (not supported)
389*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
390*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_GPE0_BLK_ADDR,
391*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
392*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
393*bb4ee6a4SAndroid Build Coastguard Worker         },
394*bb4ee6a4SAndroid Build Coastguard Worker     );
395*bb4ee6a4SAndroid Build Coastguard Worker 
396*bb4ee6a4SAndroid Build Coastguard Worker     // GPE1 Extended Address (not supported)
397*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
398*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_X_GPE1_BLK_ADDR,
399*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
400*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
401*bb4ee6a4SAndroid Build Coastguard Worker         },
402*bb4ee6a4SAndroid Build Coastguard Worker     );
403*bb4ee6a4SAndroid Build Coastguard Worker 
404*bb4ee6a4SAndroid Build Coastguard Worker     // Reset register
405*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(
406*bb4ee6a4SAndroid Build Coastguard Worker         FADT_FIELD_RESET_REGISTER,
407*bb4ee6a4SAndroid Build Coastguard Worker         GenericAddress {
408*bb4ee6a4SAndroid Build Coastguard Worker             _space_id: ADR_SPACE_SYSTEM_IO,
409*bb4ee6a4SAndroid Build Coastguard Worker             _bit_width: 8,
410*bb4ee6a4SAndroid Build Coastguard Worker             _bit_offset: 0,
411*bb4ee6a4SAndroid Build Coastguard Worker             _access_width: 1,
412*bb4ee6a4SAndroid Build Coastguard Worker             _address: reset_port.into(),
413*bb4ee6a4SAndroid Build Coastguard Worker         },
414*bb4ee6a4SAndroid Build Coastguard Worker     );
415*bb4ee6a4SAndroid Build Coastguard Worker     facp.write(FADT_FIELD_RESET_VALUE, reset_value);
416*bb4ee6a4SAndroid Build Coastguard Worker }
417*bb4ee6a4SAndroid Build Coastguard Worker 
next_offset(offset: GuestAddress, len: u64) -> Option<GuestAddress>418*bb4ee6a4SAndroid Build Coastguard Worker fn next_offset(offset: GuestAddress, len: u64) -> Option<GuestAddress> {
419*bb4ee6a4SAndroid Build Coastguard Worker     // Enforce 64-byte allocation alignment.
420*bb4ee6a4SAndroid Build Coastguard Worker     match len % 64 {
421*bb4ee6a4SAndroid Build Coastguard Worker         0 => offset.checked_add(len),
422*bb4ee6a4SAndroid Build Coastguard Worker         x => offset.checked_add(len.checked_add(64 - x)?),
423*bb4ee6a4SAndroid Build Coastguard Worker     }
424*bb4ee6a4SAndroid Build Coastguard Worker }
425*bb4ee6a4SAndroid Build Coastguard Worker 
sync_acpi_id_from_cpuid( madt: &mut SDT, cpus: BTreeMap<usize, CpuSet>, apic_ids: &mut Vec<usize>, ) -> base::Result<()>426*bb4ee6a4SAndroid Build Coastguard Worker fn sync_acpi_id_from_cpuid(
427*bb4ee6a4SAndroid Build Coastguard Worker     madt: &mut SDT,
428*bb4ee6a4SAndroid Build Coastguard Worker     cpus: BTreeMap<usize, CpuSet>,
429*bb4ee6a4SAndroid Build Coastguard Worker     apic_ids: &mut Vec<usize>,
430*bb4ee6a4SAndroid Build Coastguard Worker ) -> base::Result<()> {
431*bb4ee6a4SAndroid Build Coastguard Worker     let cpu_set = match base::get_cpu_affinity() {
432*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
433*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed to get CPU affinity: {} when create MADT", e);
434*bb4ee6a4SAndroid Build Coastguard Worker             return Err(e);
435*bb4ee6a4SAndroid Build Coastguard Worker         }
436*bb4ee6a4SAndroid Build Coastguard Worker         Ok(c) => c,
437*bb4ee6a4SAndroid Build Coastguard Worker     };
438*bb4ee6a4SAndroid Build Coastguard Worker 
439*bb4ee6a4SAndroid Build Coastguard Worker     for (vcpu, pcpu) in cpus {
440*bb4ee6a4SAndroid Build Coastguard Worker         let mut has_leafb = false;
441*bb4ee6a4SAndroid Build Coastguard Worker         let mut get_apic_id = false;
442*bb4ee6a4SAndroid Build Coastguard Worker         let mut apic_id: u8 = 0;
443*bb4ee6a4SAndroid Build Coastguard Worker 
444*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = base::set_cpu_affinity(pcpu) {
445*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed to set CPU affinity: {} when create MADT", e);
446*bb4ee6a4SAndroid Build Coastguard Worker             return Err(e);
447*bb4ee6a4SAndroid Build Coastguard Worker         }
448*bb4ee6a4SAndroid Build Coastguard Worker 
449*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
450*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we pass 0 and 0 for this call and the host supports the
451*bb4ee6a4SAndroid Build Coastguard Worker         // `cpuid` instruction
452*bb4ee6a4SAndroid Build Coastguard Worker         let mut cpuid_entry: CpuidResult = unsafe { __cpuid_count(0, 0) };
453*bb4ee6a4SAndroid Build Coastguard Worker 
454*bb4ee6a4SAndroid Build Coastguard Worker         if cpuid_entry.eax >= 0xB {
455*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
456*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because we pass 0xB and 0 for this call and the host supports the
457*bb4ee6a4SAndroid Build Coastguard Worker             // `cpuid` instruction
458*bb4ee6a4SAndroid Build Coastguard Worker             cpuid_entry = unsafe { __cpuid_count(0xB, 0) };
459*bb4ee6a4SAndroid Build Coastguard Worker 
460*bb4ee6a4SAndroid Build Coastguard Worker             if cpuid_entry.ebx != 0 {
461*bb4ee6a4SAndroid Build Coastguard Worker                 // MADT compatibility: (ACPI Spec v6.4) On some legacy OSes,
462*bb4ee6a4SAndroid Build Coastguard Worker                 // Logical processors with APIC ID values less than 255 (whether in
463*bb4ee6a4SAndroid Build Coastguard Worker                 // XAPIC or X2APIC mode) must use the Processor Local APIC structure.
464*bb4ee6a4SAndroid Build Coastguard Worker                 if cpuid_entry.edx < MADT_MIN_LOCAL_APIC_ID {
465*bb4ee6a4SAndroid Build Coastguard Worker                     apic_id = cpuid_entry.edx as u8;
466*bb4ee6a4SAndroid Build Coastguard Worker                     get_apic_id = true;
467*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
468*bb4ee6a4SAndroid Build Coastguard Worker                     // (ACPI Spec v6.4) When using the X2APIC, logical processors are
469*bb4ee6a4SAndroid Build Coastguard Worker                     // required to have a processor device object in the DSDT and must
470*bb4ee6a4SAndroid Build Coastguard Worker                     // convey the processor’s APIC information to OSPM using the Processor
471*bb4ee6a4SAndroid Build Coastguard Worker                     // Local X2APIC structure.
472*bb4ee6a4SAndroid Build Coastguard Worker                     // Now vCPUs use the DSDT passthrougt from host and the same APIC ID as
473*bb4ee6a4SAndroid Build Coastguard Worker                     // the physical CPUs. Both of them should meet ACPI specifications on
474*bb4ee6a4SAndroid Build Coastguard Worker                     // the host.
475*bb4ee6a4SAndroid Build Coastguard Worker                     has_leafb = true;
476*bb4ee6a4SAndroid Build Coastguard Worker 
477*bb4ee6a4SAndroid Build Coastguard Worker                     let x2apic = Localx2Apic {
478*bb4ee6a4SAndroid Build Coastguard Worker                         _type: MADT_TYPE_LOCAL_X2APIC,
479*bb4ee6a4SAndroid Build Coastguard Worker                         _length: std::mem::size_of::<Localx2Apic>() as u8,
480*bb4ee6a4SAndroid Build Coastguard Worker                         _x2apic_id: cpuid_entry.edx,
481*bb4ee6a4SAndroid Build Coastguard Worker                         _flags: MADT_ENABLED,
482*bb4ee6a4SAndroid Build Coastguard Worker                         _processor_id: (vcpu + 1) as u32,
483*bb4ee6a4SAndroid Build Coastguard Worker                         ..Default::default()
484*bb4ee6a4SAndroid Build Coastguard Worker                     };
485*bb4ee6a4SAndroid Build Coastguard Worker                     madt.append(x2apic);
486*bb4ee6a4SAndroid Build Coastguard Worker                     apic_ids.push(cpuid_entry.edx as usize);
487*bb4ee6a4SAndroid Build Coastguard Worker                 }
488*bb4ee6a4SAndroid Build Coastguard Worker             }
489*bb4ee6a4SAndroid Build Coastguard Worker         }
490*bb4ee6a4SAndroid Build Coastguard Worker 
491*bb4ee6a4SAndroid Build Coastguard Worker         if !has_leafb {
492*bb4ee6a4SAndroid Build Coastguard Worker             if !get_apic_id {
493*bb4ee6a4SAndroid Build Coastguard Worker                 // SAFETY:
494*bb4ee6a4SAndroid Build Coastguard Worker                 // Safe because we pass 1 for this call and the host supports the
495*bb4ee6a4SAndroid Build Coastguard Worker                 // `cpuid` instruction
496*bb4ee6a4SAndroid Build Coastguard Worker                 cpuid_entry = unsafe { __cpuid(1) };
497*bb4ee6a4SAndroid Build Coastguard Worker                 apic_id = (cpuid_entry.ebx >> CPUID_LEAF0_EBX_CPUID_SHIFT & 0xff) as u8;
498*bb4ee6a4SAndroid Build Coastguard Worker             }
499*bb4ee6a4SAndroid Build Coastguard Worker 
500*bb4ee6a4SAndroid Build Coastguard Worker             let apic = LocalApic {
501*bb4ee6a4SAndroid Build Coastguard Worker                 _type: MADT_TYPE_LOCAL_APIC,
502*bb4ee6a4SAndroid Build Coastguard Worker                 _length: std::mem::size_of::<LocalApic>() as u8,
503*bb4ee6a4SAndroid Build Coastguard Worker                 _processor_id: vcpu as u8,
504*bb4ee6a4SAndroid Build Coastguard Worker                 _apic_id: apic_id,
505*bb4ee6a4SAndroid Build Coastguard Worker                 _flags: MADT_ENABLED,
506*bb4ee6a4SAndroid Build Coastguard Worker             };
507*bb4ee6a4SAndroid Build Coastguard Worker             madt.append(apic);
508*bb4ee6a4SAndroid Build Coastguard Worker             apic_ids.push(apic_id as usize);
509*bb4ee6a4SAndroid Build Coastguard Worker         }
510*bb4ee6a4SAndroid Build Coastguard Worker     }
511*bb4ee6a4SAndroid Build Coastguard Worker 
512*bb4ee6a4SAndroid Build Coastguard Worker     if let Err(e) = base::set_cpu_affinity(cpu_set) {
513*bb4ee6a4SAndroid Build Coastguard Worker         error!("Failed to reset CPU affinity: {} when create MADT", e);
514*bb4ee6a4SAndroid Build Coastguard Worker         return Err(e);
515*bb4ee6a4SAndroid Build Coastguard Worker     }
516*bb4ee6a4SAndroid Build Coastguard Worker 
517*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
518*bb4ee6a4SAndroid Build Coastguard Worker }
519*bb4ee6a4SAndroid Build Coastguard Worker 
520*bb4ee6a4SAndroid Build Coastguard Worker /// Create ACPI tables and return the RSDP.
521*bb4ee6a4SAndroid Build Coastguard Worker /// The basic tables DSDT/FACP/MADT/XSDT are constructed in this function.
522*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
523*bb4ee6a4SAndroid Build Coastguard Worker ///
524*bb4ee6a4SAndroid Build Coastguard Worker /// * `guest_mem` - The guest memory where the tables will be stored.
525*bb4ee6a4SAndroid Build Coastguard Worker /// * `num_cpus` - Used to construct the MADT.
526*bb4ee6a4SAndroid Build Coastguard Worker /// * `sci_irq` - Used to fill the FACP SCI_INTERRUPT field, which is going to be used by the ACPI
527*bb4ee6a4SAndroid Build Coastguard Worker ///   drivers to register sci handler.
528*bb4ee6a4SAndroid Build Coastguard Worker /// * `acpi_dev_resource` - resouces needed by the ACPI devices for creating tables.
529*bb4ee6a4SAndroid Build Coastguard Worker /// * `host_cpus` - The CPU affinity per CPU used to get corresponding CPUs' apic id and set these
530*bb4ee6a4SAndroid Build Coastguard Worker ///   apic id in MADT if `--host-cpu-topology` option is set.
531*bb4ee6a4SAndroid Build Coastguard Worker /// * `apic_ids` - The apic id for vCPU will be sent to KVM by KVM_CREATE_VCPU ioctl.
532*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_rqs` - PCI device to IRQ number assignments as returned by `arch::generate_pci_root()`
533*bb4ee6a4SAndroid Build Coastguard Worker ///   (device address, IRQ number, and PCI interrupt pin assignment).
534*bb4ee6a4SAndroid Build Coastguard Worker /// * `pcie_cfg_mmio` - Base address for the pcie enhanced configuration access mechanism
535*bb4ee6a4SAndroid Build Coastguard Worker /// * `max_bus` - Max bus number in MCFG table
536*bb4ee6a4SAndroid Build Coastguard Worker 
create_acpi_tables( guest_mem: &GuestMemory, num_cpus: u8, sci_irq: u32, reset_port: u32, reset_value: u8, acpi_dev_resource: &AcpiDevResource, host_cpus: Option<VcpuAffinity>, apic_ids: &mut Vec<usize>, pci_irqs: &[(PciAddress, u32, PciInterruptPin)], pcie_cfg_mmio: u64, max_bus: u8, force_s2idle: bool, ) -> Option<GuestAddress>537*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_acpi_tables(
538*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: &GuestMemory,
539*bb4ee6a4SAndroid Build Coastguard Worker     num_cpus: u8,
540*bb4ee6a4SAndroid Build Coastguard Worker     sci_irq: u32,
541*bb4ee6a4SAndroid Build Coastguard Worker     reset_port: u32,
542*bb4ee6a4SAndroid Build Coastguard Worker     reset_value: u8,
543*bb4ee6a4SAndroid Build Coastguard Worker     acpi_dev_resource: &AcpiDevResource,
544*bb4ee6a4SAndroid Build Coastguard Worker     host_cpus: Option<VcpuAffinity>,
545*bb4ee6a4SAndroid Build Coastguard Worker     apic_ids: &mut Vec<usize>,
546*bb4ee6a4SAndroid Build Coastguard Worker     pci_irqs: &[(PciAddress, u32, PciInterruptPin)],
547*bb4ee6a4SAndroid Build Coastguard Worker     pcie_cfg_mmio: u64,
548*bb4ee6a4SAndroid Build Coastguard Worker     max_bus: u8,
549*bb4ee6a4SAndroid Build Coastguard Worker     force_s2idle: bool,
550*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<GuestAddress> {
551*bb4ee6a4SAndroid Build Coastguard Worker     // RSDP is at the HI RSDP WINDOW
552*bb4ee6a4SAndroid Build Coastguard Worker     let rsdp_offset = GuestAddress(super::ACPI_HI_RSDP_WINDOW_BASE);
553*bb4ee6a4SAndroid Build Coastguard Worker     let facs_offset = next_offset(rsdp_offset, RSDP::len() as u64)?;
554*bb4ee6a4SAndroid Build Coastguard Worker     let mut offset = next_offset(facs_offset, FACS::len() as u64)?;
555*bb4ee6a4SAndroid Build Coastguard Worker     let mut dsdt_offset: Option<GuestAddress> = None;
556*bb4ee6a4SAndroid Build Coastguard Worker     let mut tables: Vec<u64> = Vec::new();
557*bb4ee6a4SAndroid Build Coastguard Worker     let mut facp: Option<SDT> = None;
558*bb4ee6a4SAndroid Build Coastguard Worker     let mut host_madt: Option<SDT> = None;
559*bb4ee6a4SAndroid Build Coastguard Worker 
560*bb4ee6a4SAndroid Build Coastguard Worker     // User supplied System Description Tables, e.g. SSDT.
561*bb4ee6a4SAndroid Build Coastguard Worker     for sdt in acpi_dev_resource.sdts.iter() {
562*bb4ee6a4SAndroid Build Coastguard Worker         if sdt.is_signature(b"FACP") {
563*bb4ee6a4SAndroid Build Coastguard Worker             facp = Some(sdt.clone());
564*bb4ee6a4SAndroid Build Coastguard Worker             continue;
565*bb4ee6a4SAndroid Build Coastguard Worker         }
566*bb4ee6a4SAndroid Build Coastguard Worker         if sdt.is_signature(b"APIC") {
567*bb4ee6a4SAndroid Build Coastguard Worker             host_madt = Some(sdt.clone());
568*bb4ee6a4SAndroid Build Coastguard Worker             continue;
569*bb4ee6a4SAndroid Build Coastguard Worker         }
570*bb4ee6a4SAndroid Build Coastguard Worker         guest_mem.write_at_addr(sdt.as_slice(), offset).ok()?;
571*bb4ee6a4SAndroid Build Coastguard Worker         if sdt.is_signature(b"DSDT") {
572*bb4ee6a4SAndroid Build Coastguard Worker             dsdt_offset = Some(offset);
573*bb4ee6a4SAndroid Build Coastguard Worker         } else {
574*bb4ee6a4SAndroid Build Coastguard Worker             tables.push(offset.0);
575*bb4ee6a4SAndroid Build Coastguard Worker         }
576*bb4ee6a4SAndroid Build Coastguard Worker         offset = next_offset(offset, sdt.len() as u64)?;
577*bb4ee6a4SAndroid Build Coastguard Worker     }
578*bb4ee6a4SAndroid Build Coastguard Worker 
579*bb4ee6a4SAndroid Build Coastguard Worker     // FACS
580*bb4ee6a4SAndroid Build Coastguard Worker     let facs = FACS::new();
581*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem.write_at_addr(facs.as_bytes(), facs_offset).ok()?;
582*bb4ee6a4SAndroid Build Coastguard Worker 
583*bb4ee6a4SAndroid Build Coastguard Worker     // DSDT
584*bb4ee6a4SAndroid Build Coastguard Worker     let dsdt_offset = match dsdt_offset {
585*bb4ee6a4SAndroid Build Coastguard Worker         Some(dsdt_offset) => dsdt_offset,
586*bb4ee6a4SAndroid Build Coastguard Worker         None => {
587*bb4ee6a4SAndroid Build Coastguard Worker             let dsdt_offset = offset;
588*bb4ee6a4SAndroid Build Coastguard Worker             let dsdt = create_dsdt_table(&acpi_dev_resource.amls);
589*bb4ee6a4SAndroid Build Coastguard Worker             guest_mem.write_at_addr(dsdt.as_slice(), offset).ok()?;
590*bb4ee6a4SAndroid Build Coastguard Worker             offset = next_offset(offset, dsdt.len() as u64)?;
591*bb4ee6a4SAndroid Build Coastguard Worker             dsdt_offset
592*bb4ee6a4SAndroid Build Coastguard Worker         }
593*bb4ee6a4SAndroid Build Coastguard Worker     };
594*bb4ee6a4SAndroid Build Coastguard Worker 
595*bb4ee6a4SAndroid Build Coastguard Worker     // FACP aka FADT
596*bb4ee6a4SAndroid Build Coastguard Worker     let mut facp = facp.map_or_else(
597*bb4ee6a4SAndroid Build Coastguard Worker         || create_facp_table(sci_irq as u16, force_s2idle),
598*bb4ee6a4SAndroid Build Coastguard Worker         |facp| {
599*bb4ee6a4SAndroid Build Coastguard Worker             let fadt_flags: u32 = facp.read(FADT_FIELD_FLAGS);
600*bb4ee6a4SAndroid Build Coastguard Worker             if fadt_flags & FADT_POWER_BUTTON != 0 {
601*bb4ee6a4SAndroid Build Coastguard Worker                 warn!(
602*bb4ee6a4SAndroid Build Coastguard Worker                     "Control Method Power Button is not supported. FADT flags = 0x{:x}",
603*bb4ee6a4SAndroid Build Coastguard Worker                     fadt_flags
604*bb4ee6a4SAndroid Build Coastguard Worker                 );
605*bb4ee6a4SAndroid Build Coastguard Worker             }
606*bb4ee6a4SAndroid Build Coastguard Worker             facp
607*bb4ee6a4SAndroid Build Coastguard Worker         },
608*bb4ee6a4SAndroid Build Coastguard Worker     );
609*bb4ee6a4SAndroid Build Coastguard Worker 
610*bb4ee6a4SAndroid Build Coastguard Worker     write_facp_overrides(
611*bb4ee6a4SAndroid Build Coastguard Worker         &mut facp,
612*bb4ee6a4SAndroid Build Coastguard Worker         facs_offset,
613*bb4ee6a4SAndroid Build Coastguard Worker         dsdt_offset,
614*bb4ee6a4SAndroid Build Coastguard Worker         acpi_dev_resource.pm_iobase as u32,
615*bb4ee6a4SAndroid Build Coastguard Worker         reset_port,
616*bb4ee6a4SAndroid Build Coastguard Worker         reset_value,
617*bb4ee6a4SAndroid Build Coastguard Worker     );
618*bb4ee6a4SAndroid Build Coastguard Worker 
619*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem.write_at_addr(facp.as_slice(), offset).ok()?;
620*bb4ee6a4SAndroid Build Coastguard Worker     tables.push(offset.0);
621*bb4ee6a4SAndroid Build Coastguard Worker     offset = next_offset(offset, facp.len() as u64)?;
622*bb4ee6a4SAndroid Build Coastguard Worker 
623*bb4ee6a4SAndroid Build Coastguard Worker     // MADT
624*bb4ee6a4SAndroid Build Coastguard Worker     let mut madt = SDT::new(
625*bb4ee6a4SAndroid Build Coastguard Worker         *b"APIC",
626*bb4ee6a4SAndroid Build Coastguard Worker         MADT_LEN,
627*bb4ee6a4SAndroid Build Coastguard Worker         MADT_REVISION,
628*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVM",
629*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVMDT",
630*bb4ee6a4SAndroid Build Coastguard Worker         OEM_REVISION,
631*bb4ee6a4SAndroid Build Coastguard Worker     );
632*bb4ee6a4SAndroid Build Coastguard Worker     madt.write(
633*bb4ee6a4SAndroid Build Coastguard Worker         MADT_FIELD_LAPIC_ADDR,
634*bb4ee6a4SAndroid Build Coastguard Worker         super::mptable::APIC_DEFAULT_PHYS_BASE,
635*bb4ee6a4SAndroid Build Coastguard Worker     );
636*bb4ee6a4SAndroid Build Coastguard Worker     // Our IrqChip implementations (the KVM in-kernel irqchip and the split irqchip) expose a pair
637*bb4ee6a4SAndroid Build Coastguard Worker     // of PC-compatible 8259 PICs.
638*bb4ee6a4SAndroid Build Coastguard Worker     madt.write(MADT_FIELD_FLAGS, MADT_FLAG_PCAT_COMPAT);
639*bb4ee6a4SAndroid Build Coastguard Worker 
640*bb4ee6a4SAndroid Build Coastguard Worker     match host_cpus {
641*bb4ee6a4SAndroid Build Coastguard Worker         Some(VcpuAffinity::PerVcpu(cpus)) => {
642*bb4ee6a4SAndroid Build Coastguard Worker             sync_acpi_id_from_cpuid(&mut madt, cpus, apic_ids).ok()?;
643*bb4ee6a4SAndroid Build Coastguard Worker         }
644*bb4ee6a4SAndroid Build Coastguard Worker         _ => {
645*bb4ee6a4SAndroid Build Coastguard Worker             for cpu in 0..num_cpus {
646*bb4ee6a4SAndroid Build Coastguard Worker                 let apic = LocalApic {
647*bb4ee6a4SAndroid Build Coastguard Worker                     _type: MADT_TYPE_LOCAL_APIC,
648*bb4ee6a4SAndroid Build Coastguard Worker                     _length: std::mem::size_of::<LocalApic>() as u8,
649*bb4ee6a4SAndroid Build Coastguard Worker                     _processor_id: cpu,
650*bb4ee6a4SAndroid Build Coastguard Worker                     _apic_id: cpu,
651*bb4ee6a4SAndroid Build Coastguard Worker                     _flags: MADT_ENABLED,
652*bb4ee6a4SAndroid Build Coastguard Worker                 };
653*bb4ee6a4SAndroid Build Coastguard Worker                 madt.append(apic);
654*bb4ee6a4SAndroid Build Coastguard Worker                 apic_ids.push(cpu as usize);
655*bb4ee6a4SAndroid Build Coastguard Worker             }
656*bb4ee6a4SAndroid Build Coastguard Worker         }
657*bb4ee6a4SAndroid Build Coastguard Worker     }
658*bb4ee6a4SAndroid Build Coastguard Worker 
659*bb4ee6a4SAndroid Build Coastguard Worker     madt.append(Ioapic {
660*bb4ee6a4SAndroid Build Coastguard Worker         _type: MADT_TYPE_IO_APIC,
661*bb4ee6a4SAndroid Build Coastguard Worker         _length: std::mem::size_of::<Ioapic>() as u8,
662*bb4ee6a4SAndroid Build Coastguard Worker         _apic_address: super::mptable::IO_APIC_DEFAULT_PHYS_BASE,
663*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
664*bb4ee6a4SAndroid Build Coastguard Worker     });
665*bb4ee6a4SAndroid Build Coastguard Worker 
666*bb4ee6a4SAndroid Build Coastguard Worker     // Add interrupt overrides for the PCI IRQs so that they are reported as level triggered, as
667*bb4ee6a4SAndroid Build Coastguard Worker     // required by the PCI bus. The source and system GSI are identical, so this does not actually
668*bb4ee6a4SAndroid Build Coastguard Worker     // override the mapping; we just use it to set the level-triggered flag.
669*bb4ee6a4SAndroid Build Coastguard Worker     let mut unique_pci_irqs: Vec<u32> = pci_irqs.iter().map(|(_, irq_num, _)| *irq_num).collect();
670*bb4ee6a4SAndroid Build Coastguard Worker     unique_pci_irqs.sort_unstable();
671*bb4ee6a4SAndroid Build Coastguard Worker     unique_pci_irqs.dedup();
672*bb4ee6a4SAndroid Build Coastguard Worker     for irq_num in unique_pci_irqs {
673*bb4ee6a4SAndroid Build Coastguard Worker         madt.append(IoapicInterruptSourceOverride {
674*bb4ee6a4SAndroid Build Coastguard Worker             _type: MADT_TYPE_INTERRUPT_SOURCE_OVERRIDE,
675*bb4ee6a4SAndroid Build Coastguard Worker             _length: std::mem::size_of::<IoapicInterruptSourceOverride>() as u8,
676*bb4ee6a4SAndroid Build Coastguard Worker             _bus: 0, // ISA
677*bb4ee6a4SAndroid Build Coastguard Worker             _source: irq_num as u8,
678*bb4ee6a4SAndroid Build Coastguard Worker             _gsi: irq_num,
679*bb4ee6a4SAndroid Build Coastguard Worker             _flags: MADT_INT_POLARITY_ACTIVE_LOW | MADT_INT_TRIGGER_LEVEL,
680*bb4ee6a4SAndroid Build Coastguard Worker         });
681*bb4ee6a4SAndroid Build Coastguard Worker     }
682*bb4ee6a4SAndroid Build Coastguard Worker 
683*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(host_madt) = host_madt {
684*bb4ee6a4SAndroid Build Coastguard Worker         let mut idx = MADT_LEN as usize;
685*bb4ee6a4SAndroid Build Coastguard Worker         while idx + MADT_STRUCTURE_LEN < host_madt.len() {
686*bb4ee6a4SAndroid Build Coastguard Worker             let struct_type = host_madt.as_slice()[idx + MADT_STRUCTURE_TYPE];
687*bb4ee6a4SAndroid Build Coastguard Worker             let struct_len = host_madt.as_slice()[idx + MADT_STRUCTURE_LEN] as usize;
688*bb4ee6a4SAndroid Build Coastguard Worker             if struct_type == MADT_TYPE_INTERRUPT_SOURCE_OVERRIDE {
689*bb4ee6a4SAndroid Build Coastguard Worker                 if idx + struct_len <= host_madt.len() {
690*bb4ee6a4SAndroid Build Coastguard Worker                     madt.append_slice(&host_madt.as_slice()[idx..(idx + struct_len)]);
691*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
692*bb4ee6a4SAndroid Build Coastguard Worker                     error!("Malformed host MADT");
693*bb4ee6a4SAndroid Build Coastguard Worker                 }
694*bb4ee6a4SAndroid Build Coastguard Worker             }
695*bb4ee6a4SAndroid Build Coastguard Worker             idx += struct_len;
696*bb4ee6a4SAndroid Build Coastguard Worker         }
697*bb4ee6a4SAndroid Build Coastguard Worker     }
698*bb4ee6a4SAndroid Build Coastguard Worker 
699*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem.write_at_addr(madt.as_slice(), offset).ok()?;
700*bb4ee6a4SAndroid Build Coastguard Worker     tables.push(offset.0);
701*bb4ee6a4SAndroid Build Coastguard Worker     offset = next_offset(offset, madt.len() as u64)?;
702*bb4ee6a4SAndroid Build Coastguard Worker 
703*bb4ee6a4SAndroid Build Coastguard Worker     // MCFG
704*bb4ee6a4SAndroid Build Coastguard Worker     let mut mcfg = SDT::new(
705*bb4ee6a4SAndroid Build Coastguard Worker         *b"MCFG",
706*bb4ee6a4SAndroid Build Coastguard Worker         MCFG_LEN,
707*bb4ee6a4SAndroid Build Coastguard Worker         MCFG_REVISION,
708*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVM",
709*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVMDT",
710*bb4ee6a4SAndroid Build Coastguard Worker         OEM_REVISION,
711*bb4ee6a4SAndroid Build Coastguard Worker     );
712*bb4ee6a4SAndroid Build Coastguard Worker     mcfg.write(MCFG_FIELD_BASE_ADDRESS, pcie_cfg_mmio);
713*bb4ee6a4SAndroid Build Coastguard Worker     mcfg.write(MCFG_FIELD_START_BUS_NUMBER, 0_u8);
714*bb4ee6a4SAndroid Build Coastguard Worker     mcfg.write(MCFG_FIELD_END_BUS_NUMBER, max_bus);
715*bb4ee6a4SAndroid Build Coastguard Worker 
716*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem.write_at_addr(mcfg.as_slice(), offset).ok()?;
717*bb4ee6a4SAndroid Build Coastguard Worker     tables.push(offset.0);
718*bb4ee6a4SAndroid Build Coastguard Worker     offset = next_offset(offset, madt.len() as u64)?;
719*bb4ee6a4SAndroid Build Coastguard Worker 
720*bb4ee6a4SAndroid Build Coastguard Worker     // XSDT
721*bb4ee6a4SAndroid Build Coastguard Worker     let mut xsdt = SDT::new(
722*bb4ee6a4SAndroid Build Coastguard Worker         *b"XSDT",
723*bb4ee6a4SAndroid Build Coastguard Worker         acpi_tables::HEADER_LEN,
724*bb4ee6a4SAndroid Build Coastguard Worker         XSDT_REVISION,
725*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVM",
726*bb4ee6a4SAndroid Build Coastguard Worker         *b"CROSVMDT",
727*bb4ee6a4SAndroid Build Coastguard Worker         OEM_REVISION,
728*bb4ee6a4SAndroid Build Coastguard Worker     );
729*bb4ee6a4SAndroid Build Coastguard Worker     for table in tables {
730*bb4ee6a4SAndroid Build Coastguard Worker         xsdt.append(table);
731*bb4ee6a4SAndroid Build Coastguard Worker     }
732*bb4ee6a4SAndroid Build Coastguard Worker 
733*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem.write_at_addr(xsdt.as_slice(), offset).ok()?;
734*bb4ee6a4SAndroid Build Coastguard Worker 
735*bb4ee6a4SAndroid Build Coastguard Worker     // RSDP
736*bb4ee6a4SAndroid Build Coastguard Worker     let rsdp = RSDP::new(*b"CROSVM", offset.0);
737*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem.write_at_addr(rsdp.as_bytes(), rsdp_offset).ok()?;
738*bb4ee6a4SAndroid Build Coastguard Worker 
739*bb4ee6a4SAndroid Build Coastguard Worker     Some(rsdp_offset)
740*bb4ee6a4SAndroid Build Coastguard Worker }
741*bb4ee6a4SAndroid Build Coastguard Worker 
742*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
743*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
744*bb4ee6a4SAndroid Build Coastguard Worker     use crate::acpi::*;
745*bb4ee6a4SAndroid Build Coastguard Worker 
746*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
facp_table_creation()747*bb4ee6a4SAndroid Build Coastguard Worker     fn facp_table_creation() {
748*bb4ee6a4SAndroid Build Coastguard Worker         let sci_irq: u16 = 5;
749*bb4ee6a4SAndroid Build Coastguard Worker         let force_s2idle = true;
750*bb4ee6a4SAndroid Build Coastguard Worker         let facp = create_facp_table(sci_irq, force_s2idle);
751*bb4ee6a4SAndroid Build Coastguard Worker 
752*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(facp.read::<u32>(FADT_FIELD_FLAGS), FADT_LOW_POWER_S2IDLE);
753*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(facp.read::<u16>(FADT_FIELD_SCI_INTERRUPT), sci_irq);
754*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
755*bb4ee6a4SAndroid Build Coastguard Worker             facp.read::<u8>(FADT_FIELD_MINOR_REVISION),
756*bb4ee6a4SAndroid Build Coastguard Worker             FADT_MINOR_REVISION
757*bb4ee6a4SAndroid Build Coastguard Worker         );
758*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(facp.read::<[u8; 6]>(FADT_FIELD_HYPERVISOR_ID), *b"CROSVM");
759*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
760*bb4ee6a4SAndroid Build Coastguard Worker             facp.read::<u8>(FADT_FIELD_RTC_CENTURY),
761*bb4ee6a4SAndroid Build Coastguard Worker             devices::cmos::RTC_REG_CENTURY
762*bb4ee6a4SAndroid Build Coastguard Worker         );
763*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
764*bb4ee6a4SAndroid Build Coastguard Worker             facp.read::<u8>(FADT_FIELD_RTC_DAY_ALARM),
765*bb4ee6a4SAndroid Build Coastguard Worker             devices::cmos::RTC_REG_ALARM_DAY
766*bb4ee6a4SAndroid Build Coastguard Worker         );
767*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
768*bb4ee6a4SAndroid Build Coastguard Worker             facp.read::<u8>(FADT_FIELD_RTC_MONTH_ALARM),
769*bb4ee6a4SAndroid Build Coastguard Worker             devices::cmos::RTC_REG_ALARM_MONTH
770*bb4ee6a4SAndroid Build Coastguard Worker         );
771*bb4ee6a4SAndroid Build Coastguard Worker     }
772*bb4ee6a4SAndroid Build Coastguard Worker }
773