diff --git a/Cargo.lock b/Cargo.lock index 71c1704f..fa237f1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,6 +429,7 @@ dependencies = [ name = "kernel" version = "0.1.2" dependencies = [ + "linked_list_allocator", "log", "versioning", ] diff --git a/ableos/src/arch/x86_64/drivers/allocator.rs b/ableos/src/arch/x86_64/drivers/allocator.rs index b1057be9..8db70e52 100644 --- a/ableos/src/arch/x86_64/drivers/allocator.rs +++ b/ableos/src/arch/x86_64/drivers/allocator.rs @@ -1,6 +1,6 @@ -use crate::allocator::{HEAP_SIZE, HEAP_START}; use alloc::alloc::{GlobalAlloc, Layout}; use core::ptr::null_mut; +use kernel::allocator::{HEAP_SIZE, HEAP_START}; use x86_64::{ structures::paging::{ mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, @@ -39,7 +39,7 @@ pub fn init_heap( } unsafe { - crate::allocator::ALLOCATOR + kernel::allocator::ALLOCATOR .lock() .init(HEAP_START, HEAP_SIZE); } diff --git a/ableos/src/experiments/kinfo.rs b/ableos/src/experiments/kinfo.rs index 46646db5..fdacbb26 100644 --- a/ableos/src/experiments/kinfo.rs +++ b/ableos/src/experiments/kinfo.rs @@ -1,6 +1,7 @@ use super::systeminfo::SystemMemory; -use crate::{arch::drivers::sysinfo::master, ALLOCATOR}; +use crate::arch::drivers::sysinfo::master; use core::fmt::Display; +use kernel::allocator::ALLOCATOR; use versioning::Version; use x86_64::instructions::interrupts::{disable, enable}; diff --git a/ableos/src/lib.rs b/ableos/src/lib.rs index 911b3e33..98892da3 100644 --- a/ableos/src/lib.rs +++ b/ableos/src/lib.rs @@ -40,7 +40,6 @@ pub mod print; #[macro_use] pub mod serial_print; -pub mod allocator; pub mod boot_conf; pub mod devices; pub mod driver_traits; @@ -68,7 +67,6 @@ mod unicode_utils; #[prelude_import] pub use prelude::rust_2021::*; -pub use allocator::*; pub use driver_traits::*; pub use experiments::*; pub use graphics::*; diff --git a/ableos/src/rhai_shell/mod.rs b/ableos/src/rhai_shell/mod.rs index aae557bc..7886826a 100644 --- a/ableos/src/rhai_shell/mod.rs +++ b/ableos/src/rhai_shell/mod.rs @@ -2,13 +2,13 @@ use crate::arch::drivers::sysinfo::master; use crate::filesystem::FILE_SYSTEM; use crate::time::fetch_time; use crate::wasm_jumploader::interp; -use crate::ALLOCATOR; use crate::{ arch::{shutdown, sloop}, systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, KERNEL_STATE, }; use genfs::{Fs, OpenOptions}; +use kernel::allocator::ALLOCATOR; use rhai::Engine; use spin::Lazy; use x86_64::instructions::interrupts::{disable, enable}; diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs index 529f4de9..9b3ceeac 100644 --- a/ableos/src/scratchpad.rs +++ b/ableos/src/scratchpad.rs @@ -1,15 +1,51 @@ -use core::alloc::Layout; - use crate::arch::generate_process_pass; use crate::arch::interrupts::{reset_pit_for_cpu, set_pit_2}; -use crate::devices::{self, pci, pci_inner}; -use crate::encoding::bin; -use crate::port_io::{read32, read8, write8}; +use crate::devices::pci; +use crate::filesystem::FILE_SYSTEM; use crate::rhai_shell::shell; +use crate::rhai_shell::KEYBUFF; use crate::wasm_jumploader::run_program; use acpi::{AcpiTables, PlatformInfo}; +use cpuio::inb; use cpuio::outb; use genfs::Fs; +use genfs::OpenOptions; + +// TODO: move to a better place +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct AcpiStruct {} +impl acpi::AcpiHandler for AcpiStruct { + unsafe fn map_physical_region( + &self, + physical_address: usize, + size: usize, + ) -> acpi::PhysicalMapping { + info!("PHYS ADDR: {:?}", physical_address); + info!("Size: {:?}", size); + todo!("map_physical_region"); + } + fn unmap_physical_region(_region: &acpi::PhysicalMapping) { + todo!("unmap_physical_region"); + } +} + +pub struct Path { + pub path: Vec, +} + +impl Path { + pub fn new(path: String) -> Self { + let mut path_vec_string = vec![]; + + for part in path.split(&['\\', '/'][..]) { + path_vec_string.push(part.to_string()); + } + + Path { + path: path_vec_string, + } + } +} /// Experimental scratchpad for testing. pub fn scratchpad() { @@ -22,7 +58,7 @@ pub fn scratchpad() { }"; let axel = axel::parse(axel_raw.to_string()); - let xyz = devices::pci::brute_force_scan(); + let xyz = pci::brute_force_scan(); for dev in xyz { trace!("{:?}", dev); dev.bars.iter().for_each(|bar| { @@ -59,7 +95,6 @@ pub fn scratchpad() { real_shell(); } -use crate::port_io::write16; pub fn acpi() { let acpi_handler = AcpiStruct {}; @@ -71,33 +106,13 @@ pub fn acpi() { PlatformInfo { power_profile, interrupt_model, - processor_info, - pm_timer, + .. } => { info!("{:?}", power_profile); info!("{:?}", interrupt_model); // info!("{:?}", processor_info.unwrap()); // info!("{:?}", pm_timer.unwrap()); } - - _ => todo!(), - } -} -// TODO: move to a better place -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct AcpiStruct {} -impl acpi::AcpiHandler for AcpiStruct { - unsafe fn map_physical_region( - &self, - physical_address: usize, - size: usize, - ) -> acpi::PhysicalMapping { - info!("PHYS ADDR: {:?}", physical_address); - info!("Size: {:?}", size); - todo!("map_physical_region"); - } - fn unmap_physical_region(_region: &acpi::PhysicalMapping) { - todo!("unmap_physical_region"); } } @@ -139,7 +154,6 @@ pub fn real_shell() { } } } -use crate::rhai_shell::KEYBUFF; pub fn command_parser(user: String, command: String) { let fs = &*FILE_SYSTEM.lock(); @@ -210,9 +224,6 @@ pub fn command_parser(user: String, command: String) { } } -use crate::filesystem::FILE_SYSTEM; -use genfs::OpenOptions; - pub fn sound(n_frequency: u32) { let div: u32; let tmp: u8; @@ -238,45 +249,3 @@ pub fn sound_off() { }; reset_pit_for_cpu(); } - -use cpuio::inb; - -pub struct Path { - pub path: Vec, -} -impl Path { - pub fn new(path: String) -> Self { - let mut path_vec_string = vec![]; - - for part in path.split(&['\\', '/'][..]) { - path_vec_string.push(part.to_string()); - } - - Path { - path: path_vec_string, - } - } - - pub fn get_path(&self) -> String { - let mut path = String::new(); - for part in &self.path { - path.push_str(part); - path.push('/'); - } - path - } -} - -#[derive(Debug, Copy, Clone)] -pub enum GpuFormats { - BGRA8Unorm = 1, - BGRX8Unorm = 2, - ARGB8Unorm = 3, - XRGB8Unorm = 4, - - RGBA8Unorm = 67, - XBGR8Unorm = 68, - - ABGR8Unorm = 121, - RGBX8Unorm = 134, -} diff --git a/ableos/src/wasm_jumploader/host_functions.rs b/ableos/src/wasm_jumploader/host_functions.rs index 04c50550..2e6157b7 100644 --- a/ableos/src/wasm_jumploader/host_functions.rs +++ b/ableos/src/wasm_jumploader/host_functions.rs @@ -4,219 +4,165 @@ use wasmi::{ Signature, Trap, ValueType, }; -const ADD_FUNC_INDEX: usize = 0; -const GET_TIME_INDEX: usize = 2; -const GET_RANDOM_INDEX: usize = 3; -const GET_INPUT_INDEX: usize = 4; -const PRINT_CHAR: usize = 6; -const SEND_SIGNAL_INDEX: usize = 1; - -pub struct HostExternals; -impl HostExternals { - fn check_signature(&self, index: usize, signature: &Signature) -> bool { - match index { - ADD_FUNC_INDEX => { - let (params, ret_ty): (&[ValueType], Option) = - (&[ValueType::I32, ValueType::I32], Some(ValueType::I32)); - if params.len() != signature.params().len() { - return false; - } - if ret_ty != signature.return_type() { - return false; - } - for (ty, param) in params.iter().zip(signature.params()) { - if *ty != *param { - return false; - } - } - true - } - - SEND_SIGNAL_INDEX => { - let (params, ret_ty): (&[ValueType], Option) = - (&[ValueType::I32, ValueType::I32], Some(ValueType::I32)); - if params.len() != signature.params().len() { - return false; - } - if ret_ty != signature.return_type() { - return false; - } - for (ty, param) in params.iter().zip(signature.params()) { - if *ty != *param { - return false; - } - } - true - } - - GET_TIME_INDEX => { - let (params, ret_ty): (&[ValueType], Option) = - (&[], Some(ValueType::I32)); - if params.len() != signature.params().len() { - return false; - } - if ret_ty != signature.return_type() { - return false; - } - for (ty, param) in params.iter().zip(signature.params()) { - if *ty != *param { - return false; - } - } - true - } - - GET_RANDOM_INDEX => { - let (params, ret_ty): (&[ValueType], Option) = - (&[], Some(ValueType::I32)); - if params.len() != signature.params().len() { - return false; - } - if ret_ty != signature.return_type() { - return false; - } - for (ty, param) in params.iter().zip(signature.params()) { - if *ty != *param { - return false; - } - } - true - } - - GET_INPUT_INDEX => { - let (params, ret_ty): (&[ValueType], Option) = - (&[], Some(ValueType::I32)); - if params.len() != signature.params().len() { - return false; - } - if ret_ty != signature.return_type() { - return false; - } - for (ty, param) in params.iter().zip(signature.params()) { - if *ty != *param { - return false; - } - } - true - } - - PRINT_CHAR => { - let (params, ret_ty): (&[ValueType], Option) = (&[ValueType::I32], None); - if params.len() != signature.params().len() { - return false; - } - if ret_ty != signature.return_type() { - return false; - } - for (ty, param) in params.iter().zip(signature.params()) { - if *ty != *param { - return false; - } - } - true - } - _ => false, - } - } +macro_rules! wasmi_type { + (bool) => { + ValueType::I32 + }; + (u8) => { + ValueType::I32 + }; + (u16) => { + ValueType::I32 + }; + (u32) => { + ValueType::I32 + }; + (u64) => { + ValueType::I64 + }; + (i8) => { + ValueType::I32 + }; + (i16) => { + ValueType::I32 + }; + (i32) => { + ValueType::I32 + }; + (i64) => { + ValueType::I64 + }; + (f32) => { + ValueType::F32 + }; + (f64) => { + ValueType::F64 + }; } -impl Externals for HostExternals { - fn invoke_index( - &mut self, - index: usize, - args: RuntimeArgs, - ) -> Result, Trap> { - match index { - ADD_FUNC_INDEX => { - let a: u32 = args.nth_checked(0)?; - let b: u32 = args.nth_checked(1)?; - let result = a + b; - trace!("SYSCALL: {} + {} = {}", a, b, result); - Ok(Some(RuntimeValue::I32(result as i32))) - } +macro_rules! wasmi_return_type { + () => { + None + }; + ($type: ident) => { + Some(wasmi_type!($type)) + }; +} - SEND_SIGNAL_INDEX => { - let pid: u32 = args.nth_checked(0)?; - let signal: u32 = args.nth_checked(1)?; - - trace!("SYSCALL: send signal {} to pid {}", signal, pid); - let ret = RuntimeValue::I32(0); - Ok(Some(ret)) - } - - GET_TIME_INDEX => { - use core::sync::atomic::Ordering::*; - trace!("SYSCALL: get time"); - - x86_64::instructions::interrupts::disable(); - let tick_time = kernel::TICK.load(Relaxed); - x86_64::instructions::interrupts::enable(); - - let ret = RuntimeValue::I32(tick_time.try_into().unwrap()); - Ok(Some(ret)) - } - - GET_RANDOM_INDEX => { - trace!("SYSCALL: get random"); - let rand = generate_process_pass(); - - let ret = RuntimeValue::I32(rand as i32); - - // let ret = RuntimeValue::I32(rand.try_into().unwrap()); - Ok(Some(ret)) - } - - GET_INPUT_INDEX => { - let input = None; - x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()); - if let Some(chr) = input { - trace!("SYSCALL: input: {}", chr); +macro_rules! host_externals { + ( + $($index: literal: $name: ident ($($arg_name: ident: $arg_type: ident),* $(,)?) $(-> $return_type: ident)? $block: block)* + ) => { + pub struct HostExternals; + impl Externals for HostExternals { + fn invoke_index( + &mut self, + index: usize, + args: RuntimeArgs + ) -> Result, Trap> { + match index { + $( + $index => match args.as_ref() { + [$($arg_name),*] => { + $( + let $arg_name: $arg_type = (*$arg_name) + .try_into() + .ok_or(wasmi::TrapKind::UnexpectedSignature)?; + )* + $block + }, + _ => return Err(wasmi::TrapKind::UnexpectedSignature.into()), + } + ),* + _ => { + error!("Unimplemented function at {index}"); + Err(Trap::new(wasmi::TrapKind::Unreachable)) + } } - - let ret = RuntimeValue::I32(input.unwrap_or(0x00 as char) as i32); - - Ok(Some(ret)) - } - - PRINT_CHAR => { - let chr: u8 = args.nth_checked(0)?; - trace!("SYSCALL: print: {}", chr); - print!("{}", char::from(chr)); - Ok(None) - } - _ => { - error!("Unimplemented function at {}", index); - Err(Trap::new(wasmi::TrapKind::Unreachable)) } } - } + + impl ModuleImportResolver for HostExternals { + fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { + let (index, param_types, return_type): (usize, &[ValueType], Option) = + match field_name { + $( + stringify!($name) => ( + $index, + &[$(wasmi_type!($arg_type)),*], + wasmi_return_type!($($return_type)?), + ), + )* + _ => { + return Err(Error::Instantiation(format!( + "Export {field_name} not found", + ))); + }, + }; + + if !(param_types.len() != signature.params().len() || return_type != signature.return_type()) + && param_types + .iter() + .zip(signature.params()) + .find(|(ty, param)| ty != param) + .is_none() + { + trace!("Resolved export {field_name} at func {index}"); + Ok(FuncInstance::alloc_host(signature.clone(), index)) + } else { + Err(Error::Instantiation(format!( + "Export {field_name} has a bad signature {signature:?}", + ))) + } + } + } + }; } -impl ModuleImportResolver for HostExternals { - fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { - let index = match field_name { - "add" => ADD_FUNC_INDEX, - "send_signal" => SEND_SIGNAL_INDEX, - "get_time" => GET_TIME_INDEX, - "get_random" => GET_RANDOM_INDEX, - "get_input" => GET_INPUT_INDEX, - "print_char" => PRINT_CHAR, - _ => { - return Err(Error::Instantiation(format!( - "Export {} not found", - field_name - ))) - } - }; +host_externals! { + 0: add(a: u32, b: u32) -> u32 { + let result = a + b; + trace!("SYSCALL: {} + {} = {}", a, b, result); + Ok(Some(result.into())) + } - if !self.check_signature(index, signature) { - return Err(Error::Instantiation(format!( - "Export {} has a bad signature {:?}", - field_name, signature - ))); + 1: send_signal(pid: u32, signal: u32) -> i32 { + trace!("SYSCALL: send signal {} to pid {}", signal, pid); + Ok(Some(0.into())) + } + + 2: get_time() -> u32 { + use core::sync::atomic::Ordering::*; + trace!("SYSCALL: get time"); + + x86_64::instructions::interrupts::disable(); + let tick_time = kernel::TICK.load(Relaxed); + x86_64::instructions::interrupts::enable(); + + let ret: u32 = tick_time.try_into().unwrap(); + Ok(Some(ret.into())) + } + + 3: get_random() -> i32 { + trace!("SYSCALL: get random"); + let rand = generate_process_pass() as i32; + Ok(Some(rand.into())) + } + + 4: get_input() -> i32 { + let input = None; + x86_64::instructions::interrupts::without_interrupts(|| KEYBUFF.lock().pop()); + if let Some(chr) = input { + trace!("SYSCALL: input: {}", chr); } - trace!("Resolved export {} as func {}", field_name, index); - Ok(FuncInstance::alloc_host(signature.clone(), index)) + let ret = input.unwrap_or(0x00 as char) as i32; + Ok(Some(ret.into())) + } + + 5: print_char(chr: u8) { + trace!("SYSCALL: print: {}", chr); + print!("{}", char::from(chr)); + Ok(None) } } diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index b6b5df25..8a86d749 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -4,7 +4,8 @@ name = "kernel" version = "0.1.2" [dependencies] +linked_list_allocator = "0.9" log = "0.4.14" [dependencies.versioning] -git = "https://git.ablecorp.us/able/aos_userland" \ No newline at end of file +git = "https://git.ablecorp.us/able/aos_userland" diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs new file mode 100644 index 00000000..3c177d48 --- /dev/null +++ b/kernel/src/allocator.rs @@ -0,0 +1,24 @@ +//! Memory allocator + +use linked_list_allocator::LockedHeap; + +/// +pub const HEAP_START: usize = 0x_4444_4444_0000; + +/// +pub const HEAP_MULTIPLIER: usize = 100000; + +/// +pub const HEAP_BASE: usize = 100; + +/// +pub const HEAP_SIZE: usize = HEAP_BASE * HEAP_MULTIPLIER; + +/// Global allocator +#[global_allocator] +pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); + +#[alloc_error_handler] +fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { + panic!("allocation error: {:?}", layout) +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 42902107..53f1f734 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,10 +1,14 @@ //! The ableOS kernel. -#![deny(missing_docs)] -#![no_std] -#![feature(prelude_import)] +#![feature(alloc_error_handler)] #![feature(arbitrary_enum_discriminant)] +#![feature(prelude_import)] +#![no_std] +#![deny(missing_docs)] +extern crate alloc; + +pub mod allocator; pub mod device_interface; pub mod messaging; pub mod panic;