diff options
author | Peter Maydell | 2022-01-31 21:20:54 +0100 |
---|---|---|
committer | Peter Maydell | 2022-01-31 21:20:54 +0100 |
commit | 5cbe64110dbe27f82d30552001acdc5eeaade11c (patch) | |
tree | 8ea1e2e5a9bb72419d8860ffe1a9cdb990e8229c /bsd-user/arm/target_arch_cpu.h | |
parent | Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220130' into s... (diff) | |
parent | bsd-user/freebsd/target_os_ucontext.h: Prefer env as arg name for CPUArchStat... (diff) | |
download | qemu-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.h | 101 |
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) { } |