11//! Types for the Global Descriptor Table and segment selectors.
22
3- use crate :: structures:: tss:: TaskStateSegment ;
3+ use crate :: structures:: { tss:: TaskStateSegment , DescriptorTablePointer } ;
44use crate :: PrivilegeLevel ;
55use bit_field:: BitField ;
66use bitflags:: bitflags;
@@ -105,33 +105,35 @@ impl GlobalDescriptorTable {
105105 }
106106 }
107107
108- /// Adds the given segment descriptor to the GDT, returning the segment selector.
109- ///
110- /// Panics if the GDT has no free entries left.
111- #[ inline]
112- pub fn add_entry ( & mut self , entry : Descriptor ) -> SegmentSelector {
113- let index = match entry {
114- Descriptor :: UserSegment ( value) => self . push ( value) ,
115- Descriptor :: SystemSegment ( value_low, value_high) => {
116- let index = self . push ( value_low) ;
117- self . push ( value_high) ;
118- index
119- }
120- } ;
121-
122- let rpl = match entry {
123- Descriptor :: UserSegment ( value) => {
124- if DescriptorFlags :: from_bits_truncate ( value) . contains ( DescriptorFlags :: DPL_RING_3 )
125- {
126- PrivilegeLevel :: Ring3
127- } else {
128- PrivilegeLevel :: Ring0
108+ const_fn ! {
109+ /// Adds the given segment descriptor to the GDT, returning the segment selector.
110+ ///
111+ /// Panics if the GDT has no free entries left.
112+ #[ inline]
113+ pub fn add_entry( & mut self , entry: Descriptor ) -> SegmentSelector {
114+ let index = match entry {
115+ Descriptor :: UserSegment ( value) => self . push( value) ,
116+ Descriptor :: SystemSegment ( value_low, value_high) => {
117+ let index = self . push( value_low) ;
118+ self . push( value_high) ;
119+ index
129120 }
130- }
131- Descriptor :: SystemSegment ( _, _) => PrivilegeLevel :: Ring0 ,
132- } ;
121+ } ;
122+
123+ let rpl = match entry {
124+ Descriptor :: UserSegment ( value) => {
125+ if DescriptorFlags :: from_bits_truncate( value) . contains( DescriptorFlags :: DPL_RING_3 )
126+ {
127+ PrivilegeLevel :: Ring3
128+ } else {
129+ PrivilegeLevel :: Ring0
130+ }
131+ }
132+ Descriptor :: SystemSegment ( _, _) => PrivilegeLevel :: Ring0 ,
133+ } ;
133134
134- SegmentSelector :: new ( index as u16 , rpl)
135+ SegmentSelector :: new( index as u16 , rpl)
136+ }
135137 }
136138
137139 /// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
@@ -142,26 +144,33 @@ impl GlobalDescriptorTable {
142144 #[ cfg( feature = "instructions" ) ]
143145 #[ inline]
144146 pub fn load ( & ' static self ) {
145- use crate :: instructions:: tables:: { lgdt, DescriptorTablePointer } ;
146- use core:: mem:: size_of;
147-
148- let ptr = DescriptorTablePointer {
149- base : self . table . as_ptr ( ) as u64 ,
150- limit : ( self . table . len ( ) * size_of :: < u64 > ( ) - 1 ) as u16 ,
151- } ;
147+ use crate :: instructions:: tables:: lgdt;
148+ // SAFETY: static lifetime ensures no modification after loading.
149+ unsafe { lgdt ( & self . pointer ( ) ) } ;
150+ }
152151
153- unsafe { lgdt ( & ptr) } ;
152+ const_fn ! {
153+ #[ inline]
154+ fn push( & mut self , value: u64 ) -> usize {
155+ if self . next_free < self . table. len( ) {
156+ let index = self . next_free;
157+ self . table[ index] = value;
158+ self . next_free += 1 ;
159+ index
160+ } else {
161+ panic!( "GDT full" ) ;
162+ }
163+ }
154164 }
155165
156- #[ inline]
157- fn push ( & mut self , value : u64 ) -> usize {
158- if self . next_free < self . table . len ( ) {
159- let index = self . next_free ;
160- self . table [ index] = value;
161- self . next_free += 1 ;
162- index
163- } else {
164- panic ! ( "GDT full" ) ;
166+ /// Creates the descriptor pointer for this table. This pointer can only be
167+ /// safely used if the table is never modified or destroyed while in use.
168+ #[ cfg( feature = "instructions" ) ]
169+ fn pointer ( & self ) -> DescriptorTablePointer {
170+ use core:: mem:: size_of;
171+ DescriptorTablePointer {
172+ base : self . table . as_ptr ( ) as u64 ,
173+ limit : ( self . next_free * size_of :: < u64 > ( ) - 1 ) as u16 ,
165174 }
166175 }
167176}
0 commit comments