* 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:
+100
-3
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user