xref: /cloud-hypervisor/hypervisor/src/arch/x86/mod.rs (revision 5f814308d6b19037f2afb3d36fe49b0aa14c0b22)
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 DescriptorTable {
177     pub base: u64,
178     pub limit: u16,
179 }
180 
181 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
182 pub struct SpecialRegisters {
183     pub cs: SegmentRegister,
184     pub ds: SegmentRegister,
185     pub es: SegmentRegister,
186     pub fs: SegmentRegister,
187     pub gs: SegmentRegister,
188     pub ss: SegmentRegister,
189     pub tr: SegmentRegister,
190     pub ldt: SegmentRegister,
191     pub gdt: DescriptorTable,
192     pub idt: DescriptorTable,
193     pub cr0: u64,
194     pub cr2: u64,
195     pub cr3: u64,
196     pub cr4: u64,
197     pub cr8: u64,
198     pub efer: u64,
199     pub apic_base: u64,
200     pub interrupt_bitmap: [u64; 4usize],
201 }
202 
203 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
204 pub struct CpuIdEntry {
205     pub function: u32,
206     pub index: u32,
207     pub flags: u32,
208     pub eax: u32,
209     pub ebx: u32,
210     pub ecx: u32,
211     pub edx: u32,
212 }
213 
214 pub const CPUID_FLAG_VALID_INDEX: u32 = 1;
215 
216 #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
217 pub struct FpuState {
218     pub fpr: [[u8; 16usize]; 8usize],
219     pub fcw: u16,
220     pub fsw: u16,
221     pub ftwx: u8,
222     pub last_opcode: u16,
223     pub last_ip: u64,
224     pub last_dp: u64,
225     pub xmm: [[u8; 16usize]; 16usize],
226     pub mxcsr: u32,
227 }
228 
229 #[serde_with::serde_as]
230 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
231 pub struct LapicState {
232     #[serde_as(as = "[_; 1024usize]")]
233     pub(crate) regs: [::std::os::raw::c_char; 1024usize],
234 }
235 
236 impl Default for LapicState {
237     fn default() -> Self {
238         // SAFETY: this is plain old data structure
239         unsafe { ::std::mem::zeroed() }
240     }
241 }
242 
243 impl LapicState {
244     pub fn get_klapic_reg(&self, reg_offset: usize) -> u32 {
245         use byteorder::{LittleEndian, ReadBytesExt};
246         use std::io::Cursor;
247         use std::mem;
248 
249         // SAFETY: plain old data type
250         let sliceu8 = unsafe {
251             // This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
252             // Cursors are only readable on arrays of u8, not i8(c_char).
253             mem::transmute::<&[i8], &[u8]>(&self.regs[reg_offset..])
254         };
255 
256         let mut reader = Cursor::new(sliceu8);
257         // Following call can't fail if the offsets defined above are correct.
258         reader
259             .read_u32::<LittleEndian>()
260             .expect("Failed to read klapic register")
261     }
262 
263     pub fn set_klapic_reg(&mut self, reg_offset: usize, value: u32) {
264         use byteorder::{LittleEndian, WriteBytesExt};
265         use std::io::Cursor;
266         use std::mem;
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::<&mut [i8], &mut [u8]>(&mut self.regs[reg_offset..])
273         };
274 
275         let mut writer = Cursor::new(sliceu8);
276         // Following call can't fail if the offsets defined above are correct.
277         writer
278             .write_u32::<LittleEndian>(value)
279             .expect("Failed to write klapic register")
280     }
281 }
282 
283 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
284 pub struct MsrEntry {
285     pub index: u32,
286     pub data: u64,
287 }
288 
289 #[serde_with::serde_as]
290 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
291 pub struct XsaveState {
292     #[serde_as(as = "[_; 1024usize]")]
293     pub region: [u32; 1024usize],
294 }
295 
296 impl Default for XsaveState {
297     fn default() -> Self {
298         // SAFETY: this is plain old data structure
299         unsafe { ::std::mem::zeroed() }
300     }
301 }
302