11pub mod interrupt;
22
33use 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} ;
146use core:: { alloc:: Allocator , mem, ptr} ;
157use 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 ) ]
4956pub struct ProcessorInfo < ' a , A >
5057where
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).
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