funny thing

soft-float
Erin 2023-11-15 19:03:56 +01:00
parent b8432d544c
commit b84ff70014
10 changed files with 108 additions and 85 deletions

View File

@ -43,17 +43,19 @@ impl BlockCopier {
/// - Same as for [`Memory::load`] and [`Memory::store`] /// - Same as for [`Memory::load`] and [`Memory::store`]
pub unsafe fn poll(&mut self, memory: &mut impl Memory) -> Poll<Result<(), BlkCopyError>> { pub unsafe fn poll(&mut self, memory: &mut impl Memory) -> Poll<Result<(), BlkCopyError>> {
// Safety: Assuming uninit of array of MaybeUninit is sound // Safety: Assuming uninit of array of MaybeUninit is sound
let mut buf = AlignedBuf(MaybeUninit::uninit().assume_init()); let mut buf = AlignedBuf(unsafe { MaybeUninit::uninit().assume_init() });
// We have at least one buffer size to copy // We have at least one buffer size to copy
if self.n_buffers != 0 { if self.n_buffers != 0 {
if let Err(e) = act( if let Err(e) = unsafe {
memory, act(
self.src, memory,
self.dst, self.src,
buf.0.as_mut_ptr().cast(), self.dst,
BUF_SIZE, buf.0.as_mut_ptr().cast(),
) { BUF_SIZE,
)
} {
return Poll::Ready(Err(e)); return Poll::Ready(Err(e));
} }
@ -73,13 +75,15 @@ impl BlockCopier {
} }
if self.rem != 0 { if self.rem != 0 {
if let Err(e) = act( if let Err(e) = unsafe {
memory, act(
self.src, memory,
self.dst, self.src,
buf.0.as_mut_ptr().cast(), self.dst,
self.rem, buf.0.as_mut_ptr().cast(),
) { self.rem,
)
} {
return Poll::Ready(Err(e)); return Poll::Ready(Err(e));
} }
} }
@ -97,21 +101,23 @@ unsafe fn act(
buf: *mut u8, buf: *mut u8,
count: usize, count: usize,
) -> Result<(), BlkCopyError> { ) -> Result<(), BlkCopyError> {
// Load to buffer unsafe {
memory // Load to buffer
.load(src, buf, count) memory
.map_err(|super::mem::LoadError(addr)| BlkCopyError { .load(src, buf, count)
access_reason: MemoryAccessReason::Load, .map_err(|super::mem::LoadError(addr)| BlkCopyError {
addr, access_reason: MemoryAccessReason::Load,
})?; addr,
})?;
// Store from buffer // Store from buffer
memory memory
.store(dst, buf, count) .store(dst, buf, count)
.map_err(|super::mem::StoreError(addr)| BlkCopyError { .map_err(|super::mem::StoreError(addr)| BlkCopyError {
access_reason: MemoryAccessReason::Store, access_reason: MemoryAccessReason::Store,
addr, addr,
})?; })?;
}
Ok(()) Ok(())
} }

View File

@ -46,7 +46,7 @@ unsafe fn set_rounding_mode(mode: RoundingMode) {
} }
let fpcr: u64; let fpcr: u64;
asm!("mrs {}, fpcr", out(reg) fpcr); unsafe { asm!("mrs {}, fpcr", out(reg) fpcr) };
let fpcr = fpcr & !(0b11 << 22) let fpcr = fpcr & !(0b11 << 22)
| (match mode { | (match mode {
@ -56,7 +56,7 @@ unsafe fn set_rounding_mode(mode: RoundingMode) {
RoundingMode::Down => 0b10, RoundingMode::Down => 0b10,
}) << 22; }) << 22;
asm!("msr fpcr, {}", in(reg) fpcr); unsafe { asm!("msr fpcr, {}", in(reg) fpcr) };
} }
#[inline(always)] #[inline(always)]

View File

