Make MMIO devices not have control of the address of exceptions
This commit is contained in:
@@ -13,7 +13,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use nix::fcntl::fcntl;
|
use nix::fcntl::fcntl;
|
||||||
use nix::fcntl::{FcntlArg, OFlag};
|
use nix::fcntl::{FcntlArg, OFlag};
|
||||||
use trve::exceptions::{MemoryException, MemoryExceptionType};
|
use trve::exceptions::MemoryExceptionType;
|
||||||
use trve::mem::MemDeviceInterface;
|
use trve::mem::MemDeviceInterface;
|
||||||
|
|
||||||
/// byte 0: rx/tx
|
/// byte 0: rx/tx
|
||||||
@@ -77,26 +77,20 @@ impl BasicUart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MemDeviceInterface for BasicUart {
|
impl MemDeviceInterface for BasicUart {
|
||||||
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryException> {
|
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryExceptionType> {
|
||||||
match addr {
|
match addr {
|
||||||
0 => {
|
0 => {
|
||||||
self.write(value);
|
self.write(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(MemoryException {
|
_ => Err(MemoryExceptionType::AccessFault),
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_byte(&self, addr: u64) -> Result<u8, MemoryException> {
|
fn read_byte(&self, addr: u64) -> Result<u8, MemoryExceptionType> {
|
||||||
match addr {
|
match addr {
|
||||||
0 => Ok(self.read()),
|
0 => Ok(self.read()),
|
||||||
1 => Ok(1 | (self.can_read() as u8) << 1),
|
1 => Ok(1 | (self.can_read() as u8) << 1),
|
||||||
_ => Err(MemoryException {
|
_ => Err(MemoryExceptionType::AccessFault),
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ impl Core {
|
|||||||
let instr = match self.mem.read_word(self.pc) {
|
let instr = match self.mem.read_word(self.pc) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(e.to_exception_instr());
|
return Err(e.into_exception_instr());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ pub enum MemoryExceptionType {
|
|||||||
PageFault,
|
PageFault,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MemoryExceptionType {
|
||||||
|
pub(crate) fn with_addr(self, addr: u64) -> MemoryException {
|
||||||
|
MemoryException { type_: self, addr }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct MemoryException {
|
pub struct MemoryException {
|
||||||
pub type_: MemoryExceptionType,
|
pub type_: MemoryExceptionType,
|
||||||
@@ -58,7 +64,7 @@ pub struct MemoryException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryException {
|
impl MemoryException {
|
||||||
pub(crate) fn to_exception_store(&self) -> Exception {
|
pub(crate) fn into_exception_store(self) -> Exception {
|
||||||
Exception {
|
Exception {
|
||||||
type_: match self.type_ {
|
type_: match self.type_ {
|
||||||
MemoryExceptionType::AddressMisaligned => ExceptionType::StoreAmoAddressMisaligned,
|
MemoryExceptionType::AddressMisaligned => ExceptionType::StoreAmoAddressMisaligned,
|
||||||
@@ -69,7 +75,7 @@ impl MemoryException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_exception_instr(&self) -> Exception {
|
pub(crate) fn into_exception_instr(self) -> Exception {
|
||||||
Exception {
|
Exception {
|
||||||
type_: match self.type_ {
|
type_: match self.type_ {
|
||||||
MemoryExceptionType::AddressMisaligned => ExceptionType::InstructionAccessFault,
|
MemoryExceptionType::AddressMisaligned => ExceptionType::InstructionAccessFault,
|
||||||
@@ -80,7 +86,7 @@ impl MemoryException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_exception_load(&self) -> Exception {
|
pub(crate) fn into_exception_load(self) -> Exception {
|
||||||
Exception {
|
Exception {
|
||||||
type_: match self.type_ {
|
type_: match self.type_ {
|
||||||
MemoryExceptionType::AddressMisaligned => ExceptionType::LoadAddressMisaligned,
|
MemoryExceptionType::AddressMisaligned => ExceptionType::LoadAddressMisaligned,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub fn sd(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
let value = core.reg_read(instr.rs2());
|
let value = core.reg_read(instr.rs2());
|
||||||
core.mem
|
core.mem
|
||||||
.write_dword(addr, value)
|
.write_dword(addr, value)
|
||||||
.map_err(|e| e.to_exception_store())?;
|
.map_err(|e| e.into_exception_store())?;
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ pub fn ld(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_dword(addr)
|
.read_dword(addr)
|
||||||
.map_err(|e| e.to_exception_load())?,
|
.map_err(|e| e.into_exception_load())?,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -33,7 +33,7 @@ pub fn sw(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
let value = core.reg_read(instr.rs2()) as u32;
|
let value = core.reg_read(instr.rs2()) as u32;
|
||||||
core.mem
|
core.mem
|
||||||
.write_word(addr, value)
|
.write_word(addr, value)
|
||||||
.map_err(|e| e.to_exception_store())?;
|
.map_err(|e| e.into_exception_store())?;
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_word(addr)
|
.read_word(addr)
|
||||||
.map_err(|e| e.to_exception_load())? as i32 as i64 as u64,
|
.map_err(|e| e.into_exception_load())? as i32 as i64 as u64,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -56,7 +56,7 @@ pub fn lwu(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_word(addr)
|
.read_word(addr)
|
||||||
.map_err(|e| e.to_exception_load())? as u64,
|
.map_err(|e| e.into_exception_load())? as u64,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -67,7 +67,7 @@ pub fn sh(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
let value = core.reg_read(instr.rs2()) as u16;
|
let value = core.reg_read(instr.rs2()) as u16;
|
||||||
core.mem
|
core.mem
|
||||||
.write_hword(addr, value)
|
.write_hword(addr, value)
|
||||||
.map_err(|e| e.to_exception_store())?;
|
.map_err(|e| e.into_exception_store())?;
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_hword(addr)
|
.read_hword(addr)
|
||||||
.map_err(|e| e.to_exception_load())? as i16 as i64 as u64,
|
.map_err(|e| e.into_exception_load())? as i16 as i64 as u64,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -90,7 +90,7 @@ pub fn lhu(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_hword(addr)
|
.read_hword(addr)
|
||||||
.map_err(|e| e.to_exception_load())? as u64,
|
.map_err(|e| e.into_exception_load())? as u64,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -101,7 +101,7 @@ pub fn sb(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
let value = core.reg_read(instr.rs2()) as u8;
|
let value = core.reg_read(instr.rs2()) as u8;
|
||||||
core.mem
|
core.mem
|
||||||
.write_byte(addr, value)
|
.write_byte(addr, value)
|
||||||
.map_err(|e| e.to_exception_store())?;
|
.map_err(|e| e.into_exception_store())?;
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_byte(addr)
|
.read_byte(addr)
|
||||||
.map_err(|e| e.to_exception_load())? as i8 as i64 as u64,
|
.map_err(|e| e.into_exception_load())? as i8 as i64 as u64,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -124,7 +124,7 @@ pub fn lbu(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
|
|||||||
instr.rd(),
|
instr.rd(),
|
||||||
core.mem
|
core.mem
|
||||||
.read_byte(addr)
|
.read_byte(addr)
|
||||||
.map_err(|e| e.to_exception_load())? as u64,
|
.map_err(|e| e.into_exception_load())? as u64,
|
||||||
);
|
);
|
||||||
core.advance_pc();
|
core.advance_pc();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
10
src/main.rs
10
src/main.rs
@@ -10,7 +10,7 @@ use clap::Parser;
|
|||||||
|
|
||||||
use trve::{
|
use trve::{
|
||||||
core::Core,
|
core::Core,
|
||||||
exceptions::MemoryException,
|
exceptions::MemoryExceptionType,
|
||||||
gdb,
|
gdb,
|
||||||
mem::{MemConfig, MemDeviceInterface, MmioRoot, Ram},
|
mem::{MemConfig, MemDeviceInterface, MmioRoot, Ram},
|
||||||
};
|
};
|
||||||
@@ -69,22 +69,22 @@ mod basic_uart;
|
|||||||
struct DbgOut;
|
struct DbgOut;
|
||||||
|
|
||||||
impl MemDeviceInterface for DbgOut {
|
impl MemDeviceInterface for DbgOut {
|
||||||
fn write_dword(&self, addr: u64, value: u64) -> Result<(), MemoryException> {
|
fn write_dword(&self, addr: u64, value: u64) -> Result<(), MemoryExceptionType> {
|
||||||
eprintln!("Wrote DWord {value:016x} to Debug-Out address {addr:x}");
|
eprintln!("Wrote DWord {value:016x} to Debug-Out address {addr:x}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryException> {
|
fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryExceptionType> {
|
||||||
eprintln!("Wrote Word {value:08x} to Debug-Out address {addr:x}");
|
eprintln!("Wrote Word {value:08x} to Debug-Out address {addr:x}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryException> {
|
fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryExceptionType> {
|
||||||
eprintln!("Wrote HWord {value:04x} to Debug-Out address {addr:x}");
|
eprintln!("Wrote HWord {value:04x} to Debug-Out address {addr:x}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryException> {
|
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryExceptionType> {
|
||||||
eprintln!("Wrote Byte {value:02x} to Debug-Out address {addr:x}");
|
eprintln!("Wrote Byte {value:02x} to Debug-Out address {addr:x}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
80
src/mem.rs
80
src/mem.rs
@@ -49,7 +49,7 @@ impl MemConfig {
|
|||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
interface.read_dword(addr)
|
interface.read_dword(addr).map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn read_word(&self, addr: u64) -> Result<u32, MemoryException> {
|
pub fn read_word(&self, addr: u64) -> Result<u32, MemoryException> {
|
||||||
@@ -67,7 +67,7 @@ impl MemConfig {
|
|||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
interface.read_word(addr)
|
interface.read_word(addr).map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn read_hword(&self, addr: u64) -> Result<u16, MemoryException> {
|
pub fn read_hword(&self, addr: u64) -> Result<u16, MemoryException> {
|
||||||
@@ -84,7 +84,7 @@ impl MemConfig {
|
|||||||
type_: MemoryExceptionType::AccessFault,
|
type_: MemoryExceptionType::AccessFault,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
interface.read_hword(addr)
|
interface.read_hword(addr).map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn read_byte(&self, addr: u64) -> Result<u8, MemoryException> {
|
pub fn read_byte(&self, addr: u64) -> Result<u8, MemoryException> {
|
||||||
@@ -95,7 +95,7 @@ impl MemConfig {
|
|||||||
type_: MemoryExceptionType::AccessFault,
|
type_: MemoryExceptionType::AccessFault,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
interface.read_byte(addr)
|
interface.read_byte(addr).map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,9 @@ impl MemConfig {
|
|||||||
type_: MemoryExceptionType::AccessFault,
|
type_: MemoryExceptionType::AccessFault,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
interface.write_dword(addr, value)
|
interface
|
||||||
|
.write_dword(addr, value)
|
||||||
|
.map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryException> {
|
pub fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryException> {
|
||||||
@@ -130,7 +132,9 @@ impl MemConfig {
|
|||||||
type_: MemoryExceptionType::AccessFault,
|
type_: MemoryExceptionType::AccessFault,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
interface.write_word(addr, value)
|
interface
|
||||||
|
.write_word(addr, value)
|
||||||
|
.map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryException> {
|
pub fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryException> {
|
||||||
@@ -147,7 +151,9 @@ impl MemConfig {
|
|||||||
type_: MemoryExceptionType::AccessFault,
|
type_: MemoryExceptionType::AccessFault,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
interface.write_hword(addr, value)
|
interface
|
||||||
|
.write_hword(addr, value)
|
||||||
|
.map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryException> {
|
pub fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryException> {
|
||||||
@@ -158,7 +164,9 @@ impl MemConfig {
|
|||||||
type_: MemoryExceptionType::AccessFault,
|
type_: MemoryExceptionType::AccessFault,
|
||||||
addr,
|
addr,
|
||||||
})?;
|
})?;
|
||||||
interface.write_byte(addr, value)
|
interface
|
||||||
|
.write_byte(addr, value)
|
||||||
|
.map_err(|e| e.with_addr(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,53 +539,29 @@ impl Default for MmioSecondLevel {
|
|||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub trait MemDeviceInterface {
|
pub trait MemDeviceInterface {
|
||||||
fn write_dword(&self, addr: u64, value: u64) -> Result<(), MemoryException> {
|
fn write_dword(&self, addr: u64, value: u64) -> Result<(), MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryException> {
|
fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryException> {
|
fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryException> {
|
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_dword(&self, addr: u64) -> Result<u64, MemoryException> {
|
fn read_dword(&self, addr: u64) -> Result<u64, MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn read_word(&self, addr: u64) -> Result<u32, MemoryException> {
|
fn read_word(&self, addr: u64) -> Result<u32, MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn read_hword(&self, addr: u64) -> Result<u16, MemoryException> {
|
fn read_hword(&self, addr: u64) -> Result<u16, MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
fn read_byte(&self, addr: u64) -> Result<u8, MemoryException> {
|
fn read_byte(&self, addr: u64) -> Result<u8, MemoryExceptionType> {
|
||||||
Err(MemoryException {
|
Err(MemoryExceptionType::AccessFault)
|
||||||
type_: MemoryExceptionType::AccessFault,
|
|
||||||
addr,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user