@@ -71,6 +71,10 @@ pub struct SCet;
71
71
#[ derive( Debug ) ]
72
72
pub struct Pat ;
73
73
74
+ /// IA32_APIC_BASE: status and location of the local APIC
75
+ #[ derive( Debug ) ]
76
+ pub struct Apic ;
77
+
74
78
impl Efer {
75
79
/// The underlying model specific register.
76
80
pub const MSR : Msr = Msr ( 0xC000_0080 ) ;
@@ -132,6 +136,11 @@ impl Pat {
132
136
] ;
133
137
}
134
138
139
+ impl Apic {
140
+ /// The underlying model specific register.
141
+ pub const MSR : Msr = Msr ( 0x1B ) ;
142
+ }
143
+
135
144
bitflags ! {
136
145
/// Flags of the Extended Feature Enable Register.
137
146
#[ repr( transparent) ]
@@ -218,6 +227,31 @@ impl PatMemoryType {
218
227
}
219
228
}
220
229
230
+ bitflags ! {
231
+ /// Flags for the Advanced Programmable Interrupt Controler Base Register.
232
+ #[ repr( transparent) ]
233
+ #[ derive( PartialEq , Eq , PartialOrd , Ord , Hash , Debug , Clone , Copy ) ]
234
+ pub struct ApicFlags : u64 {
235
+ // bits 0 - 7 are reserved.
236
+ /// Indicates whether the current processor is the bootstrap processor
237
+ const BSP = 1 << 8 ;
238
+ // bits 9 - 10 are reserved.
239
+ /// Enables or disables the local Apic
240
+ const LAPIC_ENABLE = 1 << 11 ;
241
+ /// Specifies the base address of the APIC registers. This 24-bit value is extended by 12 bits at the low end to form the base address.
242
+ const APIC_BASE = 0b111111111111111111111111 << 12 ;
243
+ // bits 36-63 reserved
244
+ }
245
+ }
246
+
247
+ impl ApicFlags {
248
+ /// Returns the physical address of the apic registers
249
+ #[ inline]
250
+ pub fn address ( & self ) -> u64 {
251
+ self . bits ( ) & 0b11111111111111111111000000000000
252
+ }
253
+ }
254
+
221
255
#[ cfg( all( feature = "instructions" , target_arch = "x86_64" ) ) ]
222
256
mod x86_64 {
223
257
use super :: * ;
@@ -725,4 +759,75 @@ mod x86_64 {
725
759
}
726
760
}
727
761
}
762
+
763
+ impl Apic {
764
+ /// Reads the IA32_APIC_BASE.
765
+ ///
766
+ /// The APIC_BASE must be supported on the CPU, otherwise a general protection exception will
767
+ /// occur. Support can be detected using the `cpuid` instruction.
768
+ #[ inline]
769
+ pub fn read ( ) -> ApicFlags {
770
+ ApicFlags :: from_bits_truncate ( Self :: read_raw ( ) )
771
+ }
772
+
773
+ /// Reads the raw IA32_APIC_BASE.
774
+ ///
775
+ /// The APIC_BASE must be supported on the CPU, otherwise a general protection exception will
776
+ /// occur. Support can be detected using the `cpuid` instruction.
777
+ #[ inline]
778
+ pub fn read_raw ( ) -> u64 {
779
+ unsafe { Self :: MSR . read ( ) }
780
+ }
781
+
782
+ /// Writes the IA32_APIC_BASE preserving reserved values.
783
+ ///
784
+ /// Preserves the value of reserved fields.
785
+ ///
786
+ /// The APIC_BASE must be supported on the CPU, otherwise a general protection exception will
787
+ /// occur. Support can be detected using the `cpuid` instruction.
788
+ #[ inline]
789
+ pub fn write ( flags : ApicFlags ) {
790
+ let old_value = Self :: read_raw ( ) ;
791
+ let reserved = old_value & !( ApicFlags :: all ( ) . bits ( ) ) ;
792
+ let new_value = reserved | flags. bits ( ) ;
793
+
794
+ unsafe {
795
+ Self :: write_raw ( new_value) ;
796
+ }
797
+ }
798
+
799
+ /// Writes the IA32_APIC_BASE flags.
800
+ ///
801
+ /// Does not preserve any bits, including reserved fields.
802
+ ///
803
+ /// The APIC_BASE must be supported on the CPU, otherwise a general protection exception will
804
+ /// occur. Support can be detected using the `cpuid` instruction.
805
+ ///
806
+ /// ## Safety
807
+ ///
808
+ /// Unsafe because it's possible to set reserved bits to `1`.
809
+ #[ inline]
810
+ pub unsafe fn write_raw ( flags : u64 ) {
811
+ let mut msr = Self :: MSR ;
812
+ unsafe {
813
+ msr. write ( flags) ;
814
+ }
815
+ }
816
+
817
+ /// Update IA32_APIC_BASE flags.
818
+ ///
819
+ /// Preserves the value of reserved fields.
820
+ ///
821
+ /// The APIC_BASE must be supported on the CPU, otherwise a general protection exception will
822
+ /// occur. Support can be detected using the `cpuid` instruction.
823
+ #[ inline]
824
+ pub fn update < F > ( f : F )
825
+ where
826
+ F : FnOnce ( & mut ApicFlags ) ,
827
+ {
828
+ let mut flags = Self :: read ( ) ;
829
+ f ( & mut flags) ;
830
+ Self :: write ( flags) ;
831
+ }
832
+ }
728
833
}
0 commit comments