1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 use crate::cpu::CpuManager; 6 use crate::device_manager::DeviceManager; 7 use crate::memory_manager::MemoryManager; 8 use crate::pci_segment::PciSegment; 9 use crate::{GuestMemoryMmap, GuestRegionMmap}; 10 #[cfg(target_arch = "aarch64")] 11 use acpi_tables::sdt::GenericAddress; 12 use acpi_tables::{rsdp::Rsdp, sdt::Sdt, Aml}; 13 #[cfg(target_arch = "aarch64")] 14 use arch::aarch64::DeviceInfoForFdt; 15 #[cfg(target_arch = "aarch64")] 16 use arch::DeviceType; 17 use arch::NumaNodes; 18 use bitflags::bitflags; 19 use pci::PciBdf; 20 use std::sync::{Arc, Mutex}; 21 use std::time::Instant; 22 use tracer::trace_scoped; 23 use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryRegion}; 24 use zerocopy::AsBytes; 25 26 /* Values for Type in APIC sub-headers */ 27 #[cfg(target_arch = "x86_64")] 28 pub const ACPI_X2APIC_PROCESSOR: u8 = 9; 29 #[cfg(target_arch = "x86_64")] 30 pub const ACPI_APIC_IO: u8 = 1; 31 #[cfg(target_arch = "x86_64")] 32 pub const ACPI_APIC_XRUPT_OVERRIDE: u8 = 2; 33 #[cfg(target_arch = "aarch64")] 34 pub const ACPI_APIC_GENERIC_CPU_INTERFACE: u8 = 11; 35 #[cfg(target_arch = "aarch64")] 36 pub const ACPI_APIC_GENERIC_DISTRIBUTOR: u8 = 12; 37 #[cfg(target_arch = "aarch64")] 38 pub const ACPI_APIC_GENERIC_REDISTRIBUTOR: u8 = 14; 39 #[cfg(target_arch = "aarch64")] 40 pub const ACPI_APIC_GENERIC_TRANSLATOR: u8 = 15; 41 42 #[allow(dead_code)] 43 #[repr(packed)] 44 #[derive(Default, AsBytes)] 45 struct PciRangeEntry { 46 pub base_address: u64, 47 pub segment: u16, 48 pub start: u8, 49 pub end: u8, 50 _reserved: u32, 51 } 52 53 #[allow(dead_code)] 54 #[repr(packed)] 55 #[derive(Default, AsBytes)] 56 struct MemoryAffinity { 57 pub type_: u8, 58 pub length: u8, 59 pub proximity_domain: u32, 60 _reserved1: u16, 61 pub base_addr_lo: u32, 62 pub base_addr_hi: u32, 63 pub length_lo: u32, 64 pub length_hi: u32, 65 _reserved2: u32, 66 pub flags: u32, 67 _reserved3: u64, 68 } 69 70 #[allow(dead_code)] 71 #[repr(packed)] 72 #[derive(Default, AsBytes)] 73 struct ProcessorLocalX2ApicAffinity { 74 pub type_: u8, 75 pub length: u8, 76 _reserved1: u16, 77 pub proximity_domain: u32, 78 pub x2apic_id: u32, 79 pub flags: u32, 80 pub clock_domain: u32, 81 _reserved2: u32, 82 } 83 84 #[allow(dead_code)] 85 #[repr(packed)] 86 #[derive(Default, AsBytes)] 87 struct ProcessorGiccAffinity { 88 pub type_: u8, 89 pub length: u8, 90 pub proximity_domain: u32, 91 pub acpi_processor_uid: u32, 92 pub flags: u32, 93 pub clock_domain: u32, 94 } 95 96 bitflags! { 97 pub struct MemAffinityFlags: u32 { 98 const NOFLAGS = 0; 99 const ENABLE = 0b1; 100 const HOTPLUGGABLE = 0b10; 101 const NON_VOLATILE = 0b100; 102 } 103 } 104 105 impl MemoryAffinity { 106 fn from_region( 107 region: &Arc<GuestRegionMmap>, 108 proximity_domain: u32, 109 flags: MemAffinityFlags, 110 ) -> Self { 111 Self::from_range( 112 region.start_addr().raw_value(), 113 region.len(), 114 proximity_domain, 115 flags, 116 ) 117 } 118 119 fn from_range( 120 base_addr: u64, 121 size: u64, 122 proximity_domain: u32, 123 flags: MemAffinityFlags, 124 ) -> Self { 125 let base_addr_lo = (base_addr & 0xffff_ffff) as u32; 126 let base_addr_hi = (base_addr >> 32) as u32; 127 let length_lo = (size & 0xffff_ffff) as u32; 128 let length_hi = (size >> 32) as u32; 129 130 MemoryAffinity { 131 type_: 1, 132 length: 40, 133 proximity_domain, 134 base_addr_lo, 135 base_addr_hi, 136 length_lo, 137 length_hi, 138 flags: flags.bits(), 139 ..Default::default() 140 } 141 } 142 } 143 144 #[allow(dead_code)] 145 #[repr(packed)] 146 #[derive(Default, AsBytes)] 147 struct ViotVirtioPciNode { 148 pub type_: u8, 149 _reserved: u8, 150 pub length: u16, 151 pub pci_segment: u16, 152 pub pci_bdf_number: u16, 153 _reserved2: [u8; 8], 154 } 155 156 #[allow(dead_code)] 157 #[repr(packed)] 158 #[derive(Default, AsBytes)] 159 struct ViotPciRangeNode { 160 pub type_: u8, 161 _reserved: u8, 162 pub length: u16, 163 pub endpoint_start: u32, 164 pub pci_segment_start: u16, 165 pub pci_segment_end: u16, 166 pub pci_bdf_start: u16, 167 pub pci_bdf_end: u16, 168 pub output_node: u16, 169 _reserved2: [u8; 6], 170 } 171 172 pub fn create_dsdt_table( 173 device_manager: &Arc<Mutex<DeviceManager>>, 174 cpu_manager: &Arc<Mutex<CpuManager>>, 175 memory_manager: &Arc<Mutex<MemoryManager>>, 176 ) -> Sdt { 177 trace_scoped!("create_dsdt_table"); 178 // DSDT 179 let mut dsdt = Sdt::new(*b"DSDT", 36, 6, *b"CLOUDH", *b"CHDSDT ", 1); 180 181 let mut bytes = Vec::new(); 182 183 device_manager.lock().unwrap().to_aml_bytes(&mut bytes); 184 cpu_manager.lock().unwrap().to_aml_bytes(&mut bytes); 185 memory_manager.lock().unwrap().to_aml_bytes(&mut bytes); 186 dsdt.append_slice(&bytes); 187 188 dsdt 189 } 190 191 fn create_facp_table(dsdt_offset: GuestAddress, device_manager: &Arc<Mutex<DeviceManager>>) -> Sdt { 192 trace_scoped!("create_facp_table"); 193 194 // Revision 6 of the ACPI FADT table is 276 bytes long 195 let mut facp = Sdt::new(*b"FACP", 276, 6, *b"CLOUDH", *b"CHFACP ", 1); 196 197 { 198 let device_manager = device_manager.lock().unwrap(); 199 if let Some(address) = device_manager.acpi_platform_addresses().reset_reg_address { 200 // RESET_REG 201 facp.write(116, address); 202 // RESET_VALUE 203 facp.write(128, 1u8); 204 } 205 206 if let Some(address) = device_manager 207 .acpi_platform_addresses() 208 .sleep_control_reg_address 209 { 210 // SLEEP_CONTROL_REG 211 facp.write(244, address); 212 } 213 214 if let Some(address) = device_manager 215 .acpi_platform_addresses() 216 .sleep_status_reg_address 217 { 218 // SLEEP_STATUS_REG 219 facp.write(256, address); 220 } 221 222 if let Some(address) = device_manager.acpi_platform_addresses().pm_timer_address { 223 // X_PM_TMR_BLK 224 facp.write(208, address); 225 } 226 } 227 228 // aarch64 specific fields 229 #[cfg(target_arch = "aarch64")] 230 // ARM_BOOT_ARCH: enable PSCI with HVC enable-method 231 facp.write(129, 3u16); 232 233 // Architecture common fields 234 // HW_REDUCED_ACPI, RESET_REG_SUP, TMR_VAL_EXT 235 let fadt_flags: u32 = 1 << 20 | 1 << 10 | 1 << 8; 236 facp.write(112, fadt_flags); 237 // FADT minor version 238 facp.write(131, 3u8); 239 // X_DSDT 240 facp.write(140, dsdt_offset.0); 241 // Hypervisor Vendor Identity 242 facp.write_bytes(268, b"CLOUDHYP"); 243 244 facp.update_checksum(); 245 246 facp 247 } 248 249 fn create_mcfg_table(pci_segments: &[PciSegment]) -> Sdt { 250 let mut mcfg = Sdt::new(*b"MCFG", 36, 1, *b"CLOUDH", *b"CHMCFG ", 1); 251 252 // MCFG reserved 8 bytes 253 mcfg.append(0u64); 254 255 for segment in pci_segments { 256 // 32-bit PCI enhanced configuration mechanism 257 mcfg.append(PciRangeEntry { 258 base_address: segment.mmio_config_address, 259 segment: segment.id, 260 start: 0, 261 end: 0, 262 ..Default::default() 263 }); 264 } 265 mcfg 266 } 267 268 fn create_tpm2_table() -> Sdt { 269 let mut tpm = Sdt::new(*b"TPM2", 52, 3, *b"CLOUDH", *b"CHTPM2 ", 1); 270 271 tpm.write(36, 0_u16); //Platform Class 272 tpm.write(38, 0_u16); // Reserved Space 273 tpm.write(40, 0xfed4_0040_u64); // Address of Control Area 274 tpm.write(48, 7_u32); //Start Method 275 276 tpm.update_checksum(); 277 tpm 278 } 279 280 fn create_srat_table(numa_nodes: &NumaNodes) -> Sdt { 281 let mut srat = Sdt::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1); 282 // SRAT reserved 12 bytes 283 srat.append_slice(&[0u8; 12]); 284 285 // Check the MemoryAffinity structure is the right size as expected by 286 // the ACPI specification. 287 assert_eq!(std::mem::size_of::<MemoryAffinity>(), 40); 288 289 for (node_id, node) in numa_nodes.iter() { 290 let proximity_domain = *node_id; 291 292 for region in &node.memory_regions { 293 srat.append(MemoryAffinity::from_region( 294 region, 295 proximity_domain, 296 MemAffinityFlags::ENABLE, 297 )) 298 } 299 300 for region in &node.hotplug_regions { 301 srat.append(MemoryAffinity::from_region( 302 region, 303 proximity_domain, 304 MemAffinityFlags::ENABLE | MemAffinityFlags::HOTPLUGGABLE, 305 )) 306 } 307 308 #[cfg(target_arch = "x86_64")] 309 for section in &node.sgx_epc_sections { 310 srat.append(MemoryAffinity::from_range( 311 section.start().raw_value(), 312 section.size(), 313 proximity_domain, 314 MemAffinityFlags::ENABLE, 315 )) 316 } 317 318 for cpu in &node.cpus { 319 let x2apic_id = *cpu as u32; 320 321 // Flags 322 // - Enabled = 1 (bit 0) 323 // - Reserved bits 1-31 324 let flags = 1; 325 326 #[cfg(target_arch = "x86_64")] 327 srat.append(ProcessorLocalX2ApicAffinity { 328 type_: 2, 329 length: 24, 330 proximity_domain, 331 x2apic_id, 332 flags, 333 clock_domain: 0, 334 ..Default::default() 335 }); 336 #[cfg(target_arch = "aarch64")] 337 srat.append(ProcessorGiccAffinity { 338 type_: 3, 339 length: 18, 340 proximity_domain, 341 acpi_processor_uid: x2apic_id, 342 flags, 343 clock_domain: 0, 344 }); 345 } 346 } 347 srat 348 } 349 350 fn create_slit_table(numa_nodes: &NumaNodes) -> Sdt { 351 let mut slit = Sdt::new(*b"SLIT", 36, 1, *b"CLOUDH", *b"CHSLIT ", 1); 352 // Number of System Localities on 8 bytes. 353 slit.append(numa_nodes.len() as u64); 354 355 let existing_nodes: Vec<u32> = numa_nodes.keys().cloned().collect(); 356 for (node_id, node) in numa_nodes.iter() { 357 let distances = &node.distances; 358 for i in existing_nodes.iter() { 359 let dist: u8 = if *node_id == *i { 360 10 361 } else if let Some(distance) = distances.get(i) { 362 *distance 363 } else { 364 20 365 }; 366 367 slit.append(dist); 368 } 369 } 370 slit 371 } 372 373 #[cfg(target_arch = "aarch64")] 374 fn create_gtdt_table() -> Sdt { 375 const ARCH_TIMER_NS_EL2_IRQ: u32 = 10; 376 const ARCH_TIMER_VIRT_IRQ: u32 = 11; 377 const ARCH_TIMER_S_EL1_IRQ: u32 = 13; 378 const ARCH_TIMER_NS_EL1_IRQ: u32 = 14; 379 const ACPI_GTDT_INTERRUPT_MODE_LEVEL: u32 = 0; 380 const ACPI_GTDT_CAP_ALWAYS_ON: u32 = 1 << 2; 381 382 let irqflags: u32 = ACPI_GTDT_INTERRUPT_MODE_LEVEL; 383 // GTDT 384 let mut gtdt = Sdt::new(*b"GTDT", 104, 2, *b"CLOUDH", *b"CHGTDT ", 1); 385 // Secure EL1 Timer GSIV 386 gtdt.write(48, ARCH_TIMER_S_EL1_IRQ + 16); 387 // Secure EL1 Timer Flags 388 gtdt.write(52, irqflags); 389 // Non-Secure EL1 Timer GSIV 390 gtdt.write(56, ARCH_TIMER_NS_EL1_IRQ + 16); 391 // Non-Secure EL1 Timer Flags 392 gtdt.write(60, irqflags | ACPI_GTDT_CAP_ALWAYS_ON); 393 // Virtual EL1 Timer GSIV 394 gtdt.write(64, ARCH_TIMER_VIRT_IRQ + 16); 395 // Virtual EL1 Timer Flags 396 gtdt.write(68, irqflags); 397 // EL2 Timer GSIV 398 gtdt.write(72, ARCH_TIMER_NS_EL2_IRQ + 16); 399 // EL2 Timer Flags 400 gtdt.write(76, irqflags); 401 402 gtdt.update_checksum(); 403 404 gtdt 405 } 406 407 #[cfg(target_arch = "aarch64")] 408 fn create_spcr_table(base_address: u64, gsi: u32) -> Sdt { 409 // SPCR 410 let mut spcr = Sdt::new(*b"SPCR", 80, 2, *b"CLOUDH", *b"CHSPCR ", 1); 411 // Interface Type 412 spcr.write(36, 3u8); 413 // Base Address in format ACPI Generic Address Structure 414 spcr.write(40, GenericAddress::mmio_address::<u8>(base_address)); 415 // Interrupt Type: Bit[3] ARMH GIC interrupt 416 spcr.write(52, (1 << 3) as u8); 417 // Global System Interrupt used by the UART 418 spcr.write(54, gsi.to_le()); 419 // Baud Rate: 3 = 9600 420 spcr.write(58, 3u8); 421 // Stop Bits: 1 Stop bit 422 spcr.write(60, 1u8); 423 // Flow Control: Bit[1] = RTS/CTS hardware flow control 424 spcr.write(61, (1 << 1) as u8); 425 // PCI Device ID: Not a PCI device 426 spcr.write(64, 0xffff_u16); 427 // PCI Vendor ID: Not a PCI device 428 spcr.write(66, 0xffff_u16); 429 430 spcr.update_checksum(); 431 432 spcr 433 } 434 435 #[cfg(target_arch = "aarch64")] 436 fn create_dbg2_table(base_address: u64) -> Sdt { 437 let namespace = "_SB_.COM1"; 438 let debug_device_info_offset = 44usize; 439 let debug_device_info_len: u16 = 22 /* BaseAddressRegisterOffset */ + 440 12 /* BaseAddressRegister */ + 441 4 /* AddressSize */ + 442 namespace.len() as u16 + 1 /* zero-terminated */; 443 let tbl_len: u32 = debug_device_info_offset as u32 + debug_device_info_len as u32; 444 let mut dbg2 = Sdt::new(*b"DBG2", tbl_len, 0, *b"CLOUDH", *b"CHDBG2 ", 1); 445 446 /* OffsetDbgDeviceInfo */ 447 dbg2.write_u32(36, 44); 448 /* NumberDbgDeviceInfo */ 449 dbg2.write_u32(40, 1); 450 451 /* Debug Device Information structure */ 452 /* Offsets are calculated from the start of this structure. */ 453 let namespace_offset = 38u16; 454 let base_address_register_offset = 22u16; 455 let address_size_offset = 34u16; 456 /* Revision */ 457 dbg2.write_u8(debug_device_info_offset, 0); 458 /* Length */ 459 dbg2.write_u16(debug_device_info_offset + 1, debug_device_info_len); 460 /* NumberofGenericAddressRegisters */ 461 dbg2.write_u8(debug_device_info_offset + 3, 1); 462 /* NameSpaceStringLength */ 463 dbg2.write_u16(debug_device_info_offset + 4, namespace.len() as u16 + 1); 464 /* NameSpaceStringOffset */ 465 dbg2.write_u16(debug_device_info_offset + 6, namespace_offset); 466 /* OemDataLength */ 467 dbg2.write_u16(debug_device_info_offset + 8, 0); 468 /* OemDataOffset */ 469 dbg2.write_u16(debug_device_info_offset + 10, 0); 470 /* Port Type */ 471 dbg2.write_u16(debug_device_info_offset + 12, 0x8000); 472 /* Port Subtype */ 473 dbg2.write_u16(debug_device_info_offset + 14, 0x0003); 474 /* Reserved */ 475 dbg2.write_u16(debug_device_info_offset + 16, 0); 476 /* BaseAddressRegisterOffset */ 477 dbg2.write_u16(debug_device_info_offset + 18, base_address_register_offset); 478 /* AddressSizeOffset */ 479 dbg2.write_u16(debug_device_info_offset + 20, address_size_offset); 480 /* BaseAddressRegister */ 481 dbg2.write( 482 debug_device_info_offset + base_address_register_offset as usize, 483 GenericAddress::mmio_address::<u8>(base_address), 484 ); 485 /* AddressSize */ 486 dbg2.write_u32( 487 debug_device_info_offset + address_size_offset as usize, 488 0x1000, 489 ); 490 /* NamespaceString, zero-terminated ASCII */ 491 for (k, c) in namespace.chars().enumerate() { 492 dbg2.write_u8( 493 debug_device_info_offset + namespace_offset as usize + k, 494 c as u8, 495 ); 496 } 497 dbg2.write_u8( 498 debug_device_info_offset + namespace_offset as usize + namespace.len(), 499 0, 500 ); 501 502 dbg2.update_checksum(); 503 504 dbg2 505 } 506 507 #[cfg(target_arch = "aarch64")] 508 fn create_iort_table(pci_segments: &[PciSegment]) -> Sdt { 509 const ACPI_IORT_NODE_ITS_GROUP: u8 = 0x00; 510 const ACPI_IORT_NODE_PCI_ROOT_COMPLEX: u8 = 0x02; 511 const ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET: usize = 72; 512 const ACPI_IORT_NODE_ROOT_COMPLEX_SIZE: usize = 60; 513 514 // The IORT table containes: 515 // - Header (size = 40) 516 // - 1 x ITS Group Node (size = 24) 517 // - N x Root Complex Node (N = number of pci segments, size = 60 x N) 518 let iort_table_size: u32 = (ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET 519 + ACPI_IORT_NODE_ROOT_COMPLEX_SIZE * pci_segments.len()) 520 as u32; 521 let mut iort = Sdt::new(*b"IORT", iort_table_size, 2, *b"CLOUDH", *b"CHIORT ", 1); 522 iort.write(36, ((1 + pci_segments.len()) as u32).to_le()); 523 iort.write(40, (48u32).to_le()); 524 525 // ITS group node 526 iort.write(48, ACPI_IORT_NODE_ITS_GROUP); 527 // Length of the ITS group node in bytes 528 iort.write(49, (24u16).to_le()); 529 // ITS counts 530 iort.write(64, (1u32).to_le()); 531 532 // Root Complex Nodes 533 for (i, segment) in pci_segments.iter().enumerate() { 534 let node_offset: usize = 535 ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET + i * ACPI_IORT_NODE_ROOT_COMPLEX_SIZE; 536 iort.write(node_offset, ACPI_IORT_NODE_PCI_ROOT_COMPLEX); 537 // Length of the root complex node in bytes 538 iort.write( 539 node_offset + 1, 540 (ACPI_IORT_NODE_ROOT_COMPLEX_SIZE as u16).to_le(), 541 ); 542 // Revision 543 iort.write(node_offset + 3, (3u8).to_le()); 544 // Node ID 545 iort.write(node_offset + 4, (segment.id as u32).to_le()); 546 // Mapping counts 547 iort.write(node_offset + 8, (1u32).to_le()); 548 // Offset from the start of the RC node to the start of its Array of ID mappings 549 iort.write(node_offset + 12, (36u32).to_le()); 550 // Fully coherent device 551 iort.write(node_offset + 16, (1u32).to_le()); 552 // CCA = CPM = DCAS = 1 553 iort.write(node_offset + 24, 3u8); 554 // PCI segment number 555 iort.write(node_offset + 28, (segment.id as u32).to_le()); 556 // Memory address size limit 557 iort.write(node_offset + 32, (64u8).to_le()); 558 559 // From offset 32 onward is the space for ID mappings Array. 560 // Now we have only one mapping. 561 let mapping_offset: usize = node_offset + 36; 562 // The lowest value in the input range 563 iort.write(mapping_offset, (0u32).to_le()); 564 // The number of IDs in the range minus one: 565 // This should cover all the devices of a segment: 566 // 1 (bus) x 32 (devices) x 8 (functions) = 256 567 // Note: Currently only 1 bus is supported in a segment. 568 iort.write(mapping_offset + 4, (255_u32).to_le()); 569 // The lowest value in the output range 570 iort.write(mapping_offset + 8, ((256 * segment.id) as u32).to_le()); 571 // id_mapping_array_output_reference should be 572 // the ITS group node (the first node) if no SMMU 573 iort.write(mapping_offset + 12, (48u32).to_le()); 574 // Flags 575 iort.write(mapping_offset + 16, (0u32).to_le()); 576 } 577 578 iort.update_checksum(); 579 580 iort 581 } 582 583 fn create_viot_table(iommu_bdf: &PciBdf, devices_bdf: &[PciBdf]) -> Sdt { 584 // VIOT 585 let mut viot = Sdt::new(*b"VIOT", 36, 0, *b"CLOUDH", *b"CHVIOT ", 0); 586 // Node count 587 viot.append((devices_bdf.len() + 1) as u16); 588 // Node offset 589 viot.append(48u16); 590 // VIOT reserved 8 bytes 591 viot.append_slice(&[0u8; 8]); 592 593 // Virtio-iommu based on virtio-pci node 594 viot.append(ViotVirtioPciNode { 595 type_: 3, 596 length: 16, 597 pci_segment: iommu_bdf.segment(), 598 pci_bdf_number: iommu_bdf.into(), 599 ..Default::default() 600 }); 601 602 for device_bdf in devices_bdf { 603 viot.append(ViotPciRangeNode { 604 type_: 1, 605 length: 24, 606 endpoint_start: device_bdf.into(), 607 pci_segment_start: device_bdf.segment(), 608 pci_segment_end: device_bdf.segment(), 609 pci_bdf_start: device_bdf.into(), 610 pci_bdf_end: device_bdf.into(), 611 output_node: 48, 612 ..Default::default() 613 }); 614 } 615 616 viot 617 } 618 619 pub fn create_acpi_tables( 620 guest_mem: &GuestMemoryMmap, 621 device_manager: &Arc<Mutex<DeviceManager>>, 622 cpu_manager: &Arc<Mutex<CpuManager>>, 623 memory_manager: &Arc<Mutex<MemoryManager>>, 624 numa_nodes: &NumaNodes, 625 tpm_enabled: bool, 626 ) -> GuestAddress { 627 trace_scoped!("create_acpi_tables"); 628 629 let start_time = Instant::now(); 630 let rsdp_offset = arch::layout::RSDP_POINTER; 631 let mut tables: Vec<u64> = Vec::new(); 632 633 // DSDT 634 let dsdt = create_dsdt_table(device_manager, cpu_manager, memory_manager); 635 let dsdt_offset = rsdp_offset.checked_add(Rsdp::len() as u64).unwrap(); 636 guest_mem 637 .write_slice(dsdt.as_slice(), dsdt_offset) 638 .expect("Error writing DSDT table"); 639 640 // FACP aka FADT 641 let facp = create_facp_table(dsdt_offset, device_manager); 642 let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap(); 643 guest_mem 644 .write_slice(facp.as_slice(), facp_offset) 645 .expect("Error writing FACP table"); 646 tables.push(facp_offset.0); 647 648 // MADT 649 let madt = cpu_manager.lock().unwrap().create_madt(); 650 let madt_offset = facp_offset.checked_add(facp.len() as u64).unwrap(); 651 guest_mem 652 .write_slice(madt.as_slice(), madt_offset) 653 .expect("Error writing MADT table"); 654 tables.push(madt_offset.0); 655 let mut prev_tbl_len = madt.len() as u64; 656 let mut prev_tbl_off = madt_offset; 657 658 // PPTT 659 #[cfg(target_arch = "aarch64")] 660 { 661 let pptt = cpu_manager.lock().unwrap().create_pptt(); 662 let pptt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 663 guest_mem 664 .write_slice(pptt.as_slice(), pptt_offset) 665 .expect("Error writing PPTT table"); 666 tables.push(pptt_offset.0); 667 prev_tbl_len = pptt.len() as u64; 668 prev_tbl_off = pptt_offset; 669 } 670 671 // GTDT 672 #[cfg(target_arch = "aarch64")] 673 { 674 let gtdt = create_gtdt_table(); 675 let gtdt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 676 guest_mem 677 .write_slice(gtdt.as_slice(), gtdt_offset) 678 .expect("Error writing GTDT table"); 679 tables.push(gtdt_offset.0); 680 prev_tbl_len = gtdt.len() as u64; 681 prev_tbl_off = gtdt_offset; 682 } 683 684 // MCFG 685 let mcfg = create_mcfg_table(device_manager.lock().unwrap().pci_segments()); 686 let mcfg_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 687 guest_mem 688 .write_slice(mcfg.as_slice(), mcfg_offset) 689 .expect("Error writing MCFG table"); 690 tables.push(mcfg_offset.0); 691 prev_tbl_len = mcfg.len() as u64; 692 prev_tbl_off = mcfg_offset; 693 694 // SPCR and DBG2 695 #[cfg(target_arch = "aarch64")] 696 { 697 let is_serial_on = device_manager 698 .lock() 699 .unwrap() 700 .get_device_info() 701 .clone() 702 .get(&(DeviceType::Serial, DeviceType::Serial.to_string())) 703 .is_some(); 704 let serial_device_addr = arch::layout::LEGACY_SERIAL_MAPPED_IO_START.raw_value(); 705 let serial_device_irq = if is_serial_on { 706 device_manager 707 .lock() 708 .unwrap() 709 .get_device_info() 710 .clone() 711 .get(&(DeviceType::Serial, DeviceType::Serial.to_string())) 712 .unwrap() 713 .irq() 714 } else { 715 // If serial is turned off, add a fake device with invalid irq. 716 31 717 }; 718 719 // SPCR 720 let spcr = create_spcr_table(serial_device_addr, serial_device_irq); 721 let spcr_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 722 guest_mem 723 .write_slice(spcr.as_slice(), spcr_offset) 724 .expect("Error writing SPCR table"); 725 tables.push(spcr_offset.0); 726 prev_tbl_len = spcr.len() as u64; 727 prev_tbl_off = spcr_offset; 728 729 // DBG2 730 let dbg2 = create_dbg2_table(serial_device_addr); 731 let dbg2_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 732 guest_mem 733 .write_slice(dbg2.as_slice(), dbg2_offset) 734 .expect("Error writing DBG2 table"); 735 tables.push(dbg2_offset.0); 736 prev_tbl_len = dbg2.len() as u64; 737 prev_tbl_off = dbg2_offset; 738 } 739 740 if tpm_enabled { 741 // TPM2 Table 742 let tpm2 = create_tpm2_table(); 743 let tpm2_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 744 guest_mem 745 .write_slice(tpm2.as_slice(), tpm2_offset) 746 .expect("Error writing TPM2 table"); 747 tables.push(tpm2_offset.0); 748 749 prev_tbl_len = tpm2.len() as u64; 750 prev_tbl_off = tpm2_offset; 751 } 752 // SRAT and SLIT 753 // Only created if the NUMA nodes list is not empty. 754 if !numa_nodes.is_empty() { 755 // SRAT 756 let srat = create_srat_table(numa_nodes); 757 let srat_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 758 guest_mem 759 .write_slice(srat.as_slice(), srat_offset) 760 .expect("Error writing SRAT table"); 761 tables.push(srat_offset.0); 762 763 // SLIT 764 let slit = create_slit_table(numa_nodes); 765 let slit_offset = srat_offset.checked_add(srat.len() as u64).unwrap(); 766 guest_mem 767 .write_slice(slit.as_slice(), slit_offset) 768 .expect("Error writing SRAT table"); 769 tables.push(slit_offset.0); 770 771 prev_tbl_len = slit.len() as u64; 772 prev_tbl_off = slit_offset; 773 }; 774 775 #[cfg(target_arch = "aarch64")] 776 { 777 let iort = create_iort_table(device_manager.lock().unwrap().pci_segments()); 778 let iort_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 779 guest_mem 780 .write_slice(iort.as_slice(), iort_offset) 781 .expect("Error writing IORT table"); 782 tables.push(iort_offset.0); 783 prev_tbl_len = iort.len() as u64; 784 prev_tbl_off = iort_offset; 785 } 786 787 // VIOT 788 if let Some((iommu_bdf, devices_bdf)) = device_manager.lock().unwrap().iommu_attached_devices() 789 { 790 let viot = create_viot_table(iommu_bdf, devices_bdf); 791 792 let viot_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 793 guest_mem 794 .write_slice(viot.as_slice(), viot_offset) 795 .expect("Error writing VIOT table"); 796 tables.push(viot_offset.0); 797 prev_tbl_len = viot.len() as u64; 798 prev_tbl_off = viot_offset; 799 } 800 801 // XSDT 802 let mut xsdt = Sdt::new(*b"XSDT", 36, 1, *b"CLOUDH", *b"CHXSDT ", 1); 803 for table in tables { 804 xsdt.append(table); 805 } 806 xsdt.update_checksum(); 807 let xsdt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 808 guest_mem 809 .write_slice(xsdt.as_slice(), xsdt_offset) 810 .expect("Error writing XSDT table"); 811 812 // RSDP 813 let rsdp = Rsdp::new(*b"CLOUDH", xsdt_offset.0); 814 guest_mem 815 .write_slice(rsdp.as_bytes(), rsdp_offset) 816 .expect("Error writing RSDP"); 817 818 info!( 819 "Generated ACPI tables: took {}µs size = {}", 820 Instant::now().duration_since(start_time).as_micros(), 821 xsdt_offset.0 + xsdt.len() as u64 - rsdp_offset.0 822 ); 823 rsdp_offset 824 } 825 826 #[cfg(feature = "tdx")] 827 pub fn create_acpi_tables_tdx( 828 device_manager: &Arc<Mutex<DeviceManager>>, 829 cpu_manager: &Arc<Mutex<CpuManager>>, 830 memory_manager: &Arc<Mutex<MemoryManager>>, 831 numa_nodes: &NumaNodes, 832 ) -> Vec<Sdt> { 833 // DSDT 834 let mut tables = vec![create_dsdt_table( 835 device_manager, 836 cpu_manager, 837 memory_manager, 838 )]; 839 840 // FACP aka FADT 841 tables.push(create_facp_table(GuestAddress(0), device_manager)); 842 843 // MADT 844 tables.push(cpu_manager.lock().unwrap().create_madt()); 845 846 // MCFG 847 tables.push(create_mcfg_table( 848 device_manager.lock().unwrap().pci_segments(), 849 )); 850 851 // SRAT and SLIT 852 // Only created if the NUMA nodes list is not empty. 853 if !numa_nodes.is_empty() { 854 // SRAT 855 tables.push(create_srat_table(numa_nodes)); 856 857 // SLIT 858 tables.push(create_slit_table(numa_nodes)); 859 }; 860 861 // VIOT 862 if let Some((iommu_bdf, devices_bdf)) = device_manager.lock().unwrap().iommu_attached_devices() 863 { 864 tables.push(create_viot_table(iommu_bdf, devices_bdf)); 865 } 866 867 tables 868 } 869