FINALLY PAGING AND HEAP WORK WITH REALLY BAD CODE
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user