@ -56,12 +56,14 @@ fnsdef! {
/// [`default_rounding_mode`], you have to rely on inline assembly /// [`default_rounding_mode`], you have to rely on inline assembly
#[inline(always)] #[inline(always)]
unsafe fn set_rounding_mode(mode: RoundingMode) { unsafe fn set_rounding_mode(mode: RoundingMode) {
arin::_MM_SET_ROUNDING_MODE(match mode { unsafe {
RoundingMode::NearestEven => return, arin::_MM_SET_ROUNDING_MODE(match mode {
RoundingMode::Truncate => arin::_MM_ROUND_TOWARD_ZERO, RoundingMode::NearestEven => return,
RoundingMode::Up => arin::_MM_ROUND_UP, RoundingMode::Truncate => arin::_MM_ROUND_TOWARD_ZERO,
RoundingMode::Down => arin::_MM_ROUND_DOWN, RoundingMode::Up => arin::_MM_ROUND_UP,
}) RoundingMode::Down => arin::_MM_ROUND_DOWN,
})
}
} }
#[inline(always)] #[inline(always)]

View File

@ -12,6 +12,7 @@
#![no_std] #![no_std]
#![cfg_attr(feature = "nightly", feature(fn_align))] #![cfg_attr(feature = "nightly", feature(fn_align))]
#![deny(unsafe_op_in_unsafe_fn)]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;

View File

@ -48,14 +48,14 @@ impl ICache {
let pbase = self let pbase = self
.data .data
.or_else(|| self.fetch_page(self.base + self.size, root_pt))?; .or_else(|| unsafe { self.fetch_page(self.base + self.size, root_pt) })?;
// Get address base // Get address base
let base = addr.map(|x| x & self.mask); let base = addr.map(|x| x & self.mask);
// Base not matching, fetch anew // Base not matching, fetch anew
if base != self.base { if base != self.base {
self.fetch_page(base, root_pt)?; unsafe { self.fetch_page(base, root_pt) }?;
}; };
let offset = addr.get() & !self.mask; let offset = addr.get() & !self.mask;
@ -68,25 +68,27 @@ impl ICache {
let first_copy = requ_size.saturating_sub(rem); let first_copy = requ_size.saturating_sub(rem);
// Copy non-overflowing part // Copy non-overflowing part
copy_nonoverlapping(pbase.as_ptr(), ret.as_mut_ptr().cast::<u8>(), first_copy); unsafe { copy_nonoverlapping(pbase.as_ptr(), ret.as_mut_ptr().cast::<u8>(), first_copy) };
// Copy overflow // Copy overflow
if rem != 0 { if rem != 0 {
let pbase = self.fetch_page(self.base + self.size, root_pt)?; let pbase = unsafe { self.fetch_page(self.base + self.size, root_pt) }?;
// Unlikely, unsupported scenario // Unlikely, unsupported scenario
if rem > self.size as _ { if rem > self.size as _ {
return None; return None;
} }
copy_nonoverlapping( unsafe {
pbase.as_ptr(), copy_nonoverlapping(
ret.as_mut_ptr().cast::<u8>().add(first_copy), pbase.as_ptr(),
rem, ret.as_mut_ptr().cast::<u8>().add(first_copy),
); rem,
)
};
} }
Some(ret.assume_init()) Some(unsafe { ret.assume_init() })
} }
/// Fetch a page /// Fetch a page

View File

@ -36,9 +36,11 @@ impl<'p, A, const OUT_PROG_EXEC: bool> SoftPagedMem<'p, A, OUT_PROG_EXEC> {
// Walk pagetable levels // Walk pagetable levels
for lvl in (lookup_depth + 1..5).rev() { for lvl in (lookup_depth + 1..5).rev() {
let entry = (*current_pt) let entry = unsafe {
.table (*current_pt)
.get_unchecked_mut(addr_extract_index(target, lvl)); .table
.get_unchecked_mut(addr_extract_index(target, lvl))
};
let ptr = entry.ptr(); let ptr = entry.ptr();
match entry.permission() { match entry.permission() {
@ -46,13 +48,13 @@ impl<'p, A, const OUT_PROG_EXEC: bool> SoftPagedMem<'p, A, OUT_PROG_EXEC> {
// No worries! Let's create one (allocates). // No worries! Let's create one (allocates).
Permission::Empty => { Permission::Empty => {
// Increase children count // Increase children count
(*current_pt).childen += 1; unsafe { *current_pt }.childen += 1;
let table = Box::into_raw(Box::new(PtPointedData { let table = Box::into_raw(Box::new(PtPointedData {
pt: PageTable::default(), pt: PageTable::default(),
})); }));
core::ptr::write(entry, PtEntry::new(table, Permission::Node)); unsafe { core::ptr::write(entry, PtEntry::new(table, Permission::Node)) };
current_pt = table as _; current_pt = table as _;
} }
// Continue walking // Continue walking
@ -63,9 +65,11 @@ impl<'p, A, const OUT_PROG_EXEC: bool> SoftPagedMem<'p, A, OUT_PROG_EXEC> {
} }
} }
let node = (*current_pt) let node = unsafe {
.table (*current_pt)
.get_unchecked_mut(addr_extract_index(target, lookup_depth)); .table
.get_unchecked_mut(addr_extract_index(target, lookup_depth))
};
// Check if node is not mapped // Check if node is not mapped
if node.permission() != Permission::Empty { if node.permission() != Permission::Empty {
@ -73,8 +77,10 @@ impl<'p, A, const OUT_PROG_EXEC: bool> SoftPagedMem<'p, A, OUT_PROG_EXEC> {
} }
// Write entry // Write entry
(*current_pt).childen += 1; unsafe {
core::ptr::write(node, PtEntry::new(host.cast(), perm)); (*current_pt).childen += 1;
core::ptr::write(node, PtEntry::new(host.cast(), perm));
}
Ok(()) Ok(())
} }

View File

@ -51,7 +51,7 @@ impl<'p, PfH: HandlePageFault, const OUT_PROG_EXEC: bool> Memory
target, target,
count, count,
perm_check::readable, perm_check::readable,
|src, dst, count| core::ptr::copy_nonoverlapping(src, dst, count), |src, dst, count| unsafe { core::ptr::copy_nonoverlapping(src, dst, count) },
) )
.map_err(LoadError) .map_err(LoadError)
} }
@ -72,7 +72,7 @@ impl<'p, PfH: HandlePageFault, const OUT_PROG_EXEC: bool> Memory
source.cast_mut(), source.cast_mut(),
count, count,
perm_check::writable, perm_check::writable,
|dst, src, count| core::ptr::copy_nonoverlapping(src, dst, count), |dst, src, count| unsafe { core::ptr::copy_nonoverlapping(src, dst, count) },
) )
.map_err(StoreError) .map_err(StoreError)
} }
@ -80,16 +80,14 @@ impl<'p, PfH: HandlePageFault, const OUT_PROG_EXEC: bool> Memory
#[inline(always)] #[inline(always)]
unsafe fn prog_read<T>(&mut self, addr: Address) -> T { unsafe fn prog_read<T>(&mut self, addr: Address) -> T {
if OUT_PROG_EXEC && addr.truncate_usize() > self.program.len() { if OUT_PROG_EXEC && addr.truncate_usize() > self.program.len() {
return self return unsafe { self.icache.fetch::<T>(addr, self.root_pt) }
.icache
.fetch::<T>(addr, self.root_pt)
.unwrap_or_else(|| unsafe { core::mem::zeroed() }); .unwrap_or_else(|| unsafe { core::mem::zeroed() });
} }
let addr = addr.truncate_usize(); let addr = addr.truncate_usize();
self.program self.program
.get(addr..addr + size_of::<T>()) .get(addr..addr + size_of::<T>())
.map(|x| x.as_ptr().cast::<T>().read()) .map(|x| unsafe { x.as_ptr().cast::<T>().read() })
.unwrap_or_else(|| unsafe { core::mem::zeroed() }) .unwrap_or_else(|| unsafe { core::mem::zeroed() })
} }
} }

