static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
int is_write, sigset_t *old_set)
{
- CPUState *cpu;
+ CPUState *cpu = current_cpu;
CPUClass *cc;
int ret;
+ /* For synchronous signals we expect to be coming from the vCPU
+ * thread (so current_cpu should be valid) and either from running
+ * code or during translation which can fault as we cross pages.
+ *
+ * If neither is true then something has gone wrong and we should
+ * abort rather than try and restart the vCPU execution.
+ */
+ if (!cpu || !cpu->running) {
+ printf("qemu:%s received signal outside vCPU context @ pc=0x%"
+ PRIxPTR "\n", __func__, pc);
+ abort();
+ }
+
#if defined(DEBUG_SIGNAL)
printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
pc, address, is_write, *(unsigned long *)old_set);
* currently executing TB was modified and must be exited
* immediately.
*/
- cpu_exit_tb_from_sighandler(current_cpu, old_set);
+ cpu_exit_tb_from_sighandler(cpu, old_set);
g_assert_not_reached();
default:
g_assert_not_reached();
are still valid segv ones */
address = h2g_nocheck(address);
- cpu = current_cpu;
cc = CPU_GET_CLASS(cpu);
/* see if it is an MMU fault */
g_assert(cc->handle_mmu_fault);
if (ret == 0) {
return 1; /* the MMU fault was handled without causing real CPU fault */
}
- /* now we have a real cpu fault */
- cpu_restore_state(cpu, pc);
+
+ /* Now we have a real cpu fault. Since this is the exact location of
+ * the exception, we must undo the adjustment done by cpu_restore_state
+ * for handling call return addresses. */
+ cpu_restore_state(cpu, pc + GETPC_ADJ);
sigprocmask(SIG_SETMASK, old_set, NULL);
cpu_loop_exit(cpu);
#if defined(__i386__)
-#if defined(__APPLE__)
-#include <sys/ucontext.h>
-
-#define EIP_sig(context) (*((unsigned long *)&(context)->uc_mcontext->ss.eip))
-#define TRAP_sig(context) ((context)->uc_mcontext->es.trapno)
-#define ERROR_sig(context) ((context)->uc_mcontext->es.err)
-#define MASK_sig(context) ((context)->uc_sigmask)
-#elif defined(__NetBSD__)
+#if defined(__NetBSD__)
#include <ucontext.h>
#define EIP_sig(context) ((context)->uc_mcontext.__gregs[_REG_EIP])
#define TRAP_sig(context) ((context)->uc_mcontext.mc_exc)
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
-#ifdef __APPLE__
-#include <sys/ucontext.h>
-typedef struct ucontext SIGCONTEXT;
-/* All Registers access - only for local access */
-#define REG_sig(reg_name, context) \
- ((context)->uc_mcontext->ss.reg_name)
-#define FLOATREG_sig(reg_name, context) \
- ((context)->uc_mcontext->fs.reg_name)
-#define EXCEPREG_sig(reg_name, context) \
- ((context)->uc_mcontext->es.reg_name)
-#define VECREG_sig(reg_name, context) \
- ((context)->uc_mcontext->vs.reg_name)
-/* Gpr Registers access */
-#define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
-/* Program counter */
-#define IAR_sig(context) REG_sig(srr0, context)
-/* Machine State Register (Supervisor) */
-#define MSR_sig(context) REG_sig(srr1, context)
-#define CTR_sig(context) REG_sig(ctr, context)
-/* Link register */
-#define XER_sig(context) REG_sig(xer, context)
-/* User's integer exception register */
-#define LR_sig(context) REG_sig(lr, context)
-/* Condition register */
-#define CR_sig(context) REG_sig(cr, context)
-/* Float Registers access */
-#define FLOAT_sig(reg_num, context) \
- FLOATREG_sig(fpregs[reg_num], context)
-#define FPSCR_sig(context) \
- ((double)FLOATREG_sig(fpscr, context))
-/* Exception Registers access */
-/* Fault registers for coredump */
-#define DAR_sig(context) EXCEPREG_sig(dar, context)
-#define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
-/* number of powerpc exception taken */
-#define TRAP_sig(context) EXCEPREG_sig(exception, context)
-#endif /* __APPLE__ */
-
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{