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