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