@@ -115,20 +115,7 @@ impl GlobalDescriptorTable {
115
115
index
116
116
}
117
117
} ;
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 ( ) )
132
119
}
133
120
134
121
/// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
@@ -187,7 +174,7 @@ impl GlobalDescriptorTable {
187
174
///
188
175
/// Segmentation is no longer supported in 64-bit mode, so most of the descriptor
189
176
/// contents are ignored.
190
- #[ derive( Debug , Clone ) ]
177
+ #[ derive( Debug , Clone , Copy ) ]
191
178
pub enum Descriptor {
192
179
/// Descriptor for a code or data segment.
193
180
///
@@ -283,6 +270,19 @@ impl DescriptorFlags {
283
270
}
284
271
285
272
impl 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
+
286
286
/// Creates a segment descriptor for a 64-bit kernel code segment. Suitable
287
287
/// for use with `syscall` or 64-bit `sysenter`.
288
288
#[ inline]
@@ -408,4 +408,18 @@ mod tests {
408
408
// We have one free slot, but the GDT requires two
409
409
gdt. add_entry ( Descriptor :: tss_segment ( & TSS ) ) ;
410
410
}
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
+ }
411
425
}
0 commit comments