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