wip
This commit is contained in:
parent
aadedf4863
commit
bf76e671e9
1 changed files with 99 additions and 99 deletions
198
src/main.rs
198
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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue