xref: /cloud-hypervisor/hypervisor/src/arch/x86/mod.rs (revision ea4693a09123234951ae1516f112c5cfce5032ca)
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 {
74     pub fn segment_type(&self) -> u8 {
75         self.type_
76     }
77     pub fn set_segment_type(&mut self, val: u8) {
78         self.type_ = val;
79     }
80 
81     pub fn dpl(&self) -> u8 {
82         self.dpl
83     }
84 
85     pub fn set_dpl(&mut self, val: u8) {
86         self.dpl = val;
87     }
88 
89     pub fn present(&self) -> u8 {
90         self.present
91     }
92 
93     pub fn set_present(&mut self, val: u8) {
94         self.present = val;
95     }
96 
97     pub fn long(&self) -> u8 {
98         self.l
99     }
100 
101     pub fn set_long(&mut self, val: u8) {
102         self.l = val;
103     }
104 
105     pub fn avl(&self) -> u8 {
106         self.avl
107     }
108 
109     pub fn set_avl(&mut self, val: u8) {
110         self.avl = val;
111     }
112 
113     pub fn desc_type(&self) -> u8 {
114         self.s
115     }
116 
117     pub fn set_desc_type(&mut self, val: u8) {
118         self.s = val;
119     }
120 
121     pub fn granularity(&self) -> u8 {
122         self.g
123     }
124 
125     pub fn set_granularity(&mut self, val: u8) {
126         self.g = val;
127     }
128 
129     pub fn db(&self) -> u8 {
130         self.db
131     }
132 
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 
147 pub fn segment_type_code(t: u8) -> bool {
148     t & CODE_SEGMENT_TYPE != 0
149 }
150 
151 pub fn segment_type_ro(t: u8) -> bool {
152     t & !RWRX_SEGMENT_TYPE == 0
153 }
154 
155 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 {
217     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 {
255     fn default() -> Self {
256         // SAFETY: this is plain old data structure
257         unsafe { ::std::mem::zeroed() }
258     }
259 }
260 
261 impl LapicState {
262     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 
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 {
317     fn default() -> Self {
318         // SAFETY: this is plain old data structure
319         unsafe { ::std::mem::zeroed() }
320     }
321 }
322