|
1 | 1 | //! Provides functions to read and write segment registers.
|
2 | 2 |
|
3 |
| -#[cfg(doc)] |
4 |
| -use crate::{ |
5 |
| - registers::control::Cr4Flags, |
6 |
| - structures::gdt::{Descriptor, GlobalDescriptorTable}, |
7 |
| -}; |
| 3 | +pub use crate::registers::segmentation::{Segment, Segment64, CS, DS, ES, FS, GS, SS}; |
8 | 4 | use crate::{
|
9 | 5 | registers::model_specific::{FsBase, GsBase, Msr},
|
10 | 6 | structures::gdt::SegmentSelector,
|
11 | 7 | VirtAddr,
|
12 | 8 | };
|
13 | 9 |
|
14 |
| -/// An x86 segment |
15 |
| -/// |
16 |
| -/// Segment registers on x86 are 16-bit [`SegmentSelector`]s, which index into |
17 |
| -/// the [`GlobalDescriptorTable`]. The corresponding GDT entry is used to |
18 |
| -/// configure the segment itself. Note that most segmentation functionality is |
19 |
| -/// disabled in 64-bit mode. See the individual segments for more information. |
20 |
| -pub trait Segment { |
21 |
| - /// Returns the current value of the segment register. |
22 |
| - fn get_reg() -> SegmentSelector; |
23 |
| - /// Reload the segment register. Depending on the segment, this may also |
24 |
| - /// reconfigure the corresponding segment. |
25 |
| - /// |
26 |
| - /// ## Safety |
27 |
| - /// |
28 |
| - /// This function is unsafe because the caller must ensure that `sel` |
29 |
| - /// is a valid segment descriptor, and that reconfiguring the segment will |
30 |
| - /// not cause undefined behavior. |
31 |
| - unsafe fn set_reg(sel: SegmentSelector); |
32 |
| -} |
33 |
| - |
34 |
| -/// An x86 segment which is actually used in 64-bit mode |
35 |
| -/// |
36 |
| -/// While most segments are unused in 64-bit mode, the FS and GS segments are |
37 |
| -/// still partially used. Only the 64-bit segment base address is used, and this |
38 |
| -/// address can be set via the GDT, or by using the `FSGSBASE` instructions. |
39 |
| -pub trait Segment64: Segment { |
40 |
| - /// MSR containing the segment base. This MSR can be used to set the base |
41 |
| - /// when [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is **not** set. |
42 |
| - const BASE: Msr; |
43 |
| - /// Reads the segment base address |
44 |
| - /// |
45 |
| - /// ## Exceptions |
46 |
| - /// |
47 |
| - /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`. |
48 |
| - fn read_base() -> VirtAddr; |
49 |
| - /// Writes the segment base address |
50 |
| - /// |
51 |
| - /// ## Exceptions |
52 |
| - /// |
53 |
| - /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`. |
54 |
| - /// |
55 |
| - /// ## Safety |
56 |
| - /// |
57 |
| - /// The caller must ensure that this write operation has no unsafe side |
58 |
| - /// effects, as the segment base address might be in use. |
59 |
| - unsafe fn write_base(base: VirtAddr); |
60 |
| -} |
61 |
| - |
62 | 10 | macro_rules! get_reg_impl {
|
63 | 11 | ($name:literal, $asm_get:ident) => {
|
64 | 12 | fn get_reg() -> SegmentSelector {
|
@@ -120,14 +68,6 @@ macro_rules! segment64_impl {
|
120 | 68 | };
|
121 | 69 | }
|
122 | 70 |
|
123 |
| -/// Code Segment |
124 |
| -/// |
125 |
| -/// The segment base and limit are unused in 64-bit mode. Only the L (long), D |
126 |
| -/// (default operation size), and DPL (descriptor privilege-level) fields of the |
127 |
| -/// descriptor are recognized. So changing the segment register can be used to |
128 |
| -/// change privilege level or enable/disable long mode. |
129 |
| -#[derive(Debug)] |
130 |
| -pub struct CS; |
131 | 71 | impl Segment for CS {
|
132 | 72 | get_reg_impl!("cs", x86_64_asm_get_cs);
|
133 | 73 |
|
@@ -157,50 +97,11 @@ impl Segment for CS {
|
157 | 97 | }
|
158 | 98 | }
|
159 | 99 |
|
160 |
| -/// Stack Segment |
161 |
| -/// |
162 |
| -/// Entirely unused in 64-bit mode; setting the segment register does nothing. |
163 |
| -/// However, in ring 3, the SS register still has to point to a valid |
164 |
| -/// [`Descriptor`] (it cannot be zero). This means a user-mode read/write |
165 |
| -/// segment descriptor must be present in the GDT. |
166 |
| -/// |
167 |
| -/// This register is also set by the `syscall`/`sysret` and |
168 |
| -/// `sysenter`/`sysexit` instructions (even on 64-bit transitions). This is to |
169 |
| -/// maintain symmetry with 32-bit transitions where setting SS actually will |
170 |
| -/// actually have an effect. |
171 |
| -#[derive(Debug)] |
172 |
| -pub struct SS; |
173 | 100 | segment_impl!(SS, "ss", x86_64_asm_get_ss, x86_64_asm_load_ss);
|
174 |
| - |
175 |
| -/// Data Segment |
176 |
| -/// |
177 |
| -/// Entirely unused in 64-bit mode; setting the segment register does nothing. |
178 |
| -#[derive(Debug)] |
179 |
| -pub struct DS; |
180 | 101 | segment_impl!(DS, "ds", x86_64_asm_get_ds, x86_64_asm_load_ds);
|
181 |
| - |
182 |
| -/// ES Segment |
183 |
| -/// |
184 |
| -/// Entirely unused in 64-bit mode; setting the segment register does nothing. |
185 |
| -#[derive(Debug)] |
186 |
| -pub struct ES; |
187 | 102 | segment_impl!(ES, "es", x86_64_asm_get_es, x86_64_asm_load_es);
|
188 |
| - |
189 |
| -/// FS Segment |
190 |
| -/// |
191 |
| -/// Only base is used in 64-bit mode, see [`Segment64`]. This is often used in |
192 |
| -/// user-mode for Thread-Local Storage (TLS). |
193 |
| -#[derive(Debug)] |
194 |
| -pub struct FS; |
195 | 103 | segment_impl!(FS, "fs", x86_64_asm_get_fs, x86_64_asm_load_fs);
|
196 | 104 | segment64_impl!(FS, "fs", FsBase, x86_64_asm_rdfsbase, x86_64_asm_wrfsbase);
|
197 |
| - |
198 |
| -/// GS Segment |
199 |
| -/// |
200 |
| -/// Only base is used in 64-bit mode, see [`Segment64`]. In kernel-mode, the GS |
201 |
| -/// base often points to a per-cpu kernel data structure. |
202 |
| -#[derive(Debug)] |
203 |
| -pub struct GS; |
204 | 105 | segment_impl!(GS, "gs", x86_64_asm_get_gs, x86_64_asm_load_gs);
|
205 | 106 | segment64_impl!(GS, "gs", GsBase, x86_64_asm_rdgsbase, x86_64_asm_wrgsbase);
|
206 | 107 |
|
|
0 commit comments