@@ -216,42 +216,39 @@ bitflags! {
216216 const LIMIT_0_15 = 0xFFFF ;
217217 /// Bits `16..=19` of the limit field (ignored in 64-bit mode)
218218 const LIMIT_16_19 = 0xF << 48 ;
219- /// Bits `0..=23` of the base field (ignored in 64-bit mode)
219+ /// Bits `0..=23` of the base field (ignored in 64-bit mode, except for fs and gs )
220220 const BASE_0_23 = 0xFF_FFFF << 16 ;
221- /// Bits `24..=31` of the base field (ignored in 64-bit mode)
221+ /// Bits `24..=31` of the base field (ignored in 64-bit mode, except for fs and gs )
222222 const BASE_24_31 = 0xFF << 56 ;
223223 }
224224}
225225
226- /// The following constants define default values for common GDT use-cases. They
227- /// are all "flat" segments meaning that they can access the entire address
228- /// space. These values all set [`WRITABLE`][DescriptorFlags::WRITABLE] and
229- /// [`ACCESSED`][DescriptorFlags::ACCESSED].
226+ /// The following constants define default values for common GDT entries. They
227+ /// are all "flat" segments, meaning they can access the entire address space.
228+ /// These values all set [`WRITABLE`][DescriptorFlags::WRITABLE] and
229+ /// [`ACCESSED`][DescriptorFlags::ACCESSED]. They also match the values loaded
230+ /// by the `syscall`/`sysret` and `sysenter`/`sysexit` instructions.
230231///
231232/// In short, these values disable segmentation, permission checks, and access
232233/// tracking at the GDT level. Kernels using these values should use paging to
233234/// implement this functionality.
234235impl DescriptorFlags {
235- // Flags that we set for all user segments
236+ // Flags that we set for all our default segments
236237 const COMMON : Self = Self :: from_bits_truncate (
237238 Self :: USER_SEGMENT . bits ( )
238239 | Self :: PRESENT . bits ( )
239240 | Self :: WRITABLE . bits ( )
240- | Self :: ACCESSED . bits ( ) ,
241- ) ;
242- // Flags that need to be set for all flat 32-bit segments
243- const COMMON_FLAT : Self = Self :: from_bits_truncate (
244- Self :: COMMON . bits ( )
241+ | Self :: ACCESSED . bits ( )
245242 | Self :: LIMIT_0_15 . bits ( )
246243 | Self :: LIMIT_16_19 . bits ( )
247244 | Self :: GRANULARITY . bits ( ) ,
248245 ) ;
249246 /// A kernel data segment (64-bit or flat 32-bit)
250247 pub const KERNEL_DATA : Self =
251- Self :: from_bits_truncate ( Self :: COMMON_FLAT . bits ( ) | Self :: DEFAULT_SIZE . bits ( ) ) ;
248+ Self :: from_bits_truncate ( Self :: COMMON . bits ( ) | Self :: DEFAULT_SIZE . bits ( ) ) ;
252249 /// A flat 32-bit kernel code segment
253250 pub const KERNEL_CODE32 : Self = Self :: from_bits_truncate (
254- Self :: COMMON_FLAT . bits ( ) | Self :: EXECUTABLE . bits ( ) | Self :: DEFAULT_SIZE . bits ( ) ,
251+ Self :: COMMON . bits ( ) | Self :: EXECUTABLE . bits ( ) | Self :: DEFAULT_SIZE . bits ( ) ,
255252 ) ;
256253 /// A 64-bit kernel code segment
257254 pub const KERNEL_CODE64 : Self = Self :: from_bits_truncate (
@@ -269,19 +266,29 @@ impl DescriptorFlags {
269266}
270267
271268impl Descriptor {
272- /// Creates a segment descriptor for a 64-bit kernel code segment.
269+ /// Creates a segment descriptor for a 64-bit kernel code segment. Suitable
270+ /// for use with `syscall` or 64-bit `sysenter`.
273271 #[ inline]
274272 pub const fn kernel_code_segment ( ) -> Descriptor {
275273 Descriptor :: UserSegment ( DescriptorFlags :: KERNEL_CODE64 . bits ( ) )
276274 }
277275
278- /// Creates a segment descriptor for a ring 3 data segment (64-bit or 32-bit).
276+ /// Creates a segment descriptor for a kernel data segment (32-bit or
277+ /// 64-bit). Suitable for use with `syscall` or `sysenter`.
278+ #[ inline]
279+ pub const fn kernel_data_segment ( ) -> Descriptor {
280+ Descriptor :: UserSegment ( DescriptorFlags :: KERNEL_DATA . bits ( ) )
281+ }
282+
283+ /// Creates a segment descriptor for a ring 3 data segment (32-bit or
284+ /// 64-bit). Suitable for use with `sysret` or `sysexit`.
279285 #[ inline]
280286 pub const fn user_data_segment ( ) -> Descriptor {
281287 Descriptor :: UserSegment ( DescriptorFlags :: USER_DATA . bits ( ) )
282288 }
283289
284- /// Creates a segment descriptor for a 64-bit ring 3 code segment.
290+ /// Creates a segment descriptor for a 64-bit ring 3 code segment. Suitable
291+ /// for use with `sysret` or `sysexit`.
285292 #[ inline]
286293 pub const fn user_code_segment ( ) -> Descriptor {
287294 Descriptor :: UserSegment ( DescriptorFlags :: USER_CODE64 . bits ( ) )
@@ -318,15 +325,13 @@ mod tests {
318325 #[ test]
319326 #[ rustfmt:: skip]
320327 pub fn linux_kernel_defaults ( ) {
321- // Make sure our 32-bit defaults match the ones used by the Linux kernel.
328+ // Make sure our defaults match the ones used by the Linux kernel.
322329 // Constants pulled from an old version of arch/x86/kernel/cpu/common.c
330+ assert_eq ! ( Flags :: KERNEL_CODE64 . bits( ) , 0x00af9b000000ffff ) ;
323331 assert_eq ! ( Flags :: KERNEL_CODE32 . bits( ) , 0x00cf9b000000ffff ) ;
324332 assert_eq ! ( Flags :: KERNEL_DATA . bits( ) , 0x00cf93000000ffff ) ;
333+ assert_eq ! ( Flags :: USER_CODE64 . bits( ) , 0x00affb000000ffff ) ;
325334 assert_eq ! ( Flags :: USER_CODE32 . bits( ) , 0x00cffb000000ffff ) ;
326335 assert_eq ! ( Flags :: USER_DATA . bits( ) , 0x00cff3000000ffff ) ;
327-
328- // Our 64-bit code segments only use a subset of the kernel's flags
329- assert ! ( Flags :: from_bits( 0x00af9b000000ffff ) . unwrap( ) . contains( Flags :: KERNEL_CODE64 ) ) ;
330- assert ! ( Flags :: from_bits( 0x00affb000000ffff ) . unwrap( ) . contains( Flags :: KERNEL_CODE64 ) ) ;
331336 }
332337}
0 commit comments