FINALLY PAGING AND HEAP WORK WITH REALLY BAD CODE
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
[build]
|
[build]
|
||||||
# rustflags = ["-g"]
|
# rustflags = ["-g"]
|
||||||
target = ["riscv64gc-unknown-none-elf", "x86_64-unknown-none"]
|
# target = ["riscv64gc-unknown-none-elf", "x86_64-unknown-none"]
|
||||||
|
target = ["riscv64gc-unknown-none-elf"]
|
||||||
|
|
||||||
[target.riscv64gc-unknown-none-elf]
|
[target.riscv64gc-unknown-none-elf]
|
||||||
rustflags = [
|
rustflags = [
|
||||||
|
|||||||
@@ -3,11 +3,8 @@ use linked_list_allocator::LockedHeap;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||||
|
|
||||||
pub const HEAP_START: *mut u8 = 0x9000_0000 as *mut u8;
|
|
||||||
pub const HEAP_SIZE: usize = 100 * 1024;
|
|
||||||
|
|
||||||
pub fn init_heap() {
|
pub fn init_heap() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE);
|
ALLOCATOR.lock().init(crate::arch::paging::first_free(), crate::arch::paging::free_len());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,3 +27,7 @@ pub(crate) use linker_static;
|
|||||||
pub fn wfi() {
|
pub fn wfi() {
|
||||||
unsafe { asm!("wfi") }
|
unsafe { asm!("wfi") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn mret() {
|
||||||
|
asm!("mret");
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
macro_rules! csrr {
|
macro_rules! csrr {
|
||||||
($name:expr) => {{
|
($name:expr) => {{
|
||||||
let mut out: u64;
|
let mut out: u64;
|
||||||
unsafe {
|
core::arch::asm!(
|
||||||
core::arch::asm!(
|
concat!("csrr {out}, ", $name),
|
||||||
concat!("csrr {out}, ", $name),
|
out = out(reg) out,
|
||||||
out = out(reg) out,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
out
|
out
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@@ -35,15 +33,9 @@ macro_rules! csrw {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! bits {
|
|
||||||
($name:ident[$high:expr,$low:expr]) => {{
|
|
||||||
($name & ((2u64.pow($high - $low + 1) - 1) << $low)) >> $low
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod hartid {
|
pub mod hartid {
|
||||||
pub fn read() -> u64 {
|
pub fn read() -> u64 {
|
||||||
csrr!("mhartid")
|
unsafe { csrr!("mhartid") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,20 +48,60 @@ pub mod mtvec {
|
|||||||
}
|
}
|
||||||
pub(crate) use init;
|
pub(crate) use init;
|
||||||
pub fn read() -> u64 {
|
pub fn read() -> u64 {
|
||||||
csrr!("mtvec")
|
unsafe { csrr!("mtvec") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod mcause {
|
pub mod mcause {
|
||||||
pub fn read() -> u64 {
|
use core::mem::transmute;
|
||||||
csrr!("mcause")
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MCause {
|
||||||
|
// interrupt = 1
|
||||||
|
SupervisorSoftwareInterrupt = (1 << 63) | 1,
|
||||||
|
VirtualSupervisorSoftwareInterrupt = (1 << 63) | 2,
|
||||||
|
MachineSoftwareInterrupt = (1 << 63) | 3,
|
||||||
|
|
||||||
|
SupervisorTimerInterrupt = (1 << 63) | 5,
|
||||||
|
VirtualSupervisorTimerInterrupt = (1 << 63) | 6,
|
||||||
|
MachineTimerInterrupt = (1 << 63) | 7,
|
||||||
|
|
||||||
|
SupervisorExternalInterrupt = (1 << 63) | 9,
|
||||||
|
VirtualSupervisorExternalInterrupt = (1 << 63) | 10,
|
||||||
|
MachineExternalInterrupt = (1 << 63) | 11,
|
||||||
|
|
||||||
|
SupervisorGuestExternalInterrupt = (1 << 63) | 12,
|
||||||
|
|
||||||
|
// interrupt = 0
|
||||||
|
InstructionAddrMisaligned = 0,
|
||||||
|
InstructionAccessFault = 1,
|
||||||
|
IllegalInstruction = 2,
|
||||||
|
Breakpoint = 3,
|
||||||
|
LoadAddressMisaligned = 4,
|
||||||
|
LoadAccessFault = 5,
|
||||||
|
StoreAMOAddressMisaligned = 6,
|
||||||
|
StoreAMOAccessFault = 7,
|
||||||
|
EnvCallUorVU = 8,
|
||||||
|
EnvCallHS = 9,
|
||||||
|
EnvCallVS = 10,
|
||||||
|
EnvCallM = 11,
|
||||||
|
InstructionPageFault = 12,
|
||||||
|
LoadPageFault = 13,
|
||||||
|
StoreAMOPageFault = 15,
|
||||||
|
InstructionGuestPageFault = 20,
|
||||||
|
LoadGuestPageFault = 21,
|
||||||
|
VirtualInstruction = 22,
|
||||||
|
StoreAMOGuestPageFault = 23,
|
||||||
|
}
|
||||||
|
pub fn read() -> MCause {
|
||||||
|
unsafe { transmute(csrr!("mcause")) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod satp {
|
pub mod satp {
|
||||||
use core::mem::transmute;
|
use core::mem::transmute;
|
||||||
|
|
||||||
use crate::arch::paging::Table;
|
use crate::{arch::paging::Table, util::bits::get_bits};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
@@ -98,10 +130,10 @@ pub mod satp {
|
|||||||
pub ppn: *mut Table,
|
pub ppn: *mut Table,
|
||||||
}
|
}
|
||||||
pub fn read() -> Satp {
|
pub fn read() -> Satp {
|
||||||
let satp = csrr!("satp");
|
let satp = unsafe { csrr!("satp") };
|
||||||
let mode = unsafe { transmute(bits!(satp[63,60])) };
|
let mode = unsafe { transmute(get_bits!(satp[63,60])) };
|
||||||
let asid = bits!(satp[59, 44]);
|
let asid = get_bits!(satp[59, 44]);
|
||||||
let ppn = unsafe { transmute(bits!(satp[43, 0]) << 12) };
|
let ppn = unsafe { transmute(get_bits!(satp[43, 0]) << 12) };
|
||||||
Satp { mode, asid, ppn }
|
Satp { mode, asid, ppn }
|
||||||
}
|
}
|
||||||
pub fn write(satp: Satp) {
|
pub fn write(satp: Satp) {
|
||||||
@@ -109,3 +141,12 @@ pub mod satp {
|
|||||||
csrw!("satp", val);
|
csrw!("satp", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod mstatus {
|
||||||
|
pub fn read() -> u64 {
|
||||||
|
unsafe { csrr!("mstatus") }
|
||||||
|
}
|
||||||
|
pub fn write(val: u64) {
|
||||||
|
csrw!("mstatus", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{asm, csr, interrupts, paging, wait}, main, println
|
arch::{asm, csr, interrupts, paging, wait},
|
||||||
|
fdt::FDT,
|
||||||
|
main,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static mut DT_ADDR: *mut FDT = null_mut();
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[link_section = ".text.init"]
|
#[link_section = ".text.init"]
|
||||||
#[naked]
|
#[naked]
|
||||||
@@ -18,25 +24,47 @@ unsafe extern "C" fn _start() -> ! {
|
|||||||
"slli t0, t0, 12",
|
"slli t0, t0, 12",
|
||||||
"sub sp, sp, t0",
|
"sub sp, sp, t0",
|
||||||
// continue to rest of program
|
// continue to rest of program
|
||||||
"tail {entry}",
|
// "tail {entry}",
|
||||||
|
// ok so this should be done in rust
|
||||||
|
"li t0, 0b11 << 11",
|
||||||
|
"csrw mstatus, t0",
|
||||||
|
"la t0, {init}",
|
||||||
|
"csrw mepc, t0",
|
||||||
|
"la ra, 2f",
|
||||||
|
"mret",
|
||||||
|
|
||||||
entry = sym entry,
|
"2:",
|
||||||
|
"li t0, (1 << 8) | (1 << 5)",
|
||||||
|
"csrw sstatus, t0",
|
||||||
|
"li t0, (7 << 0) | (1 << 3)",
|
||||||
|
"csrw pmpcfg0, t0",
|
||||||
|
"li t0, 0xffffffffffff",
|
||||||
|
"csrw pmpaddr0, t0",
|
||||||
|
"li t2, (1 << 1) | (1 << 5) | (1 << 9)",
|
||||||
|
"csrw mideleg, t2",
|
||||||
|
"csrw sie, t2",
|
||||||
|
"la t0, {start}",
|
||||||
|
"csrw sepc, t0",
|
||||||
|
"sfence.vma",
|
||||||
|
"sret",
|
||||||
|
|
||||||
|
start = sym start,
|
||||||
|
init = sym init,
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entry() -> ! {
|
pub fn init() {
|
||||||
let dt_addr = asm::reg!("a1") as usize;
|
let dt_addr = asm::reg!("a1") as *mut u8;
|
||||||
let hart = csr::hartid::read();
|
let hart = csr::hartid::read();
|
||||||
println!("yo from hart {hart}");
|
|
||||||
if hart != 0 {
|
if hart != 0 {
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
interrupts::init();
|
interrupts::init();
|
||||||
paging::init(dt_addr);
|
let fdt = FDT::from_addr(dt_addr);
|
||||||
println!(
|
paging::init(fdt);
|
||||||
"machine trap vector base address: 0x{:x}",
|
}
|
||||||
csr::mtvec::read()
|
|
||||||
);
|
pub fn start() {
|
||||||
main(dt_addr)
|
main(unsafe { DT_ADDR });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ pub fn init() {
|
|||||||
#[repr(align(4))]
|
#[repr(align(4))]
|
||||||
pub fn stuff() -> ! {
|
pub fn stuff() -> ! {
|
||||||
let mcause = csr::mcause::read();
|
let mcause = csr::mcause::read();
|
||||||
crate::println!("interrupt triggered: {mcause}");
|
crate::println!("interrupt triggered: {mcause:?}");
|
||||||
super::qemu::exit();
|
super::qemu::exit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ SECTIONS
|
|||||||
. += 0x8000;
|
. += 0x8000;
|
||||||
PROVIDE(_stack_end = .);
|
PROVIDE(_stack_end = .);
|
||||||
. = ALIGN(4096); /* 2^12 */
|
. = ALIGN(4096); /* 2^12 */
|
||||||
PROVIDE(_heap_start = .);
|
PROVIDE(_end = .);
|
||||||
. += 0x20000000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,138 @@
|
|||||||
|
use super::asm::linker_static;
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::csr::{self, satp},
|
arch::csr::{self, satp},
|
||||||
fdt::print_mem_layout,
|
fdt::FDT,
|
||||||
println,
|
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 mut FIRST_FREE: *mut u8 = null_mut();
|
||||||
static HEAP_SIZE: usize = 128 * 1024 * 1024;
|
static mut MEM_END: *mut u8 = null_mut();
|
||||||
|
|
||||||
pub struct Entry(u64);
|
#[repr(C)]
|
||||||
|
pub struct Entry(usize);
|
||||||
|
|
||||||
pub struct Table {
|
impl Entry {
|
||||||
pub entries: [Entry; 2usize.pow(9)],
|
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 {
|
unsafe {
|
||||||
println!("heap start: 0x{:x}", HEAP_START);
|
println!("program end: 0x{:x}", END);
|
||||||
print_mem_layout(fdt);
|
let range = fdt.mem_range();
|
||||||
let table_start = HEAP_START as *mut Table;
|
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 {
|
csr::satp::write(satp::Satp {
|
||||||
mode: satp::Mode::Sv39,
|
mode: satp::Mode::Sv39,
|
||||||
asid: 0,
|
asid: 0,
|
||||||
ppn: table_start,
|
ppn: lvl2,
|
||||||
});
|
});
|
||||||
let satp = csr::satp::read();
|
let satp = csr::satp::read();
|
||||||
println!("satp: {satp:?}");
|
println!("satp: {satp:?}");
|
||||||
let x = *(0x9000_0000 as *mut u8);
|
let end = lvl0_arr.as_ptr().add(lvl0_arr.len()) as *mut u8;
|
||||||
println!("we got {x}");
|
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 }
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use crate::main;
|
|
||||||
|
|
||||||
pub mod framebuffer;
|
pub mod framebuffer;
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
@@ -13,7 +11,9 @@ fn _start(boot_info: &'static mut bootloader_api::BootInfo) -> ! {
|
|||||||
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
|
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
|
||||||
framebuffer::draw_test(framebuffer);
|
framebuffer::draw_test(framebuffer);
|
||||||
}
|
}
|
||||||
main(0);
|
// not working on this anymore for now
|
||||||
|
// main(null_mut());
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hlt_loop() -> ! {
|
pub fn hlt_loop() -> ! {
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
// NOTE: basically none of this is safe rn, ideally it's eventually made safe / able to recover
|
// 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
|
||||||
|
|
||||||
use crate::{print, println};
|
use crate::{
|
||||||
|
println,
|
||||||
|
util::bits::{u32_from_bytes, Be},
|
||||||
|
};
|
||||||
use core::{
|
use core::{
|
||||||
mem::{size_of, transmute},
|
mem::{size_of, transmute},
|
||||||
slice,
|
slice,
|
||||||
@@ -11,257 +16,222 @@ const MAGIC: u32 = 0xd00dfeed;
|
|||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum Token {
|
enum Token {
|
||||||
BeginNode = 0x00000001,
|
BeginNode,
|
||||||
EndNode = 0x00000002,
|
EndNode,
|
||||||
Prop = 0x00000003,
|
Prop,
|
||||||
Nop = 0x00000004,
|
Nop,
|
||||||
End = 0x00000009,
|
End,
|
||||||
}
|
}
|
||||||
const TOKEN_SIZE: usize = size_of::<Token>();
|
const TOKEN_SIZE: usize = size_of::<Token>();
|
||||||
impl Token {
|
impl Token {
|
||||||
pub fn from_bytes(data: &[u8]) -> Self {
|
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
|
||||||
unsafe { transmute(be_32::<TOKEN_SIZE>(data)) }
|
let val = u32_from_bytes(bytes)?.to_be();
|
||||||
|
Some(match val {
|
||||||
|
0x00000001 => Token::BeginNode,
|
||||||
|
0x00000002 => Token::EndNode,
|
||||||
|
0x00000003 => Token::Prop,
|
||||||
|
0x00000004 => Token::Nop,
|
||||||
|
0x00000009 => Token::End,
|
||||||
|
_ => {
|
||||||
|
println!("Failed to parse token!");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
pub magic: u32,
|
pub magic: Be<u32>,
|
||||||
pub totalsize: u32,
|
pub totalsize: Be<u32>,
|
||||||
pub off_dt_struct: u32,
|
pub off_dt_struct: Be<u32>,
|
||||||
pub off_dt_strings: u32,
|
pub off_dt_strings: Be<u32>,
|
||||||
pub off_mem_rsvmap: u32,
|
pub off_mem_rsvmap: Be<u32>,
|
||||||
pub version: u32,
|
pub version: Be<u32>,
|
||||||
pub last_comp_version: u32,
|
pub last_comp_version: Be<u32>,
|
||||||
pub boot_cpuid_phys: u32,
|
pub boot_cpuid_phys: Be<u32>,
|
||||||
pub size_dt_strings: u32,
|
pub size_dt_strings: Be<u32>,
|
||||||
pub size_dt_struct: u32,
|
pub size_dt_struct: Be<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HEADER_SIZE: usize = size_of::<Header>();
|
const PROP_SIZE: usize = size_of::<RawProp>();
|
||||||
impl Header {
|
pub struct RawProp {
|
||||||
pub fn from_addr(addr: usize) -> Self {
|
len: Be<u32>,
|
||||||
unsafe { transmute(from_be_32::<HEADER_SIZE>(addr)) }
|
nameoff: Be<u32>,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PROP_SIZE: usize = size_of::<Prop>();
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Prop {
|
pub struct Prop {
|
||||||
len: u32,
|
pub name: &'static str,
|
||||||
nameoff: u32,
|
pub data: &'static [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Prop {
|
impl Prop {
|
||||||
pub fn from_bytes(data: &[u8]) -> Self {
|
pub fn full_len(&self) -> usize {
|
||||||
unsafe { transmute(be_32::<PROP_SIZE>(data)) }
|
return PROP_SIZE + self.data.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FDT {
|
pub struct FDT {
|
||||||
pub header: Header,
|
pub header: &'static Header,
|
||||||
}
|
|
||||||
|
|
||||||
impl FDT {
|
|
||||||
pub fn new(addr: usize) -> Self {
|
|
||||||
let header = Header::from_addr(addr);
|
|
||||||
Self { header }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RawFDT {
|
|
||||||
pub header: Header,
|
|
||||||
pub nodes: &'static [u8],
|
pub nodes: &'static [u8],
|
||||||
pub strings: &'static [u8],
|
pub strings: &'static [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawFDT {
|
impl IntoIterator for &FDT {
|
||||||
pub fn new(addr: usize) -> Self {
|
type Item = Node;
|
||||||
let header = Header::from_addr(addr);
|
type IntoIter = NodeIter;
|
||||||
let data = unsafe { slice::from_raw_parts(addr as *mut u8, header.totalsize as usize) };
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
Self {
|
Self::IntoIter {
|
||||||
header,
|
pos: self.nodes,
|
||||||
nodes: &data[header.off_dt_struct as usize..],
|
strings: self.strings,
|
||||||
strings: &data[header.off_dt_strings as usize..],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn print_all(&self) {
|
|
||||||
let mut pos = self.nodes;
|
|
||||||
loop {
|
|
||||||
let token: Token = Token::from_bytes(pos);
|
|
||||||
pos = &pos[4..];
|
|
||||||
if let Token::End = token {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if let Token::EndNode = token {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
print!("name: ");
|
|
||||||
'outer: loop {
|
|
||||||
let bytes = &pos[..4];
|
|
||||||
pos = &pos[4..];
|
|
||||||
for byte in bytes {
|
|
||||||
if *byte == 0 {
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
let c = *byte as char;
|
|
||||||
print!("{}", c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
let node = RawNode {
|
|
||||||
data: pos,
|
|
||||||
strings: self.strings,
|
|
||||||
};
|
|
||||||
pos = node.print_props();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_node(&self, str: &str) -> Option<RawNode> {
|
|
||||||
let mut pos = self.nodes;
|
|
||||||
loop {
|
|
||||||
let token: Token = Token::from_bytes(pos);
|
|
||||||
pos = &pos[4..];
|
|
||||||
if let Token::End = token {
|
|
||||||
break None;
|
|
||||||
}
|
|
||||||
if let Token::EndNode = token {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut i = 0;
|
|
||||||
let check = str.as_bytes();
|
|
||||||
let mut failed = false;
|
|
||||||
'outer: loop {
|
|
||||||
let bytes = &pos[..4];
|
|
||||||
pos = &pos[4..];
|
|
||||||
for byte in bytes {
|
|
||||||
if *byte == 0 {
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
if i < check.len() && check[i] != *byte {
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let node = RawNode {
|
|
||||||
data: pos,
|
|
||||||
strings: self.strings,
|
|
||||||
};
|
|
||||||
if !failed && i >= check.len() {
|
|
||||||
return Some(node);
|
|
||||||
}
|
|
||||||
pos = node.pass_props();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RawNode {
|
pub struct NodeIter {
|
||||||
|
pub pos: &'static [u8],
|
||||||
pub strings: &'static [u8],
|
pub strings: &'static [u8],
|
||||||
pub data: &'static [u8],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawNode {
|
impl Iterator for NodeIter {
|
||||||
pub fn get_prop(&self, str: &str) -> Option<&'static [u8]> {
|
type Item = Node;
|
||||||
let mut pos = self.data;
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
let token: Token = Token::from_bytes(self.pos)?;
|
||||||
let token: Token = Token::from_bytes(pos);
|
self.pos = &self.pos[4..];
|
||||||
let Token::Prop = token else {
|
if let Token::End = token {
|
||||||
break None;
|
return None;
|
||||||
};
|
}
|
||||||
pos = &pos[4..];
|
let name_start = self.pos;
|
||||||
let prop: Prop = Prop::from_bytes(pos);
|
'outer: loop {
|
||||||
let name_bytes = &self.strings[prop.nameoff as usize..];
|
let bytes = &self.pos[..4];
|
||||||
let mut i = 0;
|
self.pos = &self.pos[4..];
|
||||||
let mut failed = false;
|
for byte in bytes {
|
||||||
let check = str.as_bytes();
|
|
||||||
for byte in name_bytes {
|
|
||||||
if *byte == 0 {
|
if *byte == 0 {
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let name = unsafe { transmute(&name_start[..name_start.len() - self.pos.len()]) };
|
||||||
|
let node_start = self.pos;
|
||||||
|
let node_data = if let Some(prop) = (PropIter {
|
||||||
|
strings: self.strings,
|
||||||
|
pos: self.pos,
|
||||||
|
})
|
||||||
|
.last()
|
||||||
|
{
|
||||||
|
let node_len =
|
||||||
|
(prop.data.as_ptr() as usize + prop.data.len()) - self.pos.as_ptr() as usize;
|
||||||
|
self.pos = &self.pos[node_len..];
|
||||||
|
&node_start[..node_len]
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
let node = Node {
|
||||||
|
name,
|
||||||
|
props: node_data,
|
||||||
|
strings: self.strings,
|
||||||
|
};
|
||||||
|
loop {
|
||||||
|
if let Some(token) = Token::from_bytes(self.pos) {
|
||||||
|
if let Token::EndNode = token {
|
||||||
|
self.pos = &self.pos[4..];
|
||||||
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if i < check.len() && check[i] != *byte {
|
} else {
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
pos = &pos[PROP_SIZE..];
|
|
||||||
if !failed && i >= check.len() {
|
|
||||||
return Some(&pos[..prop.len as usize]);
|
|
||||||
}
|
|
||||||
let len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
|
|
||||||
pos = &pos[len..];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn print_props(&self) -> &'static [u8] {
|
|
||||||
let mut pos = self.data;
|
|
||||||
loop {
|
|
||||||
let token: Token = Token::from_bytes(pos);
|
|
||||||
let Token::Prop = token else {
|
|
||||||
break;
|
break;
|
||||||
};
|
}
|
||||||
pos = &pos[4..];
|
}
|
||||||
let prop: Prop = Prop::from_bytes(pos);
|
Some(node)
|
||||||
let name_bytes = &self.strings[prop.nameoff as usize..];
|
}
|
||||||
print!(" ");
|
}
|
||||||
for byte in name_bytes {
|
|
||||||
if *byte == 0 {
|
impl FDT {
|
||||||
break;
|
pub fn from_addr(addr: *mut u8) -> Self {
|
||||||
|
unsafe {
|
||||||
|
let header: &Header = transmute(addr);
|
||||||
|
if header.magic.get() != MAGIC {
|
||||||
|
panic!("fdt magic wrong");
|
||||||
|
}
|
||||||
|
let data = slice::from_raw_parts(addr as *mut u8, header.totalsize.get() as usize);
|
||||||
|
Self {
|
||||||
|
header,
|
||||||
|
nodes: &data[header.off_dt_struct.get() as usize..],
|
||||||
|
strings: &data[header.off_dt_strings.get() as usize..],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn mem_range(&self) -> MemRange {
|
||||||
|
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();
|
||||||
|
// just return first one for now
|
||||||
|
return unsafe { transmute(d) };
|
||||||
}
|
}
|
||||||
let c = *byte as char;
|
|
||||||
print!("{}", c);
|
|
||||||
}
|
|
||||||
println!(": {prop:?}");
|
|
||||||
let aligned_len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
|
|
||||||
pos = &pos[PROP_SIZE + aligned_len..];
|
|
||||||
}
|
|
||||||
pos
|
|
||||||
}
|
|
||||||
pub fn pass_props(&self) -> &'static [u8] {
|
|
||||||
let mut pos = self.data;
|
|
||||||
loop {
|
|
||||||
let token: Token = Token::from_bytes(pos);
|
|
||||||
let Token::Prop = token else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
pos = &pos[4..];
|
|
||||||
let prop: Prop = Prop::from_bytes(pos);
|
|
||||||
let aligned_len = (prop.len as usize + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
|
|
||||||
pos = &pos[PROP_SIZE + aligned_len..];
|
|
||||||
}
|
|
||||||
pos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_mem_layout(addr: usize) {
|
|
||||||
let fdt = RawFDT::new(addr);
|
|
||||||
fdt.print_all();
|
|
||||||
if let Some(node) = fdt.find_node("memory") {
|
|
||||||
println!("mem:");
|
|
||||||
let data = node.get_prop("reg");
|
|
||||||
if let Some(data) = data {
|
|
||||||
for d in data.chunks(8) {
|
|
||||||
let mut arr: [u8; 8] = d.try_into().unwrap();
|
|
||||||
let num: u64 = unsafe { transmute(arr) };
|
|
||||||
println!("0x{:x}", num.to_be());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
panic!("failed to get memory range");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn from_be_32<const S: usize>(addr: usize) -> [u8; S] {
|
#[repr(C)]
|
||||||
let mut data = *(addr as *mut [u8; S]);
|
pub struct MemRange {
|
||||||
for slice in data.chunks_mut(4) {
|
pub start: Be<usize>,
|
||||||
slice.reverse();
|
pub len: Be<usize>,
|
||||||
}
|
|
||||||
data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn be_32<const S: usize>(data: &[u8]) -> [u8; S] {
|
pub struct Node {
|
||||||
let data: &[u8; S] = data[..S].try_into().unwrap();
|
pub name: &'static str,
|
||||||
let mut data = (*data).clone();
|
pub strings: &'static [u8],
|
||||||
for slice in data.chunks_mut(4) {
|
pub props: &'static [u8],
|
||||||
slice.reverse();
|
}
|
||||||
}
|
|
||||||
data
|
impl IntoIterator for &Node {
|
||||||
|
type Item = Prop;
|
||||||
|
type IntoIter = PropIter;
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
Self::IntoIter {
|
||||||
|
pos: self.props,
|
||||||
|
strings: self.strings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PropIter {
|
||||||
|
pub strings: &'static [u8],
|
||||||
|
pub pos: &'static [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PropIter {
|
||||||
|
type Item = Prop;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let token: Token = Token::from_bytes(self.pos)?;
|
||||||
|
let Token::Prop = token else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
self.pos = &self.pos[4..];
|
||||||
|
let prop: &RawProp = unsafe { transmute(self.pos.as_ptr()) };
|
||||||
|
self.pos = &self.pos[PROP_SIZE..];
|
||||||
|
let plen = prop.len.get() as usize;
|
||||||
|
let len = (plen + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
|
||||||
|
let data = &self.pos[..len];
|
||||||
|
self.pos = &self.pos[len..];
|
||||||
|
let name_start = &self.strings[prop.nameoff.get() as usize..];
|
||||||
|
for (i, c) in name_start.iter().enumerate() {
|
||||||
|
if *c == 0 {
|
||||||
|
let name: &str = unsafe { transmute(&name_start[..i]) };
|
||||||
|
return Some(Prop { name, data });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("failed to read prop name, not sure what to do");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node {
|
||||||
|
pub fn find_prop(&self, name: &str) -> Option<Prop> {
|
||||||
|
self.into_iter().find(|p| p.name == name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(fn_align)]
|
#![feature(fn_align)]
|
||||||
|
|
||||||
|
use fdt::FDT;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod allocator;
|
pub mod allocator;
|
||||||
@@ -11,14 +13,17 @@ pub mod arch;
|
|||||||
pub mod fdt;
|
pub mod fdt;
|
||||||
pub mod log;
|
pub mod log;
|
||||||
pub mod qemu;
|
pub mod qemu;
|
||||||
|
pub mod util;
|
||||||
|
|
||||||
pub fn main(dt_addr: usize) -> ! {
|
pub fn main(dt_addr: *mut FDT) -> ! {
|
||||||
println!("we out here vibin");
|
println!("we out here vibin");
|
||||||
allocator::init_heap();
|
allocator::init_heap();
|
||||||
let fdt = fdt::FDT::new(dt_addr);
|
let mut test = alloc::vec![1, 2, 3];
|
||||||
|
test.push(3);
|
||||||
|
println!("{:?}", test);
|
||||||
// for _ in 0..40000000 {}
|
// for _ in 0..40000000 {}
|
||||||
let x = unsafe { *(0xdeadbeef as *mut u8) };
|
// let x = unsafe { *(0x10000000000 as *mut u8) };
|
||||||
println!("we got {x}");
|
// println!("we got {x}");
|
||||||
qemu::exit();
|
qemu::exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
46
kernel/src/util/bits.rs
Normal file
46
kernel/src/util/bits.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use core::mem::transmute;
|
||||||
|
|
||||||
|
macro_rules! get_bits {
|
||||||
|
($name:ident[$high:expr,$low:expr]) => {{
|
||||||
|
($name & ((($name - $name + 2).pow($high - $low + 1) - 1) << $low)) >> $low
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
pub(crate) use get_bits;
|
||||||
|
|
||||||
|
pub trait BeRep {
|
||||||
|
fn _from_be(&self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Be<T: BeRep>(T);
|
||||||
|
impl<T: BeRep> Be<T> {
|
||||||
|
pub fn get(&self) -> T {
|
||||||
|
self.0._from_be()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BeRep for u32 {
|
||||||
|
fn _from_be(&self) -> Self {
|
||||||
|
self.to_be()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BeRep for u64 {
|
||||||
|
fn _from_be(&self) -> Self {
|
||||||
|
self.to_be()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BeRep for usize {
|
||||||
|
fn _from_be(&self) -> Self {
|
||||||
|
self.to_be()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn u32_from_bytes(bytes: &[u8]) -> Option<u32> {
|
||||||
|
if bytes.len() < 4 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
unsafe { Some(transmute([bytes[0], bytes[1], bytes[2], bytes[3]])) }
|
||||||
|
}
|
||||||
1
kernel/src/util/mod.rs
Normal file
1
kernel/src/util/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod bits;
|
||||||
@@ -28,7 +28,7 @@ fn run_qemu(target: &Target, gdb: Option<Option<u16>>) {
|
|||||||
let mut qemu = target.qemu();
|
let mut qemu = target.qemu();
|
||||||
qemu.args(["-d", "guest_errors"]);
|
qemu.args(["-d", "guest_errors"]);
|
||||||
qemu.args(["-m", "4G"]);
|
qemu.args(["-m", "4G"]);
|
||||||
// qemu.args(["-monitor", "telnet:127.0.0.1:1235,server,nowait"]);
|
qemu.args(["-monitor", "telnet:127.0.0.1:1235,server,nowait"]);
|
||||||
if let Some(port) = gdb {
|
if let Some(port) = gdb {
|
||||||
let port = port.unwrap_or(1234);
|
let port = port.unwrap_or(1234);
|
||||||
qemu.arg("-S");
|
qemu.arg("-S");
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ impl Target {
|
|||||||
let mut cmd = Command::new("qemu-system-riscv64");
|
let mut cmd = Command::new("qemu-system-riscv64");
|
||||||
cmd.arg("-nographic");
|
cmd.arg("-nographic");
|
||||||
cmd.arg("-semihosting");
|
cmd.arg("-semihosting");
|
||||||
|
cmd.args(["-cpu", "rv64"]);
|
||||||
cmd.args(["-machine", "virt"]);
|
cmd.args(["-machine", "virt"]);
|
||||||
cmd.args(["-bios", "none"]);
|
cmd.args(["-bios", "none"]);
|
||||||
cmd.args(["-smp", "4"]);
|
cmd.args(["-smp", "4"]);
|
||||||
|
|||||||
Reference in New Issue
Block a user