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
+ }
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 > ,
65
108
}
66
109
67
110
/// Information about the ACPI Power Management Timer (ACPI PM Timer).
95
138
/// On `x86_64` platforms that support the APIC, the processor topology must also be inferred from the
96
139
/// interrupt model. That information is stored here, if present.
97
140
pub processor_info : Option < ProcessorInfo < ' a , A > > ,
141
+ pub memory_info : Option < MemoryInfo < ' a , A > > ,
98
142
pub pm_timer : Option < PmTimer > ,
99
143
/*
100
144
* TODO: we could provide a nice view of the hardware register blocks in the FADT here.
@@ -119,17 +163,34 @@ where
119
163
where
120
164
H : AcpiHandler ,
121
165
{
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
+ } ;
124
178
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
+ }
129
191
} ;
130
- let pm_timer = PmTimer :: new ( & fadt) ?;
131
192
132
- Ok ( PlatformInfo { power_profile, interrupt_model, processor_info, pm_timer } )
193
+ Ok ( PlatformInfo { power_profile, interrupt_model, processor_info, memory_info , pm_timer } )
133
194
}
134
195
}
135
196
0 commit comments