X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/71baf787d8fa2a5d186f22d8154069fd212be37f..0c33682d5f29b0a4ae53bdec4c8e52e4fae37b34:/user-exec.c diff --git a/user-exec.c b/user-exec.c index 8ad89a466b..50e95a68de 100644 --- a/user-exec.c +++ b/user-exec.c @@ -16,9 +16,10 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ -#include "config.h" +#include "qemu/osdep.h" #include "cpu.h" #include "disas/disas.h" +#include "exec/exec-all.h" #include "tcg.h" #include "qemu/bitops.h" #include "exec/cpu_ldst.h" @@ -33,50 +34,20 @@ #undef ESI #undef EDI #undef EIP -#include #ifdef __linux__ #include #endif //#define DEBUG_SIGNAL -static void exception_action(CPUState *cpu) -{ -#if defined(TARGET_I386) - X86CPU *x86_cpu = X86_CPU(cpu); - CPUX86State *env1 = &x86_cpu->env; - - raise_exception_err(env1, cpu->exception_index, env1->error_code); -#else - cpu_loop_exit(cpu); -#endif -} - /* exit the current TB from a signal handler. The host registers are restored in a state compatible with the CPU emulator */ -void cpu_resume_from_signal(CPUState *cpu, void *puc) +static void cpu_exit_tb_from_sighandler(CPUState *cpu, sigset_t *old_set) { -#ifdef __linux__ - struct ucontext *uc = puc; -#elif defined(__OpenBSD__) - struct sigcontext *uc = puc; -#endif - - if (puc) { - /* XXX: use siglongjmp ? */ -#ifdef __linux__ -#ifdef __ia64 - sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL); -#else - sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL); -#endif -#elif defined(__OpenBSD__) - sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL); -#endif - } - cpu->exception_index = -1; - siglongjmp(cpu->jmp_env, 1); + /* XXX: use siglongjmp ? */ + sigprocmask(SIG_SETMASK, old_set, NULL); + cpu_loop_exit_noexc(cpu); } /* 'pc' is the host PC at which the exception was raised. 'address' is @@ -84,8 +55,7 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc) write caused the exception and otherwise 0'. 'old_set' is the signal set which should be restored */ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, - int is_write, sigset_t *old_set, - void *puc) + int is_write, sigset_t *old_set) { CPUState *cpu; CPUClass *cc; @@ -96,9 +66,28 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ - if (is_write && h2g_valid(address) - && page_unprotect(h2g(address), pc, puc)) { - return 1; + if (is_write && h2g_valid(address)) { + switch (page_unprotect(h2g(address), pc)) { + case 0: + /* Fault not caused by a page marked unwritable to protect + * cached translations, must be the guest binary's problem + */ + break; + case 1: + /* Fault caused by protection of cached translation; TBs + * invalidated, so resume execution + */ + return 1; + case 2: + /* Fault caused by protection of cached translation, and the + * currently executing TB was modified and must be exited + * immediately. + */ + cpu_exit_tb_from_sighandler(current_cpu, old_set); + g_assert_not_reached(); + default: + g_assert_not_reached(); + } } /* Convert forcefully to guest address space, invalid addresses @@ -119,10 +108,8 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, /* now we have a real cpu fault */ cpu_restore_state(cpu, pc); - /* we restore the process signal mask as the sigreturn should - do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); - exception_action(cpu); + cpu_loop_exit(cpu); /* never comes here */ return 1; @@ -188,7 +175,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, return handle_cpu_signal(pc, (unsigned long)info->si_addr, trapno == 0xe ? (ERROR_sig(uc) >> 1) & 1 : 0, - &MASK_sig(uc), puc); + &MASK_sig(uc)); } #elif defined(__x86_64__) @@ -234,7 +221,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, return handle_cpu_signal(pc, (unsigned long)info->si_addr, TRAP_sig(uc) == 0xe ? (ERROR_sig(uc) >> 1) & 1 : 0, - &MASK_sig(uc), puc); + &MASK_sig(uc)); } #elif defined(_ARCH_PPC) @@ -350,7 +337,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, } #endif return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask); } #elif defined(__alpha__) @@ -381,7 +368,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, } return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask); } #elif defined(__sparc__) @@ -441,7 +428,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, } } return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, sigmask, NULL); + is_write, sigmask); } #elif defined(__arm__) @@ -476,7 +463,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, is_write = extract32(uc->uc_mcontext.error_code, 11, 1); return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, - &uc->uc_sigmask, puc); + &uc->uc_sigmask); } #elif defined(__aarch64__) @@ -504,7 +491,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc) || (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */ return handle_cpu_signal(pc, (uintptr_t)info->si_addr, - is_write, &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask); } #elif defined(__mc68000) @@ -522,7 +509,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, - &uc->uc_sigmask, puc); + &uc->uc_sigmask); } #elif defined(__ia64) @@ -557,7 +544,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc) } return handle_cpu_signal(ip, (unsigned long)info->si_addr, is_write, - (sigset_t *)&uc->uc_sigmask, puc); + (sigset_t *)&uc->uc_sigmask); } #elif defined(__s390__) @@ -610,7 +597,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, break; } return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask); } #elif defined(__mips__) @@ -626,7 +613,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, /* XXX: compute is_write */ is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask); } #elif defined(__hppa__) @@ -668,7 +655,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, } return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask); } #else