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