KERNEL: Fixed holeybytes
This commit is contained in:
parent
0f151fdd52
commit
cbed32526b
975
Cargo.lock
generated
975
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,3 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["kernel", "repbuild"]
|
members = ["kernel"]
|
||||||
|
|
|
@ -15,6 +15,7 @@ xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
hashbrown = "*"
|
hashbrown = "*"
|
||||||
|
kiam = "0.1.1"
|
||||||
|
|
||||||
[dependencies.limine]
|
[dependencies.limine]
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
83
kernel/src/holeybytes.rs
Normal file
83
kernel/src/holeybytes.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
use core::{future::Future, task::Poll};
|
||||||
|
|
||||||
|
use hbvm::{
|
||||||
|
mem::{softpaging::icache::ICache, Address},
|
||||||
|
Vm, VmRunError, VmRunOk,
|
||||||
|
};
|
||||||
|
|
||||||
|
use {
|
||||||
|
alloc::boxed::Box,
|
||||||
|
hbvm::mem::softpaging::{HandlePageFault, SoftPagedMem},
|
||||||
|
};
|
||||||
|
|
||||||
|
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) => return Poll::Ready(Err(err)),
|
||||||
|
Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
|
||||||
|
Ok(VmRunOk::Ecall) => {
|
||||||
|
log::info!("Ecall");
|
||||||
|
log::info!("{:?}", self.vm.registers);
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,90 +0,0 @@
|
||||||
//! the system interface
|
|
||||||
|
|
||||||
// use {
|
|
||||||
// crate::ipc::message::Message,
|
|
||||||
// alloc::vec::Vec,
|
|
||||||
// crossbeam_queue::{ArrayQueue, SegQueue},
|
|
||||||
// // hbvm::engine::Engine,
|
|
||||||
// log::trace,
|
|
||||||
// HostError::MemoryError,
|
|
||||||
// };
|
|
||||||
/// Host errors
|
|
||||||
pub enum HostError {
|
|
||||||
/// A host memory error
|
|
||||||
MemoryError,
|
|
||||||
}
|
|
||||||
|
|
||||||
// / Check f0 register for the handle
|
|
||||||
// / check f1 for the message ptr
|
|
||||||
// / check f2 for the message length
|
|
||||||
// pub fn ipc_send(engine: &mut Engine) -> Result<(), HostError> {
|
|
||||||
// let _handle = engine.registers.f0;
|
|
||||||
// let message_start = engine.registers.f1;
|
|
||||||
// let message_length = engine.registers.f2;
|
|
||||||
|
|
||||||
// let mut ipc_msg: Vec<u8> = alloc::vec![];
|
|
||||||
|
|
||||||
// for x in message_start..message_start + message_length {
|
|
||||||
// let byte = engine.read_mem_addr_8(x);
|
|
||||||
// match byte {
|
|
||||||
// Ok(byte) => ipc_msg.push(byte),
|
|
||||||
// Err(_) => return Err(MemoryError),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// log::trace!("Message bytes {:?}", ipc_msg);
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // pub fn ipc_recv(_engine: &mut Engine) {}
|
|
||||||
|
|
||||||
// /// Check f0 for the buffer type
|
|
||||||
// /// 0 means an unbound buffer
|
|
||||||
// /// 1 means a bound buffer
|
|
||||||
// /// Check f1 if the buffer is bound
|
|
||||||
// ///
|
|
||||||
// /// f2 Return a handle to the sender
|
|
||||||
// /// f3 returns a handle the the reciever
|
|
||||||
// pub fn ipc_mkbuf(engine: &mut Engine) {
|
|
||||||
// match engine.registers.f0 as usize {
|
|
||||||
// 0 => {
|
|
||||||
// trace!("Making a new ipc unbound buffer");
|
|
||||||
// let _buf: SegQueue<Message> = SegQueue::new();
|
|
||||||
// }
|
|
||||||
// 1 => {
|
|
||||||
// let buf_len = engine.registers.f1 as usize;
|
|
||||||
// trace!("Making a new ipc buffer with capacity {}", buf_len);
|
|
||||||
// let _buf: ArrayQueue<Message> = ArrayQueue::new(buf_len);
|
|
||||||
// }
|
|
||||||
// _ => {}
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // pub fn rpc_discover(_engine: &mut Engine) {}
|
|
||||||
// // pub fn rpc_register(_engine: &mut Engine) {}
|
|
||||||
// // pub fn rpc_call(_engine: &mut Engine) {}
|
|
||||||
|
|
||||||
use hbvm::mem::softpaging::HandlePageFault;
|
|
||||||
/// AbleOS HBVM traphandler
|
|
||||||
pub struct TrapHandler;
|
|
||||||
impl HandlePageFault for TrapHandler {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,14 @@
|
||||||
//! AbleOS Kernel Entrypoint
|
//! AbleOS Kernel Entrypoint
|
||||||
|
|
||||||
|
use hbvm::mem::Address;
|
||||||
|
|
||||||
|
use crate::holeybytes::ExecThread;
|
||||||
|
|
||||||
// use crate::arch::sloop;
|
// use crate::arch::sloop;
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
bootmodules::{build_cmd, BootModules},
|
bootmodules::{build_cmd, BootModules},
|
||||||
device_tree::DeviceTree,
|
device_tree::DeviceTree,
|
||||||
scheduler::Scheduler,
|
|
||||||
},
|
},
|
||||||
alloc::format,
|
alloc::format,
|
||||||
log::{debug, info, trace},
|
log::{debug, info, trace},
|
||||||
|
@ -16,7 +19,7 @@ use {
|
||||||
pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
debug!("Entered kmain");
|
debug!("Entered kmain");
|
||||||
|
|
||||||
let kcmd = build_cmd("Kernel Command Line", &cmdline);
|
let kcmd = build_cmd("Kernel Command Line", cmdline);
|
||||||
trace!("Cmdline: {kcmd:?}");
|
trace!("Cmdline: {kcmd:?}");
|
||||||
|
|
||||||
for (i, bm) in boot_modules.iter().enumerate() {
|
for (i, bm) in boot_modules.iter().enumerate() {
|
||||||
|
@ -39,13 +42,20 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
|
|
||||||
// capabilities::example();
|
// capabilities::example();
|
||||||
|
|
||||||
let mut sched = Scheduler::new();
|
let mut executor = crate::task::Executor::default();
|
||||||
|
unsafe {
|
||||||
|
for module in boot_modules.into_iter().take(2) {
|
||||||
|
executor.spawn(async move {
|
||||||
|
if let Err(e) = ExecThread::new(&module.bytes, Address::new(4)).await {
|
||||||
|
log::error!("{e:?}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
sched.new_process(boot_modules[0].bytes.clone());
|
executor.run();
|
||||||
sched.new_process(boot_modules[1].bytes.clone());
|
};
|
||||||
|
|
||||||
sched.run();
|
crate::arch::spin_loop()
|
||||||
// spin_loop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
ptr_sub_ptr,
|
ptr_sub_ptr,
|
||||||
custom_test_frameworks
|
custom_test_frameworks
|
||||||
)]
|
)]
|
||||||
#![deny(clippy::pedantic, missing_docs, warnings)]
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![test_runner(crate::test_runner)]
|
#![test_runner(crate::test_runner)]
|
||||||
|
|
||||||
|
@ -21,16 +20,16 @@ extern crate alloc;
|
||||||
mod allocator;
|
mod allocator;
|
||||||
mod arch;
|
mod arch;
|
||||||
mod bootmodules;
|
mod bootmodules;
|
||||||
pub mod capabilities;
|
mod capabilities;
|
||||||
pub mod device_tree;
|
mod device_tree;
|
||||||
pub mod handle;
|
mod handle;
|
||||||
pub mod host;
|
mod holeybytes;
|
||||||
pub mod ipc;
|
mod ipc;
|
||||||
mod kmain;
|
mod kmain;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod scheduler;
|
mod task;
|
||||||
pub mod utils;
|
mod utils;
|
||||||
|
|
||||||
use versioning::Version;
|
use versioning::Version;
|
||||||
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
use {
|
|
||||||
alloc::{collections::VecDeque, rc::Rc, slice, vec::Vec},
|
|
||||||
hbvm::validate::validate,
|
|
||||||
};
|
|
||||||
|
|
||||||
use {crate::host::TrapHandler, hbvm::Vm};
|
|
||||||
const TIMER_QUOTIENT: usize = 100;
|
|
||||||
|
|
||||||
pub struct Scheduler<'a> {
|
|
||||||
data: VecDeque<Vm<'a, TrapHandler, TIMER_QUOTIENT>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: This is a very simple schduler and it sucks and should be replaced with a better one
|
|
||||||
// Written By Yours Truly: Munir
|
|
||||||
|
|
||||||
impl Scheduler<'_> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
data: VecDeque::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn new_process(&mut self, program: Vec<u8>) {
|
|
||||||
let prog = program.clone();
|
|
||||||
let prog_arc = Rc::new(prog);
|
|
||||||
|
|
||||||
let binding = Rc::try_unwrap(prog_arc).ok().unwrap();
|
|
||||||
|
|
||||||
#[allow(clippy::redundant_else)]
|
|
||||||
if let Err(e) = validate(&program.as_slice()) {
|
|
||||||
log::error!("Program validation error: {e:?}");
|
|
||||||
} else {
|
|
||||||
log::info!("valid program");
|
|
||||||
unsafe {
|
|
||||||
let slice = slice::from_raw_parts(binding.as_ptr(), binding.len());
|
|
||||||
let mut vm = Vm::new_unchecked(&*slice, TrapHandler);
|
|
||||||
vm.memory.insert_test_page();
|
|
||||||
self.data.push_front(vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(&mut self) -> ! {
|
|
||||||
loop {
|
|
||||||
// If there are no programs to run then sleep.
|
|
||||||
if self.data.is_empty() {
|
|
||||||
use crate::arch::spin_loop;
|
|
||||||
spin_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut prog = self.data.pop_front().unwrap();
|
|
||||||
let ret = prog.run();
|
|
||||||
match ret {
|
|
||||||
Ok(oki) => match oki {
|
|
||||||
hbvm::VmRunOk::End => {
|
|
||||||
log::info!(
|
|
||||||
"Program ended. {} programs remaining.",
|
|
||||||
// Add one here because we pop a program
|
|
||||||
self.data.len() + 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
hbvm::VmRunOk::Timer => {
|
|
||||||
log::info!("Timer exhausted. Scheduled program");
|
|
||||||
self.data.push_back(prog);
|
|
||||||
}
|
|
||||||
hbvm::VmRunOk::Ecall => {
|
|
||||||
// panic!();
|
|
||||||
log::info!("{:?}", prog.registers);
|
|
||||||
self.data.push_back(prog);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
138
kernel/src/task.rs
Normal file
138
kernel/src/task.rs
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use {
|
||||||
|
alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake},
|
||||||
|
core::{
|
||||||
|
future::Future,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll, Waker},
|
||||||
|
},
|
||||||
|
crossbeam_queue::SegQueue,
|
||||||
|
kiam::when,
|
||||||
|
slab::Slab,
|
||||||
|
spin::RwLock,
|
||||||
|
};
|
||||||
|
|
||||||
|
static SPAWN_QUEUE: RwLock<Option<SpawnQueue>> = RwLock::new(None);
|
||||||
|
pub fn spawn(future: impl Future<Output = ()> + Send + 'static) {
|
||||||
|
match &*SPAWN_QUEUE.read() {
|
||||||
|
Some(s) => s.push(Task::new(future)),
|
||||||
|
None => panic!("no task executor is running"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yield_now() -> impl Future<Output = ()> {
|
||||||
|
struct YieldNow(bool);
|
||||||
|
impl Future for YieldNow {
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
if self.0 {
|
||||||
|
Poll::Ready(())
|
||||||
|
} else {
|
||||||
|
self.0 = true;
|
||||||
|
cx.waker().wake_by_ref();
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
YieldNow(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Executor {
|
||||||
|
tasks: Slab<Task>,
|
||||||
|
queue: TaskQueue,
|
||||||
|
to_spawn: SpawnQueue,
|
||||||
|
wakers: BTreeMap<TaskId, Waker>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Executor {
|
||||||
|
pub fn spawn(&mut self, future: impl Future<Output = ()> + Send + 'static) {
|
||||||
|
self.queue
|
||||||
|
.push(TaskId(self.tasks.insert(Task::new(future))));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) {
|
||||||
|
{
|
||||||
|
let mut global_spawner = SPAWN_QUEUE.write();
|
||||||
|
if global_spawner.is_some() {
|
||||||
|
panic!("Task executor is already running");
|
||||||
|
}
|
||||||
|
|
||||||
|
*global_spawner = Some(Arc::clone(&self.to_spawn));
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
when! {
|
||||||
|
let Some(id) = self
|
||||||
|
.to_spawn
|
||||||
|
.pop()
|
||||||
|
.map(|t| TaskId(self.tasks.insert(t)))
|
||||||
|
.or_else(|| self.queue.pop())
|
||||||
|
=> {
|
||||||
|
let Some(task) = self.tasks.get_mut(id.0) else {
|
||||||
|
panic!("Attempted to get task from empty slot: {}", id.0);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cx = Context::from_waker(self.wakers.entry(id).or_insert_with(|| {
|
||||||
|
Waker::from(Arc::new(TaskWaker {
|
||||||
|
id,
|
||||||
|
queue: Arc::clone(&self.queue),
|
||||||
|
}))
|
||||||
|
}));
|
||||||
|
|
||||||
|
match task.poll(&mut cx) {
|
||||||
|
Poll::Ready(()) => {
|
||||||
|
self.tasks.remove(id.0);
|
||||||
|
self.wakers.remove(&id);
|
||||||
|
}
|
||||||
|
Poll::Pending => (),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
self.tasks.is_empty() => break,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*SPAWN_QUEUE.write() = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Task {
|
||||||
|
future: Pin<Box<dyn Future<Output = ()> + Send>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Task {
|
||||||
|
pub fn new(future: impl Future<Output = ()> + Send + 'static) -> Self {
|
||||||
|
Self {
|
||||||
|
future: Box::pin(future),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&mut self, cx: &mut Context) -> Poll<()> {
|
||||||
|
self.future.as_mut().poll(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct TaskId(usize);
|
||||||
|
|
||||||
|
type TaskQueue = Arc<SegQueue<TaskId>>;
|
||||||
|
type SpawnQueue = Arc<SegQueue<Task>>;
|
||||||
|
|
||||||
|
struct TaskWaker {
|
||||||
|
id: TaskId,
|
||||||
|
queue: TaskQueue,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Wake for TaskWaker {
|
||||||
|
fn wake(self: Arc<Self>) {
|
||||||
|
self.wake_by_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wake_by_ref(self: &Arc<Self>) {
|
||||||
|
self.queue.push(self.id);
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Loading…
Reference in a new issue