1
0
Fork 0
forked from koniifer/ableos

Zero alloc BMC!

This commit is contained in:
Erin 2023-07-22 01:03:09 +02:00
parent 1a53c80a62
commit ec7053a289

View file

@ -220,40 +220,28 @@ impl Memory {
/// - Addr-san claims it's fine but who knows is she isn't lying :ferrisSus: /// - Addr-san claims it's fine but who knows is she isn't lying :ferrisSus:
pub unsafe fn block_copy( pub unsafe fn block_copy(
&mut self, &mut self,
src: u64, mut src: u64,
dst: u64, mut dst: u64,
count: usize, count: usize,
traph: &mut impl HandlePageFault, traph: &mut impl HandlePageFault,
) -> Result<(), BlkCopyError> { ) -> Result<(), BlkCopyError> {
// Yea, i know it is possible to do this more efficiently, but I am too lazy. // Yea, i know it is possible to do this more efficiently, but I am too lazy.
const STACK_BUFFER_SIZE: usize = 512; impl Memory {
#[inline]
// Decide if to use stack-allocated buffer or to heap allocate unsafe fn act(
// Deallocation is again decided on size at the end of the function &mut self,
let mut buf = MaybeUninit::<[u8; STACK_BUFFER_SIZE]>::uninit(); src: u64,
let buf = if count <= STACK_BUFFER_SIZE { dst: u64,
buf.as_mut_ptr().cast() buf: *mut u8,
} else { count: usize,
unsafe { traph: &mut impl HandlePageFault,
let layout = core::alloc::Layout::from_size_align_unchecked(count, 1); ) -> Result<(), BlkCopyError> {
let ptr = alloc::alloc::alloc(layout);
if ptr.is_null() {
alloc::alloc::handle_alloc_error(layout);
}
ptr
}
};
// Perform memory block transfer
let status = (|| {
// Load to buffer
self.memory_access( self.memory_access(
MemoryAccessReason::Load, MemoryAccessReason::Load,
src, src,
buf, buf,
count, STACK_BUFFER_SIZE,
|perm| { |perm| {
matches!( matches!(
perm, perm,
@ -268,7 +256,6 @@ impl Memory {
addr, addr,
})?; })?;
// Store from buffer
self.memory_access( self.memory_access(
MemoryAccessReason::Store, MemoryAccessReason::Store,
dst, dst,
@ -283,18 +270,26 @@ impl Memory {
addr, addr,
})?; })?;
Ok::<_, BlkCopyError>(()) Ok(())
})(); }
// Deallocate if used heap-allocated array
if count > STACK_BUFFER_SIZE {
alloc::alloc::dealloc(
buf,
core::alloc::Layout::from_size_align_unchecked(count, 1),
);
} }
status const STACK_BUFFER_SIZE: usize = 4096;
// Decide if to use stack-allocated buffer or to heap allocate
// Deallocation is again decided on size at the end of the function
let mut buf = MaybeUninit::<[u8; STACK_BUFFER_SIZE]>::uninit();
let n_buffers = count / STACK_BUFFER_SIZE;
let rem = count % STACK_BUFFER_SIZE;
for _ in 0..n_buffers {
self.act(src, dst, buf.as_mut_ptr().cast(), STACK_BUFFER_SIZE, traph)?;
src += STACK_BUFFER_SIZE as u64;
dst += STACK_BUFFER_SIZE as u64;
}
self.act(src, dst, buf.as_mut_ptr().cast(), rem, traph)
} }
/// Split address to pages, check their permissions and feed pointers with offset /// Split address to pages, check their permissions and feed pointers with offset