Add exception values (what will go in mtval/stval)
This commit is contained in:
253
src/mem.rs
253
src/mem.rs
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user