feature/trap-handlers
ondra05 2023-06-25 00:15:55 +02:00
parent f2577f9a2c
commit 9203ea409e
No known key found for this signature in database
GPG Key ID: 0DA6D2BB2285E881
3 changed files with 39 additions and 20 deletions

View File

@ -1,5 +1,5 @@
use hbvm::vm::{
mem::{Memory, PageSize},
mem::{Memory, MemoryAccessReason, PageSize},
trap::HandleTrap,
value::Value,
};
@ -33,7 +33,14 @@ pub fn time() -> u32 {
struct TestTrapHandler;
impl HandleTrap for TestTrapHandler {
fn page_fault(&mut self, _: &mut Memory, _: u64, _: PageSize, _: *mut u8) -> bool {
fn page_fault(
&mut self,
_: MemoryAccessReason,
_: &mut Memory,
_: u64,
_: PageSize,
_: *mut u8,
) -> bool {
false
}

View File

@ -69,6 +69,7 @@ impl Memory {
traph: &mut impl HandleTrap,
) -> Result<(), LoadError> {
self.memory_access(
MemoryAccessReason::Load,
addr,
target,
count,
@ -96,6 +97,7 @@ impl Memory {
traph: &mut impl HandleTrap,
) -> Result<(), StoreError> {
self.memory_access(
MemoryAccessReason::Store,
addr,
source.cast_mut(),
count,
@ -118,7 +120,7 @@ impl Memory {
dst: u64,
count: usize,
traph: &mut impl HandleTrap,
) -> Result<(), BlkCopyError> {
) -> Result<(), MemoryAccessReason> {
// Yea, i know it is possible to do this more efficiently, but I am too lazy.
const STACK_BUFFER_SIZE: usize = 512;
@ -144,6 +146,7 @@ impl Memory {
let status = (|| {
// Load to buffer
self.memory_access(
MemoryAccessReason::Load,
src,
buf,
count,
@ -156,10 +159,11 @@ impl Memory {
|src, dst, count| core::ptr::copy(src, dst, count),
traph,
)
.map_err(|_| BlkCopyError::Load)?;
.map_err(|_| MemoryAccessReason::Load)?;
// Store from buffer
self.memory_access(
MemoryAccessReason::Store,
dst,
buf,
count,
@ -167,9 +171,9 @@ impl Memory {
|dst, src, count| core::ptr::copy(src, dst, count),
traph,
)
.map_err(|_| BlkCopyError::Store)?;
.map_err(|_| MemoryAccessReason::Store)?;
Ok::<_, BlkCopyError>(())
Ok::<_, MemoryAccessReason>(())
})();
// Deallocate if used heap-allocated array
@ -187,8 +191,10 @@ impl Memory {
/// to a specified function.
///
/// If page is not found, execute page fault trap handler.
#[allow(clippy::too_many_arguments)] // Silence peasant
fn memory_access(
&mut self,
reason: MemoryAccessReason,
src: u64,
mut dst: *mut u8,
len: usize,
@ -211,7 +217,7 @@ impl Memory {
}
Some(Err(AddrSplitError { addr, size })) => {
// Execute page fault handler
if traph.page_fault(self, addr, size, dst) {
if traph.page_fault(reason, self, addr, size, dst) {
// Shift the splitter address
pspl.bump(size);
@ -372,13 +378,21 @@ pub struct LoadError;
#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)]
pub struct StoreError;
/// Unhandled block transfer trap
#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)]
pub enum BlkCopyError {
pub enum MemoryAccessReason {
Load,
Store,
}
impl From<MemoryAccessReason> for VmRunError {
fn from(value: MemoryAccessReason) -> Self {
match value {
MemoryAccessReason::Load => Self::LoadAccessEx,
MemoryAccessReason::Store => Self::StoreAccessEx,
}
}
}
impl From<LoadError> for VmRunError {
fn from(_: LoadError) -> Self {
Self::LoadAccessEx
@ -390,12 +404,3 @@ impl From<StoreError> for VmRunError {
Self::StoreAccessEx
}
}
impl From<BlkCopyError> for VmRunError {
fn from(value: BlkCopyError) -> Self {
match value {
BlkCopyError::Load => Self::LoadAccessEx,
BlkCopyError::Store => Self::StoreAccessEx,
}
}
}

View File

@ -1,12 +1,19 @@
use super::{
mem::{Memory, PageSize},
mem::{Memory, MemoryAccessReason, PageSize},
value::Value,
};
/// Handle VM traps
pub trait HandleTrap {
/// Handle page fault
fn page_fault(&mut self, memory: &mut Memory, addr: u64, size: PageSize, dst: *mut u8) -> bool;
fn page_fault(
&mut self,
reason: MemoryAccessReason,
memory: &mut Memory,
vaddr: u64,
size: PageSize,
dataptr: *mut u8,
) -> bool;
/// Handle invalid opcode exception
fn invalid_op(