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_camel_case_types)] 17 #[allow(non_snake_case)] 18 #[allow(non_upper_case_globals)] 19 pub mod msr_index; 20 21 // MTRR constants 22 pub const MTRR_ENABLE: u64 = 0x800; // IA32_MTRR_DEF_TYPE MSR: E (MTRRs enabled) flag, bit 11 23 pub const MTRR_MEM_TYPE_WB: u64 = 0x6; 24 25 // IOAPIC pins 26 pub const NUM_IOAPIC_PINS: usize = 24; 27 28 // X86 Exceptions 29 #[allow(clippy::upper_case_acronyms)] 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 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))] 57 pub struct SegmentRegister { 58 pub base: u64, 59 pub limit: u32, 60 pub selector: u16, 61 pub type_: u8, 62 pub present: u8, 63 pub dpl: u8, 64 pub db: u8, 65 pub s: u8, 66 pub l: u8, 67 pub g: u8, 68 pub avl: u8, 69 pub unusable: u8, 70 } 71 72 impl SegmentRegister { 73 pub fn segment_type(&self) -> u8 { 74 self.type_ 75 } 76 pub fn set_segment_type(&mut self, val: u8) { 77 self.type_ = val; 78 } 79 80 pub fn dpl(&self) -> u8 { 81 self.dpl 82 } 83 84 pub fn set_dpl(&mut self, val: u8) { 85 self.dpl = val; 86 } 87 88 pub fn present(&self) -> u8 { 89 self.present 90 } 91 92 pub fn set_present(&mut self, val: u8) { 93 self.present = val; 94 } 95 96 pub fn long(&self) -> u8 { 97 self.l 98 } 99 100 pub fn set_long(&mut self, val: u8) { 101 self.l = val; 102 } 103 104 pub fn avl(&self) -> u8 { 105 self.avl 106 } 107 108 pub fn set_avl(&mut self, val: u8) { 109 self.avl = val; 110 } 111 112 pub fn desc_type(&self) -> u8 { 113 self.s 114 } 115 116 pub fn set_desc_type(&mut self, val: u8) { 117 self.s = val; 118 } 119 120 pub fn granularity(&self) -> u8 { 121 self.g 122 } 123 124 pub fn set_granularity(&mut self, val: u8) { 125 self.g = val; 126 } 127 128 pub fn db(&self) -> u8 { 129 self.db 130 } 131 132 pub fn set_db(&mut self, val: u8) { 133 self.db = val; 134 } 135 } 136 137 // Code segment 138 pub const CODE_SEGMENT_TYPE: u8 = 0x8; 139 140 // Read/Write or Read/Exec segment 141 pub const RWRX_SEGMENT_TYPE: u8 = 0x2; 142 143 // Expand down segment 144 pub const EXPAND_DOWN_SEGMENT_TYPE: u8 = 0x4; 145 146 pub fn segment_type_code(t: u8) -> bool { 147 t & CODE_SEGMENT_TYPE != 0 148 } 149 150 pub fn segment_type_ro(t: u8) -> bool { 151 t & !RWRX_SEGMENT_TYPE == 0 152 } 153 154 pub fn segment_type_expand_down(t: u8) -> bool { 155 !segment_type_code(t) && (t & EXPAND_DOWN_SEGMENT_TYPE != 0) 156 } 157 #[macro_export] 158 macro_rules! msr { 159 ($msr:expr) => { 160 MsrEntry { 161 index: $msr, 162 data: 0x0, 163 } 164 }; 165 } 166 #[macro_export] 167 macro_rules! msr_data { 168 ($msr:expr, $data:expr) => { 169 MsrEntry { 170 index: $msr, 171 data: $data, 172 } 173 }; 174 } 175 176 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] 177 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))] 178 pub struct StandardRegisters { 179 pub rax: u64, 180 pub rbx: u64, 181 pub rcx: u64, 182 pub rdx: u64, 183 pub rsi: u64, 184 pub rdi: u64, 185 pub rsp: u64, 186 pub rbp: u64, 187 pub r8: u64, 188 pub r9: u64, 189 pub r10: u64, 190 pub r11: u64, 191 pub r12: u64, 192 pub r13: u64, 193 pub r14: u64, 194 pub r15: u64, 195 pub rip: u64, 196 pub rflags: u64, 197 } 198 199 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] 200 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))] 201 pub struct DescriptorTable { 202 pub base: u64, 203 pub limit: u16, 204 } 205 206 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] 207 #[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))] 208 pub struct SpecialRegisters { 209 pub cs: SegmentRegister, 210 pub ds: SegmentRegister, 211 pub es: SegmentRegister, 212 pub fs: SegmentRegister, 213 pub gs: SegmentRegister, 214 pub ss: SegmentRegister, 215 pub tr: SegmentRegister, 216 pub ldt: SegmentRegister, 217 pub gdt: DescriptorTable, 218 pub idt: DescriptorTable, 219 pub cr0: u64, 220 pub cr2: u64, 221 pub cr3: u64, 222 pub cr4: u64, 223 pub cr8: u64, 224 pub efer: u64, 225 pub apic_base: u64, 226 pub interrupt_bitmap: [u64; 4usize], 227 } 228 229 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)] 230 pub struct CpuIdEntry { 231 pub function: u32, 232 pub index: u32, 233 pub flags: u32, 234 pub eax: u32, 235 pub ebx: u32, 236 pub ecx: u32, 237 pub edx: u32, 238 } 239 240 pub const CPUID_FLAG_VALID_INDEX: u32 = 1; 241 242 #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)] 243 pub struct FpuState { 244 pub fpr: [[u8; 16usize]; 8usize], 245 pub fcw: u16, 246 pub fsw: u16, 247 pub ftwx: u8, 248 pub last_opcode: u16, 249 pub last_ip: u64, 250 pub last_dp: u64, 251 pub xmm: [[u8; 16usize]; 16usize], 252 pub mxcsr: u32, 253 } 254 255 #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] 256 pub enum LapicState { 257 #[cfg(feature = "kvm")] 258 Kvm(kvm_bindings::kvm_lapic_state), 259 #[cfg(feature = "mshv")] 260 Mshv(mshv_bindings::LapicState), 261 } 262 263 #[cfg(any(feature = "kvm", feature = "mshv"))] 264 impl LapicState { 265 pub fn get_klapic_reg(&self, reg_offset: usize) -> u32 { 266 use byteorder::{LittleEndian, ReadBytesExt}; 267 use std::io::Cursor; 268 use std::mem; 269 270 let sliceu8 = match self { 271 #[cfg(feature = "kvm")] 272 LapicState::Kvm(s) => 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]>(&s.regs[reg_offset..]) 276 }, 277 #[cfg(feature = "mshv")] 278 LapicState::Mshv(s) => unsafe { 279 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array. 280 // Cursors are only readable on arrays of u8, not i8(c_char). 281 mem::transmute::<&[i8], &[u8]>(&s.regs[reg_offset..]) 282 }, 283 }; 284 285 let mut reader = Cursor::new(sliceu8); 286 // Following call can't fail if the offsets defined above are correct. 287 reader 288 .read_u32::<LittleEndian>() 289 .expect("Failed to read klapic register") 290 } 291 292 pub fn set_klapic_reg(&mut self, reg_offset: usize, value: u32) { 293 use byteorder::{LittleEndian, WriteBytesExt}; 294 use std::io::Cursor; 295 use std::mem; 296 297 let sliceu8 = match self { 298 #[cfg(feature = "kvm")] 299 LapicState::Kvm(s) => unsafe { 300 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array. 301 // Cursors are only readable on arrays of u8, not i8(c_char). 302 mem::transmute::<&mut [i8], &mut [u8]>(&mut s.regs[reg_offset..]) 303 }, 304 #[cfg(feature = "mshv")] 305 LapicState::Mshv(s) => unsafe { 306 // This array is only accessed as parts of a u32 word, so interpret it as a u8 array. 307 // Cursors are only readable on arrays of u8, not i8(c_char). 308 mem::transmute::<&mut [i8], &mut [u8]>(&mut s.regs[reg_offset..]) 309 }, 310 }; 311 312 let mut writer = Cursor::new(sliceu8); 313 // Following call can't fail if the offsets defined above are correct. 314 writer 315 .write_u32::<LittleEndian>(value) 316 .expect("Failed to write klapic register") 317 } 318 } 319 320 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)] 321 pub struct MsrEntry { 322 pub index: u32, 323 pub data: u64, 324 } 325