11//! Provides functions to read and write segment registers. 
22
33#[ cfg( docsrs) ]  
4- use  crate :: structures:: gdt:: GlobalDescriptorTable ; 
5- use  crate :: { structures:: gdt:: SegmentSelector ,  VirtAddr } ; 
4+ use  crate :: { registers:: control:: Cr4Flags ,  structures:: gdt:: GlobalDescriptorTable } ; 
5+ use  crate :: { 
6+     registers:: model_specific:: { FsBase ,  GsBase ,  Msr } , 
7+     structures:: gdt:: SegmentSelector , 
8+     VirtAddr , 
9+ } ; 
610
711/// An x86 segment 
812/// 
@@ -30,17 +34,20 @@ pub trait Segment {
3034/// still partially used. Only the 64-bit segment base address is used, and this 
3135/// address can be set via the GDT, or by using the `FSGSBASE` instructions. 
3236pub  trait  Segment64 :  Segment  { 
37+     /// MSR containing the segment base. This MSR can be used to set the base 
38+ /// when [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set. 
39+ const  BASE :  Msr ; 
3340    /// Reads the segment base address 
3441/// 
3542/// ## Safety 
3643/// 
37- /// If `CR4.FSGSBASE` is not set, this instruction will throw a `#UD`. 
44+ /// If [ `CR4.FSGSBASE`][Cr4Flags::FSGSBASE]  is not set, this instruction will throw a `#UD`. 
3845unsafe  fn  read_base ( )  -> VirtAddr ; 
3946    /// Writes the segment base address 
4047/// 
4148/// ## Safety 
4249/// 
43- /// If `CR4.FSGSBASE` is not set, this instruction will throw a `#UD`. 
50+ /// If [ `CR4.FSGSBASE`][Cr4Flags::FSGSBASE]  is not set, this instruction will throw a `#UD`. 
4451/// 
4552/// The caller must ensure that this write operation has no unsafe side 
4653/// effects, as the segment base address might be in use. 
@@ -81,8 +88,9 @@ macro_rules! segment_impl {
8188} 
8289
8390macro_rules!  segment64_impl { 
84-     ( $type: ty,  $name: literal,  $asm_rd: ident,  $asm_wr: ident)  => { 
91+     ( $type: ty,  $name: literal,  $base : ty ,  $ asm_rd: ident,  $asm_wr: ident)  => { 
8592        impl  Segment64  for  $type { 
93+             const  BASE :  Msr  = <$base>:: MSR ; 
8694            unsafe  fn  read_base( )  -> VirtAddr  { 
8795                #[ cfg( feature = "inline_asm" ) ] 
8896                { 
@@ -165,7 +173,7 @@ segment_impl!(ES, "es", x86_64_asm_get_es, x86_64_asm_load_es);
165173#[ derive( Debug ) ]  
166174pub  struct  FS ; 
167175segment_impl ! ( FS ,  "fs" ,  x86_64_asm_get_fs,  x86_64_asm_load_fs) ; 
168- segment64_impl ! ( FS ,  "fs" ,  x86_64_asm_rdfsbase,  x86_64_asm_wrfsbase) ; 
176+ segment64_impl ! ( FS ,  "fs" ,  FsBase ,   x86_64_asm_rdfsbase,  x86_64_asm_wrfsbase) ; 
169177
170178/// GS Segment 
171179/// 
@@ -174,7 +182,7 @@ segment64_impl!(FS, "fs", x86_64_asm_rdfsbase, x86_64_asm_wrfsbase);
174182#[ derive( Debug ) ]  
175183pub  struct  GS ; 
176184segment_impl ! ( GS ,  "gs" ,  x86_64_asm_get_gs,  x86_64_asm_load_gs) ; 
177- segment64_impl ! ( GS ,  "gs" ,  x86_64_asm_rdgsbase,  x86_64_asm_wrgsbase) ; 
185+ segment64_impl ! ( GS ,  "gs" ,  GsBase ,   x86_64_asm_rdgsbase,  x86_64_asm_wrgsbase) ; 
178186
179187impl  GS  { 
180188    /// Swap `KernelGsBase` MSR and `GsBase` MSR. 
0 commit comments