xref: /cloud-hypervisor/hypervisor/src/arch/x86/mod.rs (revision b440cb7d2330770cd415b63544a371d4caa2db3a)
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_upper_case_globals)]
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 #[allow(dead_code, clippy::upper_case_acronyms)]
31 #[derive(Clone, Debug)]
32 pub enum Exception {
33     DE = 0,  // Divide Error
34     DB = 1,  // Debug Exception
35     BP = 3,  // Breakpoint
36     OF = 4,  // Overflow
37     BR = 5,  // BOUND Range Exceeded
38     UD = 6,  // Invalid/Undefined Opcode
39     NM = 7,  // No Math Coprocessor
40     DF = 8,  // Double Fault
41     TS = 10, // Invalid TSS
42     NP = 11, // Segment Not Present
43     SS = 12, // Stack Segment Fault
44     GP = 13, // General Protection
45     PF = 14, // Page Fault
46     MF = 16, // Math Fault
47     AC = 17, // Alignment Check
48     MC = 18, // Machine Check
49     XM = 19, // SIMD Floating-Point Exception
50     VE = 20, // Virtualization Exception
51     CP = 21, // Control Protection Exception
52 }
53 
54 pub mod regs;
55 
56 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
57 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
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 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
179 pub struct StandardRegisters {
180     pub rax: u64,
181     pub rbx: u64,
182     pub rcx: u64,
183     pub rdx: u64,
184     pub rsi: u64,
185     pub rdi: u64,
186     pub rsp: u64,
187     pub rbp: u64,
188     pub r8: u64,
189     pub r9: u64,
190     pub r10: u64,
191     pub r11: u64,
192     pub r12: u64,
193     pub r13: u64,
194     pub r14: u64,
195     pub r15: u64,
196     pub rip: u64,
197     pub rflags: u64,
198 }
199 
200 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
201 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
202 pub struct DescriptorTable {
203     pub base: u64,
204     pub limit: u16,
205 }
206 
207 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
208 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))]
209 pub struct SpecialRegisters {
210     pub cs: SegmentRegister,
211     pub ds: SegmentRegister,
212     pub es: SegmentRegister,
213     pub fs: SegmentRegister,
214     pub gs: SegmentRegister,
215     pub ss: SegmentRegister,
216     pub tr: SegmentRegister,
217     pub ldt: SegmentRegister,
218     pub gdt: DescriptorTable,
219     pub idt: DescriptorTable,
220     pub cr0: u64,
221     pub cr2: u64,
222     pub cr3: u64,
223     pub cr4: u64,
224     pub cr8: u64,
225     pub efer: u64,
226     pub apic_base: u64,
227     pub interrupt_bitmap: [u64; 4usize],
228 }
229 
230 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
231 pub struct CpuIdEntry {
232     pub function: u32,
233     pub index: u32,
234     pub flags: u32,
235     pub eax: u32,
236     pub ebx: u32,
237     pub ecx: u32,
238     pub edx: u32,
239 }
240 
241 pub const CPUID_FLAG_VALID_INDEX: u32 = 1;
242 
243 #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
244 pub struct FpuState {
245     pub fpr: [[u8; 16usize]; 8usize],
246     pub fcw: u16,
247     pub fsw: u16,
248     pub ftwx: u8,
249     pub last_opcode: u16,
250     pub last_ip: u64,
251     pub last_dp: u64,
252     pub xmm: [[u8; 16usize]; 16usize],
253     pub mxcsr: u32,
254 }
255 
256 #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
257 pub enum LapicState {
258     #[cfg(feature = "kvm")]
259     Kvm(kvm_bindings::kvm_lapic_state),
260     #[cfg(feature = "mshv")]
261     Mshv(mshv_bindings::LapicState),
262 }
263 
264 #[cfg(any(feature = "kvm", feature = "mshv"))]
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         let sliceu8 = match self {
272             #[cfg(feature = "kvm")]
273             LapicState::Kvm(s) => unsafe {
274                 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
275                 // Cursors are only readable on arrays of u8, not i8(c_char).
276                 mem::transmute::<&[i8], &[u8]>(&s.regs[reg_offset..])
277             },
278             #[cfg(feature = "mshv")]
279             LapicState::Mshv(s) => unsafe {
280                 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
281                 // Cursors are only readable on arrays of u8, not i8(c_char).
282                 mem::transmute::<&[i8], &[u8]>(&s.regs[reg_offset..])
283             },
284         };
285 
286         let mut reader = Cursor::new(sliceu8);
287         // Following call can't fail if the offsets defined above are correct.
288         reader
289             .read_u32::<LittleEndian>()
290             .expect("Failed to read klapic register")
291     }
292 
293     pub fn set_klapic_reg(&mut self, reg_offset: usize, value: u32) {
294         use byteorder::{LittleEndian, WriteBytesExt};
295         use std::io::Cursor;
296         use std::mem;
297 
298         let sliceu8 = match self {
299             #[cfg(feature = "kvm")]
300             LapicState::Kvm(s) => unsafe {
301                 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
302                 // Cursors are only readable on arrays of u8, not i8(c_char).
303                 mem::transmute::<&mut [i8], &mut [u8]>(&mut s.regs[reg_offset..])
304             },
305             #[cfg(feature = "mshv")]
306             LapicState::Mshv(s) => unsafe {
307                 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
308                 // Cursors are only readable on arrays of u8, not i8(c_char).
309                 mem::transmute::<&mut [i8], &mut [u8]>(&mut s.regs[reg_offset..])
310             },
311         };
312 
313         let mut writer = Cursor::new(sliceu8);
314         // Following call can't fail if the offsets defined above are correct.
315         writer
316             .write_u32::<LittleEndian>(value)
317             .expect("Failed to write klapic register")
318     }
319 }
320 
321 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
322 pub struct MsrEntry {
323     pub index: u32,
324     pub data: u64,
325 }
326