clean up and use own heap

This commit is contained in:
Bryan McShea
2024-02-16 02:26:23 -05:00
parent 167b095bd1
commit 05e9433ceb
13 changed files with 148 additions and 112 deletions

View File

@@ -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::ptr::NonNull<[u8]>, 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<Heap>);
// 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
}
}

View File

@@ -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);
}

View File

@@ -0,0 +1,3 @@
use super::asm::linker_static;
linker_static!(PROGRAM_END: usize, ".dword _end");

View File

@@ -4,6 +4,7 @@ pub mod asm;
pub mod interrupts;
pub mod paging;
pub mod qemu;
pub mod mem;
pub fn wait() -> ! {
loop {

View File

@@ -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::<Table>();
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 }
}

1
kernel/src/dev/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod uart;

0
kernel/src/dev/uart.rs Normal file
View File

View File

@@ -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::<MemRange>()) {
let d: [u8; size_of::<MemRange>()] = d.try_into().unwrap();
for d in prop.data.chunks(size_of::<FDTMemRange>()) {
let d: [u8; size_of::<FDTMemRange>()] = 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<usize>,
pub struct FDTMemRange {
pub start: Be<*mut u8>,
pub len: Be<usize>,
}
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<Range<*mut u8>> 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],

View File

@@ -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<i32> = 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}");

View File

@@ -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<T: Debug + BeRep> Debug for Be<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}", self.get())
}
}
impl<T: Display + BeRep> Display for Be<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.get())
}
}
pub fn u32_from_bytes(bytes: &[u8]) -> Option<u32> {
if bytes.len() < 4 {
return None;