mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-09 21:31:24 +00:00
ppcmmu: Add a function to get phys address.
Since the function is for the debugger during stepping or disassembly, don't do extra logging.
This commit is contained in:
parent
500f38a496
commit
6738d7472e
@ -549,7 +549,7 @@ static TLBEntry* itlb2_refill(uint32_t guest_va)
|
|||||||
return tlb_entry;
|
return tlb_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TLBEntry* dtlb2_refill(uint32_t guest_va, int is_write)
|
static TLBEntry* dtlb2_refill(uint32_t guest_va, int is_write, bool is_dbg = false)
|
||||||
{
|
{
|
||||||
BATResult bat_res;
|
BATResult bat_res;
|
||||||
uint32_t phys_addr;
|
uint32_t phys_addr;
|
||||||
@ -569,7 +569,9 @@ static TLBEntry* dtlb2_refill(uint32_t guest_va, int is_write)
|
|||||||
if (bat_res.hit) {
|
if (bat_res.hit) {
|
||||||
// check block protection
|
// check block protection
|
||||||
if (!bat_res.prot || ((bat_res.prot & 1) && is_write)) {
|
if (!bat_res.prot || ((bat_res.prot & 1) && is_write)) {
|
||||||
|
if (!is_dbg)
|
||||||
LOG_F(9, "BAT DSI exception in TLB2 refill!");
|
LOG_F(9, "BAT DSI exception in TLB2 refill!");
|
||||||
|
if (!is_dbg)
|
||||||
LOG_F(9, "Attempt to write to read-only region, LA=0x%08X, PC=0x%08X!", guest_va, ppc_state.pc);
|
LOG_F(9, "Attempt to write to read-only region, LA=0x%08X, PC=0x%08X!", guest_va, ppc_state.pc);
|
||||||
ppc_state.spr[SPR::DSISR] = 0x08000000 | (is_write << 25);
|
ppc_state.spr[SPR::DSISR] = 0x08000000 | (is_write << 25);
|
||||||
ppc_state.spr[SPR::DAR] = guest_va;
|
ppc_state.spr[SPR::DAR] = guest_va;
|
||||||
@ -625,6 +627,7 @@ static TLBEntry* dtlb2_refill(uint32_t guest_va, int is_write)
|
|||||||
tlb_entry->phys_tag = phys_addr & ~0xFFFUL;
|
tlb_entry->phys_tag = phys_addr & ~0xFFFUL;
|
||||||
return tlb_entry;
|
return tlb_entry;
|
||||||
} else {
|
} else {
|
||||||
|
if (!is_dbg) {
|
||||||
static uint32_t last_phys_addr = -1;
|
static uint32_t last_phys_addr = -1;
|
||||||
static uint32_t first_phys_addr = -1;
|
static uint32_t first_phys_addr = -1;
|
||||||
if (phys_addr != last_phys_addr + 4) {
|
if (phys_addr != last_phys_addr + 4) {
|
||||||
@ -635,6 +638,7 @@ static TLBEntry* dtlb2_refill(uint32_t guest_va, int is_write)
|
|||||||
LOG_F(WARNING, "Access to unmapped physical memory, phys_addr=0x%08X", first_phys_addr);
|
LOG_F(WARNING, "Access to unmapped physical memory, phys_addr=0x%08X", first_phys_addr);
|
||||||
}
|
}
|
||||||
last_phys_addr = phys_addr;
|
last_phys_addr = phys_addr;
|
||||||
|
}
|
||||||
return &UnmappedMem;
|
return &UnmappedMem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1987,6 +1991,61 @@ uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size) {
|
|||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mmu_translate_dbg(uint32_t guest_va, uint32_t &guest_pa) {
|
||||||
|
uint32_t save_dsisr, save_dar;
|
||||||
|
bool is_mapped;
|
||||||
|
|
||||||
|
/* save MMU-related CPU state */
|
||||||
|
save_dsisr = ppc_state.spr[SPR::DSISR];
|
||||||
|
save_dar = ppc_state.spr[SPR::DAR];
|
||||||
|
mmu_exception_handler = dbg_exception_handler;
|
||||||
|
|
||||||
|
try {
|
||||||
|
TLBEntry *tlb1_entry, *tlb2_entry;
|
||||||
|
|
||||||
|
const uint32_t tag = guest_va & ~0xFFFUL;
|
||||||
|
|
||||||
|
// look up guest virtual address in the primary TLB
|
||||||
|
tlb1_entry = &pCurDTLB1[(guest_va >> PAGE_SIZE_BITS) & tlb_size_mask];
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (tlb1_entry->tag != tag) {
|
||||||
|
// primary TLB miss -> look up address in the secondary TLB
|
||||||
|
tlb2_entry = lookup_secondary_tlb<TLBType::DTLB>(guest_va, tag);
|
||||||
|
if (tlb2_entry == nullptr) {
|
||||||
|
// secondary TLB miss ->
|
||||||
|
// perform full address translation and refill the secondary TLB
|
||||||
|
tlb2_entry = dtlb2_refill(guest_va, 0, true);
|
||||||
|
if (tlb2_entry->flags & PAGE_NOPHYS) {
|
||||||
|
is_mapped = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlb2_entry->flags & TLBFlags::PAGE_MEM) { // is it a real memory region?
|
||||||
|
// refill the primary TLB
|
||||||
|
*tlb1_entry = *tlb2_entry;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tlb1_entry = tlb2_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guest_pa = tlb1_entry->phys_tag | (guest_va & 0xFFFUL);
|
||||||
|
is_mapped = true;
|
||||||
|
} while (0);
|
||||||
|
} catch (std::invalid_argument& exc) {
|
||||||
|
LOG_F(WARNING, "Unmapped address 0x%08X", guest_va);
|
||||||
|
is_mapped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore MMU-related CPU state */
|
||||||
|
mmu_exception_handler = ppc_exception_handler;
|
||||||
|
ppc_state.spr[SPR::DSISR] = save_dsisr;
|
||||||
|
ppc_state.spr[SPR::DAR] = save_dar;
|
||||||
|
|
||||||
|
return is_mapped;
|
||||||
|
}
|
||||||
|
|
||||||
void ppc_mmu_init()
|
void ppc_mmu_init()
|
||||||
{
|
{
|
||||||
mmu_exception_handler = ppc_exception_handler;
|
mmu_exception_handler = ppc_exception_handler;
|
||||||
|
@ -127,6 +127,7 @@ extern void tlb_flush_entry(uint32_t ea);
|
|||||||
|
|
||||||
extern uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size);
|
extern uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size);
|
||||||
uint8_t *mmu_translate_imem(uint32_t vaddr, uint32_t *paddr = nullptr);
|
uint8_t *mmu_translate_imem(uint32_t vaddr, uint32_t *paddr = nullptr);
|
||||||
|
bool mmu_translate_dbg(uint32_t guest_va, uint32_t &guest_pa);
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
extern T mmu_read_vmem(uint32_t guest_va);
|
extern T mmu_read_vmem(uint32_t guest_va);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user