View File

@ -17,7 +17,8 @@ use {
macro_rules! handler { macro_rules! handler {
($self:expr, |$ty:ident ($($ident:pat),* $(,)?)| $expr:expr) => {{ ($self:expr, |$ty:ident ($($ident:pat),* $(,)?)| $expr:expr) => {{
let $ty($($ident),*) = $self.decode::<$ty>(); #[allow(unused_unsafe)]
let $ty($($ident),*) = unsafe { $self.decode::<$ty>() };
#[allow(clippy::no_effect)] let e = $expr; #[allow(clippy::no_effect)] let e = $expr;
$self.bump_pc::<$ty>(); $self.bump_pc::<$ty>();
e e
@ -383,7 +384,7 @@ where
/// Decode instruction operands /// Decode instruction operands
#[inline(always)] #[inline(always)]
unsafe fn decode<T: Copy>(&mut self) -> T { unsafe fn decode<T: Copy>(&mut self) -> T {
self.memory.prog_read::<T>(self.pc + 1_u64) unsafe { self.memory.prog_read::<T>(self.pc + 1_u64) }
} }
/// Load /// Load
@ -400,14 +401,16 @@ where
_ => 0, _ => 0,
}; };
self.memory.load( unsafe {
self.ldst_addr_uber(dst, base, offset, count, n)?, self.memory.load(
self.registers self.ldst_addr_uber(dst, base, offset, count, n)?,
.as_mut_ptr() self.registers
.add(usize::from(dst) + usize::from(n)) .as_mut_ptr()
.cast(), .add(usize::from(dst) + usize::from(n))
usize::from(count).saturating_sub(n.into()), .cast(),
)?; usize::from(count).saturating_sub(n.into()),
)
}?;
Ok(()) Ok(())
} }
@ -421,11 +424,13 @@ where
offset: u64, offset: u64,
count: u16, count: u16,
) -> Result<(), VmRunError> { ) -> Result<(), VmRunError> {
self.memory.store( unsafe {
self.ldst_addr_uber(dst, base, offset, count, 0)?, self.memory.store(
self.registers.as_ptr().add(usize::from(dst)).cast(), self.ldst_addr_uber(dst, base, offset, count, 0)?,
count.into(), self.registers.as_ptr().add(usize::from(dst)).cast(),
)?; count.into(),
)
}?;
Ok(()) Ok(())
} }
@ -438,7 +443,7 @@ where
/// Perform binary operating over two registers /// Perform binary operating over two registers
#[inline(always)] #[inline(always)]
unsafe fn binary_op<T: ValueVariant>(&mut self, op: impl Fn(T, T) -> T) { unsafe fn binary_op<T: ValueVariant>(&mut self, op: impl Fn(T, T) -> T) {
let OpsRRR(tg, a0, a1) = self.decode(); let OpsRRR(tg, a0, a1) = unsafe { self.decode() };
self.write_reg( self.write_reg(
tg, tg,
op(self.read_reg(a0).cast::<T>(), self.read_reg(a1).cast::<T>()), op(self.read_reg(a0).cast::<T>(), self.read_reg(a1).cast::<T>()),
@ -453,7 +458,7 @@ where
#[repr(packed)] #[repr(packed)]
struct OpsRRImm<I>(OpsRR, I); struct OpsRRImm<I>(OpsRR, I);
let OpsRRImm::<T>(OpsRR(tg, reg), imm) = self.decode(); let OpsRRImm::<T>(OpsRR(tg, reg), imm) = unsafe { self.decode() };
self.write_reg(tg, op(self.read_reg(reg).cast::<T>(), imm)); self.write_reg(tg, op(self.read_reg(reg).cast::<T>(), imm));
self.bump_pc::<OpsRRImm<T>>(); self.bump_pc::<OpsRRImm<T>>();
} }
@ -461,7 +466,7 @@ where
/// Perform binary operation over register and shift immediate /// Perform binary operation over register and shift immediate
#[inline(always)] #[inline(always)]
unsafe fn binary_op_shift<T: ValueVariant>(&mut self, op: impl Fn(T, u32) -> T) { unsafe fn binary_op_shift<T: ValueVariant>(&mut self, op: impl Fn(T, u32) -> T) {
let OpsRRR(tg, a0, a1) = self.decode(); let OpsRRR(tg, a0, a1) = unsafe { self.decode() };
self.write_reg( self.write_reg(
tg, tg,
op( op(
@ -475,7 +480,7 @@ where
/// Perform binary operation over register and shift immediate /// Perform binary operation over register and shift immediate
#[inline(always)] #[inline(always)]
unsafe fn binary_op_ims<T: ValueVariant>(&mut self, op: impl Fn(T, u32) -> T) { unsafe fn binary_op_ims<T: ValueVariant>(&mut self, op: impl Fn(T, u32) -> T) {
let OpsRRB(tg, reg, imm) = self.decode(); let OpsRRB(tg, reg, imm) = unsafe { self.decode() };
self.write_reg(tg, op(self.read_reg(reg).cast::<T>(), imm.into())); self.write_reg(tg, op(self.read_reg(reg).cast::<T>(), imm.into()));
self.bump_pc::<OpsRRW>(); self.bump_pc::<OpsRRW>();
} }
@ -534,7 +539,7 @@ where
/// Jump at `PC + #3` if ordering on `#0 <=> #1` is equal to expected /// Jump at `PC + #3` if ordering on `#0 <=> #1` is equal to expected
#[inline(always)] #[inline(always)]
unsafe fn cond_jmp<T: ValueVariant + Ord>(&mut self, expected: Ordering) { unsafe fn cond_jmp<T: ValueVariant + Ord>(&mut self, expected: Ordering) {
let OpsRRP(a0, a1, ja) = self.decode(); let OpsRRP(a0, a1, ja) = unsafe { self.decode() };
if self if self
.read_reg(a0) .read_reg(a0)
.cast::<T>() .cast::<T>()

View File

@ -1,4 +1,7 @@
//! Holey Bytes Experimental Runtime //! Holey Bytes Experimental Runtime
#![deny(unsafe_op_in_unsafe_fn)]
mod mem; mod mem;
use { use {
@ -32,7 +35,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("[I] Image loaded at {ptr:p}"); eprintln!("[I] Image loaded at {ptr:p}");
// Execute program
let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) }; let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) };
// Memory access fault handling // Memory access fault handling
@ -60,6 +62,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
)?; )?;
} }
// Execute program
let stat = loop { let stat = loop {
match vm.run() { match vm.run() {
Ok(VmRunOk::Breakpoint) => eprintln!( Ok(VmRunOk::Breakpoint) => eprintln!(

View File

@ -26,6 +26,6 @@ impl Memory for HostMemory {
#[inline] #[inline]
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T { unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
core::ptr::read(addr.get() as *const T) unsafe { core::ptr::read(addr.get() as *const T) }
} }
} }