1
1
pub mod interrupt;
2
2
3
3
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
13
5
} ;
14
6
use core:: { alloc:: Allocator , mem, ptr} ;
15
7
use interrupt:: InterruptModel ;
@@ -35,6 +27,8 @@ pub struct Processor {
35
27
/// The ID of the local APIC of the processor. Will be less than `256` if the APIC is being used, but can be
36
28
/// greater than this if the X2APIC is being used.
37
29
pub local_apic_id : u32 ,
30
+ /// Proximity domain to which the processor belongs to.
31
+ pub proximity_domain : Option < u32 > ,
38
32
39
33
/// The state of this processor. Check that the processor is not `Disabled` before attempting to bring it up!
40
34
pub state : ProcessorState ,
@@ -45,6 +39,19 @@ pub struct Processor {
45
39
pub is_ap : bool ,
46
40
}
47
41
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
+
48
55
#[ derive( Debug , Clone ) ]
49
56
pub struct ProcessorInfo < ' a , A >
50
57
where
62
69
pub ( crate ) fn new ( boot_processor : Processor , application_processors : ManagedSlice < ' a , Processor , A > ) -> Self {
63
70
Self { boot_processor, application_processors }
64
71
}
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 > ,
65
110
}
66
111
67
112
/// Information about the ACPI Power Management Timer (ACPI PM Timer).
95
140
/// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
96
141
/// interrupt model. That information is stored here, if present.
97
142
pub processor_info : Option < ProcessorInfo < ' a , A > > ,
143
+ pub memory_info : Option < MemoryInfo < ' a , A > > ,
98
144
pub pm_timer : Option < PmTimer > ,
99
145
/*
100
146
* TODO: we could provide a nice view of the hardware register blocks in the FADT here.
@@ -119,17 +165,34 @@ where
119
165
where
120
166
H : AcpiHandler ,
121
167
{
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
+ } ;
124
180
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
+ }
129
193
} ;
130
- let pm_timer = PmTimer :: new ( & fadt) ?;
131
194
132
- Ok ( PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer } )
195
+ Ok ( PlatformInfo { power_profile, interrupt_model, processor_info, memory_info , pm_timer } )
133
196
}
134
197
}
135
198
0 commit comments