Skip to content

Commit de0c322

Browse files
committed
Add higher level NumaInfo type in platform
1 parent b231b6c commit de0c322

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

src/platform/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod interrupt;
2+
pub mod numa;
23
pub mod pci;
34

45
pub use interrupt::InterruptModel;

src/platform/numa.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use crate::{
2+
AcpiTables,
3+
Handler,
4+
sdt::{
5+
slit::{DistanceMatrix, Slit},
6+
srat::{LocalApicAffinityFlags, MemoryAffinityFlags, Srat, SratEntry},
7+
},
8+
};
9+
use alloc::{alloc::Global, vec::Vec};
10+
use core::alloc::Allocator;
11+
12+
/// Information about the setup of NUMA (Non-Uniform Memory Architecture) resources within the
13+
/// sytem.
14+
pub struct NumaInfo<A: Allocator = Global> {
15+
pub processor_affinity: Vec<ProcessorAffinity, A>,
16+
pub memory_affinity: Vec<MemoryAffinity, A>,
17+
pub num_proximity_domains: usize,
18+
pub distance_matrix: Vec<u8, A>,
19+
}
20+
21+
impl NumaInfo<Global> {
22+
pub fn new(tables: AcpiTables<impl Handler>) -> NumaInfo<Global> {
23+
Self::new_in(tables, Global)
24+
}
25+
}
26+
27+
impl<A: Allocator + Clone> NumaInfo<A> {
28+
pub fn new_in(tables: AcpiTables<impl Handler>, allocator: A) -> NumaInfo<A> {
29+
let mut processor_affinity = Vec::new_in(allocator.clone());
30+
let mut memory_affinity = Vec::new_in(allocator.clone());
31+
32+
if let Some(srat) = tables.find_table::<Srat>() {
33+
for entry in srat.get().entries() {
34+
match entry {
35+
SratEntry::LocalApicAffinity(entry) => processor_affinity.push(ProcessorAffinity {
36+
local_apic_id: entry.apic_id as u32,
37+
proximity_domain: entry.proximity_domain(),
38+
is_enabled: { entry.flags }.contains(LocalApicAffinityFlags::ENABLED),
39+
}),
40+
SratEntry::LocalApicX2Affinity(entry) => processor_affinity.push(ProcessorAffinity {
41+
local_apic_id: entry.x2apic_id,
42+
proximity_domain: entry.proximity_domain,
43+
is_enabled: { entry.flags }.contains(LocalApicAffinityFlags::ENABLED),
44+
}),
45+
SratEntry::MemoryAffinity(entry) => memory_affinity.push(MemoryAffinity {
46+
base_address: entry.base_address(),
47+
length: entry.length(),
48+
proximity_domain: entry.proximity_domain,
49+
is_enabled: { entry.flags }.contains(MemoryAffinityFlags::ENABLED),
50+
is_hot_pluggable: { entry.flags }.contains(MemoryAffinityFlags::HOT_PLUGGABLE),
51+
is_non_volatile: { entry.flags }.contains(MemoryAffinityFlags::NON_VOLATILE),
52+
}),
53+
_ => (),
54+
}
55+
}
56+
}
57+
58+
let (num_proximity_domains, distance_matrix) = if let Some(slit) = tables.find_table::<Slit>() {
59+
(slit.get().num_proximity_domains as usize, slit.get().matrix_raw().to_vec_in(allocator.clone()))
60+
} else {
61+
(0, Vec::new_in(allocator.clone()))
62+
};
63+
64+
NumaInfo { processor_affinity, memory_affinity, num_proximity_domains, distance_matrix }
65+
}
66+
67+
pub fn distance_matrix(&self) -> DistanceMatrix<'_> {
68+
DistanceMatrix { num_proximity_domains: self.num_proximity_domains as u64, matrix: &self.distance_matrix }
69+
}
70+
}
71+
72+
#[derive(Clone, Debug)]
73+
pub struct ProcessorAffinity {
74+
pub local_apic_id: u32,
75+
pub proximity_domain: u32,
76+
pub is_enabled: bool,
77+
}
78+
79+
#[derive(Clone, Debug)]
80+
pub struct MemoryAffinity {
81+
pub base_address: u64,
82+
pub length: u64,
83+
pub proximity_domain: u32,
84+
pub is_enabled: bool,
85+
pub is_hot_pluggable: bool,
86+
pub is_non_volatile: bool,
87+
}

