mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-23 06:31:28 +00:00
ppcmmu: add debug memory reading function.
This function saves and restores the MMU state so no invalid user input can break CPU execution.
This commit is contained in:
parent
403c19ca39
commit
461d859e73
@ -232,6 +232,7 @@ extern uint32_t supervisor_inst_num;
|
||||
|
||||
//Function prototypes
|
||||
extern void ppc_cpu_init(uint32_t proc_version);
|
||||
extern void ppc_mmu_init(void);
|
||||
|
||||
void ppc_illegalop();
|
||||
void ppc_opcode4();
|
||||
@ -276,8 +277,12 @@ void ppc_changecrf0(uint32_t set_result);
|
||||
void ppc_fp_changecrf1();
|
||||
|
||||
void ppc_tbr_update();
|
||||
|
||||
/* Exception handlers. */
|
||||
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits);
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits);
|
||||
|
||||
//MEMORY DECLARATIONS
|
||||
extern MemCtrlBase* mem_ctrl_instance;
|
||||
|
@ -1,6 +1,8 @@
|
||||
/** @file Handling of low-level PPC exceptions. */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "ppcemu.h"
|
||||
|
||||
jmp_buf exc_env; /* Global exception environment. */
|
||||
@ -91,3 +93,64 @@ jmp_buf exc_env; /* Global exception environment. */
|
||||
|
||||
longjmp(exc_env, 2); /* return to the main execution loop. */
|
||||
}
|
||||
|
||||
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits)
|
||||
{
|
||||
std::string exc_descriptor;
|
||||
|
||||
switch(exception_type) {
|
||||
case Except_Type::EXC_SYSTEM_RESET:
|
||||
exc_descriptor = "System reset exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_MACHINE_CHECK:
|
||||
exc_descriptor = "Machine check exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_DSI:
|
||||
case Except_Type::EXC_ISI:
|
||||
if (ppc_state.ppc_spr[SPR::DSISR] & 0x40000000)
|
||||
exc_descriptor = "DSI/ISI exception: unmapped memory access";
|
||||
else if (ppc_state.ppc_spr[SPR::DSISR] & 0x08000000)
|
||||
exc_descriptor = "DSI/ISI exception: access protection violation";
|
||||
else {
|
||||
if (exception_type == Except_Type::EXC_DSI)
|
||||
exc_descriptor = "DSI exception";
|
||||
else
|
||||
exc_descriptor = "ISI exception";
|
||||
}
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_EXT_INT:
|
||||
exc_descriptor = "External interrupt exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_ALIGNMENT:
|
||||
exc_descriptor = "Alignment exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_PROGRAM:
|
||||
exc_descriptor = "Program exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_NO_FPU:
|
||||
exc_descriptor = "Floating-Point unavailable exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_DECR:
|
||||
exc_descriptor = "Decrementer exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_SYSCALL:
|
||||
exc_descriptor = "Syscall exception occured";
|
||||
break;
|
||||
|
||||
case Except_Type::EXC_TRACE:
|
||||
exc_descriptor = "Trace exception occured";
|
||||
break;
|
||||
}
|
||||
|
||||
throw std::invalid_argument(exc_descriptor);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
@ -792,6 +793,8 @@ void ppc_cpu_init(uint32_t proc_version)
|
||||
ppc_state.ppc_spr[SPR::DEC] = 0xFFFFFFFFUL;
|
||||
}
|
||||
|
||||
ppc_mmu_init();
|
||||
|
||||
/* redirect code execution to reset vector */
|
||||
ppc_state.ppc_pc = 0xFFF00100;
|
||||
}
|
||||
|
@ -18,12 +18,16 @@
|
||||
#include <cstdint>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <array>
|
||||
#include "memreadwrite.h"
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include "devices/memctrlbase.h"
|
||||
|
||||
/* pointer to exception handler to be called when a MMU exception is occured. */
|
||||
void (*mmu_exception_handler)(Except_Type exception_type, uint32_t srr1_bits);
|
||||
|
||||
/** PowerPC-style MMU BAT arrays (NULL initialization isn't prescribed). */
|
||||
PPC_BAT_entry ibat_array[4] = { {0} };
|
||||
PPC_BAT_entry dbat_array[4] = { {0} };
|
||||
@ -222,7 +226,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
||||
|
||||
/* instruction fetch from a no-execute segment will cause ISI exception */
|
||||
if ((sr_val & 0x10000000) && is_instr_fetch) {
|
||||
ppc_exception_handler(Except_Type::EXC_ISI, 0x10000000);
|
||||
mmu_exception_handler(Except_Type::EXC_ISI, 0x10000000);
|
||||
}
|
||||
|
||||
page_index = (la >> 12) & 0xFFFF;
|
||||
@ -232,12 +236,12 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
||||
if (!search_pteg(calc_pteg_addr(pteg_hash1), &pte_addr, vsid, page_index, 0)) {
|
||||
if (!search_pteg(calc_pteg_addr(~pteg_hash1), &pte_addr, vsid, page_index, 1)) {
|
||||
if (is_instr_fetch) {
|
||||
ppc_exception_handler(Except_Type::EXC_ISI, 0x40000000);
|
||||
mmu_exception_handler(Except_Type::EXC_ISI, 0x40000000);
|
||||
}
|
||||
else {
|
||||
ppc_state.ppc_spr[SPR::DSISR] = 0x40000000 | (is_write << 25);
|
||||
ppc_state.ppc_spr[SPR::DAR] = la;
|
||||
ppc_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -255,12 +259,12 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
||||
// write access with PP = %11
|
||||
if ((key && (!pp || (pp == 1 && is_write))) || (pp == 3 && is_write)) {
|
||||
if (is_instr_fetch) {
|
||||
ppc_exception_handler(Except_Type::EXC_ISI, 0x08000000);
|
||||
mmu_exception_handler(Except_Type::EXC_ISI, 0x08000000);
|
||||
}
|
||||
else {
|
||||
ppc_state.ppc_spr[SPR::DSISR] = 0x08000000 | (is_write << 25);
|
||||
ppc_state.ppc_spr[SPR::DAR] = la;
|
||||
ppc_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +300,7 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la)
|
||||
bat_hit = true;
|
||||
|
||||
if (!bat_entry->prot) {
|
||||
ppc_exception_handler(Except_Type::EXC_ISI, 0x08000000);
|
||||
mmu_exception_handler(Except_Type::EXC_ISI, 0x08000000);
|
||||
}
|
||||
|
||||
// logical to physical translation
|
||||
@ -340,7 +344,7 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
|
||||
if (!bat_entry->prot || ((bat_entry->prot & 1) && is_write)) {
|
||||
ppc_state.ppc_spr[SPR::DSISR] = 0x08000000 | (is_write << 25);
|
||||
ppc_state.ppc_spr[SPR::DAR] = la;
|
||||
ppc_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
}
|
||||
|
||||
// logical to physical translation
|
||||
@ -554,3 +558,54 @@ uint8_t* quickinstruction_translate(uint32_t addr)
|
||||
|
||||
return real_addr;
|
||||
}
|
||||
|
||||
uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size)
|
||||
{
|
||||
uint32_t save_dsisr, save_dar;
|
||||
uint64_t ret_val;
|
||||
|
||||
/* save MMU-related CPU state */
|
||||
save_dsisr = ppc_state.ppc_spr[SPR::DSISR];
|
||||
save_dar = ppc_state.ppc_spr[SPR::DAR];
|
||||
mmu_exception_handler = dbg_exception_handler;
|
||||
|
||||
try {
|
||||
switch(size) {
|
||||
case 1:
|
||||
ret_val = mem_grab_byte(virt_addr);
|
||||
break;
|
||||
case 2:
|
||||
ret_val = mem_grab_word(virt_addr);
|
||||
break;
|
||||
case 4:
|
||||
ret_val = mem_grab_dword(virt_addr);
|
||||
break;
|
||||
case 8:
|
||||
ret_val = mem_grab_qword(virt_addr);
|
||||
break;
|
||||
default:
|
||||
ret_val = mem_grab_byte(virt_addr);
|
||||
}
|
||||
}
|
||||
catch (std::invalid_argument& exc) {
|
||||
/* restore MMU-related CPU state */
|
||||
mmu_exception_handler = ppc_exception_handler;
|
||||
ppc_state.ppc_spr[SPR::DSISR] = save_dsisr;
|
||||
ppc_state.ppc_spr[SPR::DAR] = save_dar;
|
||||
|
||||
/* rethrow MMU exception */
|
||||
throw exc;
|
||||
}
|
||||
|
||||
/* restore MMU-related CPU state */
|
||||
mmu_exception_handler = ppc_exception_handler;
|
||||
ppc_state.ppc_spr[SPR::DSISR] = save_dsisr;
|
||||
ppc_state.ppc_spr[SPR::DAR] = save_dar;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void ppc_mmu_init()
|
||||
{
|
||||
mmu_exception_handler = ppc_exception_handler;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ extern uint8_t mem_grab_byte(uint32_t addr);
|
||||
extern uint16_t mem_grab_word(uint32_t addr);
|
||||
extern uint32_t mem_grab_dword(uint32_t addr);
|
||||
extern uint64_t mem_grab_qword(uint32_t addr);
|
||||
extern uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size);
|
||||
extern uint8_t* quickinstruction_translate(uint32_t address_grab);
|
||||
|
||||
#endif // PPCMEMORY_H
|
||||
|
@ -58,7 +58,7 @@ static void disasm(uint32_t inst_num = 1UL, uint32_t address = ppc_state.ppc_pc)
|
||||
ctx.simplified = true;
|
||||
|
||||
for (int i = 0; i < inst_num; i++) {
|
||||
ctx.instr_code = mem_grab_dword(ctx.instr_addr);
|
||||
ctx.instr_code = mem_read_dbg(ctx.instr_addr, 4);
|
||||
cout << uppercase << hex << ctx.instr_addr << " "
|
||||
<< disassemble_single(&ctx) << endl;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user