@@ -216,42 +216,39 @@ bitflags! {
216
216
const LIMIT_0_15 = 0xFFFF ;
217
217
/// Bits `16..=19` of the limit field (ignored in 64-bit mode)
218
218
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 )
220
220
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 )
222
222
const BASE_24_31 = 0xFF << 56 ;
223
223
}
224
224
}
225
225
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.
230
231
///
231
232
/// In short, these values disable segmentation, permission checks, and access
232
233
/// tracking at the GDT level. Kernels using these values should use paging to
233
234
/// implement this functionality.
234
235
impl DescriptorFlags {
235
- // Flags that we set for all user segments
236
+ // Flags that we set for all our default segments
236
237
const COMMON : Self = Self :: from_bits_truncate (
237
238
Self :: USER_SEGMENT . bits ( )
238
239
| Self :: PRESENT . bits ( )
239
240
| 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 ( )
245
242
| Self :: LIMIT_0_15 . bits ( )
246
243
| Self :: LIMIT_16_19 . bits ( )
247
244
| Self :: GRANULARITY . bits ( ) ,
248
245
) ;
249
246
/// A kernel data segment (64-bit or flat 32-bit)
250
247
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 ( ) ) ;
252
249
/// A flat 32-bit kernel code segment
253
250
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 ( ) ,
255
252
) ;
256
253
/// A 64-bit kernel code segment
257
254
pub const KERNEL_CODE64 : Self = Self :: from_bits_truncate (
@@ -269,19 +266,29 @@ impl DescriptorFlags {
269
266
}
270
267
271
268
impl 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`.
273
271
#[ inline]
274
272
pub const fn kernel_code_segment ( ) -> Descriptor {
275
273
Descriptor :: UserSegment ( DescriptorFlags :: KERNEL_CODE64 . bits ( ) )
276
274
}
277
275
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`.
279
285
#[ inline]
280
286
pub const fn user_data_segment ( ) -> Descriptor {
281
287
Descriptor :: UserSegment ( DescriptorFlags :: USER_DATA . bits ( ) )
282
288
}
283
289
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`.
285
292
#[ inline]
286
293
pub const fn user_code_segment ( ) -> Descriptor {
287
294
Descriptor :: UserSegment ( DescriptorFlags :: USER_CODE64 . bits ( ) )
@@ -318,15 +325,13 @@ mod tests {
318
325
#[ test]
319
326
#[ rustfmt:: skip]
320
327
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.
322
329
// Constants pulled from an old version of arch/x86/kernel/cpu/common.c
330
+ assert_eq ! ( Flags :: KERNEL_CODE64 . bits( ) , 0x00af9b000000ffff ) ;
323
331
assert_eq ! ( Flags :: KERNEL_CODE32 . bits( ) , 0x00cf9b000000ffff ) ;
324
332
assert_eq ! ( Flags :: KERNEL_DATA . bits( ) , 0x00cf93000000ffff ) ;
333
+ assert_eq ! ( Flags :: USER_CODE64 . bits( ) , 0x00affb000000ffff ) ;
325
334
assert_eq ! ( Flags :: USER_CODE32 . bits( ) , 0x00cffb000000ffff ) ;
326
335
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 ) ) ;
331
336
}
332
337
}
0 commit comments