Skip to content

acpi: add support for SRAT #241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions acpi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub mod mcfg;
pub mod rsdp;
pub mod sdt;
pub mod spcr;
pub mod srat;

#[cfg(feature = "allocator_api")]
mod managed_slice;
Expand Down
2 changes: 2 additions & 0 deletions acpi/src/madt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ impl Madt {
let processor = Processor {
processor_uid: entry.processor_id as u32,
local_apic_id: entry.apic_id as u32,
proximity_domain: None,
state,
is_ap,
};
Expand All @@ -216,6 +217,7 @@ impl Madt {
let processor = Processor {
processor_uid: entry.processor_uid,
local_apic_id: entry.x2apic_id,
proximity_domain: None,
state,
is_ap,
};
Expand Down
97 changes: 80 additions & 17 deletions acpi/src/platform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
pub mod interrupt;

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

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

impl Processor {
fn attach_affinity<A>(&mut self, topology: &ProcessorTopology<A>)
where
A: Allocator,
{
for affinity in topology.processor_affinities.iter() {
if affinity.local_apic_id == self.local_apic_id {
self.proximity_domain = Some(affinity.proximity_domain);
}
}
}
}

#[derive(Debug, Clone)]
pub struct ProcessorInfo<'a, A>
where
Expand All @@ -62,6 +69,44 @@ where
pub(crate) fn new(boot_processor: Processor, application_processors: ManagedSlice<'a, Processor, A>) -> Self {
Self { boot_processor, application_processors }
}

fn attach_affinity(&mut self, topology: &ProcessorTopology<'a, A>) {
self.boot_processor.attach_affinity(topology);
for application_processor in self.application_processors.iter_mut() {
application_processor.attach_affinity(topology);
}
}
}

pub struct ProcessorAffinity {
pub local_apic_id: u32,
pub proximity_domain: u32,
pub is_enabled: bool,
}

pub struct ProcessorTopology<'a, A>
where
A: Allocator,
{
pub processor_affinities: ManagedSlice<'a, ProcessorAffinity, A>,
}

#[derive(Debug, Clone)]
pub struct MemoryRange {
pub base_address: u64,
pub length: u64,
pub proximity_domain: Option<u32>,
pub hot_pluggable: bool,
pub non_volatile: bool,
pub is_enabled: bool,
}

#[derive(Debug, Clone)]
pub struct MemoryInfo<'a, A>
where
A: Allocator,
{
pub memory_ranges: ManagedSlice<'a, MemoryRange, A>,
}

/// Information about the ACPI Power Management Timer (ACPI PM Timer).
Expand Down Expand Up @@ -95,6 +140,7 @@ where
/// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
/// interrupt model. That information is stored here, if present.
pub processor_info: Option<ProcessorInfo<'a, A>>,
pub memory_info: Option<MemoryInfo<'a, A>>,
pub pm_timer: Option<PmTimer>,
/*
* TODO: we could provide a nice view of the hardware register blocks in the FADT here.
Expand All @@ -119,17 +165,34 @@ where
where
H: AcpiHandler,
{
let fadt = tables.find_table::<Fadt>()?;
let power_profile = fadt.power_profile();
let (power_profile, pm_timer) = {
let fadt = tables.find_table::<Fadt>()?;
(fadt.power_profile(), PmTimer::new(&fadt)?)
};

let (interrupt_model, processor_info) = {
let madt = tables.find_table::<Madt>();
match madt {
Ok(madt) => madt.get().parse_interrupt_model_in(allocator.clone())?,
Err(_) => (InterruptModel::Unknown, None),
}
};

let madt = tables.find_table::<Madt>();
let (interrupt_model, processor_info) = match madt {
Ok(madt) => madt.get().parse_interrupt_model_in(allocator)?,
Err(_) => (InterruptModel::Unknown, None),
let (processor_info, memory_info) = {
let srat = tables.find_table::<Srat>();
match srat {
Ok(srat) => {
let (processor_topology, memory_info) = srat.get().parse_topology_in(allocator)?;
(processor_info.map(|mut processor_info| {
processor_info.attach_affinity(&processor_topology);
processor_info
}), Some(memory_info))
}
Err(_) => (processor_info, None),
}
};
let pm_timer = PmTimer::new(&fadt)?;

Ok(PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer })
Ok(PlatformInfo { power_profile, interrupt_model, processor_info, memory_info, pm_timer })
}
}

Expand Down
Loading
Loading