tack inplace hbvm

This commit is contained in:
Able 2023-05-15 02:19:34 -05:00
parent 282688d48b
commit 2744e8e67b
18 changed files with 247 additions and 171 deletions

23
Cargo.lock generated
View file

@ -5,9 +5,10 @@ version = 3
[[package]] [[package]]
name = "able_graphics_library" name = "able_graphics_library"
version = "0.1.2" version = "0.1.2"
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
dependencies = [ dependencies = [
"embedded-graphics", "embedded-graphics",
"log",
"versioning", "versioning",
] ]
@ -140,9 +141,9 @@ dependencies = [
[[package]] [[package]]
name = "clparse" name = "clparse"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
dependencies = [ dependencies = [
"hashbrown 0.13.2", "hashbrown 0.12.3",
"log", "log",
"toml", "toml",
] ]
@ -364,6 +365,15 @@ dependencies = [
"ahash 0.8.3", "ahash 0.8.3",
] ]
[[package]]
name = "hbvm"
version = "0.1.0"
source = "git+https://git.ablecorp.us/ableos/holey-bytes#76302b4ca8aeda6597ee51cb1cf5f59a5d385c4f"
dependencies = [
"hashbrown 0.13.2",
"log",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -457,7 +467,8 @@ dependencies = [
"derive_more", "derive_more",
"embedded-graphics", "embedded-graphics",
"error-stack 0.3.1", "error-stack 0.3.1",
"hashbrown 0.13.2", "hashbrown 0.12.3",
"hbvm",
"limine", "limine",
"log", "log",
"rdrand", "rdrand",
@ -822,7 +833,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "versioning" name = "versioning"
version = "0.1.3" version = "0.1.3"
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -1110,7 +1121,7 @@ dependencies = [
[[package]] [[package]]
name = "xml" name = "xml"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218" source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
dependencies = [ dependencies = [
"serde", "serde",
] ]

View file

@ -3,5 +3,4 @@ TODO:
# Compiling # Compiling
1. `git submodule --update init` 1. `git submodule --update init`
1. Add [this binary](https://git.ablecorp.us/AbleOS/ableos/src/commit/e6c8d184d42961cf3cfa2e4aa319fc86c8880585/test.wasm) to the root.
1. `cargo repbuild` 1. `cargo repbuild`

View file

@ -6,7 +6,7 @@ resolver = "2"
[dependencies] [dependencies]
hbvm = { git = "https://git.ablecorp.us/ableos/holey-bytes" }
embedded-graphics = "0.7.1" embedded-graphics = "0.7.1"

View file

@ -47,7 +47,8 @@ SECTIONS
/* Align initial kernel heap to page boundary */ /* Align initial kernel heap to page boundary */
. = ALIGN(4K); . = ALIGN(4K);
PROVIDE(_initial_kernel_heap_start = .); PROVIDE(_initial_kernel_heap_start = .);
PROVIDE(_initial_kernel_heap_size = 1024 * 1024); /* PROVIDE(_initial_kernel_heap_size = 1024 * 1024); */
PROVIDE(_initial_kernel_heap_size = 1024 * 4096);
. += _initial_kernel_heap_size; . += _initial_kernel_heap_size;
} :data } :data
} }

View file

