Make MMIO devices not have control of the address of exceptions

This commit is contained in:
2025-12-31 13:16:32 +01:00
parent 09fe12f516
commit 21a8479ce9
6 changed files with 63 additions and 79 deletions

View File

@@ -13,7 +13,7 @@ use std::time::Duration;
use nix::fcntl::fcntl;
use nix::fcntl::{FcntlArg, OFlag};
use trve::exceptions::{MemoryException, MemoryExceptionType};
use trve::exceptions::MemoryExceptionType;
use trve::mem::MemDeviceInterface;
/// byte 0: rx/tx
@@ -77,26 +77,20 @@ impl 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 {
0 => {
self.write(value);
Ok(())
}
_ => Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
}),
_ => Err(MemoryExceptionType::AccessFault),
}
}
fn read_byte(&self, addr: u64) -> Result<u8, MemoryException> {
fn read_byte(&self, addr: u64) -> Result<u8, MemoryExceptionType> {
match addr {
0 => Ok(self.read()),
1 => Ok(1 | (self.can_read() as u8) << 1),
_ => Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
}),
_ => Err(MemoryExceptionType::AccessFault),
}
}
}

View File

@@ -58,7 +58,7 @@ impl Core {
let instr = match self.mem.read_word(self.pc) {
Ok(i) => i,
Err(e) => {
return Err(e.to_exception_instr());
return Err(e.into_exception_instr());
}
};

View File

@@ -51,6 +51,12 @@ pub enum MemoryExceptionType {
PageFault,
}
impl MemoryExceptionType {
pub(crate) fn with_addr(self, addr: u64) -> MemoryException {
MemoryException { type_: self, addr }
}
}
#[derive(Debug, Clone, Copy)]
pub struct MemoryException {
pub type_: MemoryExceptionType,
@@ -58,7 +64,7 @@ pub struct MemoryException {
}
impl MemoryException {
pub(crate) fn to_exception_store(&self) -> Exception {
pub(crate) fn into_exception_store(self) -> Exception {
Exception {
type_: match self.type_ {
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 {
type_: match self.type_ {
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 {
type_: match self.type_ {
MemoryExceptionType::AddressMisaligned => ExceptionType::LoadAddressMisaligned,

View File

@@ -11,7 +11,7 @@ pub fn sd(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
let value = core.reg_read(instr.rs2());
core.mem
.write_dword(addr, value)
.map_err(|e| e.to_exception_store())?;
.map_err(|e| e.into_exception_store())?;
core.advance_pc();
Ok(())
}
@@ -22,7 +22,7 @@ pub fn ld(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.read_dword(addr)
.map_err(|e| e.to_exception_load())?,
.map_err(|e| e.into_exception_load())?,
);
core.advance_pc();
Ok(())
@@ -33,7 +33,7 @@ pub fn sw(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
let value = core.reg_read(instr.rs2()) as u32;
core.mem
.write_word(addr, value)
.map_err(|e| e.to_exception_store())?;
.map_err(|e| e.into_exception_store())?;
core.advance_pc();
Ok(())
}
@@ -44,7 +44,7 @@ pub fn lw(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.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();
Ok(())
@@ -56,7 +56,7 @@ pub fn lwu(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.read_word(addr)
.map_err(|e| e.to_exception_load())? as u64,
.map_err(|e| e.into_exception_load())? as u64,
);
core.advance_pc();
Ok(())
@@ -67,7 +67,7 @@ pub fn sh(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
let value = core.reg_read(instr.rs2()) as u16;
core.mem
.write_hword(addr, value)
.map_err(|e| e.to_exception_store())?;
.map_err(|e| e.into_exception_store())?;
core.advance_pc();
Ok(())
}
@@ -78,7 +78,7 @@ pub fn lh(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.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();
Ok(())
@@ -90,7 +90,7 @@ pub fn lhu(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.read_hword(addr)
.map_err(|e| e.to_exception_load())? as u64,
.map_err(|e| e.into_exception_load())? as u64,
);
core.advance_pc();
Ok(())
@@ -101,7 +101,7 @@ pub fn sb(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
let value = core.reg_read(instr.rs2()) as u8;
core.mem
.write_byte(addr, value)
.map_err(|e| e.to_exception_store())?;
.map_err(|e| e.into_exception_store())?;
core.advance_pc();
Ok(())
}
@@ -112,7 +112,7 @@ pub fn lb(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.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();
Ok(())
@@ -124,7 +124,7 @@ pub fn lbu(core: &mut Core, instr: Instruction) -> Result<(), Exception> {
instr.rd(),
core.mem
.read_byte(addr)
.map_err(|e| e.to_exception_load())? as u64,
.map_err(|e| e.into_exception_load())? as u64,
);
core.advance_pc();
Ok(())

View File

@@ -10,7 +10,7 @@ use clap::Parser;
use trve::{
core::Core,
exceptions::MemoryException,
exceptions::MemoryExceptionType,
gdb,
mem::{MemConfig, MemDeviceInterface, MmioRoot, Ram},
};
@@ -69,22 +69,22 @@ mod basic_uart;
struct 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}");
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}");
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}");
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}");
Ok(())
}

View File

@@ -49,7 +49,7 @@ impl MemConfig {
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> {
@@ -67,7 +67,7 @@ impl MemConfig {
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> {
@@ -84,7 +84,7 @@ impl MemConfig {
type_: MemoryExceptionType::AccessFault,
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> {
@@ -95,7 +95,7 @@ impl MemConfig {
type_: MemoryExceptionType::AccessFault,
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,
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> {
@@ -130,7 +132,9 @@ impl MemConfig {
type_: MemoryExceptionType::AccessFault,
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> {
@@ -147,7 +151,9 @@ impl MemConfig {
type_: MemoryExceptionType::AccessFault,
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> {
@@ -158,7 +164,9 @@ impl MemConfig {
type_: MemoryExceptionType::AccessFault,
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)]
pub trait MemDeviceInterface {
fn write_dword(&self, addr: u64, value: u64) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn write_dword(&self, addr: u64, value: u64) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn write_word(&self, addr: u64, value: u32) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn write_hword(&self, addr: u64, value: u16) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn write_byte(&self, addr: u64, value: u8) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn read_dword(&self, addr: u64) -> Result<u64, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn read_dword(&self, addr: u64) -> Result<u64, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn read_word(&self, addr: u64) -> Result<u32, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn read_word(&self, addr: u64) -> Result<u32, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn read_hword(&self, addr: u64) -> Result<u16, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn read_hword(&self, addr: u64) -> Result<u16, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
fn read_byte(&self, addr: u64) -> Result<u8, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
fn read_byte(&self, addr: u64) -> Result<u8, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
}
}