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