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