[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v6 20/66] linux-user: Add cpu_loop_exit_sigsegv
From: |
Richard Henderson |
Subject: |
[PATCH v6 20/66] linux-user: Add cpu_loop_exit_sigsegv |
Date: |
Sat, 30 Oct 2021 10:15:49 -0700 |
This is a new interface to be provided by the os emulator for
raising SIGSEGV on fault. Use the new record_sigsegv target hook.
Reviewed by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/exec-all.h | 15 +++++++++++++++
accel/tcg/user-exec.c | 33 ++++++++++++++++++---------------
linux-user/signal.c | 30 ++++++++++++++++++++++--------
3 files changed, 55 insertions(+), 23 deletions(-)
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 5dd663c153..f74578500c 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -685,6 +685,21 @@ MMUAccessType adjust_signal_pc(uintptr_t *pc, bool
is_write);
bool handle_sigsegv_accerr_write(CPUState *cpu, sigset_t *old_set,
uintptr_t host_pc, abi_ptr guest_addr);
+/**
+ * cpu_loop_exit_sigsegv:
+ * @cpu: the cpu context
+ * @addr: the guest address of the fault
+ * @access_type: access was read/write/execute
+ * @maperr: true for invalid page, false for permission fault
+ * @ra: host pc for unwinding
+ *
+ * Use the TCGCPUOps hook to record cpu state, do guest operating system
+ * specific things to raise SIGSEGV, and jump to the main cpu loop.
+ */
+void QEMU_NORETURN cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr,
+ MMUAccessType access_type,
+ bool maperr, uintptr_t ra);
+
#else
static inline void mmap_lock(void) {}
static inline void mmap_unlock(void) {}
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index a0cba61e83..c4f69908e9 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -141,35 +141,38 @@ static int probe_access_internal(CPUArchState *env,
target_ulong addr,
int fault_size, MMUAccessType access_type,
bool nonfault, uintptr_t ra)
{
- int flags;
+ int acc_flag;
+ bool maperr;
switch (access_type) {
case MMU_DATA_STORE:
- flags = PAGE_WRITE;
+ acc_flag = PAGE_WRITE_ORG;
break;
case MMU_DATA_LOAD:
- flags = PAGE_READ;
+ acc_flag = PAGE_READ;
break;
case MMU_INST_FETCH:
- flags = PAGE_EXEC;
+ acc_flag = PAGE_EXEC;
break;
default:
g_assert_not_reached();
}
- if (!guest_addr_valid_untagged(addr) ||
- page_check_range(addr, 1, flags) < 0) {
- if (nonfault) {
- return TLB_INVALID_MASK;
- } else {
- CPUState *cpu = env_cpu(env);
- CPUClass *cc = CPU_GET_CLASS(cpu);
- cc->tcg_ops->tlb_fill(cpu, addr, fault_size, access_type,
- MMU_USER_IDX, false, ra);
- g_assert_not_reached();
+ if (guest_addr_valid_untagged(addr)) {
+ int page_flags = page_get_flags(addr);
+ if (page_flags & acc_flag) {
+ return 0; /* success */
}
+ maperr = !(page_flags & PAGE_VALID);
+ } else {
+ maperr = true;
}
- return 0;
+
+ if (nonfault) {
+ return TLB_INVALID_MASK;
+ }
+
+ cpu_loop_exit_sigsegv(env_cpu(env), addr, access_type, maperr, ra);
}
int probe_access_flags(CPUArchState *env, target_ulong addr,
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b816678ba5..135983747d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -688,9 +688,27 @@ void force_sigsegv(int oldsig)
}
force_sig(TARGET_SIGSEGV);
}
-
#endif
+void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr,
+ MMUAccessType access_type, bool maperr, uintptr_t
ra)
+{
+ const struct TCGCPUOps *tcg_ops = CPU_GET_CLASS(cpu)->tcg_ops;
+
+ if (tcg_ops->record_sigsegv) {
+ tcg_ops->record_sigsegv(cpu, addr, access_type, maperr, ra);
+ } else if (tcg_ops->tlb_fill) {
+ tcg_ops->tlb_fill(cpu, addr, 0, access_type, MMU_USER_IDX, false, ra);
+ g_assert_not_reached();
+ }
+
+ force_sig_fault(TARGET_SIGSEGV,
+ maperr ? TARGET_SEGV_MAPERR : TARGET_SEGV_ACCERR,
+ addr);
+ cpu->exception_index = EXCP_INTERRUPT;
+ cpu_loop_exit_restore(cpu, ra);
+}
+
/* abort execution with signal */
static void QEMU_NORETURN dump_core_and_abort(int target_sig)
{
@@ -806,7 +824,7 @@ static void host_signal_handler(int host_sig, siginfo_t
*info, void *puc)
access_type = adjust_signal_pc(&pc, is_write);
if (host_sig == SIGSEGV) {
- const struct TCGCPUOps *tcg_ops;
+ bool maperr = true;
if (info->si_code == SEGV_ACCERR && h2g_valid(host_addr)) {
/* If this was a write to a TB protected page, restart. */
@@ -821,18 +839,14 @@ static void host_signal_handler(int host_sig, siginfo_t
*info, void *puc)
* which means that we may get ACCERR when we want MAPERR.
*/
if (page_get_flags(guest_addr) & PAGE_VALID) {
- /* maperr = false; */
+ maperr = false;
} else {
info->si_code = SEGV_MAPERR;
}
}
sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
-
- tcg_ops = CPU_GET_CLASS(cpu)->tcg_ops;
- tcg_ops->tlb_fill(cpu, guest_addr, 0, access_type,
- MMU_USER_IDX, false, pc);
- g_assert_not_reached();
+ cpu_loop_exit_sigsegv(cpu, guest_addr, access_type, maperr, pc);
} else {
sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
}
--
2.25.1
- [PATCH v6 31/66] target/nios2: Implement nios2_cpu_record_sigsegv, (continued)
- [PATCH v6 31/66] target/nios2: Implement nios2_cpu_record_sigsegv, Richard Henderson, 2021/10/30
- [PATCH v6 37/66] target/s390x: Implement s390_cpu_record_sigsegv, Richard Henderson, 2021/10/30
- [PATCH v6 15/66] linux-user/host/riscv: Populate host_signal.h, Richard Henderson, 2021/10/30
- [PATCH v6 17/66] linux-user/host/riscv: Improve host_signal_write, Richard Henderson, 2021/10/30
- [PATCH v6 18/66] linux-user/signal: Drop HOST_SIGNAL_PLACEHOLDER, Richard Henderson, 2021/10/30
- [PATCH v6 19/66] hw/core: Add TCGCPUOps.record_sigsegv, Richard Henderson, 2021/10/30
- [PATCH v6 22/66] target/arm: Use cpu_loop_exit_sigsegv for mte tag lookup, Richard Henderson, 2021/10/30
- [PATCH v6 30/66] target/mips: Make mips_cpu_tlb_fill sysemu only, Richard Henderson, 2021/10/30
- [PATCH v6 32/66] linux-user/openrisc: Abort for EXCP_RANGE, EXCP_FPE, Richard Henderson, 2021/10/30
- [PATCH v6 20/66] linux-user: Add cpu_loop_exit_sigsegv,
Richard Henderson <=
- [PATCH v6 23/66] target/arm: Implement arm_cpu_record_sigsegv, Richard Henderson, 2021/10/30
- [PATCH v6 25/66] target/hexagon: Remove hexagon_cpu_tlb_fill, Richard Henderson, 2021/10/30
- [PATCH v6 33/66] target/openrisc: Make openrisc_cpu_tlb_fill sysemu only, Richard Henderson, 2021/10/30
- [PATCH v6 36/66] target/s390x: Use probe_access_flags in s390_probe_access, Richard Henderson, 2021/10/30
- [PATCH v6 41/66] accel/tcg: Restrict TCGCPUOps::tlb_fill() to sysemu, Richard Henderson, 2021/10/30
- [PATCH v6 45/66] target/arm: Implement arm_cpu_record_sigbus, Richard Henderson, 2021/10/30
- [PATCH v6 40/66] target/xtensa: Make xtensa_cpu_tlb_fill sysemu only, Richard Henderson, 2021/10/30
- [PATCH v6 52/66] target/s390x: Implement s390x_cpu_record_sigbus, Richard Henderson, 2021/10/30
- [PATCH v6 44/66] target/alpha: Implement alpha_cpu_record_sigbus, Richard Henderson, 2021/10/30