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_srat_table(numa_nodes: &NumaNodes) -> Sdt { 268 let mut srat = Sdt::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1); 269 // SRAT reserved 12 bytes 270 srat.append_slice(&[0u8; 12]); 271 272 // Check the MemoryAffinity structure is the right size as expected by 273 // the ACPI specification. 274 assert_eq!(std::mem::size_of::<MemoryAffinity>(), 40); 275 276 for (node_id, node) in numa_nodes.iter() { 277 let proximity_domain = *node_id as u32; 278 279 for region in &node.memory_regions { 280 srat.append(MemoryAffinity::from_region( 281 region, 282 proximity_domain, 283 MemAffinityFlags::ENABLE, 284 )) 285 } 286 287 for region in &node.hotplug_regions { 288 srat.append(MemoryAffinity::from_region( 289 region, 290 proximity_domain, 291 MemAffinityFlags::ENABLE | MemAffinityFlags::HOTPLUGGABLE, 292 )) 293 } 294 295 #[cfg(target_arch = "x86_64")] 296 for section in &node.sgx_epc_sections { 297 srat.append(MemoryAffinity::from_range( 298 section.start().raw_value(), 299 section.size(), 300 proximity_domain, 301 MemAffinityFlags::ENABLE, 302 )) 303 } 304 305 for cpu in &node.cpus { 306 let x2apic_id = *cpu as u32; 307 308 // Flags 309 // - Enabled = 1 (bit 0) 310 // - Reserved bits 1-31 311 let flags = 1; 312 313 #[cfg(target_arch = "x86_64")] 314 srat.append(ProcessorLocalX2ApicAffinity { 315 type_: 2, 316 length: 24, 317 proximity_domain, 318 x2apic_id, 319 flags, 320 clock_domain: 0, 321 ..Default::default() 322 }); 323 #[cfg(target_arch = "aarch64")] 324 srat.append(ProcessorGiccAffinity { 325 type_: 3, 326 length: 18, 327 proximity_domain, 328 acpi_processor_uid: x2apic_id, 329 flags, 330 clock_domain: 0, 331 }); 332 } 333 } 334 srat 335 } 336 337 fn create_slit_table(numa_nodes: &NumaNodes) -> Sdt { 338 let mut slit = Sdt::new(*b"SLIT", 36, 1, *b"CLOUDH", *b"CHSLIT ", 1); 339 // Number of System Localities on 8 bytes. 340 slit.append(numa_nodes.len() as u64); 341 342 let existing_nodes: Vec<u32> = numa_nodes.keys().cloned().collect(); 343 for (node_id, node) in numa_nodes.iter() { 344 let distances = &node.distances; 345 for i in existing_nodes.iter() { 346 let dist: u8 = if *node_id == *i { 347 10 348 } else if let Some(distance) = distances.get(i) { 349 *distance as u8 350 } else { 351 20 352 }; 353 354 slit.append(dist); 355 } 356 } 357 slit 358 } 359 360 #[cfg(target_arch = "aarch64")] 361 fn create_gtdt_table() -> Sdt { 362 const ARCH_TIMER_NS_EL2_IRQ: u32 = 10; 363 const ARCH_TIMER_VIRT_IRQ: u32 = 11; 364 const ARCH_TIMER_S_EL1_IRQ: u32 = 13; 365 const ARCH_TIMER_NS_EL1_IRQ: u32 = 14; 366 const ACPI_GTDT_INTERRUPT_MODE_LEVEL: u32 = 0; 367 const ACPI_GTDT_CAP_ALWAYS_ON: u32 = 1 << 2; 368 369 let irqflags: u32 = ACPI_GTDT_INTERRUPT_MODE_LEVEL; 370 // GTDT 371 let mut gtdt = Sdt::new(*b"GTDT", 104, 2, *b"CLOUDH", *b"CHGTDT ", 1); 372 // Secure EL1 Timer GSIV 373 gtdt.write(48, (ARCH_TIMER_S_EL1_IRQ + 16) as u32); 374 // Secure EL1 Timer Flags 375 gtdt.write(52, irqflags); 376 // Non-Secure EL1 Timer GSIV 377 gtdt.write(56, (ARCH_TIMER_NS_EL1_IRQ + 16) as u32); 378 // Non-Secure EL1 Timer Flags 379 gtdt.write(60, (irqflags | ACPI_GTDT_CAP_ALWAYS_ON) as u32); 380 // Virtual EL1 Timer GSIV 381 gtdt.write(64, (ARCH_TIMER_VIRT_IRQ + 16) as u32); 382 // Virtual EL1 Timer Flags 383 gtdt.write(68, irqflags); 384 // EL2 Timer GSIV 385 gtdt.write(72, (ARCH_TIMER_NS_EL2_IRQ + 16) as u32); 386 // EL2 Timer Flags 387 gtdt.write(76, irqflags); 388 389 gtdt.update_checksum(); 390 391 gtdt 392 } 393 394 #[cfg(target_arch = "aarch64")] 395 fn create_spcr_table(base_address: u64, gsi: u32) -> Sdt { 396 // SPCR 397 let mut spcr = Sdt::new(*b"SPCR", 80, 2, *b"CLOUDH", *b"CHSPCR ", 1); 398 // Interface Type 399 spcr.write(36, 3u8); 400 // Base Address in format ACPI Generic Address Structure 401 spcr.write(40, GenericAddress::mmio_address::<u8>(base_address)); 402 // Interrupt Type: Bit[3] ARMH GIC interrupt 403 spcr.write(52, (1 << 3) as u8); 404 // Global System Interrupt used by the UART 405 spcr.write(54, (gsi as u32).to_le()); 406 // Baud Rate: 3 = 9600 407 spcr.write(58, 3u8); 408 // Stop Bits: 1 Stop bit 409 spcr.write(60, 1u8); 410 // Flow Control: Bit[1] = RTS/CTS hardware flow control 411 spcr.write(61, (1 << 1) as u8); 412 // PCI Device ID: Not a PCI device 413 spcr.write(64, 0xffff_u16); 414 // PCI Vendor ID: Not a PCI device 415 spcr.write(66, 0xffff_u16); 416 417 spcr.update_checksum(); 418 419 spcr 420 } 421 422 #[cfg(target_arch = "aarch64")] 423 fn create_dbg2_table(base_address: u64) -> Sdt { 424 let namespace = "_SB_.COM1"; 425 let debug_device_info_offset = 44usize; 426 let debug_device_info_len: u16 = 22 /* BaseAddressRegisterOffset */ + 427 12 /* BaseAddressRegister */ + 428 4 /* AddressSize */ + 429 namespace.len() as u16 + 1 /* zero-terminated */; 430 let tbl_len: u32 = debug_device_info_offset as u32 + debug_device_info_len as u32; 431 let mut dbg2 = Sdt::new(*b"DBG2", tbl_len, 0, *b"CLOUDH", *b"CHDBG2 ", 1); 432 433 /* OffsetDbgDeviceInfo */ 434 dbg2.write_u32(36, 44); 435 /* NumberDbgDeviceInfo */ 436 dbg2.write_u32(40, 1); 437 438 /* Debug Device Information structure */ 439 /* Offsets are calculated from the start of this structure. */ 440 let namespace_offset = 38u16; 441 let base_address_register_offset = 22u16; 442 let address_size_offset = 34u16; 443 /* Revision */ 444 dbg2.write_u8(debug_device_info_offset, 0); 445 /* Length */ 446 dbg2.write_u16(debug_device_info_offset + 1, debug_device_info_len); 447 /* NumberofGenericAddressRegisters */ 448 dbg2.write_u8(debug_device_info_offset + 3, 1); 449 /* NameSpaceStringLength */ 450 dbg2.write_u16(debug_device_info_offset + 4, namespace.len() as u16 + 1); 451 /* NameSpaceStringOffset */ 452 dbg2.write_u16(debug_device_info_offset + 6, namespace_offset); 453 /* OemDataLength */ 454 dbg2.write_u16(debug_device_info_offset + 8, 0); 455 /* OemDataOffset */ 456 dbg2.write_u16(debug_device_info_offset + 10, 0); 457 /* Port Type */ 458 dbg2.write_u16(debug_device_info_offset + 12, 0x8000); 459 /* Port Subtype */ 460 dbg2.write_u16(debug_device_info_offset + 14, 0x0003); 461 /* Reserved */ 462 dbg2.write_u16(debug_device_info_offset + 16, 0); 463 /* BaseAddressRegisterOffset */ 464 dbg2.write_u16(debug_device_info_offset + 18, base_address_register_offset); 465 /* AddressSizeOffset */ 466 dbg2.write_u16(debug_device_info_offset + 20, address_size_offset); 467 /* BaseAddressRegister */ 468 dbg2.write( 469 debug_device_info_offset + base_address_register_offset as usize, 470 GenericAddress::mmio_address::<u8>(base_address), 471 ); 472 /* AddressSize */ 473 dbg2.write_u32( 474 debug_device_info_offset + address_size_offset as usize, 475 0x1000, 476 ); 477 /* NamespaceString, zero-terminated ASCII */ 478 for (k, c) in namespace.chars().enumerate() { 479 dbg2.write_u8( 480 debug_device_info_offset + namespace_offset as usize + k, 481 c as u8, 482 ); 483 } 484 dbg2.write_u8( 485 debug_device_info_offset + namespace_offset as usize + namespace.len(), 486 0, 487 ); 488 489 dbg2.update_checksum(); 490 491 dbg2 492 } 493 494 #[cfg(target_arch = "aarch64")] 495 fn create_iort_table(pci_segments: &[PciSegment]) -> Sdt { 496 const ACPI_IORT_NODE_ITS_GROUP: u8 = 0x00; 497 const ACPI_IORT_NODE_PCI_ROOT_COMPLEX: u8 = 0x02; 498 const ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET: usize = 72; 499 const ACPI_IORT_NODE_ROOT_COMPLEX_SIZE: usize = 60; 500 501 // The IORT table containes: 502 // - Header (size = 40) 503 // - 1 x ITS Group Node (size = 24) 504 // - N x Root Complex Node (N = number of pci segments, size = 60 x N) 505 let iort_table_size: u32 = (ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET 506 + ACPI_IORT_NODE_ROOT_COMPLEX_SIZE * pci_segments.len()) 507 as u32; 508 let mut iort = Sdt::new(*b"IORT", iort_table_size, 2, *b"CLOUDH", *b"CHIORT ", 1); 509 iort.write(36, ((1 + pci_segments.len()) as u32).to_le()); 510 iort.write(40, (48u32).to_le()); 511 512 // ITS group node 513 iort.write(48, ACPI_IORT_NODE_ITS_GROUP as u8); 514 // Length of the ITS group node in bytes 515 iort.write(49, (24u16).to_le()); 516 // ITS counts 517 iort.write(64, (1u32).to_le()); 518 519 // Root Complex Nodes 520 for (i, segment) in pci_segments.iter().enumerate() { 521 let node_offset: usize = 522 ACPI_IORT_NODE_ROOT_COMPLEX_OFFSET + i * ACPI_IORT_NODE_ROOT_COMPLEX_SIZE; 523 iort.write(node_offset, ACPI_IORT_NODE_PCI_ROOT_COMPLEX as u8); 524 // Length of the root complex node in bytes 525 iort.write( 526 node_offset + 1, 527 (ACPI_IORT_NODE_ROOT_COMPLEX_SIZE as u16).to_le(), 528 ); 529 // Revision 530 iort.write(node_offset + 3, (3u8).to_le()); 531 // Node ID 532 iort.write(node_offset + 4, (segment.id as u32).to_le()); 533 // Mapping counts 534 iort.write(node_offset + 8, (1u32).to_le()); 535 // Offset from the start of the RC node to the start of its Array of ID mappings 536 iort.write(node_offset + 12, (36u32).to_le()); 537 // Fully coherent device 538 iort.write(node_offset + 16, (1u32).to_le()); 539 // CCA = CPM = DCAS = 1 540 iort.write(node_offset + 24, 3u8); 541 // PCI segment number 542 iort.write(node_offset + 28, (segment.id as u32).to_le()); 543 // Memory address size limit 544 iort.write(node_offset + 32, (64u8).to_le()); 545 546 // From offset 32 onward is the space for ID mappings Array. 547 // Now we have only one mapping. 548 let mapping_offset: usize = node_offset + 36; 549 // The lowest value in the input range 550 iort.write(mapping_offset, (0u32).to_le()); 551 // The number of IDs in the range minus one: 552 // This should cover all the devices of a segment: 553 // 1 (bus) x 32 (devices) x 8 (functions) = 256 554 // Note: Currently only 1 bus is supported in a segment. 555 iort.write(mapping_offset + 4, (255_u32).to_le()); 556 // The lowest value in the output range 557 iort.write(mapping_offset + 8, ((256 * segment.id) as u32).to_le()); 558 // id_mapping_array_output_reference should be 559 // the ITS group node (the first node) if no SMMU 560 iort.write(mapping_offset + 12, (48u32).to_le()); 561 // Flags 562 iort.write(mapping_offset + 16, (0u32).to_le()); 563 } 564 565 iort.update_checksum(); 566 567 iort 568 } 569 570 fn create_viot_table(iommu_bdf: &PciBdf, devices_bdf: &[PciBdf]) -> Sdt { 571 // VIOT 572 let mut viot = Sdt::new(*b"VIOT", 36, 0, *b"CLOUDH", *b"CHVIOT ", 0); 573 // Node count 574 viot.append((devices_bdf.len() + 1) as u16); 575 // Node offset 576 viot.append(48u16); 577 // VIOT reserved 8 bytes 578 viot.append_slice(&[0u8; 8]); 579 580 // Virtio-iommu based on virtio-pci node 581 viot.append(ViotVirtioPciNode { 582 type_: 3, 583 length: 16, 584 pci_segment: iommu_bdf.segment(), 585 pci_bdf_number: iommu_bdf.into(), 586 ..Default::default() 587 }); 588 589 for device_bdf in devices_bdf { 590 viot.append(ViotPciRangeNode { 591 type_: 1, 592 length: 24, 593 endpoint_start: device_bdf.into(), 594 pci_segment_start: device_bdf.segment(), 595 pci_segment_end: device_bdf.segment(), 596 pci_bdf_start: device_bdf.into(), 597 pci_bdf_end: device_bdf.into(), 598 output_node: 48, 599 ..Default::default() 600 }); 601 } 602 603 viot 604 } 605 606 pub fn create_acpi_tables( 607 guest_mem: &GuestMemoryMmap, 608 device_manager: &Arc<Mutex<DeviceManager>>, 609 cpu_manager: &Arc<Mutex<CpuManager>>, 610 memory_manager: &Arc<Mutex<MemoryManager>>, 611 numa_nodes: &NumaNodes, 612 ) -> GuestAddress { 613 trace_scoped!("create_acpi_tables"); 614 615 let start_time = Instant::now(); 616 let rsdp_offset = arch::layout::RSDP_POINTER; 617 let mut tables: Vec<u64> = Vec::new(); 618 619 // DSDT 620 let dsdt = create_dsdt_table(device_manager, cpu_manager, memory_manager); 621 let dsdt_offset = rsdp_offset.checked_add(Rsdp::len() as u64).unwrap(); 622 guest_mem 623 .write_slice(dsdt.as_slice(), dsdt_offset) 624 .expect("Error writing DSDT table"); 625 626 // FACP aka FADT 627 let facp = create_facp_table(dsdt_offset, device_manager); 628 let facp_offset = dsdt_offset.checked_add(dsdt.len() as u64).unwrap(); 629 guest_mem 630 .write_slice(facp.as_slice(), facp_offset) 631 .expect("Error writing FACP table"); 632 tables.push(facp_offset.0); 633 634 // MADT 635 let madt = cpu_manager.lock().unwrap().create_madt(); 636 let madt_offset = facp_offset.checked_add(facp.len() as u64).unwrap(); 637 guest_mem 638 .write_slice(madt.as_slice(), madt_offset) 639 .expect("Error writing MADT table"); 640 tables.push(madt_offset.0); 641 let mut prev_tbl_len = madt.len() as u64; 642 let mut prev_tbl_off = madt_offset; 643 644 // PPTT 645 #[cfg(target_arch = "aarch64")] 646 { 647 let pptt = cpu_manager.lock().unwrap().create_pptt(); 648 let pptt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 649 guest_mem 650 .write_slice(pptt.as_slice(), pptt_offset) 651 .expect("Error writing PPTT table"); 652 tables.push(pptt_offset.0); 653 prev_tbl_len = pptt.len() as u64; 654 prev_tbl_off = pptt_offset; 655 } 656 657 // GTDT 658 #[cfg(target_arch = "aarch64")] 659 { 660 let gtdt = create_gtdt_table(); 661 let gtdt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 662 guest_mem 663 .write_slice(gtdt.as_slice(), gtdt_offset) 664 .expect("Error writing GTDT table"); 665 tables.push(gtdt_offset.0); 666 prev_tbl_len = gtdt.len() as u64; 667 prev_tbl_off = gtdt_offset; 668 } 669 670 // MCFG 671 let mcfg = create_mcfg_table(device_manager.lock().unwrap().pci_segments()); 672 let mcfg_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 673 guest_mem 674 .write_slice(mcfg.as_slice(), mcfg_offset) 675 .expect("Error writing MCFG table"); 676 tables.push(mcfg_offset.0); 677 prev_tbl_len = mcfg.len() as u64; 678 prev_tbl_off = mcfg_offset; 679 680 // SPCR and DBG2 681 #[cfg(target_arch = "aarch64")] 682 { 683 let is_serial_on = device_manager 684 .lock() 685 .unwrap() 686 .get_device_info() 687 .clone() 688 .get(&(DeviceType::Serial, DeviceType::Serial.to_string())) 689 .is_some(); 690 let serial_device_addr = arch::layout::LEGACY_SERIAL_MAPPED_IO_START.raw_value(); 691 let serial_device_irq = if is_serial_on { 692 device_manager 693 .lock() 694 .unwrap() 695 .get_device_info() 696 .clone() 697 .get(&(DeviceType::Serial, DeviceType::Serial.to_string())) 698 .unwrap() 699 .irq() 700 } else { 701 // If serial is turned off, add a fake device with invalid irq. 702 31 703 }; 704 705 // SPCR 706 let spcr = create_spcr_table(serial_device_addr, serial_device_irq); 707 let spcr_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 708 guest_mem 709 .write_slice(spcr.as_slice(), spcr_offset) 710 .expect("Error writing SPCR table"); 711 tables.push(spcr_offset.0); 712 prev_tbl_len = spcr.len() as u64; 713 prev_tbl_off = spcr_offset; 714 715 // DBG2 716 let dbg2 = create_dbg2_table(serial_device_addr); 717 let dbg2_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 718 guest_mem 719 .write_slice(dbg2.as_slice(), dbg2_offset) 720 .expect("Error writing DBG2 table"); 721 tables.push(dbg2_offset.0); 722 prev_tbl_len = dbg2.len() as u64; 723 prev_tbl_off = dbg2_offset; 724 } 725 726 // SRAT and SLIT 727 // Only created if the NUMA nodes list is not empty. 728 if !numa_nodes.is_empty() { 729 // SRAT 730 let srat = create_srat_table(numa_nodes); 731 let srat_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 732 guest_mem 733 .write_slice(srat.as_slice(), srat_offset) 734 .expect("Error writing SRAT table"); 735 tables.push(srat_offset.0); 736 737 // SLIT 738 let slit = create_slit_table(numa_nodes); 739 let slit_offset = srat_offset.checked_add(srat.len() as u64).unwrap(); 740 guest_mem 741 .write_slice(slit.as_slice(), slit_offset) 742 .expect("Error writing SRAT table"); 743 tables.push(slit_offset.0); 744 745 prev_tbl_len = slit.len() as u64; 746 prev_tbl_off = slit_offset; 747 }; 748 749 #[cfg(target_arch = "aarch64")] 750 { 751 let iort = create_iort_table(device_manager.lock().unwrap().pci_segments()); 752 let iort_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 753 guest_mem 754 .write_slice(iort.as_slice(), iort_offset) 755 .expect("Error writing IORT table"); 756 tables.push(iort_offset.0); 757 prev_tbl_len = iort.len() as u64; 758 prev_tbl_off = iort_offset; 759 } 760 761 // VIOT 762 if let Some((iommu_bdf, devices_bdf)) = device_manager.lock().unwrap().iommu_attached_devices() 763 { 764 let viot = create_viot_table(iommu_bdf, devices_bdf); 765 766 let viot_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 767 guest_mem 768 .write_slice(viot.as_slice(), viot_offset) 769 .expect("Error writing VIOT table"); 770 tables.push(viot_offset.0); 771 prev_tbl_len = viot.len() as u64; 772 prev_tbl_off = viot_offset; 773 } 774 775 // XSDT 776 let mut xsdt = Sdt::new(*b"XSDT", 36, 1, *b"CLOUDH", *b"CHXSDT ", 1); 777 for table in tables { 778 xsdt.append(table); 779 } 780 xsdt.update_checksum(); 781 let xsdt_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); 782 guest_mem 783 .write_slice(xsdt.as_slice(), xsdt_offset) 784 .expect("Error writing XSDT table"); 785 786 // RSDP 787 let rsdp = Rsdp::new(*b"CLOUDH", xsdt_offset.0); 788 guest_mem 789 .write_slice(rsdp.as_slice(), rsdp_offset) 790 .expect("Error writing RSDP"); 791 792 info!( 793 "Generated ACPI tables: took {}µs size = {}", 794 Instant::now().duration_since(start_time).as_micros(), 795 xsdt_offset.0 + xsdt.len() as u64 - rsdp_offset.0 796 ); 797 rsdp_offset 798 } 799 800 #[cfg(feature = "tdx")] 801 pub fn create_acpi_tables_tdx( 802 device_manager: &Arc<Mutex<DeviceManager>>, 803 cpu_manager: &Arc<Mutex<CpuManager>>, 804 memory_manager: &Arc<Mutex<MemoryManager>>, 805 numa_nodes: &NumaNodes, 806 ) -> Vec<Sdt> { 807 // DSDT 808 let mut tables = vec![create_dsdt_table( 809 device_manager, 810 cpu_manager, 811 memory_manager, 812 )]; 813 814 // FACP aka FADT 815 tables.push(create_facp_table(GuestAddress(0), device_manager)); 816 817 // MADT 818 tables.push(cpu_manager.lock().unwrap().create_madt()); 819 820 // MCFG 821 tables.push(create_mcfg_table( 822 device_manager.lock().unwrap().pci_segments(), 823 )); 824 825 // SRAT and SLIT 826 // Only created if the NUMA nodes list is not empty. 827 if !numa_nodes.is_empty() { 828 // SRAT 829 tables.push(create_srat_table(numa_nodes)); 830 831 // SLIT 832 tables.push(create_slit_table(numa_nodes)); 833 }; 834 835 // VIOT 836 if let Some((iommu_bdf, devices_bdf)) = device_manager.lock().unwrap().iommu_attached_devices() 837 { 838 tables.push(create_viot_table(iommu_bdf, devices_bdf)); 839 } 840 841 tables 842 } 843