| 21 |
#include "sysdeps.h" |
#include "sysdeps.h" |
| 22 |
#include "cpu_emulation.h" |
#include "cpu_emulation.h" |
| 23 |
#include "main.h" |
#include "main.h" |
| 24 |
|
#include "prefs.h" |
| 25 |
#include "xlowmem.h" |
#include "xlowmem.h" |
| 26 |
#include "emul_op.h" |
#include "emul_op.h" |
| 27 |
#include "rom_patches.h" |
#include "rom_patches.h" |
| 537 |
* Initialize CPU emulation |
* Initialize CPU emulation |
| 538 |
*/ |
*/ |
| 539 |
|
|
| 540 |
static struct sigaction sigsegv_action; |
static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction) |
|
|
|
|
#if defined(__powerpc__) |
|
|
#include <sys/ucontext.h> |
|
|
#endif |
|
|
|
|
|
static void sigsegv_handler(int sig, siginfo_t *sip, void *scp) |
|
| 541 |
{ |
{ |
|
const uintptr addr = (uintptr)sip->si_addr; |
|
| 542 |
#if ENABLE_VOSF |
#if ENABLE_VOSF |
| 543 |
// Handle screen fault. |
// Handle screen fault |
| 544 |
extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction); |
extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t); |
| 545 |
if (Screen_fault_handler((sigsegv_address_t)addr, SIGSEGV_INVALID_PC)) |
if (Screen_fault_handler(fault_address, fault_instruction)) |
| 546 |
return; |
return SIGSEGV_RETURN_SUCCESS; |
|
#endif |
|
|
#if defined(__powerpc__) |
|
|
if (addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) { |
|
|
printf("IGNORE write access to ROM at %08x\n", addr); |
|
|
(((ucontext_t *)scp)->uc_mcontext.regs)->nip += 4; |
|
|
return; |
|
|
} |
|
|
if (addr >= 0xf3012000 && addr < 0xf3014000 && 0) { |
|
|
printf("IGNORE write access to ROM at %08x\n", addr); |
|
|
(((ucontext_t *)scp)->uc_mcontext.regs)->nip += 4; |
|
|
return; |
|
|
} |
|
| 547 |
#endif |
#endif |
| 548 |
printf("Caught SIGSEGV at address %p\n", sip->si_addr); |
|
| 549 |
printf("Native PC: %08x\n", (((ucontext_t *)scp)->uc_mcontext.regs)->nip); |
const uintptr addr = (uintptr)fault_address; |
| 550 |
printf("Current CPU: %s\n", current_cpu == main_cpu ? "main" : "interrupts"); |
#if HAVE_SIGSEGV_SKIP_INSTRUCTION |
| 551 |
#if 1 |
// Ignore writes to ROM |
| 552 |
dump_registers(); |
if ((addr - ROM_BASE) < ROM_SIZE) |
| 553 |
|
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
| 554 |
|
|
| 555 |
|
// Ignore all other faults, if requested |
| 556 |
|
if (PrefsFindBool("ignoresegv")) |
| 557 |
|
return SIGSEGV_RETURN_FAILURE; |
| 558 |
#else |
#else |
| 559 |
printf("Main CPU context\n"); |
#error "FIXME: You don't have the capability to skip instruction within signal handlers" |
|
main_cpu->dump_registers(); |
|
|
printf("Interrupts CPU context\n"); |
|
|
interrupt_cpu->dump_registers(); |
|
| 560 |
#endif |
#endif |
| 561 |
|
|
| 562 |
|
printf("SIGSEGV\n"); |
| 563 |
|
printf(" pc %p\n", fault_instruction); |
| 564 |
|
printf(" ea %p\n", fault_address); |
| 565 |
|
printf(" cpu %s\n", current_cpu == main_cpu ? "main" : "interrupts"); |
| 566 |
|
dump_registers(); |
| 567 |
current_cpu->dump_log(); |
current_cpu->dump_log(); |
| 568 |
enter_mon(); |
enter_mon(); |
| 569 |
QuitEmulator(); |
QuitEmulator(); |
| 570 |
|
|
| 571 |
|
return SIGSEGV_RETURN_FAILURE; |
| 572 |
} |
} |
| 573 |
|
|
| 574 |
void init_emul_ppc(void) |
void init_emul_ppc(void) |
| 583 |
interrupt_cpu = new sheepshaver_cpu(); |
interrupt_cpu = new sheepshaver_cpu(); |
| 584 |
#endif |
#endif |
| 585 |
|
|
| 586 |
// Install SIGSEGV handler |
// Install the handler for SIGSEGV |
| 587 |
sigemptyset(&sigsegv_action.sa_mask); |
sigsegv_install_handler(sigsegv_handler); |
|
sigsegv_action.sa_sigaction = sigsegv_handler; |
|
|
sigsegv_action.sa_flags = SA_SIGINFO; |
|
|
sigsegv_action.sa_restorer = NULL; |
|
|
sigaction(SIGSEGV, &sigsegv_action, NULL); |
|
| 588 |
|
|
| 589 |
#if ENABLE_MON |
#if ENABLE_MON |
| 590 |
// Install "regs" command in cxmon |
// Install "regs" command in cxmon |