* Add ACPI-NUMA parsing code for ARM

* Fix bug in the x86 code that caused incorrect cpu-node mapping

* Remove the usage of page mappers. Instead use the already existing
  linear mapping
This commit is contained in:
R Aadarsh
2026-07-05 15:01:48 +05:30
parent cb88ed59a2
commit 35340a80c4
3 changed files with 125 additions and 30 deletions
+100 -3
View File
@@ -1,8 +1,105 @@
use crate::acpi::srat::Srat;
use core::{ops::Add, slice, u32};
pub fn init_srat(
use rmm::{Arch, BumpAllocator, FrameAllocator, FrameCount, PhysicalAddress};
use crate::{
acpi::srat::{to_usize, Srat, SratEntry},
cpu_set::MAX_CPU_COUNT,
memory::{round_up_pages, PAGE_SIZE},
numa::{self, assign_memory_id, assign_node_id, NumaMemory},
};
pub fn init_srat<A: Arch>(
allocator: &mut BumpAllocator<A>,
srat: &Srat,
) -> (&'static [u32], &'static [u32], &'static [NumaMemory]) {
// todo
let dom_node_map_ptr = allocator
.allocate(FrameCount::new(
round_up_pages(numa::MAX_DOMAINS * size_of::<u32>()) / PAGE_SIZE,
))
.expect("Failed to allocate pages for domain-node-map")
.data();
let va = crate::memory::RmmA::phys_to_virt(PhysicalAddress::new(dom_node_map_ptr)).data();
let dom_node_map_ptr = va.data() as *mut u32;
// occupies 521 bytes
let dom_node_map = unsafe { slice::from_raw_parts_mut(dom_node_map_ptr, numa::MAX_DOMAINS) };
// occupies 512 bytes
let cpus = unsafe {
slice::from_raw_parts_mut(
dom_node_map_ptr.add(numa::MAX_DOMAINS as usize * size_of::<u32>()),
MAX_CPU_COUNT as usize,
)
};
// remaining 3072 bytes: can accomodate 128 Mem entries
let mem = unsafe {
slice::from_raw_parts_mut(
dom_node_map_ptr
.add(numa::MAX_DOMAINS)
.add(MAX_CPU_COUNT as usize) as *mut NumaMemory,
numa::MAX_DOMAINS * size_of::<NumaMemory>(),
)
};
cpus.fill(u32::MAX);
dom_node_map.fill(u32::MAX);
mem.fill(NumaMemory {
start: 0,
length: 0,
node_id: 0,
_pad: [0; 4],
});
for affinity in srat {
match affinity {
SratEntry::MemoryAffinity(memory_affinity) => {
let start = to_usize(
memory_affinity.base_address_low,
memory_affinity.base_address_high,
);
let length = to_usize(memory_affinity.length_low, memory_affinity.length_high);
if length == 0 {
continue;
}
if memory_affinity.flags & 1 == 0 {
// memory disabled
continue;
}
if memory_affinity.flags & (1 << 1) != 0 {
// memory hot-pluggable
continue;
}
if dom_node_map[memory_affinity.proximity_domain as usize] == u32::MAX {
let node = assign_node_id(true);
dom_node_map[memory_affinity.proximity_domain as usize] = node as u32;
}
let mem_id = assign_memory_id() as u32;
mem[mem_id as usize] = NumaMemory {
start,
length,
node_id: dom_node_map[memory_affinity.proximity_domain as usize],
_pad: [0u8; 4],
};
}
SratEntry::GiccAffinity(gicc_affinity) => {
if gicc_affinity.flags & 1 == 0 {
// disabled
continue;
}
let id = gicc_affinity.processor_uid;
let dom = gicc_affinity.proximity_domain;
if dom_node_map[dom as usize] == u32::MAX {
let node = assign_node_id(true);
dom_node_map[dom as usize] = node as u32;
}
cpus[id as usize] = dom_node_map[dom as usize];
}
_ => continue,
}
}
(dom_node_map, cpus, mem)
}
+11 -25
View File
@@ -1,13 +1,13 @@
use core::{iter, slice};
use hashbrown::HashMap;
use rmm::{Arch, BumpAllocator, FrameAllocator};
use rmm::{Arch, BumpAllocator, FrameAllocator, PhysicalAddress};
use crate::{
acpi::srat::{to_usize, Srat, SratEntry},
cpu_set,
memory::{self, PAGE_SIZE},
numa::{self, NumaMemory},
numa::{self, assign_memory_id, NumaMemory},
};
#[inline(always)]
@@ -27,16 +27,9 @@ pub fn init_srat<A: Arch>(
memory::round_up_pages(numa::MAX_DOMAINS * size_of::<u32>()) / PAGE_SIZE,
))
.expect("Failed to allocate memory for storing NUMA info");
let mut mapper = unsafe { rmm::PageMapper::current(rmm::TableKind::Kernel, allocator) };
let mut flags = rmm::PageFlags::<A>::new();
let flags = flags.write(true);
let dom_node_map_ptr = unsafe {
let (va, flush) = mapper
.map_linearly(dom_node_map, flags)
.expect("Failed to map NUMA info pages");
flush.flush();
va.data() as *mut u32
};
let dom_node_map_ptr =
unsafe { crate::memory::RmmA::phys_to_virt(dom_node_map).data() as *mut u32 };
// Occupies 512 bytes (1/8th of a page)
let dom_node_map: &'static mut [u32] =
unsafe { slice::from_raw_parts_mut(dom_node_map_ptr, numa::MAX_DOMAINS) };
@@ -86,7 +79,7 @@ pub fn init_srat<A: Arch>(
memories.fill(NumaMemory {
start: 0,
length: 0,
dom: 0,
node_id: 0,
_pad: [0; 4],
});
@@ -129,10 +122,11 @@ pub fn init_srat<A: Arch>(
let node_id = numa::assign_node_id(true);
dom_node_map[dom as usize] = node_id as u32;
}
memories[dom_node_map[dom as usize] as usize] = numa::NumaMemory {
let mem_id = assign_memory_id() as u32;
memories[mem_id as usize] = numa::NumaMemory {
start,
length,
dom: dom_node_map[dom as usize],
node_id: dom_node_map[dom as usize],
_pad: [0u8; 4],
};
}
@@ -146,19 +140,11 @@ pub fn init_srat<A: Arch>(
let node_id = numa::assign_node_id(true);
dom_node_map[dom as usize] = node_id as u32;
}
cpus[dom_node_map[dom as usize] as usize] =
processor_local_affinity.proximity_domain;
cpus[processor_local_affinity.x2apic_id as usize] = dom_node_map[dom as usize];
}
_ => continue,
}
}
let mut flags = rmm::PageFlags::<A>::new();
let flags = flags.write(false);
let flush = unsafe {
mapper
.remap(rmm::VirtualAddress::new(dom_node_map_ptr.addr()), flags)
.expect("Unable to make NUMA info page read-only")
};
flush.flush();
(dom_node_map, cpus, memories)
}
+14 -2
View File
@@ -1,3 +1,5 @@
use core::ops::Add;
use crate::{
acpi,
cpu_set::LogicalCpuId,
@@ -19,7 +21,7 @@ static DISTANCES: Once<&'static [u8]> = Once::new();
pub struct NumaMemory {
pub start: usize,
pub length: usize,
pub dom: u32,
pub node_id: u32,
pub _pad: [u8; 4],
}
@@ -51,6 +53,16 @@ pub fn assign_node_id(modify: bool) -> u8 {
}
}
pub fn assign_memory_id() -> u8 {
static mut MEMORY_ID: u8 = 0;
if unsafe { MEMORY_ID } >= 128 {
panic!("Maximum number of memory regions supported is 128");
}
let old = unsafe { MEMORY_ID };
unsafe { MEMORY_ID = MEMORY_ID.add(1) };
old
}
pub fn domain_to_node_id(domain_id: u32) -> Option<u32> {
Some(*DOMAIN_NODE_MAP.get()?.get(domain_id as usize)?)
}
@@ -79,7 +91,7 @@ pub fn dump_info() {
}
println!(
"Memory Block starting at address {:#x} of size {:#x} bytes : Node {}",
memories[i].start, memories[i].length, memories[i].dom
memories[i].start, memories[i].length, memories[i].node_id
);
}
} else {