Add MMU card commands to dump TLB and mapping pages
This commit is contained in:
parent
6b09e92ae7
commit
8919dc182f
205
src/mmu.rs
205
src/mmu.rs
@ -3,7 +3,7 @@ use std::fmt::Display;
|
||||
use nullable_result::NullableResult;
|
||||
|
||||
use crate::{
|
||||
backplane::{self, Backplane},
|
||||
backplane::Backplane,
|
||||
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card, Mmu},
|
||||
m68k::BusError,
|
||||
register,
|
||||
@ -26,6 +26,25 @@ pub struct MmuCard {
|
||||
tlb_clear_entry: u16,
|
||||
}
|
||||
|
||||
impl MmuCard {
|
||||
fn get_mapping(&self, page: u32, backplane: &Backplane, print_debug: bool) -> NullableResult<u32, BusError> {
|
||||
if !self.map_frames_enabled[(page >> 10) as usize] {
|
||||
if print_debug {
|
||||
println!("No mapping frame for this quarter");
|
||||
}
|
||||
return NullableResult::Null;
|
||||
}
|
||||
let map_frame = self.map_frames[(page >> 10) as usize];
|
||||
let mapping_address = (map_frame) | ((page & 0x3FF) << 2);
|
||||
if print_debug {
|
||||
println!("Mapping is at {mapping_address:#x}");
|
||||
}
|
||||
let mapping_hi = backplane.read_word_phys(mapping_address)?;
|
||||
let mapping_lo = backplane.read_word_phys(mapping_address + 2)?;
|
||||
NullableResult::Ok((u32::from(mapping_hi) << 16 | u32::from(mapping_lo)) | TLB_MAPPING_FLAG_VALID)
|
||||
}
|
||||
}
|
||||
|
||||
impl Card for MmuCard {
|
||||
fn new(_data: toml::Value) -> anyhow::Result<Self> {
|
||||
Ok(Self {
|
||||
@ -118,6 +137,174 @@ impl Card for MmuCard {
|
||||
if cmd[0] == "debug" && cmd.len() >= 2 {
|
||||
self.print_debug = cmd[1].parse()?;
|
||||
}
|
||||
if cmd[0] == "dump_tlb" {
|
||||
let mut i = 0;
|
||||
while i < 4096 {
|
||||
let entry = self.tlb[i];
|
||||
if entry & TLB_MAPPING_FLAG_VALID == 0 {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
let flags = entry & 0xFFF;
|
||||
let frame = entry & !0xFFF;
|
||||
let mut j = i;
|
||||
let mut range_one_page: Option<bool> = None;
|
||||
while j < 4095 {
|
||||
let entry = self.get_mapping((j+1) as u32, backplane, false).resulting_option()?.unwrap_or(0);
|
||||
if entry & TLB_MAPPING_FLAG_VALID == 0 {
|
||||
break;
|
||||
}
|
||||
let j_flags = entry & 0xFFF;
|
||||
let j_frame = entry & !0xFFF;
|
||||
if j_flags != flags || j_frame < frame {
|
||||
break;
|
||||
}
|
||||
if j_frame == frame {
|
||||
if range_one_page == Some(false) {
|
||||
break;
|
||||
} else {
|
||||
range_one_page = Some(true);
|
||||
}
|
||||
} else if (j_frame - frame) == ((((j - i) as u32) + 1) * 0x1000) {
|
||||
if range_one_page == Some(true) {
|
||||
break;
|
||||
} else {
|
||||
range_one_page = Some(false);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
let present_flag = (flags & MAPPING_FLAG_PRESENT) > 0;
|
||||
let wr_flag = (flags & MAPPING_FLAG_WRITABLE) > 0;
|
||||
let user_flag = (flags & MAPPING_FLAG_USER) > 0;
|
||||
let present_flag = if present_flag { "P" } else { "_" };
|
||||
let wr_flag = if wr_flag { "W" } else { "_" };
|
||||
let user_flag = if user_flag { "U" } else { "_" };
|
||||
if j == i {
|
||||
println!(
|
||||
"0x{:0>6x}: 0x{:0>8x} ({}{}{})",
|
||||
i << 12,
|
||||
frame,
|
||||
user_flag,
|
||||
wr_flag,
|
||||
present_flag
|
||||
);
|
||||
i += 1;
|
||||
} else {
|
||||
if range_one_page.unwrap() {
|
||||
println!(
|
||||
"0x{:0>6x}-0x{:0>6x}: 0x{:0>8x} ({}{}{})",
|
||||
i << 12,
|
||||
j << 12,
|
||||
frame,
|
||||
user_flag,
|
||||
wr_flag,
|
||||
present_flag
|
||||
);
|
||||
} else {
|
||||
let range_len = (j - i) as u32;
|
||||
println!(
|
||||
"0x{:0>6x}-0x{:0>6x}: 0x{:0>8x}-0x{:0>8x} ({}{}{})",
|
||||
i << 12,
|
||||
j << 12,
|
||||
frame,
|
||||
frame + (range_len * 0x1000),
|
||||
user_flag,
|
||||
wr_flag,
|
||||
present_flag
|
||||
);
|
||||
}
|
||||
i = j + 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if cmd[0] == "dump_map_pages" {
|
||||
let mut i = 0;
|
||||
while i < 4096 {
|
||||
let entry = self.get_mapping(i as u32, backplane, false).resulting_option()?.unwrap_or(0);
|
||||
if entry & TLB_MAPPING_FLAG_VALID == 0 {
|
||||
i+=1;
|
||||
continue;
|
||||
}
|
||||
let flags = entry & 0xFFF;
|
||||
let frame = entry & !0xFFF;
|
||||
let mut j = i;
|
||||
let mut range_one_page: Option<bool> = None;
|
||||
while j < 4095 {
|
||||
let entry = self.get_mapping((j+1) as u32, backplane, false).resulting_option()?.unwrap_or(0);
|
||||
if entry & TLB_MAPPING_FLAG_VALID == 0 {
|
||||
break;
|
||||
}
|
||||
let j_flags = entry & 0xFFF;
|
||||
let j_frame = entry & !0xFFF;
|
||||
if j_flags != flags || j_frame < frame {
|
||||
break;
|
||||
}
|
||||
if j_frame == frame {
|
||||
if range_one_page == Some(false) {
|
||||
break;
|
||||
} else {
|
||||
range_one_page = Some(true);
|
||||
}
|
||||
} else if (j_frame - frame) == ((((j - i) as u32) + 1) * 0x1000) {
|
||||
if range_one_page == Some(true) {
|
||||
break;
|
||||
} else {
|
||||
range_one_page = Some(false);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
let present_flag = (flags & MAPPING_FLAG_PRESENT) > 0;
|
||||
let wr_flag = (flags & MAPPING_FLAG_WRITABLE) > 0;
|
||||
let user_flag = (flags & MAPPING_FLAG_USER) > 0;
|
||||
let present_flag = if present_flag { "P" } else { "_" };
|
||||
let wr_flag = if wr_flag { "W" } else { "_" };
|
||||
let user_flag = if user_flag { "U" } else { "_" };
|
||||
if j == i {
|
||||
println!(
|
||||
"0x{:0>6x}: 0x{:0>8x} ({}{}{})",
|
||||
i << 12,
|
||||
frame,
|
||||
user_flag,
|
||||
wr_flag,
|
||||
present_flag
|
||||
);
|
||||
i += 1;
|
||||
} else {
|
||||
if range_one_page.unwrap() {
|
||||
println!(
|
||||
"0x{:0>6x}-0x{:0>6x}: 0x{:0>8x} ({}{}{})",
|
||||
i << 12,
|
||||
j << 12,
|
||||
frame,
|
||||
user_flag,
|
||||
wr_flag,
|
||||
present_flag
|
||||
);
|
||||
} else {
|
||||
let range_len = (j - i) as u32;
|
||||
println!(
|
||||
"0x{:0>6x}-0x{:0>6x}: 0x{:0>8x}-0x{:0>8x} ({}{}{})",
|
||||
i << 12,
|
||||
j << 12,
|
||||
frame,
|
||||
frame + (range_len * 0x1000),
|
||||
user_flag,
|
||||
wr_flag,
|
||||
present_flag
|
||||
);
|
||||
}
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -180,21 +367,7 @@ impl Mmu for MmuCard {
|
||||
if print_debug {
|
||||
println!("TLB miss, fetching mapping");
|
||||
}
|
||||
if !self.map_frames_enabled[(page >> 10) as usize] {
|
||||
if print_debug {
|
||||
println!("No mapping frame for this quarter");
|
||||
}
|
||||
return NullableResult::Null;
|
||||
}
|
||||
let map_frame = self.map_frames[(page >> 10) as usize];
|
||||
let mapping_address = (map_frame) | ((page & 0x3FF) << 2);
|
||||
if print_debug {
|
||||
println!("Mapping is at {mapping_address:#x}");
|
||||
}
|
||||
let mapping_hi = backplane.read_word_phys(mapping_address)?;
|
||||
let mapping_lo = backplane.read_word_phys(mapping_address + 2)?;
|
||||
let mapping =
|
||||
(u32::from(mapping_hi) << 16 | u32::from(mapping_lo)) | TLB_MAPPING_FLAG_VALID;
|
||||
let mapping = self.get_mapping(page, backplane, print_debug)?;
|
||||
self.tlb[page as usize] = mapping;
|
||||
mapping
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ use serde::Deserialize;
|
||||
use toml::Value;
|
||||
|
||||
use crate::{
|
||||
backplane::{self, Backplane}, card::{u16_get_be_byte, u16_set_be_byte, Card}, m68k::BusError, register
|
||||
backplane::Backplane, card::{u16_get_be_byte, u16_set_be_byte, Card}, m68k::BusError, register
|
||||
};
|
||||
|
||||
const ID: u16 = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user