Commit 68016c627beb3df8ce69225b64ed6433efcc967d

Authored by bellard
1 parent 9d893301

SIGSEGV signals for ARM and SPARC


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1272 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-exec.c
... ... @@ -205,9 +205,7 @@ int cpu_exec(CPUState *env1)
205 205 do_interrupt(env);
206 206 #elif defined(TARGET_SPARC)
207 207 do_interrupt(env->exception_index,
208   - 0,
209   - env->error_code,
210   - env->exception_next_pc, 0);
  208 + env->error_code);
211 209 #endif
212 210 }
213 211 env->exception_index = -1;
... ... @@ -263,7 +261,7 @@ int cpu_exec(CPUState *env1)
263 261 }
264 262 #elif defined(TARGET_SPARC)
265 263 if (interrupt_request & CPU_INTERRUPT_HARD) {
266   - do_interrupt(env->interrupt_index, 0, 0, 0, 0);
  264 + do_interrupt(env->interrupt_index, 0);
267 265 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
268 266 } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
269 267 //do_interrupt(0, 0, 0, 0, 0);
... ... @@ -731,22 +729,72 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
731 729 int is_write, sigset_t *old_set,
732 730 void *puc)
733 731 {
  732 + TranslationBlock *tb;
  733 + int ret;
  734 +
  735 + if (cpu_single_env)
  736 + env = cpu_single_env; /* XXX: find a correct solution for multithread */
  737 +#if defined(DEBUG_SIGNAL)
  738 + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  739 + pc, address, is_write, *(unsigned long *)old_set);
  740 +#endif
734 741 /* XXX: locking issue */
735 742 if (is_write && page_unprotect(address, pc, puc)) {
736 743 return 1;
737 744 }
738   - return 0;
  745 + /* see if it is an MMU fault */
  746 + ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
  747 + if (ret < 0)
  748 + return 0; /* not an MMU fault */
  749 + if (ret == 0)
  750 + return 1; /* the MMU fault was handled without causing real CPU fault */
  751 + /* now we have a real cpu fault */
  752 + tb = tb_find_pc(pc);
  753 + if (tb) {
  754 + /* the PC is inside the translated code. It means that we have
  755 + a virtual CPU fault */
  756 + cpu_restore_state(tb, env, pc, puc);
  757 + }
  758 + /* we restore the process signal mask as the sigreturn should
  759 + do it (XXX: use sigsetjmp) */
  760 + sigprocmask(SIG_SETMASK, old_set, NULL);
  761 + cpu_loop_exit();
739 762 }
740 763 #elif defined(TARGET_SPARC)
741 764 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
742 765 int is_write, sigset_t *old_set,
743 766 void *puc)
744 767 {
  768 + TranslationBlock *tb;
  769 + int ret;
  770 +
  771 + if (cpu_single_env)
  772 + env = cpu_single_env; /* XXX: find a correct solution for multithread */
  773 +#if defined(DEBUG_SIGNAL)
  774 + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
  775 + pc, address, is_write, *(unsigned long *)old_set);
  776 +#endif
745 777 /* XXX: locking issue */
746 778 if (is_write && page_unprotect(address, pc, puc)) {
747 779 return 1;
748 780 }
749   - return 0;
  781 + /* see if it is an MMU fault */
  782 + ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
  783 + if (ret < 0)
  784 + return 0; /* not an MMU fault */
  785 + if (ret == 0)
  786 + return 1; /* the MMU fault was handled without causing real CPU fault */
  787 + /* now we have a real cpu fault */
  788 + tb = tb_find_pc(pc);
  789 + if (tb) {
  790 + /* the PC is inside the translated code. It means that we have
  791 + a virtual CPU fault */
  792 + cpu_restore_state(tb, env, pc, puc);
  793 + }
  794 + /* we restore the process signal mask as the sigreturn should
  795 + do it (XXX: use sigsetjmp) */
  796 + sigprocmask(SIG_SETMASK, old_set, NULL);
  797 + cpu_loop_exit();
750 798 }
751 799 #elif defined (TARGET_PPC)
752 800 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
... ... @@ -756,10 +804,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
756 804 TranslationBlock *tb;
757 805 int ret;
758 806  
759   -#if 1
760 807 if (cpu_single_env)
761 808 env = cpu_single_env; /* XXX: find a correct solution for multithread */
762   -#endif
763 809 #if defined(DEBUG_SIGNAL)
764 810 printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
765 811 pc, address, is_write, *(unsigned long *)old_set);
... ...
linux-user/main.c
... ... @@ -368,6 +368,17 @@ void cpu_loop(CPUARMState *env)
368 368 case EXCP_INTERRUPT:
369 369 /* just indicate that signals should be handled asap */
370 370 break;
  371 + case EXCP_PREFETCH_ABORT:
  372 + case EXCP_DATA_ABORT:
  373 + {
  374 + info.si_signo = SIGSEGV;
  375 + info.si_errno = 0;
  376 + /* XXX: check env->error_code */
  377 + info.si_code = TARGET_SEGV_MAPERR;
  378 + info._sifields._sigfault._addr = env->cp15_6;
  379 + queue_signal(info.si_signo, &info);
  380 + }
  381 + break;
371 382 default:
372 383 error:
373 384 fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
... ...