@@ -3,7 +3,11 @@ use crate::{
33 AcpiTable ,
44} ;
55use bit_field:: BitField ;
6- use core:: { marker:: PhantomData , mem} ;
6+ use core:: {
7+ marker:: { PhantomData , PhantomPinned } ,
8+ mem,
9+ pin:: Pin ,
10+ } ;
711
812#[ cfg( feature = "allocator_api" ) ]
913use crate :: {
@@ -27,16 +31,22 @@ pub enum MadtError {
2731/// to read each entry from it.
2832///
2933/// 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- #[ repr( C , packed) ]
35- #[ derive( Debug , Clone , Copy ) ]
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`, thereby preventing a `Madt` from being moved before [`Madt::entries`] is called.
43+ #[ repr( C ) ]
44+ #[ derive( Debug ) ]
3645pub struct Madt {
3746 pub header : SdtHeader ,
3847 pub local_apic_address : u32 ,
3948 pub flags : u32 ,
49+ _pinned : PhantomPinned ,
4050}
4151
4252/// ### Safety: Implementation properly represents a valid MADT.
@@ -51,7 +61,7 @@ unsafe impl AcpiTable for Madt {
5161impl Madt {
5262 #[ cfg( feature = "allocator_api" ) ]
5363 pub fn parse_interrupt_model_in < ' a , A > (
54- & self ,
64+ self : Pin < & Self > ,
5565 allocator : A ,
5666 ) -> AcpiResult < ( InterruptModel < ' a , A > , Option < ProcessorInfo < ' a , A > > ) >
5767 where
@@ -96,7 +106,7 @@ impl Madt {
96106
97107 #[ cfg( feature = "allocator_api" ) ]
98108 fn parse_apic_model_in < ' a , A > (
99- & self ,
109+ self : Pin < & Self > ,
100110 allocator : A ,
101111 ) -> AcpiResult < ( InterruptModel < ' a , A > , Option < ProcessorInfo < ' a , A > > ) >
102112 where
@@ -301,9 +311,10 @@ impl Madt {
301311 ) )
302312 }
303313
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 } ;
305316 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 > ( ) ) } ,
307318 remaining_length : self . header . length - mem:: size_of :: < Madt > ( ) as u32 ,
308319 _phantom : PhantomData ,
309320 }
0 commit comments