ostd/arch/x86/vm/types.rs
1// SPDX-License-Identifier: MPL-2.0
2
3//! Types that represent guest-visible x86 CPU state.
4
5/// Guest general-purpose registers, instruction pointer, and flags.
6#[repr(C)]
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct VcpuRegs {
9 /// The `RAX` register.
10 pub rax: usize,
11 /// The `RBX` register.
12 pub rbx: usize,
13 /// The `RCX` register.
14 pub rcx: usize,
15 /// The `RDX` register.
16 pub rdx: usize,
17 /// The `RSI` register.
18 pub rsi: usize,
19 /// The `RDI` register.
20 pub rdi: usize,
21 /// The `RBP` register.
22 pub rbp: usize,
23 /// The stack pointer.
24 pub rsp: usize,
25 /// The `R8` register.
26 pub r8: usize,
27 /// The `R9` register.
28 pub r9: usize,
29 /// The `R10` register.
30 pub r10: usize,
31 /// The `R11` register.
32 pub r11: usize,
33 /// The `R12` register.
34 pub r12: usize,
35 /// The `R13` register.
36 pub r13: usize,
37 /// The `R14` register.
38 pub r14: usize,
39 /// The `R15` register.
40 pub r15: usize,
41 /// The instruction pointer.
42 pub rip: usize,
43 /// The flags register.
44 pub rflags: usize,
45}
46
47impl VcpuRegs {
48 /// Creates zeroed registers with the fixed bit of `RFLAGS` set.
49 pub const fn new() -> Self {
50 const RFLAGS_FIXED_BIT: usize = 1 << 1;
51
52 Self {
53 rax: 0,
54 rbx: 0,
55 rcx: 0,
56 rdx: 0,
57 rsi: 0,
58 rdi: 0,
59 rbp: 0,
60 rsp: 0,
61 r8: 0,
62 r9: 0,
63 r10: 0,
64 r11: 0,
65 r12: 0,
66 r13: 0,
67 r14: 0,
68 r15: 0,
69 rip: 0,
70 rflags: RFLAGS_FIXED_BIT,
71 }
72 }
73}
74
75impl Default for VcpuRegs {
76 fn default() -> Self {
77 Self::new()
78 }
79}
80
81/// Guest special-register state.
82#[repr(C)]
83#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
84pub struct VcpuSregs {
85 /// The code segment.
86 pub cs: VcpuSegment,
87 /// The data segment.
88 pub ds: VcpuSegment,
89 /// The extra data segment.
90 pub es: VcpuSegment,
91 /// The `FS` segment, including the `IA32_FS_BASE` MSR value.
92 pub fs: VcpuSegment,
93 /// The `GS` segment, including the `IA32_GS_BASE` MSR value.
94 pub gs: VcpuSegment,
95 /// The stack segment.
96 pub ss: VcpuSegment,
97 /// The task register and its cached segment descriptor.
98 pub tr: VcpuSegment,
99 /// The local descriptor-table register and its cached segment descriptor.
100 pub ldt: VcpuSegment,
101 /// The global descriptor-table register.
102 pub gdt: VcpuDescTable,
103 /// The interrupt descriptor-table register.
104 pub idt: VcpuDescTable,
105 /// The `CR0` control register.
106 pub cr0: u64,
107 /// The page-fault linear address.
108 pub cr2: u64,
109 /// The page-table root and control bits.
110 pub cr3: u64,
111 /// The `CR4` control register.
112 pub cr4: u64,
113 /// The extended feature enable register.
114 pub efer: u64,
115 /// The local APIC base address and control bits.
116 pub apic_base: u64,
117 /// The pending interrupt vectors, with one bit per vector.
118 pub interrupt_bitmap: [u64; 4],
119}
120
121impl VcpuSregs {
122 /// Creates real-mode state with zero-based 64-KiB segments and paging disabled.
123 pub fn new_real_mode() -> Self {
124 const CR0_EXTENSION_TYPE: u64 = 1 << 4;
125 const DATA_READ_WRITE_ACCESSED: u8 = 0x3;
126 const CODE_EXEC_READ_ACCESSED: u8 = 0xb;
127 const BUSY_TSS: u8 = 0xb;
128
129 let data = VcpuSegment {
130 limit: 0xffff,
131 type_: DATA_READ_WRITE_ACCESSED,
132 present: 1,
133 s: 1,
134 ..VcpuSegment::default()
135 };
136
137 Self {
138 cs: VcpuSegment {
139 type_: CODE_EXEC_READ_ACCESSED,
140 ..data
141 },
142 ds: data,
143 es: data,
144 fs: data,
145 gs: data,
146 ss: data,
147 tr: VcpuSegment {
148 type_: BUSY_TSS,
149 s: 0,
150 ..data
151 },
152 ldt: VcpuSegment {
153 unusable: 1,
154 ..VcpuSegment::default()
155 },
156 cr0: CR0_EXTENSION_TYPE,
157 ..Self::default()
158 }
159 }
160}
161
162/// Guest segment-register state.
163///
164/// Refer to: Intel SDM Vol. 3A, 3.4.5 "Segment Descriptors".
165#[repr(C)]
166#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
167pub struct VcpuSegment {
168 /// The segment base address.
169 pub base: u64,
170 /// The effective segment limit in bytes, with granularity already applied.
171 pub limit: u32,
172 /// The segment selector.
173 pub selector: u16,
174 /// The four-bit segment type.
175 pub type_: u8,
176 /// The segment-present bit.
177 pub present: u8,
178 /// The descriptor privilege level.
179 pub dpl: u8,
180 /// The default operation size or upper-bound bit.
181 pub db: u8,
182 /// The descriptor class bit: zero for system, one for code or data.
183 pub s: u8,
184 /// The 64-bit code-segment bit.
185 pub l: u8,
186 /// The granularity bit: zero for byte, one for 4-KiB granularity.
187 pub g: u8,
188 /// The descriptor bit available to software.
189 pub avl: u8,
190 /// The VMX unusable-segment bit.
191 pub unusable: u8,
192 /// The reserved padding byte.
193 pub padding: u8,
194}
195
196/// Guest descriptor-table state.
197#[repr(C)]
198#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
199pub struct VcpuDescTable {
200 /// The linear base address of the descriptor table.
201 pub base: u64,
202 /// The table size in bytes minus one.
203 pub limit: u16,
204 /// The reserved padding words.
205 pub padding: [u16; 3],
206}
207
208/// Guest MSR state that is not already stored in [`VcpuSregs`].
209#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
210pub struct VcpuMsrs {
211 /// The page attribute table.
212 pub pat: u64,
213 /// The kernel GS base exchanged by `SWAPGS`.
214 pub kernel_gs_base: u64,
215 /// The `SYSCALL` and `SYSRET` segment selectors.
216 pub star: u64,
217 /// The 64-bit `SYSCALL` entry point.
218 pub lstar: u64,
219 /// The flags cleared on `SYSCALL` entry.
220 pub syscall_mask: u64,
221 /// The accumulated TSC adjustment.
222 pub tsc_adjust: u64,
223 /// The auxiliary TSC value returned by `RDTSCP`.
224 pub tsc_aux: u64,
225 /// The `SYSENTER` code-segment selector.
226 pub sysenter_cs: u64,
227 /// The `SYSENTER` stack pointer.
228 pub sysenter_esp: u64,
229 /// The `SYSENTER` instruction pointer.
230 pub sysenter_eip: u64,
231 /// The miscellaneous processor feature controls.
232 pub misc_enable: u64,
233}
234
235/// A guest external interrupt.
236#[derive(Clone, Copy, Debug, Eq, PartialEq)]
237pub struct GuestInterrupt {
238 /// The interrupt vector, in the range 32 through 255.
239 pub vector: u8,
240}
241
242/// An instant on the guest's TSC timeline.
243#[derive(Clone, Copy, Debug, Eq, PartialEq)]
244pub struct GuestTimerInstant {
245 /// The timestamp-counter value.
246 pub tsc: u64,
247}