@@ -4,7 +4,11 @@ use crate::{
4
4
AcpiTable ,
5
5
} ;
6
6
use bit_field:: BitField ;
7
- use core:: { marker:: PhantomData , mem} ;
7
+ use core:: {
8
+ marker:: { PhantomData , PhantomPinned } ,
9
+ mem,
10
+ pin:: Pin ,
11
+ } ;
8
12
9
13
#[ cfg( feature = "allocator_api" ) ]
10
14
use crate :: {
@@ -29,16 +33,22 @@ pub enum MadtError {
29
33
/// to read each entry from it.
30
34
///
31
35
/// In modern versions of ACPI, the MADT can detail one of four interrupt models:
32
- /// * The ancient dual-i8259 legacy PIC model
33
- /// * The Advanced Programmable Interrupt Controller (APIC) model
34
- /// * The Streamlined Advanced Programmable Interrupt Controller (SAPIC) model (for Itanium systems)
35
- /// * The Generic Interrupt Controller (GIC) model (for ARM systems)
36
- #[ repr( C , packed) ]
36
+ /// - The ancient dual-i8259 legacy PIC model
37
+ /// - The Advanced Programmable Interrupt Controller (APIC) model
38
+ /// - The Streamlined Advanced Programmable Interrupt Controller (SAPIC) model (for Itanium systems)
39
+ /// - The Generic Interrupt Controller (GIC) model (for ARM systems)
40
+ ///
41
+ /// The MADT is a variable-sized structure consisting of a static header and then a variable number of entries.
42
+ /// This type only contains the static portion, and then uses pointer arithmetic to parse the following entries.
43
+ /// To make this sound, this type is `!Unpin` - this prevents you from getting anything other than a `Pin<&Madt>`
44
+ /// out of a `PhysicalMapping`, thereby preventing a `Madt` from being moved before [`Madt::entries`] is called.
45
+ #[ repr( C ) ]
37
46
#[ derive( Debug ) ]
38
47
pub struct Madt {
39
48
pub header : SdtHeader ,
40
49
pub local_apic_address : u32 ,
41
50
pub flags : u32 ,
51
+ _pinned : PhantomPinned ,
42
52
}
43
53
44
54
/// ### Safety: Implementation properly represents a valid MADT.
@@ -62,7 +72,7 @@ impl Madt {
62
72
63
73
#[ cfg( feature = "allocator_api" ) ]
64
74
pub fn parse_interrupt_model_in < ' a , A > (
65
- & self ,
75
+ self : Pin < & Self > ,
66
76
allocator : A ,
67
77
) -> AcpiResult < ( InterruptModel < ' a , A > , Option < ProcessorInfo < ' a , A > > ) >
68
78
where
@@ -107,7 +117,7 @@ impl Madt {
107
117
108
118
#[ cfg( feature = "allocator_api" ) ]
109
119
fn parse_apic_model_in < ' a , A > (
110
- & self ,
120
+ self : Pin < & Self > ,
111
121
allocator : A ,
112
122
) -> AcpiResult < ( InterruptModel < ' a , A > , Option < ProcessorInfo < ' a , A > > ) >
113
123
where
@@ -311,9 +321,10 @@ impl Madt {
311
321
) )
312
322
}
313
323
314
- pub fn entries ( & self ) -> MadtEntryIter {
324
+ pub fn entries ( self : Pin < & Self > ) -> MadtEntryIter < ' _ > {
325
+ let ptr = unsafe { Pin :: into_inner_unchecked ( self ) as * const Madt as * const u8 } ;
315
326
MadtEntryIter {
316
- pointer : unsafe { ( self as * const Madt as * const u8 ) . add ( mem:: size_of :: < Madt > ( ) ) } ,
327
+ pointer : unsafe { ptr . add ( mem:: size_of :: < Madt > ( ) ) } ,
317
328
remaining_length : self . header . length - mem:: size_of :: < Madt > ( ) as u32 ,
318
329
_phantom : PhantomData ,
319
330
}
0 commit comments