1 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 //
3 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE-BSD-3-Clause file.
6 //
7 // Copyright © 2019 Intel Corporation
8 //
9 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
10 //
11 // Copyright © 2020, Microsoft Corporation
12 //
13
14 use core::fmt;
15
16 #[cfg(all(feature = "mshv_emulator", target_arch = "x86_64"))]
17 pub mod emulator;
18 pub mod gdt;
19 #[allow(non_camel_case_types)]
20 #[allow(non_snake_case)]
21 #[allow(non_upper_case_globals)]
22 pub mod msr_index;
23
24 // MTRR constants
25 pub const MTRR_ENABLE: u64 = 0x800; // IA32_MTRR_DEF_TYPE MSR: E (MTRRs enabled) flag, bit 11
26 pub const MTRR_MEM_TYPE_WB: u64 = 0x6;
27
28 // IOAPIC pins
29 pub const NUM_IOAPIC_PINS: usize = 24;
30
31 // X86 Exceptions
32 #[derive(Clone, Debug)]
33 pub enum Exception {
34 DE = 0, // Divide Error
35 DB = 1, // Debug Exception
36 BP = 3, // Breakpoint
37 OF = 4, // Overflow
38 BR = 5, // BOUND Range Exceeded
39 UD = 6, // Invalid/Undefined Opcode
40 NM = 7, // No Math Coprocessor
41 DF = 8, // Double Fault
42 TS = 10, // Invalid TSS
43 NP = 11, // Segment Not Present
44 SS = 12, // Stack Segment Fault
45 GP = 13, // General Protection
46 PF = 14, // Page Fault
47 MF = 16, // Math Fault
48 AC = 17, // Alignment Check
49 MC = 18, // Machine Check
50 XM = 19, // SIMD Floating-Point Exception
51 VE = 20, // Virtualization Exception
52 CP = 21, // Control Protection Exception
53 }
54
55 pub mod regs;
56
57 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
58 pub struct SegmentRegister {
59 pub base: u64,
60 pub limit: u32,
61 pub selector: u16,
62 pub type_: u8,
63 pub present: u8,
64 pub dpl: u8,
65 pub db: u8,
66 pub s: u8,
67 pub l: u8,
68 pub g: u8,
69 pub avl: u8,
70 pub unusable: u8,
71 }
72
73 impl SegmentRegister {
segment_type(&self) -> u874 pub fn segment_type(&self) -> u8 {
75 self.type_
76 }
set_segment_type(&mut self, val: u8)77 pub fn set_segment_type(&mut self, val: u8) {
78 self.type_ = val;
79 }
80
dpl(&self) -> u881 pub fn dpl(&self) -> u8 {
82 self.dpl
83 }
84
set_dpl(&mut self, val: u8)85 pub fn set_dpl(&mut self, val: u8) {
86 self.dpl = val;
87 }
88
present(&self) -> u889 pub fn present(&self) -> u8 {
90 self.present
91 }
92
set_present(&mut self, val: u8)93 pub fn set_present(&mut self, val: u8) {
94 self.present = val;
95 }
96
long(&self) -> u897 pub fn long(&self) -> u8 {
98 self.l
99 }
100
set_long(&mut self, val: u8)101 pub fn set_long(&mut self, val: u8) {
102 self.l = val;
103 }
104
avl(&self) -> u8105 pub fn avl(&self) -> u8 {
106 self.avl
107 }
108
set_avl(&mut self, val: u8)109 pub fn set_avl(&mut self, val: u8) {
110 self.avl = val;
111 }
112
desc_type(&self) -> u8113 pub fn desc_type(&self) -> u8 {
114 self.s
115 }
116
set_desc_type(&mut self, val: u8)117 pub fn set_desc_type(&mut self, val: u8) {
118 self.s = val;
119 }
120
granularity(&self) -> u8121 pub fn granularity(&self) -> u8 {
122 self.g
123 }
124
set_granularity(&mut self, val: u8)125 pub fn set_granularity(&mut self, val: u8) {
126 self.g = val;
127 }
128
db(&self) -> u8129 pub fn db(&self) -> u8 {
130 self.db
131 }
132
set_db(&mut self, val: u8)133 pub fn set_db(&mut self, val: u8) {
134 self.db = val;
135 }
136 }
137
138 // Code segment
139 pub const CODE_SEGMENT_TYPE: u8 = 0x8;
140
141 // Read/Write or Read/Exec segment
142 pub const RWRX_SEGMENT_TYPE: u8 = 0x2;
143
144 // Expand down segment
145 pub const EXPAND_DOWN_SEGMENT_TYPE: u8 = 0x4;
146
segment_type_code(t: u8) -> bool147 pub fn segment_type_code(t: u8) -> bool {
148 t & CODE_SEGMENT_TYPE != 0
149 }
150
segment_type_ro(t: u8) -> bool151 pub fn segment_type_ro(t: u8) -> bool {
152 t & !RWRX_SEGMENT_TYPE == 0
153 }
154
segment_type_expand_down(t: u8) -> bool155 pub fn segment_type_expand_down(t: u8) -> bool {
156 !segment_type_code(t) && (t & EXPAND_DOWN_SEGMENT_TYPE != 0)
157 }
158 #[macro_export]
159 macro_rules! msr {
160 ($msr:expr) => {
161 MsrEntry {
162 index: $msr,
163 data: 0x0,
164 }
165 };
166 }
167 #[macro_export]
168 macro_rules! msr_data {
169 ($msr:expr, $data:expr) => {
170 MsrEntry {
171 index: $msr,
172 data: $data,
173 }
174 };
175 }
176
177 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
178 pub struct DescriptorTable {
179 pub base: u64,
180 pub limit: u16,
181 }
182
183 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
184 pub struct SpecialRegisters {
185 pub cs: SegmentRegister,
186 pub ds: SegmentRegister,
187 pub es: SegmentRegister,
188 pub fs: SegmentRegister,
189 pub gs: SegmentRegister,
190 pub ss: SegmentRegister,
191 pub tr: SegmentRegister,
192 pub ldt: SegmentRegister,
193 pub gdt: DescriptorTable,
194 pub idt: DescriptorTable,
195 pub cr0: u64,
196 pub cr2: u64,
197 pub cr3: u64,
198 pub cr4: u64,
199 pub cr8: u64,
200 pub efer: u64,
201 pub apic_base: u64,
202 pub interrupt_bitmap: [u64; 4usize],
203 }
204
205 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
206 pub struct CpuIdEntry {
207 pub function: u32,
208 pub index: u32,
209 pub flags: u32,
210 pub eax: u32,
211 pub ebx: u32,
212 pub ecx: u32,
213 pub edx: u32,
214 }
215
216 impl fmt::Display for CpuIdEntry {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218 write!(
219 f,
220 "function = 0x{:08x} \
221 index = 0x{:08x} \
222 eax = 0x{:08x} \
223 ebx = 0x{:08x} \
224 ecx = 0x{:08x} \
225 edx = 0x{:08x} \
226 flags = 0x{:08x}",
227 self.function, self.index, self.eax, self.ebx, self.ecx, self.edx, self.flags
228 )
229 }
230 }
231
232 pub const CPUID_FLAG_VALID_INDEX: u32 = 1;
233
234 #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
235 pub struct FpuState {
236 pub fpr: [[u8; 16usize]; 8usize],
237 pub fcw: u16,
238 pub fsw: u16,
239 pub ftwx: u8,
240 pub last_opcode: u16,
241 pub last_ip: u64,
242 pub last_dp: u64,
243 pub xmm: [[u8; 16usize]; 16usize],
244 pub mxcsr: u32,
245 }
246
247 #[serde_with::serde_as]
248 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
249 pub struct LapicState {
250 #[serde_as(as = "[_; 1024usize]")]
251 pub(crate) regs: [::std::os::raw::c_char; 1024usize],
252 }
253
254 impl Default for LapicState {
default() -> Self255 fn default() -> Self {
256 // SAFETY: this is plain old data structure
257 unsafe { ::std::mem::zeroed() }
258 }
259 }
260
261 impl LapicState {
get_klapic_reg(&self, reg_offset: usize) -> u32262 pub fn get_klapic_reg(&self, reg_offset: usize) -> u32 {
263 use std::io::Cursor;
264 use std::mem;
265
266 use byteorder::{LittleEndian, ReadBytesExt};
267
268 // SAFETY: plain old data type
269 let sliceu8 = unsafe {
270 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
271 // Cursors are only readable on arrays of u8, not i8(c_char).
272 mem::transmute::<&[i8], &[u8]>(&self.regs[reg_offset..])
273 };
274
275 let mut reader = Cursor::new(sliceu8);
276 // Following call can't fail if the offsets defined above are correct.
277 reader
278 .read_u32::<LittleEndian>()
279 .expect("Failed to read klapic register")
280 }
281
set_klapic_reg(&mut self, reg_offset: usize, value: u32)282 pub fn set_klapic_reg(&mut self, reg_offset: usize, value: u32) {
283 use std::io::Cursor;
284 use std::mem;
285
286 use byteorder::{LittleEndian, WriteBytesExt};
287
288 // SAFETY: plain old data type
289 let sliceu8 = unsafe {
290 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
291 // Cursors are only readable on arrays of u8, not i8(c_char).
292 mem::transmute::<&mut [i8], &mut [u8]>(&mut self.regs[reg_offset..])
293 };
294
295 let mut writer = Cursor::new(sliceu8);
296 // Following call can't fail if the offsets defined above are correct.
297 writer
298 .write_u32::<LittleEndian>(value)
299 .expect("Failed to write klapic register")
300 }
301 }
302
303 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
304 pub struct MsrEntry {
305 pub index: u32,
306 pub data: u64,
307 }
308
309 #[serde_with::serde_as]
310 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
311 pub struct XsaveState {
312 #[serde_as(as = "[_; 1024usize]")]
313 pub region: [u32; 1024usize],
314 }
315
316 impl Default for XsaveState {
default() -> Self317 fn default() -> Self {
318 // SAFETY: this is plain old data structure
319 unsafe { ::std::mem::zeroed() }
320 }
321 }
322