@@ -3,7 +3,11 @@ use crate::{
3
3
AcpiTable ,
4
4
} ;
5
5
use bit_field:: BitField ;
6
- use core:: { marker:: PhantomData , mem} ;
6
+ use core:: {
7
+ marker:: { PhantomData , PhantomPinned } ,
8
+ mem,
9
+ pin:: Pin ,
10
+ } ;
7
11
8
12
#[ cfg( feature = "allocator_api" ) ]
9
13
use crate :: {
@@ -27,16 +31,22 @@ pub enum MadtError {
27
31
/// to read each entry from it.
28
32
///
29
33
/// In modern versions of ACPI, the MADT can detail one of four interrupt models:
30
- /// * The ancient dual-i8259 legacy PIC model
31
- /// * The Advanced Programmable Interrupt Controller (APIC) model
32
- /// * The Streamlined Advanced Programmable Interrupt Controller (SAPIC) model (for Itanium systems)
33
- /// * The Generic Interrupt Controller (GIC) model (for ARM systems)
34
+ /// - The ancient dual-i8259 legacy PIC model
35
+ /// - The Advanced Programmable Interrupt Controller (APIC) model
36
+ /// - The Streamlined Advanced Programmable Interrupt Controller (SAPIC) model (for Itanium systems)
37
+ /// - The Generic Interrupt Controller (GIC) model (for ARM systems)
38
+ ///
39
+ /// The MADT is a variable-sized structure consisting of a static header and then a variable number of entries.
40
+ /// This type only contains the static portion, and then uses pointer arithmetic to parse the following entries.
41
+ /// To make this sound, this type is `!Unpin` - this prevents you from getting anything other than a `Pin<&Madt>`
42
+ /// out of a `PhysicalMapping`, and so prevents a `Madt` from being moved before [`Madt::entries`] is called.
34
43
#[ repr( C , packed) ]
35
- #[ derive( Debug , Clone , Copy ) ]
44
+ #[ derive( Debug ) ]
36
45
pub struct Madt {
37
46
pub header : SdtHeader ,
38
47
pub local_apic_address : u32 ,
39
48
pub flags : u32 ,
49
+ _pinned : PhantomPinned ,
40
50
}
41
51
42
52
/// ### Safety: Implementation properly represents a valid MADT.
@@ -51,7 +61,7 @@ unsafe impl AcpiTable for Madt {
51
61
impl Madt {
52
62
#[ cfg( feature = "allocator_api" ) ]
53
63
pub fn parse_interrupt_model_in < ' a , A > (
54
- & self ,
64
+ self : Pin < & Self > ,
55
65
allocator : A ,
56
66
) -> AcpiResult < ( InterruptModel < ' a , A > , Option < ProcessorInfo < ' a , A > > ) >
57
67
where
@@ -96,7 +106,7 @@ impl Madt {
96
106
97
107
#[ cfg( feature = "allocator_api" ) ]
98
108
fn parse_apic_model_in < ' a , A > (
99
- & self ,
109
+ self : Pin < & Self > ,
100
110
allocator : A ,
101
111
) -> AcpiResult < ( InterruptModel < ' a , A > , Option < ProcessorInfo < ' a , A > > ) >
102
112
where
@@ -301,9 +311,10 @@ impl Madt {
301
311
) )
302
312
}
303
313
304
- pub fn entries ( & self ) -> MadtEntryIter {
314
+ pub fn entries ( self : Pin < & Self > ) -> MadtEntryIter < ' _ > {
315
+ let ptr = unsafe { Pin :: into_inner_unchecked ( self ) as * const Madt as * const u8 } ;
305
316
MadtEntryIter {
306
- pointer : unsafe { ( self as * const Madt as * const u8 ) . add ( mem:: size_of :: < Madt > ( ) ) } ,
317
+ pointer : unsafe { ptr . add ( mem:: size_of :: < Madt > ( ) ) } ,
307
318
remaining_length : self . header . length - mem:: size_of :: < Madt > ( ) as u32 ,
308
319
_phantom : PhantomData ,
309
320
}
0 commit comments