1 // 2 // Copyright © 2020 Intel Corporation 3 // 4 // SPDX-License-Identifier: Apache-2.0 5 // 6 7 extern crate thiserror; 8 9 use core::fmt::Debug; 10 use std::fmt::{self, Display}; 11 use thiserror::Error; 12 13 #[derive(Clone, Copy, Error, Debug)] 14 pub struct Exception<T: Debug> { 15 vector: T, 16 ip: u64, 17 error: Option<u32>, 18 payload: Option<u64>, 19 } 20 21 impl<T: Debug> Display for Exception<T> { 22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 23 write!(f, "Exception {:?} at IP {:#x}", self.vector, self.ip) 24 } 25 } 26 27 #[derive(Error, Debug)] 28 pub enum PlatformError { 29 #[error("Invalid address: {0}")] 30 InvalidAddress(#[source] anyhow::Error), 31 32 #[error("Invalid register: {0}")] 33 InvalidRegister(#[source] anyhow::Error), 34 35 #[error("Invalid state: {0}")] 36 InvalidState(#[source] anyhow::Error), 37 38 #[error("Memory read failure: {0}")] 39 MemoryReadFailure(#[source] anyhow::Error), 40 41 #[error("Memory write failure: {0}")] 42 MemoryWriteFailure(#[source] anyhow::Error), 43 44 #[error("Get CPU state failure: {0}")] 45 GetCpuStateFailure(#[source] anyhow::Error), 46 47 #[error("Set CPU state failure: {0}")] 48 SetCpuStateFailure(#[source] anyhow::Error), 49 50 #[error("Unmapped virtual address: {0}")] 51 UnmappedGVA(#[source] anyhow::Error), 52 53 #[error("Unsupported CPU Mode: {0}")] 54 UnsupportedCpuMode(#[source] anyhow::Error), 55 } 56 57 #[derive(Error, Debug)] 58 pub enum EmulationError<T: Debug> { 59 #[error("Unsupported instruction: {0}")] 60 UnsupportedInstruction(#[source] anyhow::Error), 61 62 #[error("Unsupported memory size: {0}")] 63 UnsupportedMemorySize(#[source] anyhow::Error), 64 65 #[error("Invalid operand: {0}")] 66 InvalidOperand(#[source] anyhow::Error), 67 68 #[error("Wrong number of operands: {0}")] 69 WrongNumberOperands(#[source] anyhow::Error), 70 71 #[error("Instruction Exception: {0}")] 72 InstructionException(Exception<T>), 73 74 #[error("Instruction fetching error: {0}")] 75 InstructionFetchingError(#[source] anyhow::Error), 76 77 #[error("Platform emulation error: {0}")] 78 PlatformEmulationError(PlatformError), 79 } 80 81 /// The PlatformEmulator trait emulates a guest platform. 82 /// It's mostly a guest resources (memory and CPU state) getter and setter. 83 /// 84 /// A CpuState is an architecture specific type, representing a CPU state. 85 /// The emulator and its instruction handlers modify a given CPU state and 86 /// eventually ask the platform to commit it back through `set_cpu_state`. 87 pub trait PlatformEmulator: Send + Sync { 88 type CpuState: Clone; 89 90 /// Read guest memory into a u8 slice. 91 /// 92 /// # Arguments 93 /// 94 /// * `gva` - Guest virtual address to read from. 95 /// * `data` - Data slice to read into. 96 /// 97 fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError>; 98 99 /// Write a u8 slice into guest memory. 100 /// 101 /// # Arguments 102 /// 103 /// * `gva` - Guest virtual address to write into. 104 /// * `data` - Data slice to be written. 105 /// 106 fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError>; 107 108 /// Get a CPU state from the guest. 109 /// 110 /// # Arguments 111 /// 112 /// * `cpu_id` - Logical CPU ID. 113 /// 114 fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError>; 115 116 /// Set a guest CPU state. 117 /// 118 /// # Arguments 119 /// 120 /// * `cpu_id` - Logical CPU ID. 121 /// * `state` - State to set the CPU into. 122 /// 123 fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError>; 124 125 /// Translate a guest virtual address into a physical one 126 /// 127 /// # Arguments 128 /// 129 /// * `gva` - Guest virtual address to translate. 130 /// 131 fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError>; 132 133 /// Fetch instruction bytes from memory. 134 /// 135 /// # Arguments 136 /// 137 /// * `ip` - Instruction pointer virtual address to start fetching instructions from. 138 /// 139 fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError>; 140 } 141 142 pub type EmulationResult<S, E> = std::result::Result<S, EmulationError<E>>; 143