Tell MMU whether memory accesses are user or supervisor

This commit is contained in:
pjht 2024-03-09 12:25:54 -06:00
parent f3cec9c9a3
commit d05eb249bb
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
6 changed files with 33 additions and 16 deletions

View File

@ -151,7 +151,7 @@ impl Backplane {
.cmd(cmd) .cmd(cmd)
} }
pub fn read_word(&self, address: u32) -> Result<u16, BusError> { pub fn read_word(&self, address: u32, supervisor: bool) -> Result<u16, BusError> {
self.mem_helper( self.mem_helper(
address, address,
|address, mut card| card.read_word(address), |address, mut card| card.read_word(address),
@ -159,10 +159,11 @@ impl Backplane {
|address| self.read_word_io(address as u8), |address| self.read_word_io(address as u8),
false, false,
false, false,
supervisor,
) )
} }
pub fn read_byte(&self, address: u32) -> Result<u8, BusError> { pub fn read_byte(&self, address: u32, supervisor: bool) -> Result<u8, BusError> {
self.mem_helper( self.mem_helper(
address, address,
|address, mut card| card.read_byte(address), |address, mut card| card.read_byte(address),
@ -170,10 +171,11 @@ impl Backplane {
|address| self.read_byte_io(address as u8), |address| self.read_byte_io(address as u8),
false, false,
false, false,
supervisor,
) )
} }
pub fn write_word(&self, address: u32, data: u16) -> Result<(), BusError> { pub fn write_word(&self, address: u32, data: u16, supervisor: bool) -> Result<(), BusError> {
self.mem_helper( self.mem_helper(
address, address,
|address, mut card| card.write_word(address, data), |address, mut card| card.write_word(address, data),
@ -181,10 +183,11 @@ impl Backplane {
|address| self.write_word_io(address as u8, data), |address| self.write_word_io(address as u8, data),
false, false,
true, true,
supervisor,
) )
} }
pub fn write_byte(&self, address: u32, data: u8) -> Result<(), BusError> { pub fn write_byte(&self, address: u32, data: u8, supervisor: bool) -> Result<(), BusError> {
self.mem_helper( self.mem_helper(
address, address,
|address, mut card| card.write_byte(address, data), |address, mut card| card.write_byte(address, data),
@ -192,6 +195,7 @@ impl Backplane {
|address| self.write_byte_io(address as u8, data), |address| self.write_byte_io(address as u8, data),
false, false,
true, true,
supervisor,
) )
} }
@ -203,6 +207,7 @@ impl Backplane {
|address| self.read_word_io(address as u8), |address| self.read_word_io(address as u8),
true, true,
false, false,
true,
) )
} }
@ -215,6 +220,7 @@ impl Backplane {
|address| self.read_byte_io(address as u8), |address| self.read_byte_io(address as u8),
true, true,
false, false,
true,
) )
} }
@ -227,6 +233,7 @@ impl Backplane {
|address| self.write_word_io(address as u8, data), |address| self.write_word_io(address as u8, data),
true, true,
true, true,
true,
) )
} }
@ -239,6 +246,7 @@ impl Backplane {
|address| self.write_byte_io(address as u8, data), |address| self.write_byte_io(address as u8, data),
true, true,
true, true,
true,
) )
} }
@ -250,6 +258,7 @@ impl Backplane {
mut backplane_io_func: B, mut backplane_io_func: B,
bypass_mmu: bool, bypass_mmu: bool,
write: bool, write: bool,
supervisor: bool,
) -> Result<T, BusError> ) -> Result<T, BusError>
where where
M: FnMut(u32, RefMut<'_, dyn Card>) -> NullableResult<T, BusError>, M: FnMut(u32, RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
@ -263,7 +272,7 @@ impl Backplane {
.borrow_mut() .borrow_mut()
.try_as_mmu() .try_as_mmu()
.unwrap() .unwrap()
.translate_address(self, address, write) .translate_address(self, address, write, supervisor)
{ {
NullableResult::Ok(address) => address, NullableResult::Ok(address) => address,
NullableResult::Err(e) => return Err(e), NullableResult::Err(e) => return Err(e),

View File

@ -146,6 +146,7 @@ pub trait Mmu: Debug {
backplane: &Backplane, backplane: &Backplane,
address: u32, address: u32,
write: bool, write: bool,
supervisor: bool,
) -> NullableResult<u32, BusError>; ) -> NullableResult<u32, BusError>;
} }

View File

@ -1483,7 +1483,7 @@ impl M68K {
self.store_mem_cycles = true; self.store_mem_cycles = true;
} }
} }
let result = self.bus.read_byte(address).map_err(|_| DetailedBusError { let result = self.bus.read_byte(address, self.is_supervisor()).map_err(|_| DetailedBusError {
address, address,
cause: BusErrorCause::ReadingByte, cause: BusErrorCause::ReadingByte,
}); });
@ -1518,7 +1518,7 @@ impl M68K {
} }
let result = self let result = self
.bus .bus
.write_byte(address, data) .write_byte(address, data, self.is_supervisor())
.map_err(|_| DetailedBusError { .map_err(|_| DetailedBusError {
address, address,
cause: BusErrorCause::WritingByte, cause: BusErrorCause::WritingByte,
@ -1553,7 +1553,7 @@ impl M68K {
self.store_mem_cycles = true; self.store_mem_cycles = true;
} }
} }
let result = self.bus.read_word(address).map_err(|_| DetailedBusError { let result = self.bus.read_word(address, self.is_supervisor()).map_err(|_| DetailedBusError {
address, address,
cause: BusErrorCause::ReadingWord, cause: BusErrorCause::ReadingWord,
}); });
@ -1592,7 +1592,7 @@ impl M68K {
} }
let result = self let result = self
.bus .bus
.write_word(address, data) .write_word(address, data, self.is_supervisor())
.map_err(|_| DetailedBusError { .map_err(|_| DetailedBusError {
address, address,
cause: BusErrorCause::WritingWord, cause: BusErrorCause::WritingWord,

View File

@ -294,11 +294,11 @@ fn main() -> Result<(), anyhow::Error> {
} else { } else {
for i in 0..count { for i in 0..count {
match size { match size {
peek::Size::Byte => data.push(u32::from(bus.read_byte(addr + i)?)), peek::Size::Byte => data.push(u32::from(bus.read_byte(addr + i, true)?)),
peek::Size::Word => data.push(u32::from(bus.read_word(addr + (i * 2))?)), peek::Size::Word => data.push(u32::from(bus.read_word(addr + (i * 2), true)?)),
peek::Size::LongWord => data.push( peek::Size::LongWord => data.push(
u32::from(bus.read_word(addr + (i * 4))?) << 16 u32::from(bus.read_word(addr + (i * 4), true)?) << 16
| u32::from(bus.read_word(addr + (i * 4) + 2)?), | u32::from(bus.read_word(addr + (i * 4) + 2, true)?),
), ),
} }
} }
@ -335,10 +335,10 @@ fn main() -> Result<(), anyhow::Error> {
return Err(anyhow!("Cannot poke a word to a non-aligned address")); return Err(anyhow!("Cannot poke a word to a non-aligned address"));
} }
let data = parse::<u16>(args.get_one::<String>("data").unwrap())?; let data = parse::<u16>(args.get_one::<String>("data").unwrap())?;
state.cpu.bus_mut().write_word(address, data)?; state.cpu.bus_mut().write_word(address, data, true)?;
} else { } else {
let data = parse::<u8>(args.get_one::<String>("data").unwrap())?; let data = parse::<u8>(args.get_one::<String>("data").unwrap())?;
state.cpu.bus_mut().write_byte(address, data)?; state.cpu.bus_mut().write_byte(address, data, true)?;
} }
Ok(None) Ok(None)
} }