src/sdt/slit.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ unsafe impl AcpiTable for Slit {
2626
}
2727

2828
impl Slit {
29-
pub fn matrix(self: Pin<&Self>) -> &[u8] {
29+
pub fn matrix(self: Pin<&Self>) -> DistanceMatrix<'_> {
30+
DistanceMatrix { num_proximity_domains: self.num_proximity_domains, matrix: self.matrix_raw() }
31+
}
32+
33+
pub fn matrix_raw(self: Pin<&Self>) -> &[u8] {
3034
let mut num_entries = self.num_proximity_domains * self.num_proximity_domains;
3135
if (mem::size_of::<Slit>() + num_entries as usize * num_entries as usize * mem::size_of::<u8>())
3236
> self.header.length as usize
@@ -40,11 +44,17 @@ impl Slit {
4044
slice::from_raw_parts(ptr.byte_add(mem::size_of::<Slit>()), num_entries as usize)
4145
}
4246
}
47+
}
48+
49+
pub struct DistanceMatrix<'a> {
50+
pub num_proximity_domains: u64,
51+
pub matrix: &'a [u8],
52+
}
4353

44-
pub fn entry(self: Pin<&Self>, i: u32, j: u32) -> Option<u8> {
54+
impl DistanceMatrix<'_> {
55+
pub fn distance(&self, i: u32, j: u32) -> Option<u8> {
4556
if i as u64 <= self.num_proximity_domains && j as u64 <= self.num_proximity_domains {
46-
let matrix = self.matrix();
47-
Some(matrix[i as usize + j as usize * self.num_proximity_domains as usize])
57+
Some(self.matrix[i as usize + j as usize * self.num_proximity_domains as usize])
4858
} else {
4959
None
5060
}

src/sdt/srat.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,19 @@ pub struct LocalApicAffinity {
122122
pub header: EntryHeader,
123123
pub proximity_domain_low: u8,
124124
pub apic_id: u8,
125-
pub flags: u32,
125+
pub flags: LocalApicAffinityFlags,
126126
pub local_sapic_eid: u8,
127127
pub proximity_domain_high: [u8; 3],
128128
pub clock_domain: u32,
129129
}
130130

131+
bitflags::bitflags! {
132+
#[derive(Clone, Copy, Debug)]
133+
pub struct LocalApicAffinityFlags: u32 {
134+
const ENABLED = 1;
135+
}
136+
}
137+
131138
impl LocalApicAffinity {
132139
pub fn proximity_domain(&self) -> u32 {
133140
u32::from_le_bytes([
@@ -150,10 +157,19 @@ pub struct MemoryAffinity {
150157
pub length_low: u32,
151158
pub length_high: u32,
152159
_reserved1: u32,
153-
pub flags: u32,
160+
pub flags: MemoryAffinityFlags,
154161
_reserved2: u64,
155162
}
156163

164+
bitflags::bitflags! {
165+
#[derive(Clone, Copy, Debug)]
166+
pub struct MemoryAffinityFlags: u32 {
167+
const ENABLED = 1;
168+
const HOT_PLUGGABLE = 1 << 1;
169+
const NON_VOLATILE = 1 << 2;
170+
}
171+
}
172+
157173
impl MemoryAffinity {
158174
pub fn base_address(&self) -> u64 {
159175
let mut address = self.base_address_low as u64;
@@ -175,7 +191,7 @@ pub struct LocalApicX2Affinity {
175191
_reserved0: u16,
176192
pub proximity_domain: u32,
177193
pub x2apic_id: u32,
178-
pub flags: u32,
194+
pub flags: LocalApicAffinityFlags,
179195
pub clock_domain: u32,
180196
_reserved1: u32,
181197
}

0 commit comments

Comments
 (0)