@@ -20,6 +20,8 @@ lazy_static! {
20
20
} ;
21
21
static ref GDT : ( GlobalDescriptorTable , Selectors ) = {
22
22
let mut gdt = GlobalDescriptorTable :: new( ) ;
23
+ // Add an unused segment so we get a different value for CS
24
+ gdt. append( Descriptor :: kernel_data_segment( ) ) ;
23
25
let code_selector = gdt. append( Descriptor :: kernel_code_segment( ) ) ;
24
26
let tss_selector = gdt. append( Descriptor :: tss_segment( & TSS ) ) ;
25
27
(
@@ -41,9 +43,16 @@ pub fn init() {
41
43
use x86_64:: instructions:: segmentation:: { Segment , CS } ;
42
44
use x86_64:: instructions:: tables:: load_tss;
43
45
46
+ // Make sure loading CS actually changes the value
44
47
GDT . 0 . load ( ) ;
45
- unsafe {
46
- CS :: set_reg ( GDT . 1 . code_selector ) ;
47
- load_tss ( GDT . 1 . tss_selector ) ;
48
- }
48
+ assert_ne ! ( CS :: get_reg( ) , GDT . 1 . code_selector) ;
49
+ unsafe { CS :: set_reg ( GDT . 1 . code_selector ) } ;
50
+ assert_eq ! ( CS :: get_reg( ) , GDT . 1 . code_selector) ;
51
+
52
+ // Loading the TSS should mark the GDT entry as busy
53
+ let tss_idx: usize = GDT . 1 . tss_selector . index ( ) . into ( ) ;
54
+ let old_tss_entry = GDT . 0 . entries ( ) [ tss_idx] . clone ( ) ;
55
+ unsafe { load_tss ( GDT . 1 . tss_selector ) } ;
56
+ let new_tss_entry = GDT . 0 . entries ( ) [ tss_idx] . clone ( ) ;
57
+ assert_ne ! ( old_tss_entry, new_tss_entry) ;
49
58
}
0 commit comments