From 62d241e78ca3c0c15d6231005390e12aaf7016e4 Mon Sep 17 00:00:00 2001 From: Erin Date: Tue, 8 Aug 2023 03:03:15 +0200 Subject: [PATCH] Changed stuff aroud --- hbbytecode/src/lib.rs | 3 +- hbvm/src/{mem => }/bmc.rs | 12 ++- hbvm/src/lib.rs | 75 ++++++++++++++++--- hbvm/src/main.rs | 9 ++- hbvm/src/mem/mod.rs | 54 ------------- hbvm/src/{mem/softpaged => softpaging}/mod.rs | 0 .../{mem/softpaged => softpaging}/paging.rs | 2 + hbvm/src/value.rs | 19 ++++- 8 files changed, 99 insertions(+), 75 deletions(-) rename hbvm/src/{mem => }/bmc.rs (92%) delete mode 100644 hbvm/src/mem/mod.rs rename hbvm/src/{mem/softpaged => softpaging}/mod.rs (100%) rename hbvm/src/{mem/softpaged => softpaging}/paging.rs (97%) diff --git a/hbbytecode/src/lib.rs b/hbbytecode/src/lib.rs index 36c3a370..a1c9862c 100644 --- a/hbbytecode/src/lib.rs +++ b/hbbytecode/src/lib.rs @@ -17,6 +17,7 @@ macro_rules! constmod { }; } +#[allow(rustdoc::invalid_rust_codeblocks)] /// Invoke macro with bytecode definition /// # Input syntax /// ```no_run @@ -31,7 +32,7 @@ macro_rules! constmod { /// - Per-instructions there will be generated opcode-specific functions calling the generic ones /// - Operand types /// - R: Register (u8) -/// - I: Immediate (implements [`crate::Imm`] trait) +/// - I: Immediate /// - L: Memory load / store size (u16) /// - Other types are identity-mapped /// diff --git a/hbvm/src/mem/bmc.rs b/hbvm/src/bmc.rs similarity index 92% rename from hbvm/src/mem/bmc.rs rename to hbvm/src/bmc.rs index 4155ea15..391579f6 100644 --- a/hbvm/src/mem/bmc.rs +++ b/hbvm/src/bmc.rs @@ -1,16 +1,18 @@ +//! Block memory copier state machine + use { - super::MemoryAccessReason, - crate::{mem::Memory, VmRunError}, + super::{Memory, MemoryAccessReason, VmRunError}, core::{mem::MaybeUninit, task::Poll}, }; -// Buffer size (defaults to 4 KiB, a smallest page size on most platforms) +/// Buffer size (defaults to 4 KiB, a smallest page size on most platforms) const BUF_SIZE: usize = 4096; -// This should be equal to `BUF_SIZE` +/// Buffer of possibly uninitialised bytes, aligned to [`BUF_SIZE`] #[repr(align(4096))] struct AlignedBuf([MaybeUninit; BUF_SIZE]); +/// State for block memory copy pub struct BlockCopier { /// Source address src: u64, @@ -23,6 +25,7 @@ pub struct BlockCopier { } impl BlockCopier { + /// Construct a new one #[inline] pub fn new(src: u64, dst: u64, count: usize) -> Self { Self { @@ -93,6 +96,7 @@ impl BlockCopier { } } +/// Load to buffer and store from buffer #[inline] unsafe fn act( memory: &mut impl Memory, diff --git a/hbvm/src/lib.rs b/hbvm/src/lib.rs index ed352300..84447d98 100644 --- a/hbvm/src/lib.rs +++ b/hbvm/src/lib.rs @@ -2,8 +2,8 @@ //! //! # Alloc feature //! - Enabled by default -//! - Provides [`mem::Memory`] mapping / unmapping, as well as -//! [`Default`] and [`Drop`] implementation +//! - Provides mapping / unmapping, as well as [`Default`] and [`Drop`] +//! implementations for soft-paged memory implementation // # General safety notice: // - Validation has to assure there is 256 registers (r0 - r255) @@ -12,26 +12,30 @@ #![no_std] #![cfg_attr(feature = "nightly", feature(fn_align))] +#![warn(missing_docs, clippy::missing_docs_in_private_items)] use core::marker::PhantomData; #[cfg(feature = "alloc")] extern crate alloc; -pub mod mem; +pub mod softpaging; pub mod value; +mod bmc; + use { + bmc::BlockCopier, core::{cmp::Ordering, mem::size_of, ops}, + derive_more::Display, hbbytecode::{ valider, OpParam, ParamBB, ParamBBB, ParamBBBB, ParamBBD, ParamBBDH, ParamBBW, ParamBD, }, - mem::bmc::BlockCopier, value::{Value, ValueVariant}, }; /// HoleyBytes Virtual Machine -pub struct Vm<'a, Memory, const TIMER_QUOTIENT: usize> { +pub struct Vm<'a, Mem, const TIMER_QUOTIENT: usize> { /// Holds 256 registers /// /// Writing to register 0 is considered undefined behaviour @@ -39,7 +43,7 @@ pub struct Vm<'a, Memory, const TIMER_QUOTIENT: usize> { pub registers: [Value; 256], /// Memory implementation - pub memory: Memory, + pub memory: Mem, /// Program counter pub pc: usize, @@ -60,15 +64,15 @@ pub struct Vm<'a, Memory, const TIMER_QUOTIENT: usize> { copier: Option, } -impl<'a, Memory, const TIMER_QUOTIENT: usize> Vm<'a, Memory, TIMER_QUOTIENT> +impl<'a, Mem, const TIMER_QUOTIENT: usize> Vm<'a, Mem, TIMER_QUOTIENT> where - Memory: mem::Memory, + Mem: Memory, { /// Create a new VM with program and trap handler /// /// # Safety /// Program code has to be validated - pub unsafe fn new_unchecked(program: &'a [u8], memory: Memory) -> Self { + pub unsafe fn new_unchecked(program: &'a [u8], memory: Mem) -> Self { Self { registers: [Value::from(0_u64); 256], memory, @@ -82,7 +86,7 @@ where } /// Create a new VM with program and trap handler only if it passes validation - pub fn new_validated(program: &'a [u8], memory: Memory) -> Result { + pub fn new_validated(program: &'a [u8], memory: Mem) -> Result { valider::validate(program)?; Ok(unsafe { Self::new_unchecked(program, memory) }) } @@ -502,3 +506,54 @@ pub enum VmRunOk { /// Environment call Ecall, } + +/// Load-store memory access +pub trait Memory { + /// Load data from memory on address + /// + /// # Safety + /// - Shall not overrun the buffer + unsafe fn load(&mut self, addr: u64, target: *mut u8, count: usize) -> Result<(), LoadError>; + + /// Store data to memory on address + /// + /// # Safety + /// - Shall not overrun the buffer + unsafe fn store( + &mut self, + addr: u64, + source: *const u8, + count: usize, + ) -> Result<(), StoreError>; +} + +/// Unhandled load access trap +#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)] +#[display(fmt = "Load access error at address {_0:#x}")] +pub struct LoadError(pub u64); + +/// Unhandled store access trap +#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)] +#[display(fmt = "Store access error at address {_0:#x}")] +pub struct StoreError(pub u64); + +/// Reason to access memory +#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)] +pub enum MemoryAccessReason { + /// Memory was accessed for load (read) + Load, + /// Memory was accessed for store (write) + Store, +} + +impl From for VmRunError { + fn from(value: LoadError) -> Self { + Self::LoadAccessEx(value.0) + } +} + +impl From for VmRunError { + fn from(value: StoreError) -> Self { + Self::StoreAccessEx(value.0) + } +} diff --git a/hbvm/src/main.rs b/hbvm/src/main.rs index fd46a3e5..05d23c7f 100644 --- a/hbvm/src/main.rs +++ b/hbvm/src/main.rs @@ -1,8 +1,9 @@ -use hbvm::mem::softpaged::{HandlePageFault, PageSize, SoftPagedMem}; - use { hbbytecode::valider::validate, - hbvm::{mem::MemoryAccessReason, Vm}, + hbvm::{ + softpaging::{HandlePageFault, PageSize, SoftPagedMem}, + MemoryAccessReason, Vm, + }, std::io::{stdin, Read}, }; @@ -31,7 +32,7 @@ fn main() -> Result<(), Box> { .map( data, 0, - hbvm::mem::softpaged::paging::Permission::Write, + hbvm::softpaging::paging::Permission::Write, PageSize::Size4K, ) .unwrap(); diff --git a/hbvm/src/mem/mod.rs b/hbvm/src/mem/mod.rs deleted file mode 100644 index 2391a3bf..00000000 --- a/hbvm/src/mem/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Program memory implementation - -pub mod bmc; -pub mod softpaged; - -use {super::VmRunError, derive_more::Display}; - -pub trait Memory { - /// Load data from memory on address - /// - /// # Safety - /// - Shall not overrun the buffer - unsafe fn load(&mut self, addr: u64, target: *mut u8, count: usize) -> Result<(), LoadError>; - - /// Store data to memory on address - /// - /// # Safety - /// - Shall not overrun the buffer - unsafe fn store( - &mut self, - addr: u64, - source: *const u8, - count: usize, - ) -> Result<(), StoreError>; -} - -/// Unhandled load access trap -#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)] -#[display(fmt = "Load access error at address {_0:#x}")] -pub struct LoadError(pub u64); - -/// Unhandled store access trap -#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)] -#[display(fmt = "Store access error at address {_0:#x}")] -pub struct StoreError(pub u64); - -/// Reason to access memory -#[derive(Clone, Copy, Display, Debug, PartialEq, Eq)] -pub enum MemoryAccessReason { - Load, - Store, -} - -impl From for VmRunError { - fn from(value: LoadError) -> Self { - Self::LoadAccessEx(value.0) - } -} - -impl From for VmRunError { - fn from(value: StoreError) -> Self { - Self::StoreAccessEx(value.0) - } -} diff --git a/hbvm/src/mem/softpaged/mod.rs b/hbvm/src/softpaging/mod.rs similarity index 100% rename from hbvm/src/mem/softpaged/mod.rs rename to hbvm/src/softpaging/mod.rs diff --git a/hbvm/src/mem/softpaged/paging.rs b/hbvm/src/softpaging/paging.rs similarity index 97% rename from hbvm/src/mem/softpaged/paging.rs rename to hbvm/src/softpaging/paging.rs index 05511537..c1ab8426 100644 --- a/hbvm/src/mem/softpaged/paging.rs +++ b/hbvm/src/softpaging/paging.rs @@ -59,7 +59,9 @@ impl Debug for PtEntry { #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(align(4096))] pub struct PageTable { + /// How much entries are in use pub childen: u8, + /// Entries pub table: [PtEntry; 256], } diff --git a/hbvm/src/value.rs b/hbvm/src/value.rs index fb8738e3..50d36d1e 100644 --- a/hbvm/src/value.rs +++ b/hbvm/src/value.rs @@ -13,7 +13,10 @@ macro_rules! value_def { #[derive(Copy, Clone)] #[repr(packed)] pub union Value { - $(pub $ty: $ty),* + $( + #[doc = concat!(stringify!($ty), " type")] + pub $ty: $ty + ),* } @@ -37,10 +40,22 @@ macro_rules! value_def { } impl Value { + /// Byte reinterpret value to target variant #[inline] - pub fn cast(self) -> Variant { + pub fn cast(self) -> V { + /// Evil. + /// + /// Transmute cannot be performed with generic type + /// as size is unknown, so union is used. + /// + /// # Safety + /// If [`ValueVariant`] implemented correctly, it's fine :) + /// + /// :ferrisClueless: union Transmute { + /// Self src: Value, + /// Target variant variant: Variant, }