Add MMU card commands to dump TLB and mapping pages

This commit is contained in:
pjht 2024-03-09 12:25:55 -06:00
parent 6b09e92ae7
commit 8919dc182f
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
2 changed files with 190 additions and 17 deletions

View File

@ -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
};

View File

@ -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;