mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-01 17:35:19 +00:00
hypervisor: Architecture agnostic instruction emulation interface
In order to emulate instructions, we need a way to get access to some of the guest resources. The PlatformEmulator interface provides guest memory and CPU state access to emulator implementations. Typically, an hypervisor will implement PlatformEmulator for architecture specific instruction emulators to build their framework on top of. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
ae96aeda65
commit
f0360aff83
122
hypervisor/src/arch/emulator/mod.rs
Normal file
122
hypervisor/src/arch/emulator/mod.rs
Normal file
@ -0,0 +1,122 @@
|
||||
//
|
||||
// Copyright © 2020 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
extern crate thiserror;
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum PlatformError {
|
||||
#[error("Invalid register: {0}")]
|
||||
InvalidRegister(#[source] anyhow::Error),
|
||||
|
||||
#[error("Memory read failure: {0}")]
|
||||
MemoryReadFailure(#[source] anyhow::Error),
|
||||
|
||||
#[error("Memory write failure: {0}")]
|
||||
MemoryWriteFailure(#[source] anyhow::Error),
|
||||
|
||||
#[error("Get CPU state failure: {0}")]
|
||||
GetCpuStateFailure(#[source] anyhow::Error),
|
||||
|
||||
#[error("Set CPU state failure: {0}")]
|
||||
SetCpuStateFailure(#[source] anyhow::Error),
|
||||
|
||||
#[error("Unmapped virtual address: {0}")]
|
||||
UnmappedGVA(#[source] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum EmulationError<T: Debug> {
|
||||
#[error("Unsupported instruction: {0}")]
|
||||
UnsupportedInstruction(#[source] anyhow::Error),
|
||||
|
||||
#[error("Unsupported memory size: {0}")]
|
||||
UnsupportedMemorySize(#[source] anyhow::Error),
|
||||
|
||||
#[error("Invalid operand: {0}")]
|
||||
InvalidOperand(#[source] anyhow::Error),
|
||||
|
||||
#[error("Wrong number of operands: {0}")]
|
||||
WrongNumberOperands(#[source] anyhow::Error),
|
||||
|
||||
#[error("Instruction Exception: {0}")]
|
||||
InstructionException(Exception<T>),
|
||||
|
||||
#[error("Platform emulation error: {0}")]
|
||||
PlatformEmulationError(PlatformError),
|
||||
}
|
||||
|
||||
/// 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: Send + Sync {
|
||||
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>;
|
||||
|
||||
/// Translate a guest virtual address into a physical one
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `gva` - Guest virtual address to translate.
|
||||
///
|
||||
fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError>;
|
||||
}
|
||||
|
||||
pub type EmulationResult<S, E> = std::result::Result<S, EmulationError<E>>;
|
@ -11,5 +11,7 @@
|
||||
// Copyright © 2020, Microsoft Corporation
|
||||
//
|
||||
|
||||
pub mod emulator;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod x86;
|
||||
|
Loading…
x
Reference in New Issue
Block a user