@ -39,6 +39,8 @@ struct Allocator(Mutex<Option<Heap>>);
unsafe impl GlobalAlloc for Allocator { unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
// log::info!("Global allocation");
let mut lock = self.0.lock(); let mut lock = self.0.lock();
let allocator = lock.as_mut().expect("heap allocator should be initialized"); let allocator = lock.as_mut().expect("heap allocator should be initialized");

View file

@ -12,6 +12,7 @@ use {
pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| { pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
static FB_REQ: FramebufferRequest = FramebufferRequest::new(0); static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0]; let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
{ {
use crate::alloc::string::ToString; use crate::alloc::string::ToString;
let mut dt = DEVICE_TREE.lock(); let mut dt = DEVICE_TREE.lock();
@ -22,8 +23,13 @@ pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
disp.set_attribute("bits per pixel", fb1.bpp); disp.set_attribute("bits per pixel", fb1.bpp);
dt.devices.insert("Displays".to_string(), alloc::vec![disp]); dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
} }
let size: usize = (fb1.width * fb1.height).try_into().unwrap();
let back_buffer: alloc::vec::Vec<u32> = alloc::vec![0; 800*600];
let m = Mutex::new(Display { let m = Mutex::new(Display {
fb: fb1.address.as_ptr().unwrap().cast(), fb: fb1.address.as_ptr().unwrap().cast(),
// bb: fb1.address.as_ptr().unwrap().cast(),
bb: back_buffer.as_slice().as_ptr() as *mut u32,
size: Size::new(fb1.width as u32, fb1.height as u32), size: Size::new(fb1.width as u32, fb1.height as u32),
color: Rgb888::WHITE, color: Rgb888::WHITE,
}); });

View file

@ -7,7 +7,7 @@ use {
uart_16550::SerialPort, uart_16550::SerialPort,
}; };
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) }); pub static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new())); static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
pub fn init() { pub fn init() {
@ -17,8 +17,10 @@ pub fn init() {
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
x86_64::instructions::interrupts::without_interrupts(|| { x86_64::instructions::interrupts::without_interrupts(|| {
TERMINAL_LOGGER.lock().write_fmt(args)?; // TERMINAL_LOGGER.lock().write_fmt(args)?;
SERIAL_CONSOLE.lock().write_fmt(args) let mut sc = SERIAL_CONSOLE.lock();
sc.write_fmt(args)?;
Ok(())
}) })
} }

View file

@ -8,9 +8,9 @@ pub mod memory;
mod cpuid; mod cpuid;
mod gdt; mod gdt;
mod graphics; pub mod graphics;
pub(crate) mod interrupts; pub(crate) mod interrupts;
mod logging; pub mod logging;
pub mod pci; pub mod pci;
pub mod virtio; pub mod virtio;
@ -114,11 +114,56 @@ unsafe extern "C" fn _kernel_start() -> ! {
graphics::init(); graphics::init();
let mut dis = DISPLAY.lock(); let mut dis = DISPLAY.lock();
use {able_graphics_library::raw_pixel, embedded_graphics::prelude::RgbColor}; use {able_graphics_library::raw_pixel, embedded_graphics::prelude::RgbColor};
dis.set_color(Rgb888::GREEN); // dis.set_color(Rgb888::GREEN);
dis.line(1, 1, 700, 1000, 1); // dis.line(400, 400, 700, 100, 50);
// dis.line(10, 10, 100, 10, 10);
// dis.line(100, 10, 1, 1, 10); // dis.set_color(Rgb888::new(100, 23, 100));
// dis.line(100, 100, 400, 400, 3);
// dis.line(100, 100, 700, 100, 1);
dis.set_color(Rgb888::YELLOW);
let thick = 3;
let p1 = (400, 30);
let p2 = (200, 150);
let p3 = (600, 150);
let p4 = (200, 350);
let p5 = (600, 350);
let p6 = (400, 470);
{
//HEXAGON
dis.line(p1.0, p1.1, p2.0, p2.1, thick);
dis.line(p1.0, p1.1, p3.0, p3.1, thick);
dis.line(p2.0, p2.1, p4.0, p4.1, thick);
dis.line(p3.0, p3.1, p5.0, p5.1, thick);
dis.line(p6.0, p6.1, p4.0, p4.1, thick);
dis.line(p6.0, p6.1, p5.0, p5.1, thick);
} }
{
dis.line(600, 150, 200, 350, thick);
dis.line(600, 350, 400, 250, thick);
}
{
dis.set_color(Rgb888::WHITE);
let hp1 = (350, 150);
let hp2 = (350, 350);
let hp3 = (450, 250);
let hp4 = (350, 250);
let hp5 = (450, 150);
let hp6 = (450, 350);
dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
}
dis.swap_buffers();
}
let rand = xml::XMLElement::new("Random");
crate::kmain::kmain( crate::kmain::kmain(
KFILE_REQ KFILE_REQ
@ -144,7 +189,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
}), }),
) )
} }
use embedded_graphics::prelude::WebColors;
/// Spin loop /// Spin loop
pub fn sloop() -> ! { pub fn sloop() -> ! {
loop { loop {

View file

@ -23,10 +23,22 @@ pub fn init() {
let id = device_info.device_id.id; let id = device_info.device_id.id;
use Vendor::*; use Vendor::*;
let (dev_type, dev_name) = match (vendor, id) { let (dev_type, dev_name) = match (vendor, id) {
(Qemu, 4369) => ("GPUs", "QEMU VGA"),
(VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"), (VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"),
(CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446? (CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446?
(_, _) => ("Unidentified PCI", "UNKNOWN DEVICE"), (_, _) => ("Unidentified PCI", "UNKNOWN DEVICE"),
}; };
// let (dev_type, dev_name) = match device_info.full_class {
// PciFullClass::Unclassified_NonVgaCompatible => todo!(),
// PciFullClass::Unclassified_VgaCompatible => todo!(),
// PciFullClass::Display_VGA => ("GPUs", "VGA Device"),
// PciFullClass::Display_XGA => ("GPUs", "XGA Device"),
// PciFullClass::Display_3D => ("GPUs", "3D Device"),
// PciFullClass::Display_Other => ("GPUs", "Other"),
// _ => ("Unidentified PCI", "UNKNOWN DEVICE"),
// };
let mut dev = xml::XMLElement::new(dev_name); let mut dev = xml::XMLElement::new(dev_name);
let mut pci_info = xml::XMLElement::new("PCI Info"); let mut pci_info = xml::XMLElement::new("PCI Info");

View file

@ -3,6 +3,7 @@ use alloc::{string::String, vec::Vec};
use {crate::alloc::string::ToString, core::fmt, hashbrown::HashMap}; use {crate::alloc::string::ToString, core::fmt, hashbrown::HashMap};
pub type Device = xml::XMLElement; pub type Device = xml::XMLElement;
// TODO: alphabatize this list
#[derive(Debug)] #[derive(Debug)]
pub struct DeviceTree { pub struct DeviceTree {
pub devices: HashMap<String, Vec<Device>>, pub devices: HashMap<String, Vec<Device>>,

View file

@ -0,0 +1,57 @@
use {alloc::collections::VecDeque, hbvm::engine::Engine};
use {
crossbeam_queue::{ArrayQueue, SegQueue},
log::trace,
};
use crate::{ipc::message::Message, kmain::DEVICE_TREE};
pub enum HostError {
MemoryError,
}
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: alloc::vec::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(HostError::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) {}

15
kernel/src/ipc/buffer.rs Normal file
View file

@ -0,0 +1,15 @@
use crossbeam_queue::{ArrayQueue, SegQueue};
use super::message::Message;
enum BufferTypes {
Unbound(SegQueue<Message>),
Bound(ArrayQueue<Message>),
}
pub struct IpcBuffer {
protocol: Protocol,
buffer: BufferTypes,
}
pub struct Protocol {}

View file

@ -0,0 +1,3 @@
use alloc::vec::Vec;
pub type Message = Vec<u8>;

24
kernel/src/ipc/mod.rs Normal file
View file

@ -0,0 +1,24 @@
pub mod buffer;
pub mod message;
use alloc::string::ToString;
pub struct IpcV1 {
abc: alloc::string::String,
}
pub struct IpcV2 {
abc: alloc::string::String,
}
pub fn IPCV1_to_IPCV2(ipc_v1: IpcV1) -> IpcV2 {
return IpcV2 {
abc: "abc".to_string(),
};
}
pub fn IPCV2_to_IPCV1(ipc_v2: IpcV2) -> IpcV1 {
return IpcV1 {
abc: "abc".to_string(),
};
}

View file

@ -7,7 +7,13 @@ use {
spin::{Lazy, Mutex}, spin::{Lazy, Mutex},
}; };
use crate::device_tree::DeviceTree; use {embedded_graphics::pixelcolor::Rgb888, hbvm::engine::Engine};
use crate::{
arch::{graphics::DISPLAY, logging::SERIAL_CONSOLE},
device_tree::DeviceTree,
// host_functions::read_device_tree,
};
use crate::alloc::string::ToString; use crate::alloc::string::ToString;
@ -39,10 +45,40 @@ pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! {
let mut dt = DEVICE_TREE.lock(); let mut dt = DEVICE_TREE.lock();
info!("Device Tree {}", &dt); info!("Device Tree {}", &dt);
let bytes = alloc::vec![0];
let mut prog = Engine::new(bytes);
// prog.enviroment_call_table[0] = read_device_tree;
prog.run();
prog.dump();
// TODO: change this to a driver
{
let mut buf = [8; 128 * 4];
let mut sc = SERIAL_CONSOLE.lock();
loop {
let byte = sc.receive();
if byte == b'\r' {
sc.send(b'\n');
}
sc.send(byte);
}
}
crate::arch::sloop() crate::arch::sloop()
} }
use embedded_graphics::prelude::RgbColor;
use hbvm::bytecode::ops::Operations::*;
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| { pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
let mut dt = DeviceTree::new(); let mut dt = DeviceTree::new();
Mutex::new(dt) Mutex::new(dt)
}); });
#[test_case]
fn trivial_assertion() {
trace!("trivial assertion... ");
assert_eq!(1, 1);
info!("[ok]");
}

View file

@ -10,6 +10,9 @@
ptr_sub_ptr ptr_sub_ptr
)] )]
#![no_std] #![no_std]
#![feature(custom_test_frameworks)]
#![test_runner(crate::test_runner)]
// #![deny(missing_docs)] // #![deny(missing_docs)]
extern crate alloc; extern crate alloc;
@ -18,10 +21,11 @@ mod allocator;
mod arch; mod arch;
pub mod device_tree; pub mod device_tree;
pub mod handle; pub mod handle;
pub mod host_functions;
pub mod ipc;
mod kmain; mod kmain;
mod logger; mod logger;
mod memory; mod memory;
mod task;
pub mod utils; pub mod utils;
use versioning::Version; use versioning::Version;
@ -50,3 +54,11 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
loop {} loop {}
} }
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
println!("Running {} tests", tests.len());
for test in tests {
test();
}
}

