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/ -----BEGIN PGP SIGNATURE----- Comment: GPGTools - https://gpgtools.org iQIzBAABCgAdFiEEIDX4lLAKo898zeG3bBzRKH2wEQAFAmH4PscACgkQbBzRKH2w EQAQew/7BgyFU2IIGqIw6Bu1XKPiBeJsS1n2D5FaUMHgj6a44RLRHURHeHi4PwHj D1nT51VeLKo5GfSSwlYS2Tum47fSWBAW/rDuqZ3FMAbsBzOxwEbY+gOhINPEJwSd TVzbJOq78IkDAocVCQwH97bd6FYVYVB4PEznU04tAcVd9pR/HQGa/hN5p4h6TeNi TL0WOt0IEneiMaEA2kAg9f/AtuRa6f+zzB8u8dN4HmxJ3M2z91fIujHAOg28e136 Y+XIC5b+4l+q8TrIC+lMhC1VCknQcRDYLR2T9nHuTlKyH57BN8LNfccVQKMsKiuw 1m+3o1otwYYHnW8UuUutcXLvUYTOKbgm5/hDlrFhx5jEXbYyEXzdkznnuiUhIL1y vdgq/O7uSlA0+xdCeUBfvh31+JPlgrcFInXL+moUwFWGpXRYazLme4KTcbm36T0d 5V8BwDy9aJhquNf/UD0OcpEZ+nLtULuFYHI4ZAT/yZeKXkPfx9cVwWfhwtxYEC5J JMyeNWZ+QAO2riq8S2wmkyXmPKPMFS/h9L1X1zWekS8pa1oTa13Na+jzEFZ4+sip 0KzSTkSkqrpmwjHNRWTDdPF9AKNqMKj1u2xd93L83N1KAJDM3SlLDgCD4C91OVxw 5XzLcnX5uQsKk8ZcvGP/pongs13tolce3AU4OSHEdygFdTmUsj4= =aZPm -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
5cbe64110d
@ -3186,6 +3186,7 @@ R: Kyle Evans <kevans@freebsd.org>
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: bsd-user/
|
F: bsd-user/
|
||||||
F: configs/targets/*-bsd-user.mak
|
F: configs/targets/*-bsd-user.mak
|
||||||
|
F: tests/vm/*bsd
|
||||||
T: git https://github.com/qemu-bsd-user/qemu-bsd-user bsd-user-rebase-3.1
|
T: git https://github.com/qemu-bsd-user/qemu-bsd-user bsd-user-rebase-3.1
|
||||||
|
|
||||||
Linux user
|
Linux user
|
||||||
|
@ -59,19 +59,31 @@ abi_long set_sigtramp_args(CPUARMState *env, int sig,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static abi_long get_vfpcontext(CPUARMState *env, abi_ulong frame_addr,
|
||||||
|
struct target_sigframe *frame)
|
||||||
|
{
|
||||||
|
/* see sendsig and get_vfpcontext in sys/arm/arm/exec_machdep.c */
|
||||||
|
target_mcontext_vfp_t *vfp = &frame->sf_vfp;
|
||||||
|
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
|
||||||
|
|
||||||
|
/* Assumes that mcp and vfp are locked */
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
vfp->mcv_reg[i] = tswap64(*aa32_vfp_dreg(env, i));
|
||||||
|
}
|
||||||
|
vfp->mcv_fpscr = tswap32(vfp_get_fpscr(env));
|
||||||
|
mcp->mc_vfp_size = tswap32(sizeof(*vfp));
|
||||||
|
mcp->mc_vfp_ptr = tswap32(frame_addr + ((uintptr_t)vfp - (uintptr_t)frame));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare to arm/arm/machdep.c get_mcontext()
|
* Compare to arm/arm/exec_machdep.c get_mcontext()
|
||||||
* Assumes that the memory is locked if mcp points to user memory.
|
* Assumes that the memory is locked if mcp points to user memory.
|
||||||
*/
|
*/
|
||||||
abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags)
|
abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags)
|
||||||
{
|
{
|
||||||
int err = 0;
|
|
||||||
uint32_t *gr = mcp->__gregs;
|
uint32_t *gr = mcp->__gregs;
|
||||||
|
|
||||||
if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(target_mcontext_vfp_t)) {
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gr[TARGET_REG_CPSR] = tswap32(cpsr_read(env));
|
gr[TARGET_REG_CPSR] = tswap32(cpsr_read(env));
|
||||||
if (flags & TARGET_MC_GET_CLEAR_RET) {
|
if (flags & TARGET_MC_GET_CLEAR_RET) {
|
||||||
gr[TARGET_REG_R0] = 0;
|
gr[TARGET_REG_R0] = 0;
|
||||||
@ -97,17 +109,30 @@ abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags)
|
|||||||
gr[TARGET_REG_LR] = tswap32(env->regs[14]);
|
gr[TARGET_REG_LR] = tswap32(env->regs[14]);
|
||||||
gr[TARGET_REG_PC] = tswap32(env->regs[15]);
|
gr[TARGET_REG_PC] = tswap32(env->regs[15]);
|
||||||
|
|
||||||
if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_ptr != 0) {
|
/*
|
||||||
/* see get_vfpcontext in sys/arm/arm/exec_machdep.c */
|
* FreeBSD's get_mcontext doesn't save VFP info, but sets the pointer and
|
||||||
target_mcontext_vfp_t *vfp;
|
* size to zero. Applications that need the VFP state use
|
||||||
vfp = lock_user(VERIFY_WRITE, mcp->mc_vfp_ptr, sizeof(*vfp), 0);
|
* sysarch(ARM_GET_VFPSTATE) and are expected to adjust mcontext after that.
|
||||||
for (int i = 0; i < 32; i++) {
|
*/
|
||||||
vfp->mcv_reg[i] = tswap64(*aa32_vfp_dreg(env, i));
|
mcp->mc_vfp_size = 0;
|
||||||
}
|
mcp->mc_vfp_ptr = 0;
|
||||||
vfp->mcv_fpscr = tswap32(vfp_get_fpscr(env));
|
memset(&mcp->mc_spare, 0, sizeof(mcp->mc_spare));
|
||||||
unlock_user(vfp, mcp->mc_vfp_ptr, sizeof(*vfp));
|
|
||||||
}
|
return 0;
|
||||||
return err;
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare to arm/arm/exec_machdep.c sendsig()
|
||||||
|
* Assumes that the memory is locked if frame points to user memory.
|
||||||
|
*/
|
||||||
|
abi_long setup_sigframe_arch(CPUARMState *env, abi_ulong frame_addr,
|
||||||
|
struct target_sigframe *frame, int flags)
|
||||||
|
{
|
||||||
|
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
|
||||||
|
|
||||||
|
get_mcontext(env, mcp, flags);
|
||||||
|
get_vfpcontext(env, frame_addr, frame);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare to arm/arm/exec_machdep.c set_mcontext() */
|
/* Compare to arm/arm/exec_machdep.c set_mcontext() */
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define _TARGET_ARCH_CPU_H_
|
#define _TARGET_ARCH_CPU_H_
|
||||||
|
|
||||||
#include "target_arch.h"
|
#include "target_arch.h"
|
||||||
|
#include "signal-common.h"
|
||||||
|
|
||||||
#define TARGET_DEFAULT_CPU_MODEL "any"
|
#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)
|
static inline void target_cpu_loop(CPUARMState *env)
|
||||||
{
|
{
|
||||||
int trapnr;
|
int trapnr, si_signo, si_code;
|
||||||
target_siginfo_t info;
|
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
|
|
||||||
@ -50,33 +50,22 @@ static inline void target_cpu_loop(CPUARMState *env)
|
|||||||
process_queued_cpu_work(cs);
|
process_queued_cpu_work(cs);
|
||||||
switch (trapnr) {
|
switch (trapnr) {
|
||||||
case EXCP_UDEF:
|
case EXCP_UDEF:
|
||||||
{
|
case EXCP_NOCP:
|
||||||
/* See arm/arm/undefined.c undefinedinstruction(); */
|
case EXCP_INVSTATE:
|
||||||
info.si_addr = env->regs[15];
|
/*
|
||||||
|
* See arm/arm/undefined.c undefinedinstruction();
|
||||||
/* illegal instruction */
|
*
|
||||||
info.si_signo = TARGET_SIGILL;
|
* A number of details aren't emulated (they likely don't matter):
|
||||||
info.si_errno = 0;
|
* o Misaligned PC generates ILL_ILLADR (these can't come from qemu)
|
||||||
info.si_code = TARGET_ILL_ILLOPC;
|
* o Thumb-2 instructions generate ILLADR
|
||||||
queue_signal(env, info.si_signo, &info);
|
* o Both modes implement coprocessor instructions, which we don't
|
||||||
|
* do here. FreeBSD just implements them for the VFP coprocessor
|
||||||
/* TODO: What about instruction emulation? */
|
* and special kernel breakpoints, trace points, dtrace, etc.
|
||||||
}
|
*/
|
||||||
|
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->regs[15]);
|
||||||
break;
|
break;
|
||||||
case EXCP_SWI:
|
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];
|
n = env->regs[7];
|
||||||
if (bsd_type == target_freebsd) {
|
if (bsd_type == target_freebsd) {
|
||||||
int ret;
|
int ret;
|
||||||
@ -84,7 +73,7 @@ static inline void target_cpu_loop(CPUARMState *env)
|
|||||||
int32_t syscall_nr = n;
|
int32_t syscall_nr = n;
|
||||||
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
|
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) {
|
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
|
||||||
syscall_nr = env->regs[0];
|
syscall_nr = env->regs[0];
|
||||||
arg1 = env->regs[1];
|
arg1 = env->regs[1];
|
||||||
@ -160,32 +149,52 @@ static inline void target_cpu_loop(CPUARMState *env)
|
|||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
break;
|
break;
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
/* See arm/arm/trap.c prefetch_abort_handler() */
|
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
/* See arm/arm/trap.c data_abort_handler() */
|
/*
|
||||||
info.si_signo = TARGET_SIGSEGV;
|
* See arm/arm/trap-v6.c prefetch_abort_handler() and
|
||||||
info.si_errno = 0;
|
* data_abort_handler()
|
||||||
/* XXX: check env->error_code */
|
*
|
||||||
info.si_code = 0;
|
* However, FreeBSD maps these to a generic value and then uses that
|
||||||
info.si_addr = env->exception.vaddress;
|
* to maybe fault in pages in vm/vm_fault.c:vm_fault_trap(). I
|
||||||
queue_signal(env, info.si_signo, &info);
|
* believe that the indirection maps the same as Linux, but haven't
|
||||||
|
* chased down every single possible indirection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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;
|
break;
|
||||||
case EXCP_DEBUG:
|
case EXCP_DEBUG:
|
||||||
{
|
case EXCP_BKPT:
|
||||||
|
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[15]);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EXCP_ATOMIC:
|
|
||||||
cpu_exec_step_atomic(cs);
|
|
||||||
break;
|
break;
|
||||||
case EXCP_YIELD:
|
case EXCP_YIELD:
|
||||||
/* nothing to do here for user-mode, just resume guest code */
|
/* nothing to do here for user-mode, just resume guest code */
|
||||||
break;
|
break;
|
||||||
|
case EXCP_ATOMIC:
|
||||||
|
cpu_exec_step_atomic(cs);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||||
trapnr);
|
trapnr);
|
||||||
@ -204,7 +213,7 @@ static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
|
|||||||
env->regs[0] = 0;
|
env->regs[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void target_cpu_reset(CPUArchState *cpu)
|
static inline void target_cpu_reset(CPUArchState *env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,11 +71,24 @@ typedef struct target_siginfo {
|
|||||||
int32_t _mqd;
|
int32_t _mqd;
|
||||||
} _mesgp;
|
} _mesgp;
|
||||||
|
|
||||||
/* SIGPOLL */
|
/* SIGPOLL -- Not really genreated in FreeBSD ??? */
|
||||||
struct {
|
struct {
|
||||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||||
} _poll;
|
} _poll;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int _mqd;
|
||||||
|
} _mesgq;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/*
|
||||||
|
* Syscall number for signals delivered as a result of system calls
|
||||||
|
* denied by Capsicum.
|
||||||
|
*/
|
||||||
|
int _syscall;
|
||||||
|
} _capsicum;
|
||||||
|
|
||||||
|
/* Spare for future growth */
|
||||||
struct {
|
struct {
|
||||||
abi_long __spare1__;
|
abi_long __spare1__;
|
||||||
int32_t __spare2_[7];
|
int32_t __spare2_[7];
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "target_os_siginfo.h"
|
#include "target_os_siginfo.h"
|
||||||
#include "target_arch_signal.h"
|
#include "target_arch_signal.h"
|
||||||
|
|
||||||
|
abi_long setup_sigframe_arch(CPUArchState *env, abi_ulong frame_addr,
|
||||||
|
struct target_sigframe *frame, int flags);
|
||||||
|
|
||||||
/* Compare to sys/signal.h */
|
/* Compare to sys/signal.h */
|
||||||
#define TARGET_SIGHUP 1 /* hangup */
|
#define TARGET_SIGHUP 1 /* hangup */
|
||||||
#define TARGET_SIGINT 2 /* interrupt */
|
#define TARGET_SIGINT 2 /* interrupt */
|
||||||
|
@ -36,9 +36,9 @@ abi_long set_sigtramp_args(CPUArchState *env, int sig,
|
|||||||
struct target_sigframe *frame,
|
struct target_sigframe *frame,
|
||||||
abi_ulong frame_addr,
|
abi_ulong frame_addr,
|
||||||
struct target_sigaction *ka);
|
struct target_sigaction *ka);
|
||||||
abi_long get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags);
|
abi_long get_mcontext(CPUArchState *env, target_mcontext_t *mcp, int flags);
|
||||||
abi_long set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int srflag);
|
abi_long set_mcontext(CPUArchState *env, target_mcontext_t *mcp, int srflag);
|
||||||
abi_long get_ucontext_sigreturn(CPUArchState *regs, abi_ulong target_sf,
|
abi_long get_ucontext_sigreturn(CPUArchState *env, abi_ulong target_sf,
|
||||||
abi_ulong *target_uc);
|
abi_ulong *target_uc);
|
||||||
|
|
||||||
#endif /* TARGET_OS_UCONTEXT_H */
|
#endif /* TARGET_OS_UCONTEXT_H */
|
||||||
|
35
bsd-user/host/arm/host-signal.h
Normal file
35
bsd-user/host/arm/host-signal.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* host-signal.h: signal info dependent on the host architecture
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Warner Losh
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARM_HOST_SIGNAL_H
|
||||||
|
#define ARM_HOST_SIGNAL_H
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
|
||||||
|
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||||
|
{
|
||||||
|
return uc->uc_mcontext.__gregs[_REG_PC];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
|
||||||
|
{
|
||||||
|
uc->uc_mcontext.__gregs[_REG_PC] = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* In the FSR, bit 11 is WnR. FreeBSD returns this as part of the
|
||||||
|
* si_info.si_trapno.
|
||||||
|
*/
|
||||||
|
uint32_t fsr = info->si_trapno;
|
||||||
|
|
||||||
|
return extract32(fsr, 11, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
37
bsd-user/host/i386/host-signal.h
Normal file
37
bsd-user/host/i386/host-signal.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* host-signal.h: signal info dependent on the host architecture
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Warner Losh
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef I386_HOST_SIGNAL_H
|
||||||
|
#define I386_HOST_SIGNAL_H
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
|
||||||
|
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||||
|
{
|
||||||
|
return uc->uc_mcontext.mc_eip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
|
||||||
|
{
|
||||||
|
uc->uc_mcontext.mc_eip = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Look in sys/i386/i386/trap.c. NOTE: mc_err == tr_err due to type punning
|
||||||
|
* between a trapframe and mcontext on FreeBSD/i386.
|
||||||
|
*/
|
||||||
|
return uc->uc_mcontext.mc_trapno == T_PAGEFLT &&
|
||||||
|
uc->uc_mcontext.mc_err & PGEX_W;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
37
bsd-user/host/x86_64/host-signal.h
Normal file
37
bsd-user/host/x86_64/host-signal.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* host-signal.h: signal info dependent on the host architecture
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Warner Losh
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef X86_64_HOST_SIGNAL_H
|
||||||
|
#define X86_64_HOST_SIGNAL_H
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
#include <machine/pmap.h>
|
||||||
|
|
||||||
|
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||||
|
{
|
||||||
|
return uc->uc_mcontext.mc_rip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
|
||||||
|
{
|
||||||
|
uc->uc_mcontext.mc_rip = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Look in sys/amd64/amd64/trap.c. NOTE: mc_err == tr_err due to type
|
||||||
|
* punning between a trapframe and mcontext on FreeBSD/amd64.
|
||||||
|
*/
|
||||||
|
return uc->uc_mcontext.mc_trapno == T_PAGEFLT &&
|
||||||
|
uc->uc_mcontext.mc_err & PGEX_W;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -32,6 +32,19 @@ abi_long set_sigtramp_args(CPUX86State *env, int sig,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare to i386/i386/exec_machdep.c sendsig()
|
||||||
|
* Assumes that the memory is locked if frame points to user memory.
|
||||||
|
*/
|
||||||
|
abi_long setup_sigframe_arch(CPUX86State *env, abi_ulong frame_addr,
|
||||||
|
struct target_sigframe *frame, int flags)
|
||||||
|
{
|
||||||
|
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
|
||||||
|
|
||||||
|
get_mcontext(env, mcp, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compare to i386/i386/machdep.c get_mcontext() */
|
/* Compare to i386/i386/machdep.c get_mcontext() */
|
||||||
abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags)
|
abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define _TARGET_ARCH_CPU_H_
|
#define _TARGET_ARCH_CPU_H_
|
||||||
|
|
||||||
#include "target_arch.h"
|
#include "target_arch.h"
|
||||||
|
#include "signal-common.h"
|
||||||
|
|
||||||
#define TARGET_DEFAULT_CPU_MODEL "qemu32"
|
#define TARGET_DEFAULT_CPU_MODEL "qemu32"
|
||||||
|
|
||||||
@ -199,9 +200,9 @@ static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
|
|||||||
env->regs[R_EAX] = 0;
|
env->regs[R_EAX] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void target_cpu_reset(CPUArchState *cpu)
|
static inline void target_cpu_reset(CPUArchState *env)
|
||||||
{
|
{
|
||||||
cpu_reset(env_cpu(cpu));
|
cpu_reset(env_cpu(env));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ! _TARGET_ARCH_CPU_H_ */
|
#endif /* ! _TARGET_ARCH_CPU_H_ */
|
||||||
|
@ -215,15 +215,13 @@ void qemu_cpu_kick(CPUState *cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Assumes contents are already zeroed. */
|
/* Assumes contents are already zeroed. */
|
||||||
void init_task_state(TaskState *ts)
|
static void init_task_state(TaskState *ts)
|
||||||
{
|
{
|
||||||
int i;
|
ts->sigaltstack_used = (struct target_sigaltstack) {
|
||||||
|
.ss_sp = 0,
|
||||||
ts->first_free = ts->sigqueue_table;
|
.ss_size = 0,
|
||||||
for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
|
.ss_flags = TARGET_SS_DISABLE,
|
||||||
ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
|
};
|
||||||
}
|
|
||||||
ts->sigqueue_table[i].next = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gemu_log(const char *fmt, ...)
|
void gemu_log(const char *fmt, ...)
|
||||||
|
@ -70,17 +70,9 @@ struct image_info {
|
|||||||
uint32_t elf_flags;
|
uint32_t elf_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SIGQUEUE_SIZE 1024
|
|
||||||
|
|
||||||
struct qemu_sigqueue {
|
|
||||||
struct qemu_sigqueue *next;
|
|
||||||
target_siginfo_t info;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct emulated_sigtable {
|
struct emulated_sigtable {
|
||||||
int pending; /* true if signal is pending */
|
int pending; /* true if signal is pending */
|
||||||
struct qemu_sigqueue *first;
|
target_siginfo_t info;
|
||||||
struct qemu_sigqueue info; /* Put first signal info here */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -93,15 +85,39 @@ typedef struct TaskState {
|
|||||||
struct bsd_binprm *bprm;
|
struct bsd_binprm *bprm;
|
||||||
struct image_info *info;
|
struct image_info *info;
|
||||||
|
|
||||||
|
struct emulated_sigtable sync_signal;
|
||||||
|
/*
|
||||||
|
* TODO: Since we block all signals while returning to the main CPU
|
||||||
|
* loop, this needn't be an array
|
||||||
|
*/
|
||||||
struct emulated_sigtable sigtab[TARGET_NSIG];
|
struct emulated_sigtable sigtab[TARGET_NSIG];
|
||||||
struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
/*
|
||||||
struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
|
* Nonzero if process_pending_signals() needs to do something (either
|
||||||
int signal_pending; /* non zero if a signal may be pending */
|
* handle a pending signal or unblock signals).
|
||||||
|
* This flag is written from a signal handler so should be accessed via
|
||||||
|
* the qatomic_read() and qatomic_set() functions. (It is not accessed
|
||||||
|
* from multiple threads.)
|
||||||
|
*/
|
||||||
|
int signal_pending;
|
||||||
|
/* True if we're leaving a sigsuspend and sigsuspend_mask is valid. */
|
||||||
|
bool in_sigsuspend;
|
||||||
|
/*
|
||||||
|
* This thread's signal mask, as requested by the guest program.
|
||||||
|
* The actual signal mask of this thread may differ:
|
||||||
|
* + we don't let SIGSEGV and SIGBUS be blocked while running guest code
|
||||||
|
* + sometimes we block all signals to avoid races
|
||||||
|
*/
|
||||||
|
sigset_t signal_mask;
|
||||||
|
/*
|
||||||
|
* The signal mask imposed by a guest sigsuspend syscall, if we are
|
||||||
|
* currently in the middle of such a syscall
|
||||||
|
*/
|
||||||
|
sigset_t sigsuspend_mask;
|
||||||
|
|
||||||
uint8_t stack[];
|
/* This thread's sigaltstack, if it has one */
|
||||||
|
struct target_sigaltstack sigaltstack_used;
|
||||||
} __attribute__((aligned(16))) TaskState;
|
} __attribute__((aligned(16))) TaskState;
|
||||||
|
|
||||||
void init_task_state(TaskState *ts);
|
|
||||||
void stop_all_tasks(void);
|
void stop_all_tasks(void);
|
||||||
extern const char *qemu_uname_release;
|
extern const char *qemu_uname_release;
|
||||||
|
|
||||||
@ -201,16 +217,18 @@ print_openbsd_syscall(int num,
|
|||||||
abi_long arg1, abi_long arg2, abi_long arg3,
|
abi_long arg1, abi_long arg2, abi_long arg3,
|
||||||
abi_long arg4, abi_long arg5, abi_long arg6);
|
abi_long arg4, abi_long arg5, abi_long arg6);
|
||||||
void print_openbsd_syscall_ret(int num, abi_long ret);
|
void print_openbsd_syscall_ret(int num, abi_long ret);
|
||||||
|
/**
|
||||||
|
* print_taken_signal:
|
||||||
|
* @target_signum: target signal being taken
|
||||||
|
* @tinfo: target_siginfo_t which will be passed to the guest for the signal
|
||||||
|
*
|
||||||
|
* Print strace output indicating that this signal is being taken by the guest,
|
||||||
|
* in a format similar to:
|
||||||
|
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
|
||||||
|
*/
|
||||||
|
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo);
|
||||||
extern int do_strace;
|
extern int do_strace;
|
||||||
|
|
||||||
/* signal.c */
|
|
||||||
void process_pending_signals(CPUArchState *cpu_env);
|
|
||||||
void signal_init(void);
|
|
||||||
long do_sigreturn(CPUArchState *env);
|
|
||||||
long do_rt_sigreturn(CPUArchState *env);
|
|
||||||
void queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
|
|
||||||
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
|
|
||||||
|
|
||||||
/* mmap.c */
|
/* mmap.c */
|
||||||
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
|
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
|
||||||
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||||
@ -451,4 +469,6 @@ static inline void *lock_user_string(abi_ulong guest_addr)
|
|||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "user/safe-syscall.h"
|
||||||
|
|
||||||
#endif /* QEMU_H */
|
#endif /* QEMU_H */
|
||||||
|
70
bsd-user/signal-common.h
Normal file
70
bsd-user/signal-common.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Emulation of BSD signals
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Stacey Son
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SIGNAL_COMMON_H
|
||||||
|
#define SIGNAL_COMMON_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* block_signals: block all signals while handling this guest syscall
|
||||||
|
*
|
||||||
|
* Block all signals, and arrange that the signal mask is returned to
|
||||||
|
* its correct value for the guest before we resume execution of guest code.
|
||||||
|
* If this function returns non-zero, then the caller should immediately
|
||||||
|
* return -TARGET_ERESTARTSYS to the main loop, which will take the pending
|
||||||
|
* signal and restart execution of the syscall.
|
||||||
|
* If block_signals() returns zero, then the caller can continue with
|
||||||
|
* emulation of the system call knowing that no signals can be taken
|
||||||
|
* (and therefore that no race conditions will result).
|
||||||
|
* This should only be called once, because if it is called a second time
|
||||||
|
* it will always return non-zero. (Think of it like a mutex that can't
|
||||||
|
* be recursively locked.)
|
||||||
|
* Signals will be unblocked again by process_pending_signals().
|
||||||
|
*
|
||||||
|
* Return value: non-zero if there was a pending signal, zero if not.
|
||||||
|
*/
|
||||||
|
int block_signals(void); /* Returns non zero if signal pending */
|
||||||
|
|
||||||
|
long do_rt_sigreturn(CPUArchState *env);
|
||||||
|
int do_sigaction(int sig, const struct target_sigaction *act,
|
||||||
|
struct target_sigaction *oact);
|
||||||
|
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
|
||||||
|
long do_sigreturn(CPUArchState *env, abi_ulong addr);
|
||||||
|
void force_sig_fault(int sig, int code, abi_ulong addr);
|
||||||
|
int host_to_target_signal(int sig);
|
||||||
|
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
|
||||||
|
void process_pending_signals(CPUArchState *env);
|
||||||
|
void queue_signal(CPUArchState *env, int sig, int si_type,
|
||||||
|
target_siginfo_t *info);
|
||||||
|
void signal_init(void);
|
||||||
|
int target_to_host_signal(int sig);
|
||||||
|
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Within QEMU the top 8 bits of si_code indicate which of the parts of the
|
||||||
|
* union in target_siginfo is valid. This only applies between
|
||||||
|
* host_to_target_siginfo_noswap() and tswap_siginfo(); it does not appear
|
||||||
|
* either within host siginfo_t or in target_siginfo structures which we get
|
||||||
|
* from the guest userspace program. Linux kenrels use this internally, but BSD
|
||||||
|
* kernels don't do this, but its a useful abstraction.
|
||||||
|
*
|
||||||
|
* The linux-user version of this uses the top 16 bits, but FreeBSD's SI_USER
|
||||||
|
* and other signal indepenent SI_ codes have bit 16 set, so we only use the top
|
||||||
|
* byte instead.
|
||||||
|
*
|
||||||
|
* For FreeBSD, we have si_pid, si_uid, si_status, and si_addr always. Linux and
|
||||||
|
* {Open,Net}BSD have a different approach (where their reason field is larger,
|
||||||
|
* but whose siginfo has fewer fields always).
|
||||||
|
*/
|
||||||
|
#define QEMU_SI_NOINFO 0 /* nothing other than si_signo valid */
|
||||||
|
#define QEMU_SI_FAULT 1 /* _fault is valid in _reason */
|
||||||
|
#define QEMU_SI_TIMER 2 /* _timer is valid in _reason */
|
||||||
|
#define QEMU_SI_MESGQ 3 /* _mesgq is valid in _reason */
|
||||||
|
#define QEMU_SI_POLL 4 /* _poll is valid in _reason */
|
||||||
|
#define QEMU_SI_CAPSICUM 5 /* _capsicum is valid in _reason */
|
||||||
|
|
||||||
|
#endif
|
1008
bsd-user/signal.c
1008
bsd-user/signal.c
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,24 @@ int do_strace;
|
|||||||
/*
|
/*
|
||||||
* Utility functions
|
* Utility functions
|
||||||
*/
|
*/
|
||||||
|
static const char *
|
||||||
|
get_comma(int last)
|
||||||
|
{
|
||||||
|
return (last) ? "" : ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints out raw parameter using given format. Caller needs
|
||||||
|
* to do byte swapping if needed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_raw_param(const char *fmt, abi_long param, int last)
|
||||||
|
{
|
||||||
|
char format[64];
|
||||||
|
|
||||||
|
(void)snprintf(format, sizeof(format), "%s%s", fmt, get_comma(last));
|
||||||
|
gemu_log(format, param);
|
||||||
|
}
|
||||||
|
|
||||||
static void print_sysctl(const struct syscallname *name, abi_long arg1,
|
static void print_sysctl(const struct syscallname *name, abi_long arg1,
|
||||||
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
|
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
|
||||||
@ -239,3 +257,82 @@ void print_openbsd_syscall_ret(int num, abi_long ret)
|
|||||||
|
|
||||||
print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
|
print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_signal(abi_ulong arg, int last)
|
||||||
|
{
|
||||||
|
const char *signal_name = NULL;
|
||||||
|
switch (arg) {
|
||||||
|
case TARGET_SIGHUP:
|
||||||
|
signal_name = "SIGHUP";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGINT:
|
||||||
|
signal_name = "SIGINT";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGQUIT:
|
||||||
|
signal_name = "SIGQUIT";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGILL:
|
||||||
|
signal_name = "SIGILL";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGABRT:
|
||||||
|
signal_name = "SIGABRT";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGFPE:
|
||||||
|
signal_name = "SIGFPE";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGKILL:
|
||||||
|
signal_name = "SIGKILL";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGSEGV:
|
||||||
|
signal_name = "SIGSEGV";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGPIPE:
|
||||||
|
signal_name = "SIGPIPE";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGALRM:
|
||||||
|
signal_name = "SIGALRM";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGTERM:
|
||||||
|
signal_name = "SIGTERM";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGUSR1:
|
||||||
|
signal_name = "SIGUSR1";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGUSR2:
|
||||||
|
signal_name = "SIGUSR2";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGCHLD:
|
||||||
|
signal_name = "SIGCHLD";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGCONT:
|
||||||
|
signal_name = "SIGCONT";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGSTOP:
|
||||||
|
signal_name = "SIGSTOP";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGTTIN:
|
||||||
|
signal_name = "SIGTTIN";
|
||||||
|
break;
|
||||||
|
case TARGET_SIGTTOU:
|
||||||
|
signal_name = "SIGTTOU";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (signal_name == NULL) {
|
||||||
|
print_raw_param("%ld", arg, last);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gemu_log("%s%s", signal_name, get_comma(last));
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Print the strace output for a signal being taken:
|
||||||
|
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
|
||||||
|
*/
|
||||||
|
gemu_log("%d ", getpid());
|
||||||
|
gemu_log("--- ");
|
||||||
|
print_signal(target_signum, 1);
|
||||||
|
gemu_log(" ---\n");
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define _SYSCALL_DEFS_H_
|
#define _SYSCALL_DEFS_H_
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include "errno_defs.h"
|
#include "errno_defs.h"
|
||||||
|
|
||||||
|
11
bsd-user/trace-events
Normal file
11
bsd-user/trace-events
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# See docs/tracing.txt for syntax documentation.
|
||||||
|
|
||||||
|
# bsd-user/signal.c
|
||||||
|
user_setup_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
|
||||||
|
user_setup_rt_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
|
||||||
|
user_do_rt_sigreturn(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
|
||||||
|
user_do_sigreturn(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
|
||||||
|
user_dump_core_and_abort(void *env, int target_sig, int host_sig) "env=%p signal %d (host %d)"
|
||||||
|
user_handle_signal(void *env, int target_sig) "env=%p signal %d"
|
||||||
|
user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d("
|
||||||
|
user_queue_signal(void *env, int target_sig) "env=%p signal %d"
|
1
bsd-user/trace.h
Normal file
1
bsd-user/trace.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "trace/trace-bsd_user.h"
|
@ -30,6 +30,19 @@ abi_long set_sigtramp_args(CPUX86State *regs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare to amd64/amd64/exec_machdep.c sendsig()
|
||||||
|
* Assumes that the memory is locked if frame points to user memory.
|
||||||
|
*/
|
||||||
|
abi_long setup_sigframe_arch(CPUX86State *env, abi_ulong frame_addr,
|
||||||
|
struct target_sigframe *frame, int flags)
|
||||||
|
{
|
||||||
|
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext;
|
||||||
|
|
||||||
|
get_mcontext(env, mcp, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compare to amd64/amd64/machdep.c get_mcontext() */
|
/* Compare to amd64/amd64/machdep.c get_mcontext() */
|
||||||
abi_long get_mcontext(CPUX86State *regs,
|
abi_long get_mcontext(CPUX86State *regs,
|
||||||
target_mcontext_t *mcp, int flags)
|
target_mcontext_t *mcp, int flags)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define _TARGET_ARCH_CPU_H_
|
#define _TARGET_ARCH_CPU_H_
|
||||||
|
|
||||||
#include "target_arch.h"
|
#include "target_arch.h"
|
||||||
|
#include "signal-common.h"
|
||||||
|
|
||||||
#define TARGET_DEFAULT_CPU_MODEL "qemu64"
|
#define TARGET_DEFAULT_CPU_MODEL "qemu64"
|
||||||
|
|
||||||
@ -237,9 +238,9 @@ static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
|
|||||||
env->regs[R_EAX] = 0;
|
env->regs[R_EAX] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void target_cpu_reset(CPUArchState *cpu)
|
static inline void target_cpu_reset(CPUArchState *env)
|
||||||
{
|
{
|
||||||
cpu_reset(env_cpu(cpu));
|
cpu_reset(env_cpu(env));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ! _TARGET_ARCH_CPU_H_ */
|
#endif /* ! _TARGET_ARCH_CPU_H_ */
|
||||||
|
@ -2458,9 +2458,12 @@ trace_events_subdirs = [
|
|||||||
'monitor',
|
'monitor',
|
||||||
'util',
|
'util',
|
||||||
]
|
]
|
||||||
if have_user
|
if have_linux_user
|
||||||
trace_events_subdirs += [ 'linux-user' ]
|
trace_events_subdirs += [ 'linux-user' ]
|
||||||
endif
|
endif
|
||||||
|
if have_bsd_user
|
||||||
|
trace_events_subdirs += [ 'bsd-user' ]
|
||||||
|
endif
|
||||||
if have_block
|
if have_block
|
||||||
trace_events_subdirs += [
|
trace_events_subdirs += [
|
||||||
'authz',
|
'authz',
|
||||||
@ -2947,6 +2950,7 @@ foreach target : target_dirs
|
|||||||
if 'CONFIG_BSD_USER' in config_target
|
if 'CONFIG_BSD_USER' in config_target
|
||||||
base_dir = 'bsd-user'
|
base_dir = 'bsd-user'
|
||||||
target_inc += include_directories('bsd-user/' / targetos)
|
target_inc += include_directories('bsd-user/' / targetos)
|
||||||
|
target_inc += include_directories('bsd-user/host/' / host_arch)
|
||||||
dir = base_dir / abi
|
dir = base_dir / abi
|
||||||
arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
|
arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c')
|
||||||
endif
|
endif
|
||||||
|
Loading…
Reference in New Issue
Block a user