@@ -185,6 +185,7 @@ bitflags! {
185
185
/// Flags for a GDT descriptor. Not all flags are valid for all descriptor types.
186
186
pub struct DescriptorFlags : u64 {
187
187
/// Set by the processor if this segment has been accessed. Only cleared by software.
188
+ /// _Setting_ this bit in software prevents GDT writes on first use.
188
189
const ACCESSED = 1 << 40 ;
189
190
/// For 32-bit data segments, sets the segment as writable. For 32-bit code segments,
190
191
/// sets the segment as _readable_. In 64-bit mode, ignored for all segments.
@@ -205,42 +206,68 @@ bitflags! {
205
206
const AVAILABLE = 1 << 52 ;
206
207
/// Must be set for 64-bit code segments, unset otherwise.
207
208
const LONG_MODE = 1 << 53 ;
208
- /// Use 32-bit (as opposed to 16-bit) operands. If [`LONG_MODE`] is set,
209
+ /// Use 32-bit (as opposed to 16-bit) operands. If [`LONG_MODE`][Self::LONG_MODE] is set,
209
210
/// this must be unset. In 64-bit mode, ignored for data segments.
210
211
const DEFAULT_SIZE = 1 << 54 ;
211
212
/// Limit field is scaled by 4096 bytes. In 64-bit mode, ignored for all segments.
212
213
const GRANULARITY = 1 << 55 ;
213
214
214
- /// Bits 0..=15 of the limit field (ignored in 64-bit mode)
215
+ /// Bits ` 0..=15` of the limit field (ignored in 64-bit mode)
215
216
const LIMIT_0_15 = 0xFFFF ;
216
- /// Bits 16..=19 of the limit field (ignored in 64-bit mode)
217
+ /// Bits ` 16..=19` of the limit field (ignored in 64-bit mode)
217
218
const LIMIT_16_19 = 0xF << 48 ;
218
- /// 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)
219
220
const BASE_0_23 = 0xFF_FFFF << 16 ;
220
- /// 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)
221
222
const BASE_24_31 = 0xFF << 56 ;
222
-
223
- /// Flags that should be set for all flat user segments
224
- const FLAT_COMMON = Self :: LIMIT_0_15 . bits | Self :: LIMIT_16_19 . bits
225
- | Self :: GRANULARITY . bits | Self :: ACCESSED . bits | Self :: WRITABLE . bits
226
- | Self :: USER_SEGMENT . bits | Self :: PRESENT . bits;
227
-
228
- /// Flags for a flat 32-bit kernel code segment
229
- const KERNEL_CODE32 = Self :: FLAT_COMMON . bits | Self :: EXECUTABLE . bits | Self :: DEFAULT_SIZE . bits;
230
- /// Flags for a 64-bit kernel code segment
231
- const KERNEL_CODE64 = Self :: FLAT_COMMON . bits | Self :: EXECUTABLE . bits | Self :: LONG_MODE . bits;
232
- /// Flags for a kernel data segment (64-bit or flat 32-bit)
233
- const KERNEL_DATA = Self :: FLAT_COMMON . bits | Self :: DEFAULT_SIZE . bits;
234
-
235
- /// Flags for a flat 32-bit user code segment
236
- const USER_CODE32 = Self :: KERNEL_CODE32 . bits | Self :: DPL_RING_3 . bits;
237
- /// Flags for a 64-bit user code segment
238
- const USER_CODE64 = Self :: KERNEL_CODE64 . bits | Self :: DPL_RING_3 . bits;
239
- /// Flags for a user data segment (64-bit or flat 32-bit)
240
- const USER_DATA = Self :: KERNEL_DATA . bits | Self :: DPL_RING_3 . bits;
241
223
}
242
224
}
243
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].
230
+ ///
231
+ /// In short, these values disable segmentation, permission checks, and access
232
+ /// tracking at the GDT level. Kernels using these values should use paging to
233
+ /// implement this functionality.
234
+ impl DescriptorFlags {
235
+ // Flags that we set for all user segments
236
+ const COMMON : Self = Self :: from_bits_truncate (
237
+ Self :: USER_SEGMENT . bits ( )
238
+ | Self :: PRESENT . bits ( )
239
+ | 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 ( )
245
+ | Self :: LIMIT_0_15 . bits ( )
246
+ | Self :: LIMIT_16_19 . bits ( )
247
+ | Self :: GRANULARITY . bits ( ) ,
248
+ ) ;
249
+ /// A kernel data segment (64-bit or flat 32-bit)
250
+ pub const KERNEL_DATA : Self =
251
+ Self :: from_bits_truncate ( Self :: COMMON_FLAT . bits ( ) | Self :: DEFAULT_SIZE . bits ( ) ) ;
252
+ /// A flat 32-bit kernel code segment
253
+ pub const KERNEL_CODE32 : Self = Self :: from_bits_truncate (
254
+ Self :: COMMON_FLAT . bits ( ) | Self :: EXECUTABLE . bits ( ) | Self :: DEFAULT_SIZE . bits ( ) ,
255
+ ) ;
256
+ /// A 64-bit kernel code segment
257
+ pub const KERNEL_CODE64 : Self = Self :: from_bits_truncate (
258
+ Self :: COMMON . bits ( ) | Self :: EXECUTABLE . bits ( ) | Self :: LONG_MODE . bits ( ) ,
259
+ ) ;
260
+ /// A user data segment (64-bit or flat 32-bit)
261
+ pub const USER_DATA : Self =
262
+ Self :: from_bits_truncate ( Self :: KERNEL_DATA . bits ( ) | Self :: DPL_RING_3 . bits ( ) ) ;
263
+ /// A flat 32-bit user code segment
264
+ pub const USER_CODE32 : Self =
265
+ Self :: from_bits_truncate ( Self :: KERNEL_CODE32 . bits ( ) | Self :: DPL_RING_3 . bits ( ) ) ;
266
+ /// A 64-bit user code segment
267
+ pub const USER_CODE64 : Self =
268
+ Self :: from_bits_truncate ( Self :: KERNEL_CODE64 . bits ( ) | Self :: DPL_RING_3 . bits ( ) ) ;
269
+ }
270
+
244
271
impl Descriptor {
245
272
/// Creates a segment descriptor for a 64-bit kernel code segment.
246
273
#[ inline]
@@ -291,13 +318,15 @@ mod tests {
291
318
#[ test]
292
319
#[ rustfmt:: skip]
293
320
pub fn linux_kernel_defaults ( ) {
294
- // Make sure our defaults match the ones used by the Linux kernel.
321
+ // Make sure our 32-bit defaults match the ones used by the Linux kernel.
295
322
// Constants pulled from an old version of arch/x86/kernel/cpu/common.c
296
323
assert_eq ! ( Flags :: KERNEL_CODE32 . bits( ) , 0x00cf9b000000ffff ) ;
297
- assert_eq ! ( Flags :: KERNEL_CODE64 . bits( ) , 0x00af9b000000ffff ) ;
298
324
assert_eq ! ( Flags :: KERNEL_DATA . bits( ) , 0x00cf93000000ffff ) ;
299
325
assert_eq ! ( Flags :: USER_CODE32 . bits( ) , 0x00cffb000000ffff ) ;
300
326
assert_eq ! ( Flags :: USER_DATA . bits( ) , 0x00cff3000000ffff ) ;
301
- assert_eq ! ( Flags :: USER_CODE64 . bits( ) , 0x00affb000000ffff ) ;
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 ) ) ;
302
331
}
303
332
}
0 commit comments