mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de> On-behalf-of: SAP philipp.schuster@sap.com
151 lines
4.1 KiB
Rust
151 lines
4.1 KiB
Rust
//
|
|
// Copyright © 2020 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
use core::fmt::Debug;
|
|
use std::fmt::{self, Display};
|
|
|
|
use thiserror::Error;
|
|
|
|
#[derive(Clone, Copy, Error, Debug)]
|
|
pub struct Exception<T: Debug> {
|
|
vector: T,
|
|
ip: u64,
|
|
error: Option<u32>,
|
|
payload: Option<u64>,
|
|
}
|
|
|
|
impl<T: Debug> Display for Exception<T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"Exception {:?} at IP {:#x}{}{}",
|
|
self.vector,
|
|
self.ip,
|
|
self.error
|
|
.map(|e| format!(": error {e:x}"))
|
|
.unwrap_or_default(),
|
|
self.payload
|
|
.map(|payload| format!(": payload {payload:x}"))
|
|
.unwrap_or_default()
|
|
)
|
|
}
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum PlatformError {
|
|
#[error("Invalid address")]
|
|
InvalidAddress(#[source] anyhow::Error),
|
|
|
|
#[error("Invalid register")]
|
|
InvalidRegister(#[source] anyhow::Error),
|
|
|
|
#[error("Invalid state")]
|
|
InvalidState(#[source] anyhow::Error),
|
|
|
|
#[error("Memory read failure")]
|
|
MemoryReadFailure(#[source] anyhow::Error),
|
|
|
|
#[error("Memory write failure")]
|
|
MemoryWriteFailure(#[source] anyhow::Error),
|
|
|
|
#[error("Get CPU state failure")]
|
|
GetCpuStateFailure(#[source] anyhow::Error),
|
|
|
|
#[error("Set CPU state failure")]
|
|
SetCpuStateFailure(#[source] anyhow::Error),
|
|
|
|
#[error("Translate virtual address")]
|
|
TranslateVirtualAddress(#[source] anyhow::Error),
|
|
|
|
#[error("Unsupported CPU Mode")]
|
|
UnsupportedCpuMode(#[source] anyhow::Error),
|
|
|
|
#[error("Invalid instruction operand")]
|
|
InvalidOperand(#[source] anyhow::Error),
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum EmulationError<T: Debug> {
|
|
#[error("Unsupported instruction")]
|
|
UnsupportedInstruction(#[source] anyhow::Error),
|
|
|
|
#[error("Unsupported memory size")]
|
|
UnsupportedMemorySize(#[source] anyhow::Error),
|
|
|
|
#[error("Invalid operand")]
|
|
InvalidOperand(#[source] anyhow::Error),
|
|
|
|
#[error("Wrong number of operands")]
|
|
WrongNumberOperands(#[source] anyhow::Error),
|
|
|
|
#[error("Instruction Exception")]
|
|
InstructionException(#[source] Exception<T>),
|
|
|
|
#[error("Instruction fetching error")]
|
|
InstructionFetchingError(#[source] anyhow::Error),
|
|
|
|
#[error("Platform emulation error")]
|
|
PlatformEmulationError(#[source] PlatformError),
|
|
|
|
#[error(transparent)]
|
|
EmulationError(#[from] anyhow::Error),
|
|
}
|
|
|
|
/// The PlatformEmulator trait emulates a guest platform.
|
|
/// It's mostly a guest resources (memory and CPU state) getter and setter.
|
|
///
|
|
/// A CpuState is an architecture specific type, representing a CPU state.
|
|
/// The emulator and its instruction handlers modify a given CPU state and
|
|
/// eventually ask the platform to commit it back through `set_cpu_state`.
|
|
pub trait PlatformEmulator {
|
|
type CpuState: Clone;
|
|
|
|
/// Read guest memory into a u8 slice.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `gva` - Guest virtual address to read from.
|
|
/// * `data` - Data slice to read into.
|
|
///
|
|
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError>;
|
|
|
|
/// Write a u8 slice into guest memory.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `gva` - Guest virtual address to write into.
|
|
/// * `data` - Data slice to be written.
|
|
///
|
|
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError>;
|
|
|
|
/// Get a CPU state from the guest.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `cpu_id` - Logical CPU ID.
|
|
///
|
|
fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError>;
|
|
|
|
/// Set a guest CPU state.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `cpu_id` - Logical CPU ID.
|
|
/// * `state` - State to set the CPU into.
|
|
///
|
|
fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError>;
|
|
|
|
/// Fetch instruction bytes from memory.
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `ip` - Instruction pointer virtual address to start fetching instructions from.
|
|
///
|
|
fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError>;
|
|
}
|
|
|
|
pub type EmulationResult<S, E> = std::result::Result<S, EmulationError<E>>;
|