mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
vmm: acpi: Create the SRAT table
The SRAT table (System Resource Affinity Table) is needed to describe NUMA nodes and how memory ranges and CPUs are attached to them. For now it simply attaches a list of Memory Affinity structures based on the list of NUMA nodes created from the VMM. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
cf81254a8d
commit
65a23c6fc6
@ -2,21 +2,17 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
use crate::cpu::CpuManager;
|
||||
use crate::device_manager::DeviceManager;
|
||||
use crate::memory_manager::MemoryManager;
|
||||
use acpi_tables::{
|
||||
aml::Aml,
|
||||
rsdp::RSDP,
|
||||
sdt::{GenericAddress, SDT},
|
||||
};
|
||||
use vm_memory::{GuestAddress, GuestMemoryMmap};
|
||||
|
||||
use vm_memory::{Address, ByteValued, Bytes};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::cpu::CpuManager;
|
||||
use crate::device_manager::DeviceManager;
|
||||
use crate::memory_manager::MemoryManager;
|
||||
use arch::layout;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vm_memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryMmap, GuestMemoryRegion};
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Default)]
|
||||
@ -28,6 +24,22 @@ struct PCIRangeEntry {
|
||||
_reserved: u32,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Default)]
|
||||
struct MemoryAffinity {
|
||||
pub type_: u8,
|
||||
pub length: u8,
|
||||
pub proximity_domain: u32,
|
||||
_reserved1: u16,
|
||||
pub base_addr_lo: u32,
|
||||
pub base_addr_hi: u32,
|
||||
pub length_lo: u32,
|
||||
pub length_hi: u32,
|
||||
_reserved2: u32,
|
||||
pub flags: u32,
|
||||
_reserved3: u64,
|
||||
}
|
||||
|
||||
pub fn create_dsdt_table(
|
||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||
cpu_manager: &Arc<Mutex<CpuManager>>,
|
||||
@ -125,6 +137,60 @@ pub fn create_acpi_tables(
|
||||
.expect("Error writing MCFG table");
|
||||
tables.push(mcfg_offset.0);
|
||||
|
||||
// SRAT
|
||||
// Only created if the NUMA nodes list is not empty.
|
||||
let numa_nodes = memory_manager.lock().unwrap().numa_nodes().clone();
|
||||
let (prev_tbl_len, prev_tbl_off) = if numa_nodes.is_empty() {
|
||||
(mcfg.len(), mcfg_offset)
|
||||
} else {
|
||||
let mut srat = SDT::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1);
|
||||
// SRAT reserved 12 bytes
|
||||
srat.append_slice(&[0u8; 12]);
|
||||
|
||||
// Check the MemoryAffinity structure is the right size as expected by
|
||||
// the ACPI specification.
|
||||
assert_eq!(std::mem::size_of::<MemoryAffinity>(), 40);
|
||||
|
||||
for (node_id, node) in numa_nodes.iter() {
|
||||
for region in node.memory_regions() {
|
||||
let proximity_domain = *node_id as u32;
|
||||
let base_addr = region.start_addr().raw_value();
|
||||
let base_addr_lo = (base_addr & 0xffff_ffff) as u32;
|
||||
let base_addr_hi = (base_addr >> 32) as u32;
|
||||
let length = region.len() as u64;
|
||||
let length_lo = (length & 0xffff_ffff) as u32;
|
||||
let length_hi = (length >> 32) as u32;
|
||||
|
||||
// Flags
|
||||
// - Enabled = 1 (bit 0)
|
||||
// - Hot Pluggable = 0 (bit 1)
|
||||
// - NonVolatile = 0 (bit 2)
|
||||
// - Reserved bits 3-31
|
||||
let flags = 1;
|
||||
|
||||
srat.append(MemoryAffinity {
|
||||
type_: 1,
|
||||
length: 40,
|
||||
proximity_domain,
|
||||
base_addr_lo,
|
||||
base_addr_hi,
|
||||
length_lo,
|
||||
length_hi,
|
||||
flags,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let srat_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
|
||||
guest_mem
|
||||
.write_slice(srat.as_slice(), srat_offset)
|
||||
.expect("Error writing SRAT table");
|
||||
tables.push(srat_offset.0);
|
||||
|
||||
(srat.len(), srat_offset)
|
||||
};
|
||||
|
||||
// XSDT
|
||||
let mut xsdt = SDT::new(*b"XSDT", 36, 1, *b"CLOUDH", *b"CHXSDT ", 1);
|
||||
for table in tables {
|
||||
@ -132,7 +198,7 @@ pub fn create_acpi_tables(
|
||||
}
|
||||
xsdt.update_checksum();
|
||||
|
||||
let xsdt_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
|
||||
let xsdt_offset = prev_tbl_off.checked_add(prev_tbl_len as u64).unwrap();
|
||||
guest_mem
|
||||
.write_slice(xsdt.as_slice(), xsdt_offset)
|
||||
.expect("Error writing XSDT table");
|
||||
|
Loading…
Reference in New Issue
Block a user