@@ -30,32 +30,24 @@ use core::ptr::addr_of;
30
30
31
31
use alloc:: alloc:: alloc_zeroed;
32
32
33
- bitflags:: bitflags! {
34
- /// Specifies which element to load into a segment from
35
- /// descriptor tables (i.e., is a index to LDT or GDT table
36
- /// with some additional flags).
37
- pub struct SegmentSelector : u16 {
38
- const RPL_0 = 0b00 ;
39
- const RPL_1 = 0b01 ;
40
- const RPL_2 = 0b10 ;
41
- const RPL_3 = 0b11 ;
42
- const TI_GDT = 0 << 2 ;
43
- const TI_LDT = 1 << 2 ;
44
- }
45
- }
46
-
47
33
bitflags:: bitflags! {
48
34
struct GdtEntryFlags : u8 {
49
- const NULL = 0 ;
50
35
const PROTECTED_MODE = 1 << 6 ;
51
36
const LONG_MODE = 1 << 5 ;
52
37
}
53
38
}
54
39
55
- #[ derive( Debug , Clone , Copy , PartialEq ) ]
56
- pub enum Ring {
57
- Ring0 = 0b00 ,
58
- Ring3 = 0b11 ,
40
+ #[ derive( Debug , Copy , Clone , PartialEq ) ]
41
+ #[ repr( u8 ) ]
42
+ pub enum PrivilegeLevel {
43
+ Ring0 = 0 ,
44
+ Ring3 = 3 ,
45
+ }
46
+
47
+ impl PrivilegeLevel {
48
+ pub fn is_user ( & self ) -> bool {
49
+ matches ! ( self , Self :: Ring3 )
50
+ }
59
51
}
60
52
61
53
const BOOT_GDT_ENTRY_COUNT : usize = 4 ;
@@ -155,7 +147,7 @@ static GDT: [GdtEntry; GDT_ENTRY_COUNT] = [
155
147
// GDT TSS descriptor.
156
148
GdtEntry :: new (
157
149
GdtAccessFlags :: PRESENT | GdtAccessFlags :: RING_3 | GdtAccessFlags :: TSS_AVAIL ,
158
- GdtEntryFlags :: NULL ,
150
+ GdtEntryFlags :: empty ( ) ,
159
151
) ,
160
152
// GDT null descriptor as the TSS should be 16 bytes long
161
153
// and twice the normal size.
@@ -175,10 +167,10 @@ impl GdtAccessFlags {
175
167
const TSS_AVAIL : u8 = 9 ;
176
168
}
177
169
178
- pub struct GdtEntryType ;
170
+ pub struct GdtEntryIndex ;
179
171
180
172
#[ rustfmt:: skip]
181
- impl GdtEntryType {
173
+ impl GdtEntryIndex {
182
174
pub const KERNEL_CODE : u16 = 1 ;
183
175
pub const KERNEL_DATA : u16 = 2 ;
184
176
pub const KERNEL_TLS : u16 = 3 ;
@@ -188,10 +180,32 @@ impl GdtEntryType {
188
180
pub const TSS_HI : u16 = 9 ;
189
181
}
190
182
183
+ #[ derive( Debug , Copy , Clone ) ]
184
+ #[ repr( transparent) ]
185
+ pub struct SegmentSelector ( u16 ) ;
186
+
191
187
impl SegmentSelector {
192
- const fn new ( index : u16 , rpl : Ring ) -> Self {
193
- Self {
194
- bits : index << 3 | ( rpl as u16 ) ,
188
+ pub const fn empty ( ) -> Self {
189
+ Self ( 0 )
190
+ }
191
+
192
+ pub const fn new ( index : u16 , privilege_level : PrivilegeLevel ) -> Self {
193
+ Self ( index << 3 | ( privilege_level as u16 ) )
194
+ }
195
+
196
+ pub const fn bits ( & self ) -> u16 {
197
+ self . 0
198
+ }
199
+
200
+ pub const fn from_bits ( value : u16 ) -> Self {
201
+ Self ( value)
202
+ }
203
+
204
+ pub const fn privilege_level ( & self ) -> PrivilegeLevel {
205
+ match self . bits ( ) & 0b11 {
206
+ 0 => PrivilegeLevel :: Ring0 ,
207
+ 3 => PrivilegeLevel :: Ring3 ,
208
+ _ => unreachable ! ( ) ,
195
209
}
196
210
}
197
211
}
@@ -230,7 +244,7 @@ pub(super) struct GdtEntry {
230
244
}
231
245
232
246
impl GdtEntry {
233
- const NULL : Self = Self :: new ( GdtAccessFlags :: NULL , GdtEntryFlags :: NULL ) ;
247
+ const NULL : Self = Self :: new ( GdtAccessFlags :: NULL , GdtEntryFlags :: empty ( ) ) ;
234
248
235
249
const fn new ( access_flags : u8 , entry_flags : GdtEntryFlags ) -> Self {
236
250
Self {
@@ -311,19 +325,45 @@ pub fn init_boot() {
311
325
312
326
// Load the GDT segments.
313
327
unsafe {
314
- load_cs ( SegmentSelector :: new ( GdtEntryType :: KERNEL_CODE , Ring :: Ring0 ) ) ;
315
- load_ds ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
316
- load_es ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
317
- load_fs ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
318
- load_gs ( SegmentSelector :: new ( GdtEntryType :: KERNEL_TLS , Ring :: Ring0 ) ) ;
319
- load_ss ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
328
+ load_cs ( SegmentSelector :: new (
329
+ GdtEntryIndex :: KERNEL_CODE ,
330
+ PrivilegeLevel :: Ring0 ,
331
+ ) ) ;
332
+
333
+ load_ds ( SegmentSelector :: new (
334
+ GdtEntryIndex :: KERNEL_DATA ,
335
+ PrivilegeLevel :: Ring0 ,
336
+ ) ) ;
337
+
338
+ load_es ( SegmentSelector :: new (
339
+ GdtEntryIndex :: KERNEL_DATA ,
340
+ PrivilegeLevel :: Ring0 ,
341
+ ) ) ;
342
+
343
+ load_fs ( SegmentSelector :: new (
344
+ GdtEntryIndex :: KERNEL_DATA ,
345
+ PrivilegeLevel :: Ring0 ,
346
+ ) ) ;
347
+
348
+ load_gs ( SegmentSelector :: new (
349
+ GdtEntryIndex :: KERNEL_TLS ,
350
+ PrivilegeLevel :: Ring0 ,
351
+ ) ) ;
352
+
353
+ load_ss ( SegmentSelector :: new (
354
+ GdtEntryIndex :: KERNEL_DATA ,
355
+ PrivilegeLevel :: Ring0 ,
356
+ ) ) ;
320
357
}
321
358
}
322
359
323
360
static STK : [ u8 ; 4096 * 16 ] = [ 0 ; 4096 * 16 ] ;
324
361
325
- pub const USER_SS : SegmentSelector = SegmentSelector :: new ( GdtEntryType :: USER_DATA , Ring :: Ring3 ) ;
326
- pub const USER_CS : SegmentSelector = SegmentSelector :: new ( GdtEntryType :: USER_CODE , Ring :: Ring3 ) ;
362
+ pub const USER_SS : SegmentSelector =
363
+ SegmentSelector :: new ( GdtEntryIndex :: USER_DATA , PrivilegeLevel :: Ring3 ) ;
364
+
365
+ pub const USER_CS : SegmentSelector =
366
+ SegmentSelector :: new ( GdtEntryIndex :: USER_CODE , PrivilegeLevel :: Ring3 ) ;
327
367
328
368
/// Initialize the *actual* GDT stored in TLS.
329
369
///
@@ -347,9 +387,9 @@ pub fn init() {
347
387
unsafe {
348
388
let tss_ptr = TSS . addr ( ) . as_mut_ptr :: < Tss > ( ) ;
349
389
350
- gdt[ GdtEntryType :: TSS as usize ] . set_offset ( tss_ptr as u32 ) ;
351
- gdt[ GdtEntryType :: TSS as usize ] . set_limit ( mem:: size_of :: < Tss > ( ) as u32 ) ;
352
- gdt[ GdtEntryType :: TSS_HI as usize ] . set_raw ( ( tss_ptr as u64 ) >> 32 ) ;
390
+ gdt[ GdtEntryIndex :: TSS as usize ] . set_offset ( tss_ptr as u32 ) ;
391
+ gdt[ GdtEntryIndex :: TSS as usize ] . set_limit ( mem:: size_of :: < Tss > ( ) as u32 ) ;
392
+ gdt[ GdtEntryIndex :: TSS_HI as usize ] . set_raw ( ( tss_ptr as u64 ) >> 32 ) ;
353
393
354
394
TSS . rsp [ 0 ] = STK . as_ptr ( ) . offset ( 4096 * 16 ) as u64 ;
355
395
@@ -361,13 +401,28 @@ pub fn init() {
361
401
load_gdt ( & gdt_descriptor) ;
362
402
363
403
// Reload the GDT segments.
364
- load_cs ( SegmentSelector :: new ( GdtEntryType :: KERNEL_CODE , Ring :: Ring0 ) ) ;
365
- load_ds ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
366
- load_es ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
367
- load_ss ( SegmentSelector :: new ( GdtEntryType :: KERNEL_DATA , Ring :: Ring0 ) ) ;
404
+ load_cs ( SegmentSelector :: new (
405
+ GdtEntryIndex :: KERNEL_CODE ,
406
+ PrivilegeLevel :: Ring0 ,
407
+ ) ) ;
408
+ load_ds ( SegmentSelector :: new (
409
+ GdtEntryIndex :: KERNEL_DATA ,
410
+ PrivilegeLevel :: Ring0 ,
411
+ ) ) ;
412
+ load_es ( SegmentSelector :: new (
413
+ GdtEntryIndex :: KERNEL_DATA ,
414
+ PrivilegeLevel :: Ring0 ,
415
+ ) ) ;
416
+ load_ss ( SegmentSelector :: new (
417
+ GdtEntryIndex :: KERNEL_DATA ,
418
+ PrivilegeLevel :: Ring0 ,
419
+ ) ) ;
368
420
369
421
// Load the Task State Segment.
370
- load_tss ( SegmentSelector :: new ( GdtEntryType :: TSS , Ring :: Ring0 ) ) ;
422
+ load_tss ( SegmentSelector :: new (
423
+ GdtEntryIndex :: TSS ,
424
+ PrivilegeLevel :: Ring0 ,
425
+ ) ) ;
371
426
}
372
427
373
428
// // Now we update the per-cpu storage to store a reference
0 commit comments