Files
RedBear-OS/src/numa.rs
T
R Aadarsh 35340a80c4 * 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
2026-07-05 15:01:48 +05:30

103 lines
2.8 KiB
Rust

use core::ops::Add;
use crate::{
acpi,
cpu_set::LogicalCpuId,
sync::{CleanLockToken, Mutex, L0},
};
use alloc::{sync::Arc, vec::Vec};
use hashbrown::HashMap;
use rmm::{Arch, BumpAllocator};
use spin::once::Once;
pub const MAX_DOMAINS: usize = 128;
static DOMAIN_NODE_MAP: Once<&'static [u32]> = Once::new();
static NUMA_CPUS: Once<&'static [u32]> = Once::new();
static NUMA_MEMORY: Once<&'static [NumaMemory]> = Once::new();
static DISTANCES: Once<&'static [u8]> = Once::new();
#[derive(Debug, Clone)]
pub struct NumaMemory {
pub start: usize,
pub length: usize,
pub node_id: u32,
pub _pad: [u8; 4],
}
#[derive(Debug)]
pub struct NumaCpu {
pub id: u32,
}
pub fn init<A: Arch>(allocator: &mut BumpAllocator<A>) {
#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]
{
acpi::srat::init(allocator, &DOMAIN_NODE_MAP, &NUMA_CPUS, &NUMA_MEMORY);
acpi::slit::init(allocator, &DISTANCES);
}
}
pub fn assign_node_id(modify: bool) -> u8 {
static mut NODE_ID: u8 = 0;
if unsafe { NODE_ID } >= 128 {
panic!("Maximum number of domains supported is 128");
}
unsafe {
NODE_ID += 1;
let return_value = NODE_ID - 1;
if !modify {
NODE_ID -= 1;
}
return_value
}
}
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)?)
}
pub fn cpu_belongs_to_which_node(cpu_id: usize) -> Option<u32> {
Some(*NUMA_CPUS.get()?.get(cpu_id)?)
}
/// A helper function that prints information about NUMA - available nodes, cpus and memory blocks in them
/// their starts and lengths
pub fn dump_info() {
if let Some(map) = DOMAIN_NODE_MAP.get()
&& let Some(cpus) = NUMA_CPUS.get()
&& let Some(memories) = NUMA_MEMORY.get()
{
println!("Number of NUMA nodes: {}", assign_node_id(false));
for i in 0..cpus.len() {
if cpus[i] == u32::MAX {
continue;
}
println!("CPU {} : Node {}", i, cpus[i])
}
for i in 0..memories.len() {
if memories[i].length == 0 {
continue;
}
println!(
"Memory Block starting at address {:#x} of size {:#x} bytes : Node {}",
memories[i].start, memories[i].length, memories[i].node_id
);
}
} else {
println!(
"The system has either no support for NUMA or there was an error during initialisation"
);
}
}