Add exception values (what will go in mtval/stval)

This commit is contained in:
2025-12-27 21:33:39 +01:00
parent b5d36b7969
commit 5c008bfc04
9 changed files with 295 additions and 161 deletions

View File

@@ -13,7 +13,7 @@ use memmap2::MmapMut;
use crate::{
consts::{Addr, Byte, DWord, HWord, Word},
exceptions::MemoryExceptionType,
exceptions::{MemoryException, MemoryExceptionType},
};
pub type PageNum = usize;
@@ -37,119 +37,140 @@ impl MemConfig {
}
}
pub fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryExceptionType> {
pub fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryException> {
if addr >= RAM_START {
self.ram.read_dword(addr - RAM_START)
} else {
if !addr.is_multiple_of(8) && self.mmio_root.crosses_boundary(addr, 8) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.read_dword(addr)
}
}
pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryExceptionType> {
pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryException> {
if addr >= RAM_START {
self.ram.read_word(addr - RAM_START)
} else {
if !addr.is_multiple_of(4) && self.mmio_root.crosses_boundary(addr, 4) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.read_word(addr)
}
}
pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryExceptionType> {
pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryException> {
if addr >= RAM_START {
self.ram.read_hword(addr - RAM_START)
} else {
if !addr.is_multiple_of(2) && self.mmio_root.crosses_boundary(addr, 2) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.read_hword(addr)
}
}
pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryExceptionType> {
pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
if addr >= RAM_START {
self.ram.read_byte(addr - RAM_START)
} else {
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.read_byte(addr)
}
}
pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> {
pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> {
if addr >= RAM_START {
self.ram.write_dword(addr - RAM_START, value)
} else {
if !addr.is_multiple_of(8) && self.mmio_root.crosses_boundary(addr, 8) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.write_dword(addr, value)
}
}
pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> {
pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> {
if addr >= RAM_START {
self.ram.write_word(addr - RAM_START, value)
} else {
if !addr.is_multiple_of(4) && self.mmio_root.crosses_boundary(addr, 4) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.write_word(addr, value)
}
}
pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> {
pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> {
if addr >= RAM_START {
self.ram.write_hword(addr - RAM_START, value)
} else {
if !addr.is_multiple_of(2) && self.mmio_root.crosses_boundary(addr, 2) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.write_hword(addr, value)
}
}
pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> {
pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> {
if addr >= RAM_START {
self.ram.write_byte(addr - RAM_START, value)
} else {
let (interface, addr) = self
.mmio_root
.get_device(addr)
.ok_or(MemoryExceptionType::AccessFault)?;
let (interface, addr) = self.mmio_root.get_device(addr).ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?;
interface.write_byte(addr, value)
}
}
pub fn get_atomic_dword(&self, addr: Addr) -> Result<&AtomicU64, MemoryExceptionType> {
pub fn get_atomic_dword(&self, addr: Addr) -> Result<&AtomicU64, MemoryException> {
if !addr.is_multiple_of(8) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
let index = ((addr - RAM_START) / 8) as usize;
@@ -157,16 +178,25 @@ impl MemConfig {
self.ram
.buf_transmuted::<AtomicU64>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
}
pub fn get_atomic_word(&self, addr: Addr) -> Result<&AtomicU32, MemoryExceptionType> {
pub fn get_atomic_word(&self, addr: Addr) -> Result<&AtomicU32, MemoryException> {
if !addr.is_multiple_of(4) {
return Err(MemoryExceptionType::AddressMisaligned);
return Err(MemoryException {
type_: MemoryExceptionType::AddressMisaligned,
addr,
});
}
if addr < RAM_START {
return Err(MemoryExceptionType::AccessFault);
return Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
});
}
let index = ((addr - RAM_START) / 4) as usize;
@@ -174,7 +204,10 @@ impl MemConfig {
self.ram
.buf_transmuted::<AtomicU32>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
}
}
@@ -229,7 +262,7 @@ impl Ram {
}
#[inline]
pub fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryExceptionType> {
pub fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryException> {
if !addr.is_multiple_of(8) {
let high_word_addr = addr.wrapping_add(4);
@@ -243,12 +276,15 @@ impl Ram {
Ok(unsafe {
self.buf_transmuted::<AtomicU64>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}?
.load(Relaxed))
}
#[inline]
pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryExceptionType> {
pub fn read_word(&self, addr: Addr) -> Result<Word, MemoryException> {
if !addr.is_multiple_of(4) {
let high_hword_addr = addr.wrapping_add(2);
@@ -262,12 +298,15 @@ impl Ram {
Ok(unsafe {
self.buf_transmuted::<AtomicU32>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}?
.load(Relaxed))
}
#[inline]
pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryExceptionType> {
pub fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryException> {
if !addr.is_multiple_of(2) {
let high_byte_addr = addr.wrapping_add(1);
@@ -281,21 +320,27 @@ impl Ram {
Ok(unsafe {
self.buf_transmuted::<AtomicU16>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}?
.load(Relaxed))
}
#[inline]
pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryExceptionType> {
pub fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
Ok(self
.buf_atomic()
.get(addr as usize)
.ok_or(MemoryExceptionType::AccessFault)?
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?
.load(Relaxed))
}
#[inline]
pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> {
pub fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> {
if !addr.is_multiple_of(8) {
let low_word = value as Word;
let high_word = (value >> 32) as Word;
@@ -311,13 +356,16 @@ impl Ram {
unsafe {
self.buf_transmuted::<AtomicU64>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}?
.store(value, Relaxed);
Ok(())
}
#[inline]
pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> {
pub fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> {
if !addr.is_multiple_of(4) {
let low_hword = value as HWord;
let high_hword = (value >> 16) as HWord;
@@ -333,13 +381,16 @@ impl Ram {
unsafe {
self.buf_transmuted::<AtomicU32>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}?
.store(value, Relaxed);
Ok(())
}
#[inline]
pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> {
pub fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> {
if !addr.is_multiple_of(2) {
let low_byte = value as Byte;
let high_byte = (value >> 8) as Byte;
@@ -355,16 +406,22 @@ impl Ram {
unsafe {
self.buf_transmuted::<AtomicU16>()
.get(index)
.ok_or(MemoryExceptionType::AccessFault)
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}?
.store(value, Relaxed);
Ok(())
}
#[inline]
pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> {
pub fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> {
self.buf_atomic()
.get(addr as usize)
.ok_or(MemoryExceptionType::AccessFault)?
.ok_or(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})?
.store(value, Relaxed);
Ok(())
}
@@ -477,29 +534,53 @@ impl Default for MmioSecondLevel {
#[allow(unused_variables)]
pub trait MemDeviceInterface {
fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn read_dword(&self, addr: Addr) -> Result<DWord, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn read_word(&self, addr: Addr) -> Result<Word, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn read_word(&self, addr: Addr) -> Result<Word, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn read_hword(&self, addr: Addr) -> Result<HWord, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryExceptionType> {
Err(MemoryExceptionType::AccessFault)
fn read_byte(&self, addr: Addr) -> Result<Byte, MemoryException> {
Err(MemoryException {
type_: MemoryExceptionType::AccessFault,
addr,
})
}
}