EXCEPTION SYSTEM (initial version - may change later)
This commit is contained in:
150
src/mem.rs
150
src/mem.rs
@@ -11,7 +11,10 @@ use std::sync::{
|
||||
|
||||
use memmap2::MmapMut;
|
||||
|
||||
use crate::consts::{Byte, DWord, HWord, Word};
|
||||
use crate::{
|
||||
consts::{Byte, DWord, HWord, Word},
|
||||
exceptions::ExceptionType,
|
||||
};
|
||||
|
||||
pub type PageNum = usize;
|
||||
|
||||
@@ -45,38 +48,46 @@ impl MemConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, MemAccessFault> {
|
||||
pub fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.read_dword(page - self.ram_start, offset)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::LoadAccessFault)?;
|
||||
|
||||
entry.interface.read_dword(page - entry.base, offset)
|
||||
}
|
||||
}
|
||||
pub fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, MemAccessFault> {
|
||||
pub fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.read_word(page - self.ram_start, offset)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::LoadAccessFault)?;
|
||||
|
||||
entry.interface.read_word(page - entry.base, offset)
|
||||
}
|
||||
}
|
||||
pub fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, MemAccessFault> {
|
||||
pub fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.read_hword(page - self.ram_start, offset)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::LoadAccessFault)?;
|
||||
|
||||
entry.interface.read_hword(page - entry.base, offset)
|
||||
}
|
||||
}
|
||||
pub fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, MemAccessFault> {
|
||||
pub fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.read_byte(page - self.ram_start, offset)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::LoadAccessFault)?;
|
||||
|
||||
entry.interface.read_byte(page - entry.base, offset)
|
||||
}
|
||||
@@ -87,26 +98,25 @@ impl MemConfig {
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: DWord,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
) -> Result<(), ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.write_dword(page - self.ram_start, offset, value)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?;
|
||||
entry
|
||||
.interface
|
||||
.write_dword(page - entry.base, offset, value)
|
||||
}
|
||||
}
|
||||
pub fn write_word(
|
||||
&self,
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: Word,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
pub fn write_word(&self, page: PageNum, offset: u16, value: Word) -> Result<(), ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.write_word(page - self.ram_start, offset, value)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?;
|
||||
entry.interface.write_word(page - entry.base, offset, value)
|
||||
}
|
||||
}
|
||||
@@ -115,26 +125,25 @@ impl MemConfig {
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: HWord,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
) -> Result<(), ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.write_hword(page - self.ram_start, offset, value)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?;
|
||||
entry
|
||||
.interface
|
||||
.write_hword(page - entry.base, offset, value)
|
||||
}
|
||||
}
|
||||
pub fn write_byte(
|
||||
&self,
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: Byte,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
pub fn write_byte(&self, page: PageNum, offset: u16, value: Byte) -> Result<(), ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
self.ram.write_byte(page - self.ram_start, offset, value)
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?;
|
||||
entry.interface.write_byte(page - entry.base, offset, value)
|
||||
}
|
||||
}
|
||||
@@ -143,7 +152,7 @@ impl MemConfig {
|
||||
&self,
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
) -> Result<&AtomicU64, MemAccessFault> {
|
||||
) -> Result<&AtomicU64, ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
debug_assert!(((offset * 8) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 8) + (offset as usize);
|
||||
@@ -151,18 +160,16 @@ impl MemConfig {
|
||||
self.ram
|
||||
.buf_transmuted::<AtomicU64>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::HardwareError)
|
||||
}
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?;
|
||||
entry.interface.get_atomic_dword(page - entry.base, offset)
|
||||
}
|
||||
}
|
||||
pub fn get_atomic_word(
|
||||
&self,
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
) -> Result<&AtomicU32, MemAccessFault> {
|
||||
pub fn get_atomic_word(&self, page: PageNum, offset: u16) -> Result<&AtomicU32, ExceptionType> {
|
||||
if page_in_range(page, self.ram_start, self.ram.pages) {
|
||||
debug_assert!(((offset * 4) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 4) + (offset as usize);
|
||||
@@ -170,10 +177,12 @@ impl MemConfig {
|
||||
self.ram
|
||||
.buf_transmuted::<AtomicU32>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::HardwareError)
|
||||
}
|
||||
} else {
|
||||
let entry = self.find_device_by_page(page).ok_or(MemAccessFault)?;
|
||||
let entry = self
|
||||
.find_device_by_page(page)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?;
|
||||
entry.interface.get_atomic_word(page - entry.base, offset)
|
||||
}
|
||||
}
|
||||
@@ -232,46 +241,46 @@ impl Ram {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, MemAccessFault> {
|
||||
pub fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, ExceptionType> {
|
||||
debug_assert!(((offset * 8) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 8) + (offset as usize);
|
||||
Ok(unsafe {
|
||||
self.buf_transmuted::<AtomicU64>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::LoadAccessFault)
|
||||
}?
|
||||
.load(Relaxed))
|
||||
}
|
||||
#[inline]
|
||||
pub fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, MemAccessFault> {
|
||||
pub fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, ExceptionType> {
|
||||
debug_assert!(((offset * 4) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 4) + (offset as usize);
|
||||
Ok(unsafe {
|
||||
self.buf_transmuted::<AtomicU32>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::LoadAccessFault)
|
||||
}?
|
||||
.load(Relaxed))
|
||||
}
|
||||
#[inline]
|
||||
pub fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, MemAccessFault> {
|
||||
pub fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, ExceptionType> {
|
||||
debug_assert!(((offset * 2) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 2) + (offset as usize);
|
||||
Ok(unsafe {
|
||||
self.buf_transmuted::<AtomicU16>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::LoadAccessFault)
|
||||
}?
|
||||
.load(Relaxed))
|
||||
}
|
||||
#[inline]
|
||||
pub fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, MemAccessFault> {
|
||||
pub fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, ExceptionType> {
|
||||
debug_assert!((offset as usize) < PAGE_SIZE);
|
||||
let index = page * PAGE_SIZE + (offset as usize);
|
||||
Ok(self
|
||||
.buf_atomic()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)?
|
||||
.ok_or(ExceptionType::LoadAccessFault)?
|
||||
.load(Relaxed))
|
||||
}
|
||||
|
||||
@@ -281,30 +290,25 @@ impl Ram {
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: DWord,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
) -> Result<(), ExceptionType> {
|
||||
debug_assert!(((offset * 8) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 8) + (offset as usize);
|
||||
unsafe {
|
||||
self.buf_transmuted::<AtomicU64>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)
|
||||
}?
|
||||
.store(value, Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
#[inline]
|
||||
pub fn write_word(
|
||||
&self,
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: Word,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
pub fn write_word(&self, page: PageNum, offset: u16, value: Word) -> Result<(), ExceptionType> {
|
||||
debug_assert!(((offset * 4) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 4) + (offset as usize);
|
||||
unsafe {
|
||||
self.buf_transmuted::<AtomicU32>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)
|
||||
}?
|
||||
.store(value, Relaxed);
|
||||
Ok(())
|
||||
@@ -315,29 +319,24 @@ impl Ram {
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: HWord,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
) -> Result<(), ExceptionType> {
|
||||
debug_assert!(((offset * 2) as usize) < PAGE_SIZE);
|
||||
let index = page * (PAGE_SIZE / 2) + (offset as usize);
|
||||
unsafe {
|
||||
self.buf_transmuted::<AtomicU16>()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)
|
||||
}?
|
||||
.store(value, Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
#[inline]
|
||||
pub fn write_byte(
|
||||
&self,
|
||||
page: PageNum,
|
||||
offset: u16,
|
||||
value: Byte,
|
||||
) -> Result<(), MemAccessFault> {
|
||||
pub fn write_byte(&self, page: PageNum, offset: u16, value: Byte) -> Result<(), ExceptionType> {
|
||||
debug_assert!((offset as usize) < PAGE_SIZE);
|
||||
let index = page * PAGE_SIZE + (offset as usize);
|
||||
self.buf_atomic()
|
||||
.get(index)
|
||||
.ok_or(MemAccessFault)?
|
||||
.ok_or(ExceptionType::StoreAmoAccessFault)?
|
||||
.store(value, Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
@@ -351,21 +350,16 @@ pub struct DeviceEntry {
|
||||
}
|
||||
|
||||
pub trait MemDeviceInterface {
|
||||
fn write_dword(&self, page: PageNum, offset: u16, value: DWord) -> Result<(), MemAccessFault>;
|
||||
fn write_word(&self, page: PageNum, offset: u16, value: Word) -> Result<(), MemAccessFault>;
|
||||
fn write_hword(&self, page: PageNum, offset: u16, value: HWord) -> Result<(), MemAccessFault>;
|
||||
fn write_byte(&self, page: PageNum, offset: u16, value: Byte) -> Result<(), MemAccessFault>;
|
||||
fn write_dword(&self, page: PageNum, offset: u16, value: DWord) -> Result<(), ExceptionType>;
|
||||
fn write_word(&self, page: PageNum, offset: u16, value: Word) -> Result<(), ExceptionType>;
|
||||
fn write_hword(&self, page: PageNum, offset: u16, value: HWord) -> Result<(), ExceptionType>;
|
||||
fn write_byte(&self, page: PageNum, offset: u16, value: Byte) -> Result<(), ExceptionType>;
|
||||
|
||||
fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, MemAccessFault>;
|
||||
fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, MemAccessFault>;
|
||||
fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, MemAccessFault>;
|
||||
fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, MemAccessFault>;
|
||||
fn read_dword(&self, page: PageNum, offset: u16) -> Result<DWord, ExceptionType>;
|
||||
fn read_word(&self, page: PageNum, offset: u16) -> Result<Word, ExceptionType>;
|
||||
fn read_hword(&self, page: PageNum, offset: u16) -> Result<HWord, ExceptionType>;
|
||||
fn read_byte(&self, page: PageNum, offset: u16) -> Result<Byte, ExceptionType>;
|
||||
|
||||
fn get_atomic_word(&self, page: PageNum, offset: u16) -> Result<&AtomicU32, MemAccessFault>;
|
||||
fn get_atomic_dword(&self, page: PageNum, offset: u16) -> Result<&AtomicU64, MemAccessFault>;
|
||||
fn get_atomic_word(&self, page: PageNum, offset: u16) -> Result<&AtomicU32, ExceptionType>;
|
||||
fn get_atomic_dword(&self, page: PageNum, offset: u16) -> Result<&AtomicU64, ExceptionType>;
|
||||
}
|
||||
|
||||
/// Error that means something has gone wrong accessing memory
|
||||
/// Examples are: Accessing unmapped memory, accessing an MMIO register at the wrong size
|
||||
#[derive(Debug)]
|
||||
pub struct MemAccessFault;
|
||||
|
||||
Reference in New Issue
Block a user