@@ -115,20 +115,7 @@ impl GlobalDescriptorTable {
115115 index
116116 }
117117 } ;
118-
119- let rpl = match entry {
120- Descriptor :: UserSegment ( value) => {
121- if DescriptorFlags :: from_bits_truncate ( value) . contains ( DescriptorFlags :: DPL_RING_3 )
122- {
123- PrivilegeLevel :: Ring3
124- } else {
125- PrivilegeLevel :: Ring0
126- }
127- }
128- Descriptor :: SystemSegment ( _, _) => PrivilegeLevel :: Ring0 ,
129- } ;
130-
131- SegmentSelector :: new ( index as u16 , rpl)
118+ SegmentSelector :: new ( index as u16 , entry. dpl ( ) )
132119 }
133120
134121 /// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
@@ -187,7 +174,7 @@ impl GlobalDescriptorTable {
187174///
188175/// Segmentation is no longer supported in 64-bit mode, so most of the descriptor
189176/// contents are ignored.
190- #[ derive( Debug , Clone ) ]
177+ #[ derive( Debug , Clone , Copy ) ]
191178pub enum Descriptor {
192179 /// Descriptor for a code or data segment.
193180 ///
@@ -283,6 +270,19 @@ impl DescriptorFlags {
283270}
284271
285272impl Descriptor {
273+ /// Returns the Descriptor Privilage Level (DPL). When using this descriptor
274+ /// via a [`SegmentSelector`], the `rpl` and Current Privilage Level (CPL)
275+ /// must less than or equal to the DPL.
276+ #[ inline]
277+ pub const fn dpl ( self ) -> PrivilegeLevel {
278+ let value_low = match self {
279+ Descriptor :: UserSegment ( v) => v,
280+ Descriptor :: SystemSegment ( v, _) => v,
281+ } ;
282+ let dpl = ( value_low & DescriptorFlags :: DPL_RING_3 . bits ( ) ) >> 45 ;
283+ PrivilegeLevel :: from_u16 ( dpl as u16 )
284+ }
285+
286286 /// Creates a segment descriptor for a 64-bit kernel code segment. Suitable
287287 /// for use with `syscall` or 64-bit `sysenter`.
288288 #[ inline]
@@ -408,4 +408,18 @@ mod tests {
408408 // We have one free slot, but the GDT requires two
409409 gdt. add_entry ( Descriptor :: tss_segment ( & TSS ) ) ;
410410 }
411+
412+ #[ test]
413+ pub fn descriptor_dpl ( ) {
414+ assert_eq ! (
415+ Descriptor :: kernel_code_segment( ) . dpl( ) ,
416+ PrivilegeLevel :: Ring0
417+ ) ;
418+ assert_eq ! (
419+ Descriptor :: kernel_data_segment( ) . dpl( ) ,
420+ PrivilegeLevel :: Ring0
421+ ) ;
422+ assert_eq ! ( Descriptor :: user_code_segment( ) . dpl( ) , PrivilegeLevel :: Ring3 ) ;
423+ assert_eq ! ( Descriptor :: user_code_segment( ) . dpl( ) , PrivilegeLevel :: Ring3 ) ;
424+ }
411425}
0 commit comments