This commit is contained in:
Brooke Vibber 2025-12-30 19:31:24 -08:00
commit bf76e671e9

View file

@ -51,7 +51,7 @@ impl PageTableEntry {
return self.flags; 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; 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); 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) { if (address as u64) < (self.memory.len() as u64) {
return PageTableEntry::new(self.ld_physical(address as usize)); return self.memory[address as usize] as i8 as i64;
} else {
panic!("xxx");
} }
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) { if (address as u64) < (self.memory.len() as u64) {
self.sd_physical(address as usize, entry.as_i64()); return self.memory[address as usize] as u8 as i64;
} else {
panic!("xxx");
} }
panic!("@fixme: trap on out of bounds physical read");
} }
fn lb_physical(&self, address: usize) -> i64 { fn lh_physical(&self, address: i64) -> i64 {
return self.memory[address] as i8 as 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 { fn lhu_physical(&self, address: i64) -> i64 {
return self.memory[address] as u8 as 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 { fn lw_physical(&self, address: i64) -> i64 {
return ( if (address as u64) < (self.memory.len() as u64 - 3) {
(self.memory[address ] as u16) | return (
((self.memory[address + 1] as u16) << 8) ( self.memory[address as usize ] as u32) |
) as i16 as i64; ((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 { fn lwu_physical(&self, address: i64) -> i64 {
return ( if (address as u64) < (self.memory.len() as u64 - 3) {
(self.memory[address ] as u16) | return (
((self.memory[address + 1] as u16) << 8) ( self.memory[address as usize ] as u32) |
) as i64; ((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 { fn ld_physical(&self, address: i64) -> i64 {
return ( if (address as u64) < (self.memory.len() as u64 - 7) {
(self.memory[address ] as u32) | return (
((self.memory[address + 1] as u32) << 8) | ( self.memory[address as usize ] as u64) |
((self.memory[address + 2] as u32) << 16) | ((self.memory[address as usize + 1] as u64) << 8) |
((self.memory[address + 3] as u32) << 24) ((self.memory[address as usize + 2] as u64) << 16) |
) as i32 as i64; ((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 { fn sb_physical(&mut self, address: i64, value: i64) {
return ( self.memory[address as usize] = value as u8;
(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 ld_physical(&self, address: usize) -> i64 { fn sh_physical(&mut self, address: i64, value: i64) {
return ( self.memory[address as usize] = value as u8;
(self.memory[address ] as u64) | self.memory[address as usize + 1] = (value >> 8) as u8;
((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 sb_physical(&mut self, address: usize, value: i64) { fn sw_physical(&mut self, address: i64, value: i64) {
self.memory[address] = value 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;
fn sh_physical(&mut self, address: usize, value: i64) { self.memory[address as usize + 3] = (value >> 24) as u8;
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 sd_physical(&mut self, address: usize, value: i64) { fn sd_physical(&mut self, address: usize, value: i64) {
self.memory[address] = value as u8; self.memory[address as usize] = value as u8;
self.memory[address + 1] = (value >> 8) as u8; self.memory[address as usize + 1] = (value >> 8) as u8;
self.memory[address + 2] = (value >> 16) as u8; self.memory[address as usize + 2] = (value >> 16) as u8;
self.memory[address + 3] = (value >> 24) as u8; self.memory[address as usize + 3] = (value >> 24) as u8;
self.memory[address + 4] = (value >> 32) as u8; self.memory[address as usize + 4] = (value >> 32) as u8;
self.memory[address + 5] = (value >> 40) as u8; self.memory[address as usize + 5] = (value >> 40) as u8;
self.memory[address + 6] = (value >> 48) as u8; self.memory[address as usize + 6] = (value >> 48) as u8;
self.memory[address + 7] = (value >> 56) as u8; self.memory[address as usize + 7] = (value >> 56) as u8;
} }
fn store_buffer_physical(&mut self, address: usize, bytes: &[u8]) { fn store_buffer_physical(&mut self, address: usize, bytes: &[u8]) {
@ -228,7 +233,7 @@ impl MachineState {
struct CoreState { struct CoreState {
// Integer registers // Integer registers
x: [i64; 32], x: [i64; 32],
satp_ppn: i64, satp: i64,
// Do we need pc? we're passing it around as active state // 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,
0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0
], ],
satp_ppn: 0, satp: 0,
f: [ 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,
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"); 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) { 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 usize;
let high = ((address as u64) >> 39) as i64; let vpn2 = (((address as u64) << (64 - 39)) >> (64 - 9)) as usize;
let vpn2 = (((address as u64) << (64 - 39)) >> (64 - 9)) as i64; let vpn1 = (((address as u64) << (64 - 39 + 9)) >> (64 - 9 - 9)) as usize;
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 usize;
let vpn0 = (((address as u64) << (64 - 39 + 9 + 9)) >> (64 - 9 - 9)) as i64;
if high != 0 { if high == 0 {
panic!("@fixme: handle trap for kernel address space or invalid SV39 address"); let ppn = self.satp << (64 - 44) >> (64 - 44);
} let pte2 = PageTableEntry::new(
machine.ld_physical(ppn + (vpn2 << 3))
let pte2 = machine.get_page_table_entry(self.satp_ppn + (vpn2 << 3)); );
if !pte2.is_leaf() { if pte2.is_pointer() {
let pte1 = machine.get_page_table_entry(pte2.get_physical() + (vpn1 << 3)); let pte1 = PageTableEntry::new(
if !pte1.is_leaf() { machine.ld_physical(pte2.get_physical() + (vpn1 << 3))
let pte0 = machine.get_page_table_entry(pte1.get_physical() + (vpn0 << 3)); );
if pte0.is_leaf() { if pte1.is_pointer() {
// 4 KiB pages let pte0 = PageTableEntry::new(machine.ld_physical(pte1.get_physical() + (vpn0 << 3)));
let shift = 64 - 12; if !pte0.is_pointer() {
return (pte0, (raw << shift >> shift) as usize); // 4 KiB pages
} else { let shift = 64 - 12;
panic!("@fixme: trap on leaf node when we're out of levels"); return (pte0, (raw << shift >> shift) as usize);
}
panic!("@fixme: trap on pointer node when we're out of levels");
} }
} else {
// 2 MiB megapages // 2 MiB megapages
let shift = 64 - 12 - 9; let shift = 64 - 12 - 9;
return (pte1, (raw << shift >> shift) as usize); return (pte1, (raw << shift >> shift) as usize);
} }
} else {
// 1 GiB gigapages // 1 GiB gigapages
let shift = 64 - 12 - 9 - 9; let shift = 64 - 12 - 9 - 9;
return (pte2, (raw << shift >> shift) as usize); 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 { fn lb(&mut self, machine: &mut MachineState, pc: i64, rd: usize, rs1: usize, imm: i32) -> i64 {