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