diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index a6a298e..ce15e8a 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -83,7 +83,6 @@ dependencies = [ "bootloader_api", "embedded-graphics", "lazy_static", - "linked_list_allocator", "pc-keyboard", "pic8259", "uart_16550", @@ -99,25 +98,6 @@ dependencies = [ "spin", ] -[[package]] -name = "linked_list_allocator" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" -dependencies = [ - "spinning_top", -] - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "micromath" version = "2.1.0" @@ -163,27 +143,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spinning_top" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" -dependencies = [ - "lock_api", -] - [[package]] name = "uart_16550" version = "0.3.0" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c4c4207..0b05781 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -11,7 +11,6 @@ bench = false [dependencies] embedded-graphics = "0.8.1" pc-keyboard = "0.5.0" -linked_list_allocator = "0.10.5" [target.'cfg(target_arch = "x86_64")'.dependencies] pic8259 = "0.10.1" diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs index f82ad94..40209fa 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/allocator.rs @@ -1,30 +1,60 @@ -use core::alloc::Allocator; +use core::{alloc::GlobalAlloc, ops::Range, ptr::null_mut}; + +use crate::util::mutex::Mutex; #[global_allocator] -static ALLOCATOR: Alloc = Alloc::empty(); +static ALLOCATOR: LockedHeap = LockedHeap::empty(); -struct Alloc { - base: *mut u8, +struct Heap { cur: *mut u8, + end: *mut u8, } -unsafe impl Allocator for Alloc { - fn allocate(&self, layout: core::alloc::Layout) -> Result, core::alloc::AllocError> { - +impl Heap { + pub const fn empty() -> Self { + Self { + cur: null_mut(), + end: null_mut(), + } + } + + pub fn init(&mut self, start: *mut u8, end: *mut u8) { + self.cur = start; + self.end = end; } } -impl Alloc { - pub fn empty() -> Self { +pub fn init_heap(range: Range<*mut u8>) { + ALLOCATOR.init(range.start, range.end); +} + +struct LockedHeap(Mutex); + +// should look into why I need this, didn't see it in linked list alloc crate +unsafe impl Sync for LockedHeap {} + +impl LockedHeap { + pub const fn empty() -> Self { + Self(Mutex::new(Heap::empty())) } - - pub fn init(&mut self, start: *mut u8, len: usize) { - + pub fn init(&self, start: *mut u8, end: *mut u8) { + self.0.lock().init(start, end); } } -pub fn init_heap() { - unsafe { - ALLOCATOR.init(crate::arch::paging::first_free(), crate::arch::paging::free_len()); +unsafe impl GlobalAlloc for LockedHeap { + unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 { + // blazing fast implementation :sunglasses: + // (gonna switch to my own linked list later) + let mut heap = self.0.lock(); + let pointer = heap.cur; + heap.cur = heap.cur.add(layout.size()); + if heap.cur >= heap.end { + return null_mut(); + } + return pointer; + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) { + // bet ur impl is slower } } diff --git a/kernel/src/arch/riscv64/init.rs b/kernel/src/arch/riscv64/init.rs index f186d4c..4c02e57 100644 --- a/kernel/src/arch/riscv64/init.rs +++ b/kernel/src/arch/riscv64/init.rs @@ -1,4 +1,4 @@ -use core::ptr::null_mut; +use core::{arch::asm, ops::Range}; use crate::{ arch::{asm, csr, interrupts, paging, wait}, @@ -6,13 +6,11 @@ use crate::{ main, }; -static mut DT_ADDR: *mut FDT = null_mut(); - #[no_mangle] #[link_section = ".text.init"] #[naked] unsafe extern "C" fn _start() -> ! { - core::arch::asm!( + asm!( // disable interrupts "csrw mie, zero", // set up gp & sp @@ -32,10 +30,15 @@ unsafe extern "C" fn _start() -> ! { "csrw mstatus, t0", "la t0, {init}", "csrw mepc, t0", - "la ra, 2f", "mret", - "2:", + init = sym init, + options(noreturn) + ); +} + +pub unsafe fn to_supervisor() { + asm!( "li t0, (1 << 8) | (1 << 5)", "csrw sstatus, t0", "li t0, (7 << 0) | (1 << 3)", @@ -45,18 +48,14 @@ unsafe extern "C" fn _start() -> ! { "li t2, (1 << 1) | (1 << 5) | (1 << 9)", "csrw mideleg, t2", "csrw sie, t2", - "la t0, {start}", + "mv t0, ra", "csrw sepc, t0", "sfence.vma", "sret", - - start = sym start, - init = sym init, - options(noreturn) ); } -pub fn init() { +pub unsafe fn init() -> ! { let dt_addr = asm::reg!("a1") as *mut u8; let hart = csr::hartid::read(); if hart != 0 { @@ -64,9 +63,12 @@ pub fn init() { } interrupts::init(); let fdt = FDT::from_addr(dt_addr); - paging::init(fdt); -} - -pub fn start() { - main(unsafe { DT_ADDR }); + let raw_mem_range = fdt.mem_range(); + let heap_start = paging::init(raw_mem_range.end()); + let heap_mem = Range { + start: heap_start, + end: raw_mem_range.end(), + }; + to_supervisor(); + main(heap_mem, fdt); } diff --git a/kernel/src/arch/riscv64/mem.rs b/kernel/src/arch/riscv64/mem.rs new file mode 100644 index 0000000..527ccc8 --- /dev/null +++ b/kernel/src/arch/riscv64/mem.rs @@ -0,0 +1,3 @@ +use super::asm::linker_static; + +linker_static!(PROGRAM_END: usize, ".dword _end"); diff --git a/kernel/src/arch/riscv64/mod.rs b/kernel/src/arch/riscv64/mod.rs index 3118c12..e0f2f3a 100644 --- a/kernel/src/arch/riscv64/mod.rs +++ b/kernel/src/arch/riscv64/mod.rs @@ -4,6 +4,7 @@ pub mod asm; pub mod interrupts; pub mod paging; pub mod qemu; +pub mod mem; pub fn wait() -> ! { loop { diff --git a/kernel/src/arch/riscv64/paging.rs b/kernel/src/arch/riscv64/paging.rs index 304db3d..c62127b 100644 --- a/kernel/src/arch/riscv64/paging.rs +++ b/kernel/src/arch/riscv64/paging.rs @@ -1,20 +1,15 @@ -use super::asm::linker_static; use crate::{ arch::csr::{self, satp}, - fdt::FDT, - println, util::bits::get_bits, }; -use core::{ptr::null_mut, slice}; +use core::slice; + +use super::mem::PROGRAM_END; -linker_static!(END: usize, ".dword _end"); const PAGE_SIZE: usize = 4096; const TABLE_LEN: usize = 2usize.pow(9); const TABLE_SIZE: usize = core::mem::size_of::(); -static mut FIRST_FREE: *mut u8 = null_mut(); -static mut MEM_END: *mut u8 = null_mut(); - #[repr(C)] pub struct Entry(usize); @@ -53,19 +48,12 @@ pub struct Table { pub entries: [Entry; TABLE_LEN], } -pub fn init(fdt: FDT) { +pub fn init(mem_end: *mut u8) -> *mut u8 { unsafe { - println!("program end: 0x{:x}", END); - let range = fdt.mem_range(); - let start = range.start.get(); - let len = range.len.get(); - let end = start + len; - MEM_END = end as *mut u8; - println!("memory range: 0x{:x} -> 0x{:x}", start, end); - let total_pages = end / 4096; + let total_pages = mem_end as usize / 4096; let lvl1_count = (total_pages.saturating_sub(1)) / TABLE_LEN + 1; let lvl2_count = (lvl1_count.saturating_sub(1)) / TABLE_LEN + 1; - let lvl2 = &mut *(END as *mut Table); + let lvl2 = &mut *(PROGRAM_END as *mut Table); let lvl1_arr = slice::from_raw_parts_mut((lvl2 as *mut Table).add(TABLE_SIZE), lvl2_count); let lvl0_arr = slice::from_raw_parts_mut( lvl1_arr.as_ptr().add(lvl1_arr.len()) as *mut Table, @@ -106,10 +94,8 @@ pub fn init(fdt: FDT) { asid: 0, ppn: lvl2, }); - let satp = csr::satp::read(); - println!("satp: {satp:?}"); - let end = lvl0_arr.as_ptr().add(lvl0_arr.len()) as *mut u8; - FIRST_FREE = end; + let table_end = lvl0_arr.as_ptr().add(lvl0_arr.len()) as *mut u8; + table_end } } @@ -128,11 +114,3 @@ pub fn virt_to_physical(table: &Table, addr: usize) -> usize { addr } } - -pub fn first_free() -> *mut u8 { - unsafe { FIRST_FREE } -} - -pub fn free_len() -> usize { - unsafe { MEM_END.offset_from(FIRST_FREE) as usize } -} diff --git a/kernel/src/dev/mod.rs b/kernel/src/dev/mod.rs new file mode 100644 index 0000000..8c20360 --- /dev/null +++ b/kernel/src/dev/mod.rs @@ -0,0 +1 @@ +pub mod uart; diff --git a/kernel/src/dev/uart.rs b/kernel/src/dev/uart.rs new file mode 100644 index 0000000..e69de29 diff --git a/kernel/src/fdt.rs b/kernel/src/fdt.rs index a8a82c3..77c680c 100644 --- a/kernel/src/fdt.rs +++ b/kernel/src/fdt.rs @@ -1,14 +1,11 @@ -// NOTE: basically none of this is safe rn, ideally it's eventually made safe / able to recover -// also, I do a ton of slice.try_into and then transmuting which I'm pretty sure is bad and -// I really should be transmuting into references but I cannot be bothered rn +// garbage .1% finished FDT implementation use crate::{ println, util::bits::{u32_from_bytes, Be}, }; use core::{ - mem::{size_of, transmute}, - slice, + fmt::Debug, mem::{size_of, transmute}, ops::Range, slice }; const MAGIC: u32 = 0xd00dfeed; @@ -161,12 +158,12 @@ impl FDT { } } } - pub fn mem_range(&self) -> MemRange { + pub fn mem_range(&self) -> FDTMemRange { if let Some(node) = self.into_iter().find(|n| n.name.starts_with("memory@")) { let prop = node.find_prop("reg"); if let Some(prop) = prop { - for d in prop.data.chunks(size_of::()) { - let d: [u8; size_of::()] = d.try_into().unwrap(); + for d in prop.data.chunks(size_of::()) { + let d: [u8; size_of::()] = d.try_into().unwrap(); // just return first one for now return unsafe { transmute(d) }; } @@ -177,11 +174,38 @@ impl FDT { } #[repr(C)] -pub struct MemRange { - pub start: Be, +pub struct FDTMemRange { + pub start: Be<*mut u8>, pub len: Be, } +impl FDTMemRange { + pub fn start(&self) -> *mut u8 { + self.start.get() + } + pub fn len(&self) -> usize { + self.len.get() + } + pub fn end(&self) -> *mut u8 { + unsafe { self.start().add(self.len.get()) } + } +} + +impl Debug for FDTMemRange { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}..{:?}", self.start(), self.end()) + } +} + +impl Into> for FDTMemRange { + fn into(self) -> Range<*mut u8> { + Range { + start: self.start(), + end: self.end(), + } + } +} + pub struct Node { pub name: &'static str, pub strings: &'static [u8], diff --git a/kernel/src/main.rs b/kernel/src/main.rs index d1e4c4b..6edf2fc 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -4,6 +4,8 @@ #![feature(naked_functions)] #![feature(fn_align)] +use core::ops::Range; + use fdt::FDT; extern crate alloc; @@ -14,10 +16,16 @@ pub mod fdt; pub mod log; pub mod qemu; pub mod util; +pub mod dev; -pub fn main(dt_addr: *mut FDT) -> ! { +pub fn main(heap_mem: Range<*mut u8>, fdt: FDT) -> ! { println!("we out here vibin"); - allocator::init_heap(); + println!("memory range: {:?}", fdt.mem_range()); + println!("heap range: {:?}", heap_mem); + for node in &fdt { + + } + allocator::init_heap(heap_mem); let mut test = alloc::vec![1, 2, 3]; test.push(3); println!("{:?}", test); @@ -25,6 +33,10 @@ pub fn main(dt_addr: *mut FDT) -> ! { let x = *(0x3000 as *const u8); println!("{}", x); } + for i in 0..10000 { + let test2: alloc::vec::Vec = alloc::vec::Vec::with_capacity(10_000_000); + println!("{}", i); + } // for _ in 0..40000000 {} // let x = unsafe { *(0x10000000000 as *mut u8) }; // println!("we got {x}"); diff --git a/kernel/src/util/bits.rs b/kernel/src/util/bits.rs index 237aba2..f07001c 100644 --- a/kernel/src/util/bits.rs +++ b/kernel/src/util/bits.rs @@ -1,4 +1,7 @@ -use core::mem::transmute; +use core::{ + fmt::{Debug, Display}, + mem::transmute, +}; macro_rules! get_bits { ($name:ident[$high:expr,$low:expr]) => {{ @@ -38,6 +41,24 @@ impl BeRep for usize { } } +impl BeRep for *mut u8 { + fn _from_be(&self) -> Self { + (*self as usize).to_be() as *mut u8 + } +} + +impl Debug for Be { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self.get()) + } +} + +impl Display for Be { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.get()) + } +} + pub fn u32_from_bytes(bytes: &[u8]) -> Option { if bytes.len() < 4 { return None; diff --git a/runner/src/main.rs b/runner/src/main.rs index a431ebf..2d38e87 100644 --- a/runner/src/main.rs +++ b/runner/src/main.rs @@ -27,7 +27,7 @@ fn main() { fn run_qemu(target: &Target, gdb: Option>) { let mut qemu = target.qemu(); qemu.args(["-d", "guest_errors"]); - qemu.args(["-m", "4G"]); + qemu.args(["-m", "1G"]); qemu.args(["-monitor", "telnet:127.0.0.1:1235,server,nowait"]); if let Some(port) = gdb { let port = port.unwrap_or(1234);