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