Skip to content

Commit 5c8a0e7

Browse files
committed
acpi: add support for SRAT
1 parent bc88428 commit 5c8a0e7

File tree

4 files changed

+410
-17
lines changed

4 files changed

+410
-17
lines changed

acpi/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub mod mcfg;
7373
pub mod rsdp;
7474
pub mod sdt;
7575
pub mod spcr;
76+
pub mod srat;
7677

7778
#[cfg(feature = "allocator_api")]
7879
mod managed_slice;

acpi/src/madt.rs

+2
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ impl Madt {
191191
let processor = Processor {
192192
processor_uid: entry.processor_id as u32,
193193
local_apic_id: entry.apic_id as u32,
194+
proximity_domain: None,
194195
state,
195196
is_ap,
196197
};
@@ -216,6 +217,7 @@ impl Madt {
216217
let processor = Processor {
217218
processor_uid: entry.processor_uid,
218219
local_apic_id: entry.x2apic_id,
220+
proximity_domain: None,
219221
state,
220222
is_ap,
221223
};

acpi/src/platform/mod.rs

+80-17
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
pub mod interrupt;
22

33
use crate::{
4-
address::GenericAddress,
5-
fadt::Fadt,
6-
madt::{Madt, MadtError, MpProtectedModeWakeupCommand, MultiprocessorWakeupMailbox},
7-
AcpiError,
8-
AcpiHandler,
9-
AcpiResult,
10-
AcpiTables,
11-
ManagedSlice,
12-
PowerProfile,
4+
address::GenericAddress, fadt::Fadt, madt::{Madt, MadtError, MpProtectedModeWakeupCommand, MultiprocessorWakeupMailbox}, srat::Srat, AcpiError, AcpiHandler, AcpiResult, AcpiTables, ManagedSlice, PowerProfile
135
};
146
use core::{alloc::Allocator, mem, ptr};
157
use interrupt::InterruptModel;
@@ -35,6 +27,8 @@ pub struct Processor {
3527
/// The ID of the local APIC of the processor. Will be less than `256` if the APIC is being used, but can be
3628
/// greater than this if the X2APIC is being used.
3729
pub local_apic_id: u32,
30+
/// Proximity domain to which the processor belongs to.
31+
pub proximity_domain: Option<u32>,
3832

3933
/// The state of this processor. Check that the processor is not `Disabled` before attempting to bring it up!
4034
pub state: ProcessorState,
@@ -45,6 +39,19 @@ pub struct Processor {
4539
pub is_ap: bool,
4640
}
4741

42+
impl Processor {
43+
fn attach_affinity<'a, A>(&mut self, topology: &ProcessorTopology<'a, A>)
44+
where
45+
A: Allocator,
46+
{
47+
for affinity in topology.processor_affinities.iter() {
48+
if affinity.local_apic_id == self.local_apic_id {
49+
self.proximity_domain = Some(affinity.proximity_domain);
50+
}
51+
}
52+
}
53+
}
54+
4855
#[derive(Debug, Clone)]
4956
pub struct ProcessorInfo<'a, A>
5057
where
@@ -62,6 +69,44 @@ where
6269
pub(crate) fn new(boot_processor: Processor, application_processors: ManagedSlice<'a, Processor, A>) -> Self {
6370
Self { boot_processor, application_processors }
6471
}
72+
73+
fn attach_affinity(&mut self, topology: &ProcessorTopology<'a, A>) {
74+
self.boot_processor.attach_affinity(topology);
75+
for application_processor in self.application_processors.iter_mut() {
76+
application_processor.attach_affinity(topology);
77+
}
78+
}
79+
}
80+
81+
pub struct ProcessorAffinity {
82+
pub local_apic_id: u32,
83+
pub proximity_domain: u32,
84+
pub is_enabled: bool,
85+
}
86+
87+
pub struct ProcessorTopology<'a, A>
88+
where
89+
A: Allocator,
90+
{
91+
pub processor_affinities: ManagedSlice<'a, ProcessorAffinity, A>,
92+
}
93+
94+
#[derive(Debug, Clone)]
95+
pub struct MemoryRange {
96+
pub base_address: u64,
97+
pub length: u64,
98+
pub proximity_domain: Option<u32>,
99+
pub hot_pluggable: bool,
100+
pub non_volatile: bool,
101+
pub is_enabled: bool,
102+
}
103+
104+
#[derive(Debug, Clone)]
105+
pub struct MemoryInfo<'a, A>
106+
where
107+
A: Allocator,
108+
{
109+
pub memory_ranges: ManagedSlice<'a, MemoryRange, A>,
65110
}
66111

67112
/// Information about the ACPI Power Management Timer (ACPI PM Timer).
@@ -95,6 +140,7 @@ where
95140
/// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
96141
/// interrupt model. That information is stored here, if present.
97142
pub processor_info: Option<ProcessorInfo<'a, A>>,
143+
pub memory_info: Option<MemoryInfo<'a, A>>,
98144
pub pm_timer: Option<PmTimer>,
99145
/*
100146
* TODO: we could provide a nice view of the hardware register blocks in the FADT here.
@@ -119,17 +165,34 @@ where
119165
where
120166
H: AcpiHandler,
121167
{
122-
let fadt = tables.find_table::<Fadt>()?;
123-
let power_profile = fadt.power_profile();
168+
let (power_profile, pm_timer) = {
169+
let fadt = tables.find_table::<Fadt>()?;
170+
(fadt.power_profile(), PmTimer::new(&fadt)?)
171+
};
172+
173+
let (interrupt_model, processor_info) = {
174+
let madt = tables.find_table::<Madt>();
175+
match madt {
176+
Ok(madt) => madt.get().parse_interrupt_model_in(allocator.clone())?,
177+
Err(_) => (InterruptModel::Unknown, None),
178+
}
179+
};
124180

125-
let madt = tables.find_table::<Madt>();
126-
let (interrupt_model, processor_info) = match madt {
127-
Ok(madt) => madt.get().parse_interrupt_model_in(allocator)?,
128-
Err(_) => (InterruptModel::Unknown, None),
181+
let (processor_info, memory_info) = {
182+
let srat = tables.find_table::<Srat>();
183+
match srat {
184+
Ok(srat) => {
185+
let (processor_topology, memory_info) = srat.get().parse_topology_in(allocator)?;
186+
(processor_info.and_then(|mut processor_info| {
187+
processor_info.attach_affinity(&processor_topology);
188+
Some(processor_info)
189+
}), Some(memory_info))
190+
}
191+
Err(_) => (processor_info, None),
192+
}
129193
};
130-
let pm_timer = PmTimer::new(&fadt)?;
131194

132-
Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
195+
Ok(PlatformInfo { power_profile, interrupt_model, processor_info, memory_info, pm_timer })
133196
}
134197
}
135198

0 commit comments

Comments
 (0)