View file

@ -1,4 +1,3 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
extern crate kernel; extern crate kernel;

View file

@ -1,149 +0,0 @@
//! Async task and executor
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake};
use core::{
future::Future,
pin::Pin,
task::{Context, Poll, Waker},
};
use crossbeam_queue::SegQueue;
use slab::Slab;
use spin::RwLock;
type TaskQueue = Arc<SegQueue<TaskId>>;
type SpawnQueue = Arc<SegQueue<Task>>;
static SPAWN_QUEUE: RwLock<Option<SpawnQueue>> = RwLock::new(None);
/// Spawn a new task
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"),
}
}
/// Forcibly yield a task
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)
}
/// Tasks executor
#[derive(Default)]
pub struct Executor {
/// All spawned tasks' stash
tasks: Slab<Task>,
/// Awake tasks' queue
queue: TaskQueue,
/// Incoming tasks to enqueue
incoming: SpawnQueue,
/// Wakers
wakers: BTreeMap<TaskId, Waker>,
}
impl Executor {
/// Spawn a task
pub fn spawn(&mut self, future: impl Future<Output = ()> + Send + 'static) {
self.queue
.push(TaskId(self.tasks.insert(Task::new(future))));
}
/// Spin poll loop until it runs out of tasks
pub fn run(&mut self) {
// Assign `self.incoming` to global spawn queue to spawn tasks
// from within
{
let mut spawner = SPAWN_QUEUE.write();
if spawner.is_some() {
panic!("task executor is already running");
}
*spawner = Some(Arc::clone(&self.incoming));
}
// Try to get incoming task, if none available, poll
// enqueued one
while let Some(id) = self
.incoming
.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 non-extant task with id {}", 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(()) => {
// Task done, unregister
self.tasks.remove(id.0);
self.wakers.remove(&id);
}
Poll::Pending => (),
}
}
*SPAWN_QUEUE.write() = None;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct TaskId(usize);
/// Async task
struct Task {
future: Pin<Box<dyn Future<Output = ()> + Send>>,
}
impl Task {
/// Create a new task from a future
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)
}
}
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);
}
}