Skip to content

Commit 73338b7

Browse files
committed
acpi: add support for SRAT
1 parent bc88428 commit 73338b7

File tree

4 files changed

+413
-17
lines changed

4 files changed

+413
-17
lines changed

acpi/src/lib.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 78 additions & 17 deletions
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,42 @@ 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+
}
85+
86+
pub struct ProcessorTopology<'a, A>
87+
where
88+
A: Allocator,
89+
{
90+
pub processor_affinities: ManagedSlice<'a, ProcessorAffinity, A>,
91+
}
92+
93+
#[derive(Debug, Clone)]
94+
pub struct MemoryRange {
95+
pub base_address: u64,
96+
pub length: u64,
97+
pub proximity_domain: Option<u32>,
98+
pub hot_pluggable: bool,
99+
pub non_volatile: bool,
100+
}
101+
102+
#[derive(Debug, Clone)]
103+
pub struct MemoryInfo<'a, A>
104+
where
105+
A: Allocator,
106+
{
107+
pub memory_ranges: ManagedSlice<'a, MemoryRange, A>,
65108
}
66109

67110
/// Information about the ACPI Power Management Timer (ACPI PM Timer).
@@ -95,6 +138,7 @@ where
95138
/// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
96139
/// interrupt model. That information is stored here, if present.
97140
pub processor_info: Option<ProcessorInfo<'a, A>>,
141+
pub memory_info: Option<MemoryInfo<'a, A>>,
98142
pub pm_timer: Option<PmTimer>,
99143
/*
100144
* TODO: we could provide a nice view of the hardware register blocks in the FADT here.
@@ -119,17 +163,34 @@ where
119163
where
120164
H: AcpiHandler,
121165
{
122-
let fadt = tables.find_table::<Fadt>()?;
123-
let power_profile = fadt.power_profile();
166+
let (power_profile, pm_timer) = {
167+
let fadt = tables.find_table::<Fadt>()?;
168+
(fadt.power_profile(), PmTimer::new(&fadt)?)
169+
};
170+
171+
let (interrupt_model, processor_info) = {
172+
let madt = tables.find_table::<Madt>();
173+
match madt {
174+
Ok(madt) => madt.get().parse_interrupt_model_in(allocator.clone())?,
175+
Err(_) => (InterruptModel::Unknown, None),
176+
}
177+
};
124178

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),
179+
let (processor_info, memory_info) = {
180+
let srat = tables.find_table::<Srat>();
181+
match srat {
182+
Ok(srat) => {
183+
let (processor_topology, memory_info) = srat.get().parse_topology_in(allocator)?;
184+
(processor_info.and_then(|mut processor_info| {
185+
processor_info.attach_affinity(&processor_topology);
186+
Some(processor_info)
187+
}), Some(memory_info))
188+
}
189+
Err(_) => (processor_info, None),
190+
}
129191
};
130-
let pm_timer = PmTimer::new(&fadt)?;
131192

132-
Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
193+
Ok(PlatformInfo { power_profile, interrupt_model, processor_info, memory_info, pm_timer })
133194
}
134195
}
135196

0 commit comments

Comments
 (0)