FINALLY PAGING AND HEAP WORK WITH REALLY BAD CODE

This commit is contained in:
Bryan McShea
2024-01-28 19:11:27 -05:00
parent 260c5c223a
commit f9e7f85a8c
15 changed files with 472 additions and 274 deletions
+119 -14
View File
@@ -1,33 +1,138 @@
use super::asm::linker_static;
use crate::{
arch::csr::{self, satp},
fdt::print_mem_layout,
fdt::FDT,
println,
util::bits::get_bits,
};
use core::{ptr::null_mut, slice};
use super::asm::linker_static;
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>();
linker_static!(HEAP_START: usize, ".dword _heap_start");
static HEAP_SIZE: usize = 128 * 1024 * 1024;
static mut FIRST_FREE: *mut u8 = null_mut();
static mut MEM_END: *mut u8 = null_mut();
pub struct Entry(u64);
#[repr(C)]
pub struct Entry(usize);
pub struct Table {
pub entries: [Entry; 2usize.pow(9)],
impl Entry {
pub fn set_table(&mut self, addr: *const Table) {
self.0 = addr as usize >> 2;
self.set_valid(true);
}
pub fn set_valid(&mut self, valid: bool) {
if valid {
self.0 |= 1;
} else {
self.0 &= !1;
}
}
pub fn set_addr(&mut self, addr: usize) {
self.clear();
self.0 |= addr as usize >> 2;
self.0 |= 0b1110;
self.set_valid(true);
}
pub fn get_table(&self) -> *const Table {
((self.0 & !0b1111111111) << 2) as *const Table
}
pub fn get_addr(&self) -> usize {
let val = self.0;
get_bits!(val[53,10]) << 12
}
pub fn clear(&mut self) {
self.0 = 0;
}
}
pub fn init(fdt: usize) {
#[repr(C, align(4096))]
pub struct Table {
pub entries: [Entry; TABLE_LEN],
}
pub fn init(fdt: FDT) {
unsafe {
println!("heap start: 0x{:x}", HEAP_START);
print_mem_layout(fdt);
let table_start = HEAP_START as *mut Table;
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 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 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,
lvl1_count,
);
let mut lvl1itr = lvl1_arr.iter();
for entry in &mut lvl2.entries {
if let Some(table) = lvl1itr.next() {
entry.set_table(table as *const Table);
} else {
entry.clear();
}
}
let mut lvl0itr = lvl0_arr.iter();
for lvl1 in lvl1_arr {
for entry in &mut lvl1.entries {
if let Some(table) = lvl0itr.next() {
entry.set_table(table as *const Table);
} else {
entry.clear();
}
}
}
let mut i = 0;
for lvl0 in &mut *lvl0_arr {
for entry in &mut lvl0.entries {
if i < total_pages {
entry.set_addr(i * PAGE_SIZE);
} else {
entry.clear()
}
i += 1;
}
}
csr::satp::write(satp::Satp {
mode: satp::Mode::Sv39,
asid: 0,
ppn: table_start,
ppn: lvl2,
});
let satp = csr::satp::read();
println!("satp: {satp:?}");
let x = *(0x9000_0000 as *mut u8);
println!("we got {x}");
let end = lvl0_arr.as_ptr().add(lvl0_arr.len()) as *mut u8;
FIRST_FREE = end;
}
}
pub fn virt_to_physical(table: &Table, addr: usize) -> usize {
let ppn2 = get_bits!(addr[38,30]);
let ppn1 = get_bits!(addr[29,21]);
let ppn0 = get_bits!(addr[20,12]);
let offset = get_bits!(addr[11,0]);
// let satp = csr::satp::read();
unsafe {
let lvl2 = table as *const Table;
let lvl1 = (*lvl2).entries[ppn2].get_table();
let lvl0 = (*lvl1).entries[ppn1].get_table();
let base = (*lvl0).entries[ppn0].get_addr();
let addr = base + offset;
addr
}
}
pub fn first_free() -> *mut u8 {
unsafe { FIRST_FREE }
}
pub fn free_len() -> usize {
unsafe { MEM_END.offset_from(FIRST_FREE) as usize }
}