From bf76e671e9b8447f21b3f26a4b8b64c783d88603 Mon Sep 17 00:00:00 2001 From: Brooke Vibber Date: Tue, 30 Dec 2025 19:31:24 -0800 Subject: [PATCH] wip --- src/main.rs | 198 ++++++++++++++++++++++++++-------------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5435d43..99b94b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ impl PageTableEntry { return self.flags; } - fn is_leaf(&self) -> bool { + fn is_pointer(&self) -> bool { return self.flags & (BIT_V | BIT_R | BIT_W | BIT_X) == BIT_V; } @@ -123,100 +123,105 @@ impl MachineState { return Self::new_with_state(memory, pages); } - fn get_page_table_entry(&self, address: i64) -> PageTableEntry { + fn lb_physical(&self, address: i64) -> i64 { if (address as u64) < (self.memory.len() as u64) { - return PageTableEntry::new(self.ld_physical(address as usize)); - } else { - panic!("xxx"); + return self.memory[address as usize] as i8 as i64; } + panic!("@fixme: trap on out of bounds physical read"); } - fn set_page_table_entry(&mut self, address: i64, entry: PageTableEntry) { + fn lbu_physical(&self, address: i64) -> i64 { if (address as u64) < (self.memory.len() as u64) { - self.sd_physical(address as usize, entry.as_i64()); - } else { - panic!("xxx"); + return self.memory[address as usize] as u8 as i64; } + panic!("@fixme: trap on out of bounds physical read"); } - fn lb_physical(&self, address: usize) -> i64 { - return self.memory[address] as i8 as i64; + fn lh_physical(&self, address: i64) -> i64 { + if (address as u64) < (self.memory.len() as u64 - 1) { + return ( + ( self.memory[address as usize ] as u16) | + ((self.memory[address as usize + 1] as u16) << 8) + ) as i16 as i64; + } + panic!("@fixme: trap on out of bounds physical read"); } - fn lbu_physical(&self, address: usize) -> i64 { - return self.memory[address] as u8 as i64; + fn lhu_physical(&self, address: i64) -> i64 { + if (address as u64) < (self.memory.len() as u64 - 1) { + return ( + ( self.memory[address as usize ] as u16) | + ((self.memory[address as usize + 1] as u16) << 8) + ) as i64; + } + panic!("@fixme: trap on out of bounds physical read"); } - fn lh_physical(&self, address: usize) -> i64 { - return ( - (self.memory[address ] as u16) | - ((self.memory[address + 1] as u16) << 8) - ) as i16 as i64; + fn lw_physical(&self, address: i64) -> i64 { + if (address as u64) < (self.memory.len() as u64 - 3) { + return ( + ( self.memory[address as usize ] as u32) | + ((self.memory[address as usize + 1] as u32) << 8) | + ((self.memory[address as usize + 2] as u32) << 16) | + ((self.memory[address as usize + 3] as u32) << 24) + ) as i32 as i64; + } + panic!("@fixme: trap on out of bounds physical read"); } - fn lhu_physical(&self, address: usize) -> i64 { - return ( - (self.memory[address ] as u16) | - ((self.memory[address + 1] as u16) << 8) - ) as i64; + fn lwu_physical(&self, address: i64) -> i64 { + if (address as u64) < (self.memory.len() as u64 - 3) { + return ( + ( self.memory[address as usize ] as u32) | + ((self.memory[address as usize + 1] as u32) << 8) | + ((self.memory[address as usize + 2] as u32) << 16) | + ((self.memory[address as usize + 3] as u32) << 24) + ) as u32 as i64; + } + panic!("@fixme: trap on out of bounds physical read"); } - fn lw_physical(&self, address: usize) -> i64 { - return ( - (self.memory[address ] as u32) | - ((self.memory[address + 1] as u32) << 8) | - ((self.memory[address + 2] as u32) << 16) | - ((self.memory[address + 3] as u32) << 24) - ) as i32 as i64; + fn ld_physical(&self, address: i64) -> i64 { + if (address as u64) < (self.memory.len() as u64 - 7) { + return ( + ( self.memory[address as usize ] as u64) | + ((self.memory[address as usize + 1] as u64) << 8) | + ((self.memory[address as usize + 2] as u64) << 16) | + ((self.memory[address as usize + 3] as u64) << 24) | + ((self.memory[address as usize + 4] as u64) << 32) | + ((self.memory[address as usize + 5] as u64) << 40) | + ((self.memory[address as usize + 6] as u64) << 48) | + ((self.memory[address as usize + 7] as u64) << 56) + ) as i64; + } + panic!("@fixme: trap on out of bounds physical read"); } - fn lwu_physical(&self, address: usize) -> i64 { - return ( - (self.memory[address ] as u32) | - ((self.memory[address + 1] as u32) << 8) | - ((self.memory[address + 2] as u32) << 16) | - ((self.memory[address + 3] as u32) << 24) - ) as u32 as i64; + fn sb_physical(&mut self, address: i64, value: i64) { + self.memory[address as usize] = value as u8; } - fn ld_physical(&self, address: usize) -> i64 { - return ( - (self.memory[address ] as u64) | - ((self.memory[address + 1] as u64) << 8) | - ((self.memory[address + 2] as u64) << 16) | - ((self.memory[address + 3] as u64) << 24) | - ((self.memory[address + 4] as u64) << 32) | - ((self.memory[address + 5] as u64) << 40) | - ((self.memory[address + 6] as u64) << 48) | - ((self.memory[address + 7] as u64) << 56) - ) as i64; + fn sh_physical(&mut self, address: i64, value: i64) { + self.memory[address as usize] = value as u8; + self.memory[address as usize + 1] = (value >> 8) as u8; } - fn sb_physical(&mut self, address: usize, value: i64) { - self.memory[address] = value as u8; - } - - fn sh_physical(&mut self, address: usize, value: i64) { - self.memory[address] = value as u8; - self.memory[address + 1] = (value >> 8) as u8; - } - - fn sw_physical(&mut self, address: usize, value: i64) { - self.memory[address] = value as u8; - self.memory[address + 1] = (value >> 8) as u8; - self.memory[address + 2] = (value >> 16) as u8; - self.memory[address + 3] = (value >> 24) as u8; + fn sw_physical(&mut self, address: i64, value: i64) { + self.memory[address as usize] = value as u8; + self.memory[address as usize + 1] = (value >> 8) as u8; + self.memory[address as usize + 2] = (value >> 16) as u8; + self.memory[address as usize + 3] = (value >> 24) as u8; } fn sd_physical(&mut self, address: usize, value: i64) { - self.memory[address] = value as u8; - self.memory[address + 1] = (value >> 8) as u8; - self.memory[address + 2] = (value >> 16) as u8; - self.memory[address + 3] = (value >> 24) as u8; - self.memory[address + 4] = (value >> 32) as u8; - self.memory[address + 5] = (value >> 40) as u8; - self.memory[address + 6] = (value >> 48) as u8; - self.memory[address + 7] = (value >> 56) as u8; + self.memory[address as usize] = value as u8; + self.memory[address as usize + 1] = (value >> 8) as u8; + self.memory[address as usize + 2] = (value >> 16) as u8; + self.memory[address as usize + 3] = (value >> 24) as u8; + self.memory[address as usize + 4] = (value >> 32) as u8; + self.memory[address as usize + 5] = (value >> 40) as u8; + self.memory[address as usize + 6] = (value >> 48) as u8; + self.memory[address as usize + 7] = (value >> 56) as u8; } fn store_buffer_physical(&mut self, address: usize, bytes: &[u8]) { @@ -228,7 +233,7 @@ impl MachineState { struct CoreState { // Integer registers x: [i64; 32], - satp_ppn: i64, + satp: i64, // Do we need pc? we're passing it around as active state @@ -273,7 +278,7 @@ impl CoreState { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - satp_ppn: 0, + satp: 0, f: [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -290,44 +295,39 @@ impl CoreState { panic!("@fixme implement traps"); } - fn get_page_table_entry(&mut self, machine: &mut MachineState, page: i64) -> PageTableEntry { - return machine.get_page_table_entry(page) - } - fn dereference(&mut self, machine: &mut MachineState, address: i64) -> (PageTableEntry, usize) { - let raw = (address as u64) as i64; - let high = ((address as u64) >> 39) as i64; - let vpn2 = (((address as u64) << (64 - 39)) >> (64 - 9)) as i64; - let vpn1 = (((address as u64) << (64 - 39 + 9)) >> (64 - 9 - 9)) as i64; - let vpn0 = (((address as u64) << (64 - 39 + 9 + 9)) >> (64 - 9 - 9)) as i64; + let high = ((address as u64) >> 39) as usize; + let vpn2 = (((address as u64) << (64 - 39)) >> (64 - 9)) as usize; + let vpn1 = (((address as u64) << (64 - 39 + 9)) >> (64 - 9 - 9)) as usize; + let vpn0 = (((address as u64) << (64 - 39 + 9 + 9)) >> (64 - 9 - 9)) as usize; - if high != 0 { - panic!("@fixme: handle trap for kernel address space or invalid SV39 address"); - } - - let pte2 = machine.get_page_table_entry(self.satp_ppn + (vpn2 << 3)); - if !pte2.is_leaf() { - let pte1 = machine.get_page_table_entry(pte2.get_physical() + (vpn1 << 3)); - if !pte1.is_leaf() { - let pte0 = machine.get_page_table_entry(pte1.get_physical() + (vpn0 << 3)); - if pte0.is_leaf() { - // 4 KiB pages - let shift = 64 - 12; - return (pte0, (raw << shift >> shift) as usize); - } else { - panic!("@fixme: trap on leaf node when we're out of levels"); + if high == 0 { + let ppn = self.satp << (64 - 44) >> (64 - 44); + let pte2 = PageTableEntry::new( + machine.ld_physical(ppn + (vpn2 << 3)) + ); + if pte2.is_pointer() { + let pte1 = PageTableEntry::new( + machine.ld_physical(pte2.get_physical() + (vpn1 << 3)) + ); + if pte1.is_pointer() { + let pte0 = PageTableEntry::new(machine.ld_physical(pte1.get_physical() + (vpn0 << 3))); + if !pte0.is_pointer() { + // 4 KiB pages + let shift = 64 - 12; + return (pte0, (raw << shift >> shift) as usize); + } + panic!("@fixme: trap on pointer node when we're out of levels"); } - } else { // 2 MiB megapages let shift = 64 - 12 - 9; return (pte1, (raw << shift >> shift) as usize); } - } else { // 1 GiB gigapages let shift = 64 - 12 - 9 - 9; return (pte2, (raw << shift >> shift) as usize); } - panic!("@fixme: handle unexpected non-leaf node"); + panic!("@fixme: handle trap for kernel address space or invalid SV39 address"); } fn lb(&mut self, machine: &mut MachineState, pc: i64, rd: usize, rs1: usize, imm: i32) -> i64 {