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;
}
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 lbu_physical(&self, address: usize) -> i64 {
return self.memory[address] as u8 as i64;
}
fn lh_physical(&self, address: usize) -> i64 {
fn lh_physical(&self, address: i64) -> i64 {
if (address as u64) < (self.memory.len() as u64 - 1) {
return (
(self.memory[address ] as u16) |
((self.memory[address + 1] as u16) << 8)
( self.memory[address as usize ] as u16) |
((self.memory[address as usize + 1] as u16) << 8)
) as i16 as i64;
}
fn lhu_physical(&self, address: usize) -> i64 {
return (
(self.memory[address ] as u16) |
((self.memory[address + 1] as u16) << 8)
) as i64;
panic!("@fixme: trap on out of bounds physical read");
}
fn lw_physical(&self, address: usize) -> i64 {
fn lhu_physical(&self, address: i64) -> i64 {
if (address as u64) < (self.memory.len() as u64 - 1) {
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)
( 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 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 lwu_physical(&self, address: usize) -> i64 {
fn lwu_physical(&self, address: i64) -> i64 {
if (address as u64) < (self.memory.len() as u64 - 3) {
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)
( 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 ld_physical(&self, address: usize) -> i64 {
fn ld_physical(&self, address: i64) -> i64 {
if (address as u64) < (self.memory.len() as u64 - 7) {
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)
( 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;
}
fn sb_physical(&mut self, address: usize, value: i64) {
self.memory[address] = value as u8;
panic!("@fixme: trap on out of bounds physical read");
}
fn sh_physical(&mut self, address: usize, value: i64) {
self.memory[address] = value as u8;
self.memory[address + 1] = (value >> 8) as u8;
fn sb_physical(&mut self, address: i64, value: i64) {
self.memory[address as usize] = value 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 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 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() {
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);
} else {
panic!("@fixme: trap on leaf node when we're out of levels");
}
} else {
panic!("@fixme: trap on pointer node when we're out of levels");
}
// 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 {