xref: /cloud-hypervisor/hypervisor/src/arch/emulator/mod.rs (revision e5211a6e1d840e76a6cec0fba386977687e08603)
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("Translate virtual address: {0}")]
51     TranslateVirtualAddress(#[source] anyhow::Error),
52 
53     #[error("Unsupported CPU Mode: {0}")]
54     UnsupportedCpuMode(#[source] anyhow::Error),
55 
56     #[error("Invalid instruction operand: {0}")]
57     InvalidOperand(#[source] anyhow::Error),
58 }
59 
60 #[derive(Error, Debug)]
61 pub enum EmulationError<T: Debug> {
62     #[error("Unsupported instruction: {0}")]
63     UnsupportedInstruction(#[source] anyhow::Error),
64 
65     #[error("Unsupported memory size: {0}")]
66     UnsupportedMemorySize(#[source] anyhow::Error),
67 
68     #[error("Invalid operand: {0}")]
69     InvalidOperand(#[source] anyhow::Error),
70 
71     #[error("Wrong number of operands: {0}")]
72     WrongNumberOperands(#[source] anyhow::Error),
73 
74     #[error("Instruction Exception: {0}")]
75     InstructionException(Exception<T>),
76 
77     #[error("Instruction fetching error: {0}")]
78     InstructionFetchingError(#[source] anyhow::Error),
79 
80     #[error("Platform emulation error: {0}")]
81     PlatformEmulationError(PlatformError),
82 
83     #[error(transparent)]
84     EmulationError(#[from] anyhow::Error),
85 }
86 
87 /// The PlatformEmulator trait emulates a guest platform.
88 /// It's mostly a guest resources (memory and CPU state) getter and setter.
89 ///
90 /// A CpuState is an architecture specific type, representing a CPU state.
91 /// The emulator and its instruction handlers modify a given CPU state and
92 /// eventually ask the platform to commit it back through `set_cpu_state`.
93 pub trait PlatformEmulator: Send + Sync {
94     type CpuState: Clone;
95 
96     /// Read guest memory into a u8 slice.
97     ///
98     /// # Arguments
99     ///
100     /// * `gva` - Guest virtual address to read from.
101     /// * `data` - Data slice to read into.
102     ///
103     fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError>;
104 
105     /// Write a u8 slice into guest memory.
106     ///
107     /// # Arguments
108     ///
109     /// * `gva` - Guest virtual address to write into.
110     /// * `data` - Data slice to be written.
111     ///
112     fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError>;
113 
114     /// Get a CPU state from the guest.
115     ///
116     /// # Arguments
117     ///
118     /// * `cpu_id` - Logical CPU ID.
119     ///
120     fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError>;
121 
122     /// Set a guest CPU state.
123     ///
124     /// # Arguments
125     ///
126     /// * `cpu_id` - Logical CPU ID.
127     /// * `state` - State to set the CPU into.
128     ///
129     fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError>;
130 
131     /// Translate a guest virtual address into a physical one
132     ///
133     /// # Arguments
134     ///
135     /// * `gva` - Guest virtual address to translate.
136     ///
137     fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError>;
138 
139     /// Fetch instruction bytes from memory.
140     ///
141     /// # Arguments
142     ///
143     /// * `ip` - Instruction pointer virtual address to start fetching instructions from.
144     ///
145     fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError>;
146 }
147 
148 pub type EmulationResult<S, E> = std::result::Result<S, EmulationError<E>>;
149