forked from AbleOS/ableos
139 lines
3.9 KiB
Rust
139 lines
3.9 KiB
Rust
use {
|
|
alloc::boxed::Box,
|
|
core::{default, future::Future, task::Poll},
|
|
hbvm::{
|
|
mem::{
|
|
softpaging::{icache::ICache, HandlePageFault, SoftPagedMem},
|
|
Address,
|
|
},
|
|
Vm, VmRunError, VmRunOk,
|
|
},
|
|
};
|
|
|
|
const TIMER_QUOTIENT: usize = 100;
|
|
|
|
pub struct ExecThread<'p> {
|
|
vm: Vm<SoftPagedMem<'p, PageFaultHandler, true>, TIMER_QUOTIENT>,
|
|
}
|
|
|
|
unsafe impl<'p> Send for ExecThread<'p> {}
|
|
impl<'p> ExecThread<'p> {
|
|
pub unsafe fn new(program: &'p [u8], entrypoint: Address) -> Self {
|
|
ExecThread {
|
|
vm: unsafe {
|
|
Vm::new(
|
|
SoftPagedMem {
|
|
root_pt: Box::into_raw(Box::default()),
|
|
pf_handler: PageFaultHandler,
|
|
program,
|
|
icache: ICache::default(),
|
|
},
|
|
entrypoint,
|
|
)
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'p> Future for ExecThread<'p> {
|
|
type Output = Result<(), VmRunError>;
|
|
|
|
fn poll(
|
|
mut self: core::pin::Pin<&mut Self>,
|
|
cx: &mut core::task::Context<'_>,
|
|
) -> Poll<Self::Output> {
|
|
match self.vm.run() {
|
|
Err(err) => {
|
|
log::error!(
|
|
"HBVM Error\r
|
|
Register dump: {:?}",
|
|
self.vm.registers
|
|
);
|
|
|
|
return Poll::Ready(Err(err));
|
|
}
|
|
Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
|
|
Ok(VmRunOk::Ecall) => {
|
|
let r255 = self.vm.registers[255];
|
|
let r254 = self.vm.registers[254];
|
|
let r253 = self.vm.registers[253];
|
|
|
|
log::debug!("Ecall number {:?}", r255);
|
|
log::trace!("Register dump: {:?}", self.vm.registers);
|
|
|
|
match r255.cast::<u64>() {
|
|
0 => {
|
|
// TODO: explode computer
|
|
// hello world ecall
|
|
for x in 0u64..=255 {
|
|
self.vm.registers[x as usize] = x.into();
|
|
}
|
|
}
|
|
1 => {
|
|
// Make buffer
|
|
log::trace!(
|
|
"bounded: {}\n\r
|
|
length: {:?}",
|
|
match unsafe { r254.u64 } {
|
|
0 => {
|
|
false
|
|
}
|
|
1 => {
|
|
true
|
|
}
|
|
_ => {
|
|
// TODO: throw this back to the runtime
|
|
panic!("Bad");
|
|
}
|
|
},
|
|
r253
|
|
)
|
|
}
|
|
2 => {
|
|
// Delete buffer
|
|
log::warn!("Syscall 2");
|
|
}
|
|
3 => {
|
|
log::warn!("Syscall 3");
|
|
}
|
|
4 => {
|
|
log::warn!("Syscall 4");
|
|
}
|
|
|
|
_ => {
|
|
log::error!("Syscall unknown {:?}", r255)
|
|
}
|
|
}
|
|
}
|
|
Ok(VmRunOk::Timer) => (),
|
|
}
|
|
|
|
cx.waker().wake_by_ref();
|
|
Poll::Pending
|
|
}
|
|
}
|
|
|
|
struct PageFaultHandler;
|
|
impl HandlePageFault for PageFaultHandler {
|
|
fn page_fault(
|
|
&mut self,
|
|
reason: hbvm::mem::MemoryAccessReason,
|
|
pagetable: &mut hbvm::mem::softpaging::paging::PageTable,
|
|
vaddr: hbvm::mem::Address,
|
|
size: hbvm::mem::softpaging::PageSize,
|
|
dataptr: *mut u8,
|
|
) -> bool
|
|
where
|
|
Self: Sized,
|
|
{
|
|
log::error!(
|
|
"REASON: {reason} \
|
|
vaddr: {vaddr} \
|
|
size: {size:?} \
|
|
Dataptr {dataptr:p}",
|
|
);
|
|
|
|
false
|
|
}
|
|
}
|