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

View File

@@ -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 = [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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() -> ! {

View File

@@ -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::IntoIter {
pos: self.nodes,
strings: self.strings,
}
}
}
pub struct NodeIter {
pub pos: &'static [u8],
pub strings: &'static [u8],
}
impl Iterator for NodeIter {
type Item = Node;
fn next(&mut self) -> Option<Self::Item> {
let token: Token = Token::from_bytes(self.pos)?;
self.pos = &self.pos[4..];
if let Token::End = token {
return None;
}
let name_start = self.pos;
'outer: loop {
let bytes = &self.pos[..4];
self.pos = &self.pos[4..];
for byte in bytes {
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;
}
} else {
break;
}
}
Some(node)
}
}
impl FDT {
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 { Self {
header, header,
nodes: &data[header.off_dt_struct as usize..], nodes: &data[header.off_dt_struct.get() as usize..],
strings: &data[header.off_dt_strings as usize..], strings: &data[header.off_dt_strings.get() 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 { pub fn mem_range(&self) -> MemRange {
continue; if let Some(node) = self.into_iter().find(|n| n.name.starts_with("memory@")) {
} let prop = node.find_prop("reg");
print!("name: "); if let Some(prop) = prop {
'outer: loop { for d in prop.data.chunks(size_of::<MemRange>()) {
let bytes = &pos[..4]; let d: [u8; size_of::<MemRange>()] = d.try_into().unwrap();
pos = &pos[4..]; // just return first one for now
for byte in bytes { return unsafe { transmute(d) };
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();
} }
panic!("failed to get memory range");
} }
} }
pub struct RawNode { #[repr(C)]
pub struct MemRange {
pub start: Be<usize>,
pub len: Be<usize>,
}
pub struct Node {
pub name: &'static str,
pub strings: &'static [u8], pub strings: &'static [u8],
pub data: &'static [u8], pub props: &'static [u8],
} }
impl RawNode { impl IntoIterator for &Node {
pub fn get_prop(&self, str: &str) -> Option<&'static [u8]> { type Item = Prop;
let mut pos = self.data; type IntoIter = PropIter;
loop { fn into_iter(self) -> Self::IntoIter {
let token: Token = Token::from_bytes(pos); 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 { let Token::Prop = token else {
break None; return None;
}; };
pos = &pos[4..]; self.pos = &self.pos[4..];
let prop: Prop = Prop::from_bytes(pos); let prop: &RawProp = unsafe { transmute(self.pos.as_ptr()) };
let name_bytes = &self.strings[prop.nameoff as usize..]; self.pos = &self.pos[PROP_SIZE..];
let mut i = 0; let plen = prop.len.get() as usize;
let mut failed = false; let len = (plen + (TOKEN_SIZE - 1)) & !(TOKEN_SIZE - 1);
let check = str.as_bytes(); let data = &self.pos[..len];
for byte in name_bytes { self.pos = &self.pos[len..];
if *byte == 0 { let name_start = &self.strings[prop.nameoff.get() as usize..];
break; for (i, c) in name_start.iter().enumerate() {
} if *c == 0 {
if i < check.len() && check[i] != *byte { let name: &str = unsafe { transmute(&name_start[..i]) };
failed = true; return Some(Prop { name, data });
}
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] { println!("failed to read prop name, not sure what to do");
let mut pos = self.data; None
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 name_bytes = &self.strings[prop.nameoff as usize..];
print!(" ");
for byte in name_bytes {
if *byte == 0 {
break;
}
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) { impl Node {
let fdt = RawFDT::new(addr); pub fn find_prop(&self, name: &str) -> Option<Prop> {
fdt.print_all(); self.into_iter().find(|p| p.name == name)
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());
}
}
} }
} }
pub unsafe fn from_be_32<const S: usize>(addr: usize) -> [u8; S] {
let mut data = *(addr as *mut [u8; S]);
for slice in data.chunks_mut(4) {
slice.reverse();
}
data
}
pub unsafe fn be_32<const S: usize>(data: &[u8]) -> [u8; S] {
let data: &[u8; S] = data[..S].try_into().unwrap();
let mut data = (*data).clone();
for slice in data.chunks_mut(4) {
slice.reverse();
}
data
}

View File

@@ -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
View 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
View File

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

View File

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

View File

@@ -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"]);