summaryrefslogtreecommitdiffstats
path: root/bsd-user/arm/target_arch_cpu.h
diff options
context:
space:
mode:
authorPeter Maydell2022-01-31 21:20:54 +0100
committerPeter Maydell2022-01-31 21:20:54 +0100
commit5cbe64110dbe27f82d30552001acdc5eeaade11c (patch)
tree8ea1e2e5a9bb72419d8860ffe1a9cdb990e8229c /bsd-user/arm/target_arch_cpu.h
parentMerge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220130' into s... (diff)
parentbsd-user/freebsd/target_os_ucontext.h: Prefer env as arg name for CPUArchStat... (diff)
downloadqemu-5cbe64110dbe27f82d30552001acdc5eeaade11c.tar.gz
qemu-5cbe64110dbe27f82d30552001acdc5eeaade11c.tar.xz
qemu-5cbe64110dbe27f82d30552001acdc5eeaade11c.zip
Merge remote-tracking branch 'remotes/bsdimp/tags/bsd-user-arm-2022q1-pull-request' into staging
bsd-user: upstream signal implementation Upstream the bsd-user fork signal implementation, for the most part. This series of commits represents nearly all of the infrastructure that surround signals, except the actual system call glue (that was also reworked in the fork and needs its own series). In addition, this adds the sigsegv and sigbus code to arm. Even in the fork, we don't have good x86 signal implementation, so there's little to upstream for that at the moment. bsd-user's signal implementation is similar to linux-user's. The full context can be found in the bsd-user's fork's 'blitz branch' at https://github.com/qemu-bsd-user/qemu-bsd-user/tree/blitz which shows how these are used to implement various system calls. Since this was built from linux-user's stack stuff, evolved for BSD with the passage of a few years, it no-doubt missed some bug fixes from linux-user (though nothing obvious stood out in the quick comparison I made). After the first round of reviews, many of these improvements have been incorporated. Patchew history: https://patchew.org/QEMU/20220125012947.14974-1-imp@bsdimp.com/ # gpg: Signature made Mon 31 Jan 2022 19:55:51 GMT # gpg: using RSA key 2035F894B00AA3CF7CCDE1B76C1CD1287DB01100 # gpg: Good signature from "Warner Losh <wlosh@netflix.com>" [unknown] # gpg: aka "Warner Losh <imp@bsdimp.com>" [unknown] # gpg: aka "Warner Losh <imp@freebsd.org>" [unknown] # gpg: aka "Warner Losh <imp@village.org>" [unknown] # gpg: aka "Warner Losh <wlosh@bsdimp.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 2035 F894 B00A A3CF 7CCD E1B7 6C1C D128 7DB0 1100 * remotes/bsdimp/tags/bsd-user-arm-2022q1-pull-request: (40 commits) bsd-user/freebsd/target_os_ucontext.h: Prefer env as arg name for CPUArchState args bsd-user: Rename arg name for target_cpu_reset to env MAINTAINERS: Add tests/vm/*bsd to the list to get reviews on bsd-user/signal.c: do_sigaltstack bsd-user/signal.c: implement do_sigaction bsd-user/signal.c: implement do_sigreturn bsd-user/signal.c: process_pending_signals bsd-user/signal.c: tswap_siginfo bsd-user/signal.c: handle_pending_signal bsd-user/signal.c: setup_frame bsd-user/signal.c: sigset manipulation routines. bsd-user/signal.c: Fill in queue_signal bsd-user/signal.c: Implement dump_core_and_abort bsd-user/strace.c: print_taken_signal bsd-user/signal.c: Implement host_signal_handler bsd-user/signal.c: Implement rewind_if_in_safe_syscall bsd-user/signal.c: host_to_target_siginfo_noswap bsd-user: Add trace events for bsd-user bsd-user: Add host signals to the build bsd-user/host/x86_64/host-signal.h: Implement host_signal_* ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'bsd-user/arm/target_arch_cpu.h')
-rw-r--r--bsd-user/arm/target_arch_cpu.h101
1 files changed, 55 insertions, 46 deletions
diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h
index c675419c30..b087db48fa 100644
--- a/bsd-user/arm/target_arch_cpu.h
+++ b/bsd-user/arm/target_arch_cpu.h
@@ -21,6 +21,7 @@
#define _TARGET_ARCH_CPU_H_
#include "target_arch.h"
+#include "signal-common.h"
#define TARGET_DEFAULT_CPU_MODEL "any"
@@ -38,8 +39,7 @@ static inline void target_cpu_init(CPUARMState *env,
static inline void target_cpu_loop(CPUARMState *env)
{
- int trapnr;
- target_siginfo_t info;
+ int trapnr, si_signo, si_code;
unsigned int n;
CPUState *cs = env_cpu(env);
@@ -50,33 +50,22 @@ static inline void target_cpu_loop(CPUARMState *env)
process_queued_cpu_work(cs);
switch (trapnr) {
case EXCP_UDEF:
- {
- /* See arm/arm/undefined.c undefinedinstruction(); */
- info.si_addr = env->regs[15];
-
- /* illegal instruction */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- queue_signal(env, info.si_signo, &info);
-
- /* TODO: What about instruction emulation? */
- }
+ case EXCP_NOCP:
+ case EXCP_INVSTATE:
+ /*
+ * See arm/arm/undefined.c undefinedinstruction();
+ *
+ * A number of details aren't emulated (they likely don't matter):
+ * o Misaligned PC generates ILL_ILLADR (these can't come from qemu)
+ * o Thumb-2 instructions generate ILLADR
+ * o Both modes implement coprocessor instructions, which we don't
+ * do here. FreeBSD just implements them for the VFP coprocessor
+ * and special kernel breakpoints, trace points, dtrace, etc.
+ */
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->regs[15]);
break;
case EXCP_SWI:
- case EXCP_BKPT:
{
- /*
- * system call
- * See arm/arm/trap.c cpu_fetch_syscall_args()
- */
- if (trapnr == EXCP_BKPT) {
- if (env->thumb) {
- env->regs[15] += 2;
- } else {
- env->regs[15] += 4;
- }
- }
n = env->regs[7];
if (bsd_type == target_freebsd) {
int ret;
@@ -84,7 +73,7 @@ static inline void target_cpu_loop(CPUARMState *env)
int32_t syscall_nr = n;
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
- /* See arm/arm/trap.c cpu_fetch_syscall_args() */
+ /* See arm/arm/syscall.c cpu_fetch_syscall_args() */
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
syscall_nr = env->regs[0];
arg1 = env->regs[1];
@@ -160,32 +149,52 @@ static inline void target_cpu_loop(CPUARMState *env)
/* just indicate that signals should be handled asap */
break;
case EXCP_PREFETCH_ABORT:
- /* See arm/arm/trap.c prefetch_abort_handler() */
case EXCP_DATA_ABORT:
- /* See arm/arm/trap.c data_abort_handler() */
- info.si_signo = TARGET_SIGSEGV;
- info.si_errno = 0;
- /* XXX: check env->error_code */
- info.si_code = 0;
- info.si_addr = env->exception.vaddress;
- queue_signal(env, info.si_signo, &info);
- break;
- case EXCP_DEBUG:
- {
+ /*
+ * See arm/arm/trap-v6.c prefetch_abort_handler() and
+ * data_abort_handler()
+ *
+ * However, FreeBSD maps these to a generic value and then uses that
+ * to maybe fault in pages in vm/vm_fault.c:vm_fault_trap(). I
+ * believe that the indirection maps the same as Linux, but haven't
+ * chased down every single possible indirection.
+ */
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- info.si_addr = env->exception.vaddress;
- queue_signal(env, info.si_signo, &info);
+ /* For user-only we don't set TTBCR_EAE, so look at the FSR. */
+ switch (env->exception.fsr & 0x1f) {
+ case 0x1: /* Alignment */
+ si_signo = TARGET_SIGBUS;
+ si_code = TARGET_BUS_ADRALN;
+ break;
+ case 0x3: /* Access flag fault, level 1 */
+ case 0x6: /* Access flag fault, level 2 */
+ case 0x9: /* Domain fault, level 1 */
+ case 0xb: /* Domain fault, level 2 */
+ case 0xd: /* Permission fault, level 1 */
+ case 0xf: /* Permission fault, level 2 */
+ si_signo = TARGET_SIGSEGV;
+ si_code = TARGET_SEGV_ACCERR;
+ break;
+ case 0x5: /* Translation fault, level 1 */
+ case 0x7: /* Translation fault, level 2 */
+ si_signo = TARGET_SIGSEGV;
+ si_code = TARGET_SEGV_MAPERR;
+ break;
+ default:
+ g_assert_not_reached();
}
+ force_sig_fault(si_signo, si_code, env->exception.vaddress);
break;
- case EXCP_ATOMIC:
- cpu_exec_step_atomic(cs);
+ case EXCP_DEBUG:
+ case EXCP_BKPT:
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[15]);
break;
case EXCP_YIELD:
/* nothing to do here for user-mode, just resume guest code */
break;
+ case EXCP_ATOMIC:
+ cpu_exec_step_atomic(cs);
+ break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
@@ -204,7 +213,7 @@ static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
env->regs[0] = 0;
}
-static inline void target_cpu_reset(CPUArchState *cpu)
+static inline void target_cpu_reset(CPUArchState *env)
{
}