View File

@ -161,6 +161,7 @@ impl Mmu for MmuCard {
backplane: &Backplane, backplane: &Backplane,
address: u32, address: u32,
write: bool, write: bool,
supervisor: bool,
) -> NullableResult<u32, BusError> { ) -> NullableResult<u32, BusError> {
let print_debug = self.print_debug; let print_debug = self.print_debug;
if self.enabled { if self.enabled {
@ -198,6 +199,12 @@ impl Mmu for MmuCard {
mapping mapping
}; };
if mapping & MAPPING_FLAG_PRESENT > 0 { if mapping & MAPPING_FLAG_PRESENT > 0 {
if !supervisor && (mapping & MAPPING_FLAG_USER == 0) {
if print_debug {
println!("Page not user accessible");
}
return NullableResult::Err(BusError);
}
if write && (mapping & MAPPING_FLAG_WRITABLE == 0) { if write && (mapping & MAPPING_FLAG_WRITABLE == 0) {
if print_debug { if print_debug {
println!("Page not writable"); println!("Page not writable");

View File

@ -156,7 +156,7 @@ impl Card for Storage {
// Closure is used to drop the mutex guard // Closure is used to drop the mutex guard
// between pop calls to prevent deadlock // between pop calls to prevent deadlock
while let Some(data) = (|| self.read_data.pop_front())() { while let Some(data) = (|| self.read_data.pop_front())() {
backplane.write_byte(address, data).unwrap(); backplane.write_byte(address, data, true).unwrap();
address += 1; address += 1;
} }
self.transfer = false; self.transfer = false;