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 > ( & mut self , topology : & ProcessorTopology < 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+ 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).
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. map ( |mut processor_info| {
187+ processor_info. attach_affinity ( & processor_topology) ;
188+ 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