diff --git a/Cargo.lock b/Cargo.lock index 522080ea..7944be6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] + [[package]] name = "addr2line" version = "0.24.1" @@ -52,9 +61,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" +checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" [[package]] name = "autocfg" @@ -381,17 +390,17 @@ dependencies = [ [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#b51f964caee71ad350d0c1f66e4694202a5d7f12" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc418bd5e0b962ec9413af72e5d624e17febcbf2" [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/ableos/holey-bytes#b51f964caee71ad350d0c1f66e4694202a5d7f12" +source = "git+https://git.ablecorp.us/ableos/holey-bytes#dc418bd5e0b962ec9413af72e5d624e17febcbf2" [[package]] name = "hblang" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#b51f964caee71ad350d0c1f66e4694202a5d7f12" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc418bd5e0b962ec9413af72e5d624e17febcbf2" dependencies = [ "hbvm 0.1.0 (git+https://git.ablecorp.us/AbleOS/holey-bytes.git)", ] @@ -399,7 +408,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#b51f964caee71ad350d0c1f66e4694202a5d7f12" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc418bd5e0b962ec9413af72e5d624e17febcbf2" dependencies = [ "hbbytecode 0.1.0 (git+https://git.ablecorp.us/AbleOS/holey-bytes.git)", ] @@ -407,7 +416,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/ableos/holey-bytes#b51f964caee71ad350d0c1f66e4694202a5d7f12" +source = "git+https://git.ablecorp.us/ableos/holey-bytes#dc418bd5e0b962ec9413af72e5d624e17febcbf2" dependencies = [ "hbbytecode 0.1.0 (git+https://git.ablecorp.us/ableos/holey-bytes)", ] @@ -583,8 +592,8 @@ dependencies = [ name = "kernel" version = "0.2.0" dependencies = [ + "aarch64-cpu", "crossbeam-queue", - "crossbeam-utils", "derive_more", "embedded-graphics", "hashbrown", @@ -592,6 +601,7 @@ dependencies = [ "limine", "log", "sbi", + "slab", "spin", "uart_16550", "versioning", @@ -989,9 +999,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "once_cell", "ring", @@ -1218,6 +1228,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" + [[package]] name = "tokio" version = "1.40.0" @@ -1349,9 +1365,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index be0aa8a6..d1764db2 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -9,6 +9,7 @@ embedded-graphics = "0.8" hbvm.git = "https://git.ablecorp.us/ableos/holey-bytes" log = "0.4" spin = "0.9" +slab = { version = "0.4", default-features = false } uart_16550 = { version = "0.3", features = ["nightly"] } xml.git = "https://git.ablecorp.us/ableos/ableos_userland" versioning.git = "https://git.ablecorp.us/ableos/ableos_userland" @@ -24,10 +25,6 @@ version = "0.3" default-features = false features = ["alloc", "nightly"] -[dependencies.crossbeam-utils] -version = "0.8" -default-features = false - # [dependencies.clparse] # git = "https://git.ablecorp.us/ableos/ableos_userland" # default-features = false @@ -56,3 +53,6 @@ virtio-drivers = "0.7" [target.'cfg(target_arch = "riscv64")'.dependencies] sbi = "0.2.0" + +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = "9" diff --git a/kernel/src/arch/aarch64/logging.rs b/kernel/src/arch/aarch64/logging.rs index 5db9bc05..20e73f81 100644 --- a/kernel/src/arch/aarch64/logging.rs +++ b/kernel/src/arch/aarch64/logging.rs @@ -1,5 +1,5 @@ use {crate::logger::TERMINAL_LOGGER, core::fmt::Write, spin::Mutex}; -const SERIAL_CONSOLE: Mutex = Mutex::new(SerialConsole { +static SERIAL_CONSOLE: Mutex = Mutex::new(SerialConsole { uart: 0x09000000 as *mut u8, }); @@ -17,6 +17,9 @@ impl core::fmt::Write for SerialConsole { } } +unsafe impl Sync for SerialConsole {} +unsafe impl Send for SerialConsole {} + pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { SERIAL_CONSOLE.lock().write_fmt(args)?; TERMINAL_LOGGER.lock().write_fmt(args)?; diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 793288ab..54b1a26b 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -1,6 +1,7 @@ pub use logging::log; use { crate::{allocator, bootmodules::BootModule, kmain::kmain}, + alloc::vec::Vec, core::arch::asm, limine::FramebufferRequest, }; @@ -41,7 +42,7 @@ unsafe extern "C" fn _kernel_start() -> ! { static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0); static MOD_REQ: ModuleRequest = ModuleRequest::new(0); - let mut bootmodules = alloc::vec::Vec::new(); + let mut bootmodules = Vec::new(); if bm.is_some() { let bm = bm.unwrap(); @@ -52,18 +53,13 @@ unsafe extern "C" fn _kernel_start() -> ! { let raw_bytes = core::slice::from_raw_parts( file.base.as_ptr().expect("invalid initrd"), file.length as usize, - ) - .to_vec(); - - let file_path = alloc::string::String::from_utf8( - file.path.to_str().unwrap().to_bytes().to_vec(), ); + + let file_path = file.path.to_str().unwrap().to_str(); if file_path.is_err() { panic!("invalid file path: {:?}", file_path); } - let file_cmd = alloc::string::String::from_utf8( - file.cmdline.to_str().unwrap().to_bytes().to_vec(), - ); + let file_cmd = file.cmdline.to_str().unwrap().to_str(); if file_cmd.is_err() { panic!("invalid module cmd: {:?}", file_cmd); } @@ -85,7 +81,7 @@ unsafe extern "C" fn _kernel_start() -> ! { assert_eq!(bm.module_count, bootmodules.len() as u64); } - crate::kmain::kmain( + kmain( KFILE_REQ .get_response() .get() @@ -99,8 +95,6 @@ unsafe extern "C" fn _kernel_start() -> ! { .unwrap_or_default(), bootmodules, ); - - spin_loop(); } pub fn spin_loop() -> ! { @@ -110,7 +104,15 @@ pub fn spin_loop() -> ! { } pub fn hardware_random_u64() -> u64 { - 0 + if let Some(rng) = aarch64_cpu::asm::random::ArmRng::new() { + if let Some(rnd) = rng.rndr() { + rnd + } else { + panic!("RNG failure :(") + } + } else { + panic!("RNDR failure :(((") + } } pub fn register_dump() {} diff --git a/kernel/src/arch/riscv64/mod.rs b/kernel/src/arch/riscv64/mod.rs index 2caa6c3b..c1a85198 100644 --- a/kernel/src/arch/riscv64/mod.rs +++ b/kernel/src/arch/riscv64/mod.rs @@ -1,7 +1,7 @@ mod memory; use { - alloc::boxed::Box, + alloc::{boxed::Box, vec::Vec}, core::{ arch::{asm, global_asm}, fmt::Write, @@ -45,7 +45,7 @@ extern "C" { static USABLE_MEMORY_SIZE: usize; } -static SERIAL_CONSOLE: Once> = Once::new(); +pub static SERIAL_CONSOLE: Once> = Once::new(); #[no_mangle] unsafe extern "C" fn _kernel_start() -> ! { @@ -95,7 +95,7 @@ unsafe extern "C" fn _kernel_start() -> ! { in(reg) satp_value, ); - crate::kmain::kmain("baka=9", None); + crate::kmain::kmain("baka=9", Vec::new()); } /// Spin loop @@ -105,6 +105,12 @@ pub fn spin_loop() -> ! { } } +pub fn hardware_random_u64() -> u64 { + 0 +} + +pub fn register_dump() {} + pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result { SERIAL_CONSOLE.get().unwrap().lock().write_fmt(args) } diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index c9d491c8..a1e77591 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -11,6 +11,9 @@ use { pub const DOUBLE_FAULT_IX: u16 = 0; +const STACK_SIZE: usize = 5 * 1024; +const STACK_ALIGNMENT: usize = 4096; + pub unsafe fn init() { use x86_64::instructions::{ segmentation::{Segment, CS, SS}, @@ -32,15 +35,15 @@ struct Selectors { static TSS: Lazy = Lazy::new(|| { let mut tss = TaskStateSegment::new(); - tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = { - const SIZE: usize = 5 * 1024; - let stack = unsafe { - alloc::alloc::alloc_zeroed( - alloc::alloc::Layout::from_size_align(SIZE, 1).expect("stack pointer"), - ) - }; - VirtAddr::from_ptr(stack) + SIZE as u64 + + let stack_ptr = unsafe { + let layout = alloc::alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGNMENT) + .expect("Failed to create stack layout"); + let stack = alloc::alloc::alloc_zeroed(layout); + VirtAddr::from_ptr(stack) + STACK_SIZE as u64 }; + + tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = stack_ptr; tss }); diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index be68b5f7..51dd9ee5 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,4 +1,4 @@ -use core::arch::x86_64::{_rdrand32_step, _rdrand64_step, _rdseed32_step, _rdseed64_step}; +use core::arch::x86_64::{_rdrand64_step, _rdseed64_step}; use {crate::bootmodules::BootModule, core::arch::asm, log::warn}; pub mod memory; @@ -142,18 +142,13 @@ unsafe extern "C" fn start() -> ! { let raw_bytes = core::slice::from_raw_parts( file.base.as_ptr().expect("invalid initrd"), file.length as usize, - ) - .to_vec(); - - let file_path = alloc::string::String::from_utf8( - file.path.to_str().unwrap().to_bytes().to_vec(), ); + + let file_path = file.path.to_str().unwrap().to_str(); if file_path.is_err() { panic!("invalid file path: {:?}", file_path); } - let file_cmd = alloc::string::String::from_utf8( - file.cmdline.to_str().unwrap().to_bytes().to_vec(), - ); + let file_cmd = file.cmdline.to_str().unwrap().to_str(); if file_cmd.is_err() { panic!("invalid module cmd: {:?}", file_cmd); } @@ -191,15 +186,10 @@ unsafe extern "C" fn start() -> ! { ) } -use crossbeam_utils::Backoff; - /// Spin loop pub fn spin_loop() -> ! { - let backoff = Backoff::new(); loop { - core::hint::spin_loop(); - // x86_64::instructions::hlt(); - backoff.spin() + x86_64::instructions::hlt() } } @@ -218,21 +208,6 @@ pub fn hardware_random_u64() -> u64 { } } -pub fn hardware_random_u32() -> u32 { - let mut out: u32 = 0; - match unsafe { _rdrand32_step(&mut out) } { - 1 => out, - _ => { - warn!("RDRand not supported."); - // Try rdseed - match unsafe { _rdseed32_step(&mut out) } { - 1 => out, - _ => panic!("Neither RDRand or RDSeed are supported"), - } - } - } -} - pub fn get_edid() {} #[allow(unused)] diff --git a/kernel/src/bootmodules.rs b/kernel/src/bootmodules.rs index b8595eea..81d15b48 100644 --- a/kernel/src/bootmodules.rs +++ b/kernel/src/bootmodules.rs @@ -1,20 +1,20 @@ use { // crate::alloc::string::ToString, - alloc::{string::String, vec::Vec}, + alloc::vec::Vec, // clparse::Arguments, // core::fmt::{Debug, Display}, // log::trace, // xml::XMLElement, }; -pub type BootModules = Vec; +pub type BootModules<'a> = Vec>; -pub struct BootModule { - pub path: String, - pub bytes: Vec, - pub cmd: String, +pub struct BootModule<'a> { + pub path: &'a str, + pub bytes: &'a [u8], + pub cmd: &'a str, } -impl BootModule { - pub fn new(path: String, bytes: Vec, cmd: String) -> Self { +impl<'a> BootModule<'a> { + pub fn new(path: &'a str, bytes: &'a [u8], cmd: &'a str) -> Self { Self { path, bytes, cmd } } } diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs index 50f12d6e..e18ee18c 100644 --- a/kernel/src/holeybytes/ecah.rs +++ b/kernel/src/holeybytes/ecah.rs @@ -5,7 +5,6 @@ use crate::holeybytes::kernel_services::{block_read, service_definition_service: use { super::Vm, crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS}, - alloc::string::String, log::{debug, error, info, trace, warn}, }; @@ -79,26 +78,19 @@ pub fn handler(vm: &mut Vm) { Err(_) => {} } } + #[cfg(not(target_arch = "x86_64"))] + 3 => info!("TODO: implement whatever buffer 3 does for no x86_64"), + #[cfg(target_arch = "x86_64")] 3 => { - unsafe fn x86_in(address: u16) -> u8 { - x86_64::instructions::port::Port::new(address).read() - } - unsafe fn x86_in_16(address: u16) -> u16 { - x86_64::instructions::port::Port::new(address).read() - } - unsafe fn x86_in_32(address: u16) -> u32 { - x86_64::instructions::port::Port::new(address).read() - } - unsafe fn x86_out(address: u16, value: u8) { + unsafe fn x86_out( + address: u16, + value: T, + ) { x86_64::instructions::port::Port::new(address).write(value); } - unsafe fn x86_out_16(address: u16, value: u16) { - x86_64::instructions::port::Port::new(address).write(value); + unsafe fn x86_in(address: u16) -> T { + x86_64::instructions::port::Port::new(address).read() } - unsafe fn x86_out_32(address: u16, value: u32) { - x86_64::instructions::port::Port::new(address).write(value); - } - let msg_vec = block_read(mem_addr, length); let msg_type = msg_vec[0]; match msg_type { @@ -115,9 +107,9 @@ pub fn handler(vm: &mut Vm) { let addr = u16::from_le_bytes(msg_vec[1..3].try_into().unwrap()); let value = unsafe { match size { - 1 => x86_in(addr) as u64, - 2 => x86_in_16(addr) as u64, - 4 => x86_in_32(addr) as u64, + 1 => x86_in::(addr) as u64, + 2 => x86_in::(addr) as u64, + 4 => x86_in::(addr) as u64, _ => panic!("how?"), } }; @@ -141,13 +133,13 @@ pub fn handler(vm: &mut Vm) { unsafe { match size { 1 => x86_out(addr, msg_vec[3]), - 2 => x86_out_16( + 2 => x86_out( addr, u16::from_le_bytes( msg_vec[3..5].try_into().unwrap_unchecked(), ), ), - 4 => x86_out_32( + 4 => x86_out( addr, u32::from_le_bytes( msg_vec[3..7].try_into().unwrap_unchecked(), @@ -162,7 +154,18 @@ pub fn handler(vm: &mut Vm) { } // source of rng 4 => { - vm.registers[1] = hbvm::value::Value(crate::arch::hardware_random_u32() as u64); + // limit to last 32 bits + vm.registers[1] = + hbvm::value::Value(crate::arch::hardware_random_u64() & 0xFFFFFFFF); + } + 5 => { + if cfg!(target_arch = "x86_64") { + vm.registers[1] = hbvm::value::Value(0); + } else if cfg!(target_arch = "aarch64") { + vm.registers[1] = hbvm::value::Value(1); + } else { + vm.registers[1] = hbvm::value::Value(u64::MAX) + } } buffer_id => { let mut buffs = IPC_BUFFERS.lock(); @@ -247,10 +250,10 @@ pub fn handler(vm: &mut Vm) { fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> { // let message_length = 8 + 8 + 8; // log::info!("Mem Addr 0x{:x?} length {}", mem_addr, length); - let mut msg_vec = block_read(mem_addr, length); + let msg_vec = block_read(mem_addr, length); - let log_level = msg_vec.pop().unwrap(); - match String::from_utf8(msg_vec) { + let log_level = msg_vec.last().unwrap(); + match core::str::from_utf8(&msg_vec[1..]) { Ok(strr) => { // use LogLevel::*; let _ll = match log_level { diff --git a/kernel/src/holeybytes/kernel_services/mod.rs b/kernel/src/holeybytes/kernel_services/mod.rs index c08f2ac9..8c80f498 100644 --- a/kernel/src/holeybytes/kernel_services/mod.rs +++ b/kernel/src/holeybytes/kernel_services/mod.rs @@ -1,15 +1,9 @@ -use alloc::vec::Vec; +use core::slice; pub mod mem_serve; pub mod service_definition_service; -pub fn block_read(mem_addr: u64, length: usize) -> Vec { - let mut msg_vec = Vec::with_capacity(length); - let xyz = mem_addr as *const u8; - - for x in 0..(length as isize) { - let value = unsafe { xyz.offset(x).read() }; - msg_vec.push(value); - } - msg_vec +#[inline(always)] +pub fn block_read<'a>(mem_addr: u64, length: usize) -> &'a [u8] { + unsafe { slice::from_raw_parts(mem_addr as *const u8, length) } } diff --git a/kernel/src/holeybytes/kernel_services/service_definition_service.rs b/kernel/src/holeybytes/kernel_services/service_definition_service.rs index 0a8f696c..3382f1b5 100644 --- a/kernel/src/holeybytes/kernel_services/service_definition_service.rs +++ b/kernel/src/holeybytes/kernel_services/service_definition_service.rs @@ -5,12 +5,11 @@ use { ipc::{buffer::IpcBuffer, protocol::Protocol}, kmain::IPC_BUFFERS, }, - alloc::string::String, hashbrown::HashMap, log::{info, trace}, spin::{lazy::Lazy, Mutex}, }; -pub struct Services(HashMap); +pub struct Services<'a>(HashMap>); pub static SERVICES: Lazy> = Lazy::new(|| { let mut dt = Services(HashMap::new()); dt.0.insert(0, Protocol::void()); @@ -18,25 +17,26 @@ pub static SERVICES: Lazy> = Lazy::new(|| { }); pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> { - let mut msg_vec = block_read(mem_addr, length); + let msg_vec = block_read(mem_addr, length); if msg_vec.is_empty() { return Err(LogError::NoMessages); } let sds_event_type: ServiceEventType = msg_vec[0].into(); - msg_vec.remove(0); // info!("Length {}", msg_vec.len()); use ServiceEventType::*; match sds_event_type { CreateService => { - let string = String::from_utf8(msg_vec).expect("Our bytes should be valid utf8"); + let string = + core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8"); let ret = sds_create_service(string); vm.registers[1] = hbvm::value::Value(ret as u64); } DeleteService => todo!(), SearchServices => { - let string = String::from_utf8(msg_vec).expect("Our bytes should be valid utf8"); + let string = + core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8"); let ret = sds_search_service(string); vm.registers[1] = hbvm::value::Value(ret as u64); } @@ -78,16 +78,16 @@ impl From for ServiceEventType { } } -fn sds_create_service(protocol: String) -> u64 { +fn sds_create_service(protocol: &'static str) -> u64 { let buff_id = hardware_random_u64(); let mut services = SERVICES.lock(); let mut buffers = IPC_BUFFERS.lock(); - let protocol_ = Protocol::from(protocol.clone()); + let protocol_ = Protocol::from(protocol); let mut buff = IpcBuffer::new(false, 0); services.0.insert(buff_id, protocol_.clone()); - buff.protocol = protocol_.clone(); + buff.protocol = protocol_; buffers.insert(buff_id, buff); trace!("BufferID({}) => {}", buff_id, protocol); @@ -95,13 +95,13 @@ fn sds_create_service(protocol: String) -> u64 { buff_id } -fn sds_search_service(protocol: String) -> u64 { +fn sds_search_service(protocol: &str) -> u64 { let services = SERVICES.lock(); - let compare = Protocol::from(protocol.clone()); + let compare = Protocol::from(protocol); for (bid, protocol_canidate) in &services.0 { trace!("BID-{bid} protocol_canidate {:?}", protocol_canidate); if protocol_canidate == &compare { - trace!("BufferID({}) => {}", bid, protocol.clone()); + trace!("BufferID({}) => {}", bid, protocol); return *bid; } } diff --git a/kernel/src/holeybytes/mod.rs b/kernel/src/holeybytes/mod.rs index 77dad395..aecadd3c 100644 --- a/kernel/src/holeybytes/mod.rs +++ b/kernel/src/holeybytes/mod.rs @@ -3,12 +3,11 @@ mod kernel_services; mod mem; use { + alloc::alloc::{alloc_zeroed, dealloc}, core::{ alloc::Layout, future::Future, - marker::PhantomData, pin::Pin, - ptr::NonNull, task::{Context, Poll}, }, hbvm::{ @@ -22,21 +21,20 @@ const STACK_SIZE: usize = 1024 * 1024; const TIMER_QUOTIENT: usize = 1000; type Vm = hbvm::Vm; -pub struct ExecThread<'p> { +pub struct ExecThread { vm: Vm, - stack_bottom: NonNull, - _phantom: PhantomData<&'p [u8]>, + stack_bottom: *mut u8, } -unsafe impl<'p> Send for ExecThread<'p> {} +unsafe impl Send for ExecThread {} -impl<'p> ExecThread<'p> { +impl ExecThread { pub fn set_arguments(&mut self, ptr: u64, length: u64) { self.vm.registers[1] = hbvm::value::Value(ptr); self.vm.registers[2] = hbvm::value::Value(length); } - pub unsafe fn new(program: &'p [u8], entrypoint: Address) -> Self { + pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self { let mut vm = Vm::new( mem::Memory {}, Address::new(program.as_ptr() as u64 + entrypoint.get()), @@ -44,27 +42,21 @@ impl<'p> ExecThread<'p> { let stack_bottom = allocate_stack(); - vm.write_reg( - 254, - (stack_bottom.as_ptr() as usize + STACK_SIZE - 1) as u64, - ); + vm.write_reg(254, (stack_bottom as usize + STACK_SIZE - 1) as u64); - ExecThread { - vm, - stack_bottom, - _phantom: PhantomData, - } + ExecThread { vm, stack_bottom } } } -impl<'p> Drop for ExecThread<'p> { +impl<'p> Drop for ExecThread { fn drop(&mut self) { - unsafe { alloc::alloc::dealloc(self.stack_bottom.as_ptr(), stack_layout()) }; + unsafe { dealloc(self.stack_bottom, stack_layout()) }; } } -impl<'p> Future for ExecThread<'p> { +impl<'p> Future for ExecThread { type Output = Result<(), VmRunError>; + #[inline(always)] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.vm.run() { @@ -105,7 +97,6 @@ impl HandlePageFault for PageFaultHandler { dataptr: *mut u8, ) -> bool { error!("REASON: {reason} vaddr: {vaddr} size: {size:?} Dataptr {dataptr:p}"); - false } } @@ -116,8 +107,6 @@ const fn stack_layout() -> Layout { } #[inline(always)] -fn allocate_stack() -> NonNull { - let layout = stack_layout(); - NonNull::new(unsafe { alloc::alloc::alloc_zeroed(layout) }) - .unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout)) +fn allocate_stack() -> *mut u8 { + unsafe { alloc_zeroed(stack_layout()) } } diff --git a/kernel/src/ipc/buffer.rs b/kernel/src/ipc/buffer.rs index bdbfce9d..a7c19204 100644 --- a/kernel/src/ipc/buffer.rs +++ b/kernel/src/ipc/buffer.rs @@ -9,12 +9,12 @@ pub enum BufferTypes { Bound(ArrayQueue), } /// Interproccess buffer -pub struct IpcBuffer { - pub protocol: Protocol, +pub struct IpcBuffer<'a> { + pub protocol: Protocol<'a>, pub buffer: BufferTypes, } -impl IpcBuffer { +impl<'a> IpcBuffer<'a> { pub fn new(bounded: bool, length: u64) -> Self { log::debug!( "New IPCBuffer\r diff --git a/kernel/src/ipc/protocol.rs b/kernel/src/ipc/protocol.rs index 1b45a9e9..0e8427ed 100644 --- a/kernel/src/ipc/protocol.rs +++ b/kernel/src/ipc/protocol.rs @@ -10,11 +10,11 @@ pub struct Funct { gives: Vec, } #[derive(Debug, PartialEq, Clone)] -pub struct Protocol { - types: HashMap, - fns: HashMap, +pub struct Protocol<'a> { + types: HashMap<&'a str, Type>, + fns: HashMap<&'a str, Funct>, } -impl Protocol { +impl<'a> Protocol<'a> { pub fn void() -> Self { Self { types: HashMap::new(), @@ -27,8 +27,8 @@ impl Protocol { } } -impl From for Protocol { - fn from(value: alloc::string::String) -> Self { +impl<'a> From<&'a str> for Protocol<'a> { + fn from(value: &'a str) -> Self { let mut hm_t = HashMap::new(); hm_t.insert(value, Type {}); Self { diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs index 7543345d..dcd2ad80 100644 --- a/kernel/src/kmain.rs +++ b/kernel/src/kmain.rs @@ -72,25 +72,24 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { for module in boot_modules.into_iter().take(bm_take) { let mut cmd = module.cmd; if cmd.len() > 2 { - // Remove the quotes - cmd.remove(0); - cmd.pop(); + // // Remove the quotes + // cmd.remove(0); + // cmd.pop(); + cmd = &cmd[1..cmd.len()] } - let cmd_len = cmd.as_bytes().len() as u64; + let cmd_len = cmd.len() as u64; log::info!("Spawning {} with arguments \"{}\"", module.path, cmd); - executor - .spawn(async move { - let mut thr = ExecThread::new(&module.bytes, Address::new(0)); - if cmd_len > 0 { - thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len); - } - if let Err(e) = thr.await { - log::error!("{e:?}"); - } - }) - .unwrap(); + executor.spawn(async move { + let mut thr = ExecThread::new(&module.bytes, Address::new(0)); + if cmd_len > 0 { + thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len); + } + if let Err(e) = thr.await { + log::error!("{e:?}"); + } + }) } info!("Random number: {}", hardware_random_u64()); @@ -107,7 +106,7 @@ pub static DEVICE_TREE: Lazy> = Lazy::new(|| { }); pub static FB_REQ: FramebufferRequest = FramebufferRequest::new(0); -pub type IpcBuffers = HashMap; +pub type IpcBuffers<'a> = HashMap>; pub static IPC_BUFFERS: Lazy> = Lazy::new(|| { let mut bufs = HashMap::new(); let log_buffer = IpcBuffer::new(false, 0); diff --git a/kernel/src/task.rs b/kernel/src/task.rs index 8db84d1b..241f64c5 100644 --- a/kernel/src/task.rs +++ b/kernel/src/task.rs @@ -1,17 +1,14 @@ use { - alloc::{boxed::Box, sync::Arc, task::Wake}, + alloc::{boxed::Box, sync::Arc}, core::{ future::Future, pin::Pin, - sync::atomic::{AtomicUsize, Ordering}, - task::{Context, Poll, Waker}, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }, crossbeam_queue::SegQueue, - crossbeam_utils::CachePadded, + slab::Slab, }; -use alloc::vec::Vec; - pub fn yield_now() -> impl Future { struct YieldNow(bool); impl Future for YieldNow { @@ -32,37 +29,34 @@ pub fn yield_now() -> impl Future { YieldNow(false) } -#[derive(Default)] -pub struct Executor { - tasks: Vec>, +pub struct Executor + Send> { + tasks: Slab>, task_queue: Arc, - max_tasks: usize, } -impl Executor { - pub fn new(max_tasks: usize) -> Self { +impl + Send> Executor { + pub fn new(size: usize) -> Self { Self { - tasks: (0..max_tasks) - .map(|_| CachePadded::new(TaskSlot::default())) - .collect(), - task_queue: Arc::new(TaskQueue::new(max_tasks)), - max_tasks, + tasks: Slab::with_capacity(size), + task_queue: Arc::new(TaskQueue::new()), } } - pub fn spawn(&mut self, future: impl Future + Send + 'static) -> Result<(), ()> { - let task_id = self.task_queue.allocate_task_id().ok_or(())?; - self.tasks[task_id.0].lock.replace(Task::new(future)); - self.task_queue.push(task_id); - Ok(()) + #[inline] + pub fn spawn(&mut self, future: F) { + self.task_queue + .queue + .push(self.tasks.insert(Task::new(future))); } pub fn run(&mut self) { - let mut task_batch = Vec::with_capacity(16); + let mut task_batch = [0; 32]; + let mut batch_len = 0; loop { - self.task_queue.batch_pop(&mut task_batch); - if task_batch.is_empty() { + self.task_queue.batch_pop(&mut task_batch, &mut batch_len); + + if batch_len == 0 { if self.task_queue.is_empty() { break; } else { @@ -70,23 +64,18 @@ impl Executor { } } - for id in task_batch.drain(..) { - let task_slot = &mut self.tasks[id.0]; + for &id in &task_batch[..batch_len] { + if let Some(task) = self.tasks.get_mut(id) { + let waker = task + .waker + .get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue))); - let mut task_opt = task_slot.lock.take(); - if let Some(task) = &mut task_opt { - let waker = task_slot.waker.get_or_insert_with(|| { - Arc::new(TaskWaker::new(id, Arc::clone(&self.task_queue))) - }); - - let waker = Waker::from(Arc::clone(waker)); + let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) }; let mut cx = Context::from_waker(&waker); if let Poll::Ready(()) = task.poll(&mut cx) { - task_slot.waker = None; - self.task_queue.free_task_id(id); - } else { - task_slot.lock.replace(task_opt.take().unwrap()); + self.tasks.remove(id); + self.task_queue.free_tasks.push(id); } } } @@ -94,21 +83,17 @@ impl Executor { } } -#[derive(Default)] -struct TaskSlot { - lock: Option, - waker: Option>, +struct Task + Send> { + future: Pin>, + waker: Option, } -struct Task { - future: Pin + Send>>, -} - -impl Task { +impl + Send> Task { #[inline(always)] - pub fn new(future: impl Future + Send + 'static) -> Self { + pub fn new(future: F) -> Self { Self { future: Box::pin(future), + waker: None, } } @@ -118,77 +103,69 @@ impl Task { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -struct TaskId(usize); - struct TaskWaker { - id: TaskId, + id: usize, task_queue: Arc, } impl TaskWaker { #[inline(always)] - pub fn new(id: TaskId, task_queue: Arc) -> Self { + fn new(id: usize, task_queue: Arc) -> Self { Self { id, task_queue } } -} -impl Wake for TaskWaker { #[inline(always)] - fn wake(self: Arc) { - self.task_queue.push(self.id); + fn wake(&self) { + self.task_queue.queue.push(self.id); } - #[inline(always)] - fn wake_by_ref(self: &Arc) { - self.task_queue.push(self.id); + fn into_raw_waker(waker: &TaskWaker) -> RawWaker { + let ptr = waker as *const TaskWaker; + RawWaker::new(ptr.cast(), &VTABLE) } } -#[derive(Default)] +const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw); + +unsafe fn clone_raw(ptr: *const ()) -> RawWaker { + let waker = &*(ptr as *const TaskWaker); + TaskWaker::into_raw_waker(waker) +} + +unsafe fn wake_raw(ptr: *const ()) { + let waker = &*(ptr as *const TaskWaker); + waker.wake(); +} + +unsafe fn wake_by_ref_raw(ptr: *const ()) { + let waker = &*(ptr as *const TaskWaker); + waker.wake(); +} + +unsafe fn drop_raw(_: *const ()) {} + struct TaskQueue { - queue: SegQueue, - next_task: AtomicUsize, - max_tasks: usize, - free_tasks: SegQueue, + queue: SegQueue, + next_task: usize, + free_tasks: SegQueue, } impl TaskQueue { - fn new(max_tasks: usize) -> Self { + fn new() -> Self { Self { - queue: SegQueue::new(), - next_task: AtomicUsize::new(0), - max_tasks, + queue: SegQueue::new(), + next_task: 0, free_tasks: SegQueue::new(), } } - fn allocate_task_id(&self) -> Option { - self.free_tasks.pop().or_else(|| { - let id = self.next_task.fetch_add(1, Ordering::Relaxed); - if id < self.max_tasks { - Some(TaskId(id)) - } else { - None - } - }) - } - #[inline(always)] - fn free_task_id(&self, id: TaskId) { - self.free_tasks.push(id); - } - - #[inline(always)] - fn push(&self, id: TaskId) { - self.queue.push(id); - } - - #[inline(always)] - fn batch_pop(&self, output: &mut Vec) { + fn batch_pop(&self, output: &mut [usize], len: &mut usize) { + *len = 0; while let Some(id) = self.queue.pop() { - output.push(id); - if output.len() >= output.capacity() { + output[*len] = id; + *len += 1; + if *len == output.len() { break; } } diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs index 3e3ad95b..02c1b8d7 100644 --- a/repbuild/src/main.rs +++ b/repbuild/src/main.rs @@ -370,7 +370,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> { #[rustfmt::skip] com.args([ "-M", "virt", - "-cpu", "cortex-a72", + "-cpu", "max", "-device", "ramfb", "-device", "qemu-xhci", "-device", "usb-kbd", diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index 6a082455..4354131b 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -29,8 +29,7 @@ total_pages := 1 + fb_bytes >> 12 front_buffer := @as(^Color, @bitcast(0xFFFF8000C0000000)) // jank back buffer time, im sure nothing will go wrong -// will be removed as soon as i can figure out a fast way of doing runtime global scope -back_buffer := @as(^Color, @bitcast(0xFFFF8000C0000000 + fb_bytes)) +back_buffer := front_buffer + fb_pixels create_back_buffer := fn(): ^Color { if total_pages <= 0xFF { @@ -50,25 +49,26 @@ create_back_buffer := fn(): ^Color { } clear := fn(color: Color): void { - n := 0 - loop if n == 512 break else { - *(back_buffer + n) = color - n += 1 + cursor := back_buffer + boundary := cursor + 512 + loop if cursor == boundary break else { + *cursor = color + cursor += 1 } - n = 1 - loop if n == 8 break else { - *(@as(^[Color; 512], @bitcast(back_buffer)) + n) = *@as(^[Color; 512], @bitcast(back_buffer)) - n += 1 + boundary += 512 * 7 + loop if cursor == boundary break else { + *@as(^[Color; 512], @bitcast(cursor)) = *@as(^[Color; 512], @bitcast(back_buffer)) + cursor += 512 } - n = 1 - loop if n == copy_pixels >> 12 break else { - *(@as(^[Color; 4096], @bitcast(back_buffer)) + n) = *@as(^[Color; 4096], @bitcast(back_buffer)) - n += 1 + boundary += copy_pixels - 4096 + loop if cursor == boundary break else { + *@as(^[Color; 4096], @bitcast(cursor)) = *@as(^[Color; 4096], @bitcast(back_buffer)) + cursor += 4096 } - n = 1 - loop if n == partitions break else { - *(@as(^[Color; copy_pixels], @bitcast(back_buffer)) + n) = *@as(^[Color; copy_pixels], @bitcast(back_buffer)) - n += 1 + boundary += (partitions - 1) * copy_pixels + loop if cursor == boundary break else { + *@as(^[Color; copy_pixels], @bitcast(cursor)) = *@as(^[Color; copy_pixels], @bitcast(back_buffer)) + cursor += @sizeof([u8; copy_pixels]) } return } @@ -214,6 +214,13 @@ set_dimensions := fn(new: IVec2): void { } init := fn(): void { + arch := @eca(int, 3, 5) + // 0: x86_64, 1: aarch64, 2: riscv, (2^64)-1: other + if arch == 0 { + front_buffer = @as(^Color, @bitcast(0xFFFF8000C0000000)) + } else if arch == 1 { + front_buffer = @as(^Color, @bitcast(0xFFFF8000BC430000)) + } back_buffer = create_back_buffer() return } \ No newline at end of file diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb index 35b2706e..336f76d1 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1,4 +1,4 @@ -.{example} := @use("./examples/amogus.hb") +.{example} := @use("./examples/random.hb") main := fn(): void { @inline(example) diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index 380f7916..d90a7fb5 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -23,14 +23,14 @@ resolution = "1024x768x24" [boot.limine.ableos.modules.1render_driver] path = "boot:///render_driver.hbf" -[boot.limine.ableos.modules.0serial_driver] -path = "boot:///serial_driver.hbf" +# [boot.limine.ableos.modules.0serial_driver] +# path = "boot:///serial_driver.hbf" -[boot.limine.ableos.modules.diskio_driver] -path = "boot:///diskio_driver.hbf" +# [boot.limine.ableos.modules.diskio_driver] +# path = "boot:///diskio_driver.hbf" [boot.limine.ableos.modules.render_example] path = "boot:///render_example.hbf" -[boot.limine.ableos.modules.serial_driver_test] -path = "boot:///serial_driver_test.hbf" +# [boot.limine.ableos.modules.serial_driver_test] +# path = "boot:///serial_driver_test.hbf"