mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20211102' into staging
- Split out host signal handing from accel/tcg/user-exec.c to linux-user/host/arch/host-signal.h - Replace TCGCPUOps.tlb_fill with TCGCPUOps.record_sigsegv for user-only - Add TCGCPUOps.record_sigbus for user-only - Remove a lot of target-specific cpu_loop handling for signals, now accomplished with generic code. # gpg: Signature made Tue 02 Nov 2021 07:06:14 AM EDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * remotes/rth/tags/pull-tcg-20211102: (60 commits) linux-user: Handle BUS_ADRALN in host_signal_handler tcg: Add helper_unaligned_{ld,st} for user-only sigbus accel/tcg: Report unaligned load/store for user-only accel/tcg: Report unaligned atomics for user-only target/sparc: Set fault address in sparc_cpu_do_unaligned_access target/sparc: Split out build_sfsr target/sparc: Remove DEBUG_UNALIGNED target/sh4: Set fault address in superh_cpu_do_unaligned_access target/s390x: Implement s390x_cpu_record_sigbus linux-user/ppc: Remove POWERPC_EXCP_ALIGN handling target/ppc: Restrict ppc_cpu_do_unaligned_access to sysemu target/ppc: Set fault address in ppc_cpu_do_unaligned_access target/ppc: Move SPR_DSISR setting to powerpc_excp target/microblaze: Do not set MO_ALIGN for user-only linux-user/hppa: Remove EXCP_UNALIGN handling target/arm: Implement arm_cpu_record_sigbus target/alpha: Implement alpha_cpu_record_sigbus linux-user: Add cpu_loop_exit_sigbus hw/core: Add TCGCPUOps.record_sigbus accel/tcg: Restrict TCGCPUOps::tlb_fill() to sysemu ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -462,6 +462,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
* memory.
|
||||
*/
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
clear_helper_retaddr();
|
||||
tcg_debug_assert(!have_mmap_lock());
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
@@ -471,7 +472,6 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* As we start the exclusive region before codegen we must still
|
||||
* be in the region if we longjump out of either the codegen or
|
||||
@@ -916,6 +916,7 @@ int cpu_exec(CPUState *cpu)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
clear_helper_retaddr();
|
||||
tcg_debug_assert(!have_mmap_lock());
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
|
||||
+101
-760
File diff suppressed because it is too large
Load Diff
@@ -570,11 +570,7 @@ elif check_define __s390__ ; then
|
||||
cpu="s390"
|
||||
fi
|
||||
elif check_define __riscv ; then
|
||||
if check_define _LP64 ; then
|
||||
cpu="riscv64"
|
||||
else
|
||||
cpu="riscv32"
|
||||
fi
|
||||
cpu="riscv"
|
||||
elif check_define __arm__ ; then
|
||||
cpu="arm"
|
||||
elif check_define __aarch64__ ; then
|
||||
@@ -587,7 +583,7 @@ ARCH=
|
||||
# Normalise host CPU name and set ARCH.
|
||||
# Note that this case should only have supported host CPUs, not guests.
|
||||
case "$cpu" in
|
||||
ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64)
|
||||
ppc|ppc64|s390x|sparc64|x32|riscv)
|
||||
;;
|
||||
ppc64le)
|
||||
ARCH="ppc64"
|
||||
|
||||
+47
-8
@@ -664,16 +664,55 @@ static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_signal_handler
|
||||
* @signum: host signal number
|
||||
* @pinfo: host siginfo_t
|
||||
* @puc: host ucontext_t
|
||||
* adjust_signal_pc:
|
||||
* @pc: raw pc from the host signal ucontext_t.
|
||||
* @is_write: host memory operation was write, or read-modify-write.
|
||||
*
|
||||
* To be called from the SIGBUS and SIGSEGV signal handler to inform the
|
||||
* virtual cpu of exceptions. Returns true if the signal was handled by
|
||||
* the virtual CPU.
|
||||
* Alter @pc as required for unwinding. Return the type of the
|
||||
* guest memory access -- host reads may be for guest execution.
|
||||
*/
|
||||
int cpu_signal_handler(int signum, void *pinfo, void *puc);
|
||||
MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write);
|
||||
|
||||
/**
|
||||
* handle_sigsegv_accerr_write:
|
||||
* @cpu: the cpu context
|
||||
* @old_set: the sigset_t from the signal ucontext_t
|
||||
* @host_pc: the host pc, adjusted for the signal
|
||||
* @host_addr: the host address of the fault
|
||||
*
|
||||
* Return true if the write fault has been handled, and should be re-tried.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* cpu_loop_exit_sigbus:
|
||||
* @cpu: the cpu context
|
||||
* @addr: the guest address of the alignment fault
|
||||
* @access_type: access was read/write/execute
|
||||
* @ra: host pc for unwinding
|
||||
*
|
||||
* Use the TCGCPUOps hook to record cpu state, do guest operating system
|
||||
* specific things to raise SIGBUS, and jump to the main cpu loop.
|
||||
*/
|
||||
void QEMU_NORETURN cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
|
||||
MMUAccessType access_type,
|
||||
uintptr_t ra);
|
||||
|
||||
#else
|
||||
static inline void mmap_lock(void) {}
|
||||
|
||||
@@ -35,18 +35,6 @@ struct TCGCPUOps {
|
||||
void (*cpu_exec_enter)(CPUState *cpu);
|
||||
/** @cpu_exec_exit: Callback for cpu_exec cleanup */
|
||||
void (*cpu_exec_exit)(CPUState *cpu);
|
||||
/**
|
||||
* @tlb_fill: Handle a softmmu tlb miss or user-only address fault
|
||||
*
|
||||
* For system mode, if the access is valid, call tlb_set_page
|
||||
* and return true; if the access is invalid, and probe is
|
||||
* true, return false; otherwise raise an exception and do
|
||||
* not return. For user-only mode, always raise an exception
|
||||
* and do not return.
|
||||
*/
|
||||
bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
/** @debug_excp_handler: Callback for handling debug exceptions */
|
||||
void (*debug_excp_handler)(CPUState *cpu);
|
||||
|
||||
@@ -68,6 +56,16 @@ struct TCGCPUOps {
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
/** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
|
||||
bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
|
||||
/**
|
||||
* @tlb_fill: Handle a softmmu tlb miss
|
||||
*
|
||||
* If the access is valid, call tlb_set_page and return true;
|
||||
* if the access is invalid and probe is true, return false;
|
||||
* otherwise raise an exception and do not return.
|
||||
*/
|
||||
bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
/**
|
||||
* @do_transaction_failed: Callback for handling failed memory transactions
|
||||
* (ie bus faults or external aborts; not MMU faults)
|
||||
@@ -111,6 +109,55 @@ struct TCGCPUOps {
|
||||
*/
|
||||
bool (*io_recompile_replay_branch)(CPUState *cpu,
|
||||
const TranslationBlock *tb);
|
||||
#else
|
||||
/**
|
||||
* record_sigsegv:
|
||||
* @cpu: cpu context
|
||||
* @addr: faulting guest address
|
||||
* @access_type: access was read/write/execute
|
||||
* @maperr: true for invalid page, false for permission fault
|
||||
* @ra: host pc for unwinding
|
||||
*
|
||||
* We are about to raise SIGSEGV with si_code set for @maperr,
|
||||
* and si_addr set for @addr. Record anything further needed
|
||||
* for the signal ucontext_t.
|
||||
*
|
||||
* If the emulated kernel does not provide anything to the signal
|
||||
* handler with anything besides the user context registers, and
|
||||
* the siginfo_t, then this hook need do nothing and may be omitted.
|
||||
* Otherwise, record the data and return; the caller will raise
|
||||
* the signal, unwind the cpu state, and return to the main loop.
|
||||
*
|
||||
* If it is simpler to re-use the sysemu tlb_fill code, @ra is provided
|
||||
* so that a "normal" cpu exception can be raised. In this case,
|
||||
* the signal must be raised by the architecture cpu_loop.
|
||||
*/
|
||||
void (*record_sigsegv)(CPUState *cpu, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
bool maperr, uintptr_t ra);
|
||||
/**
|
||||
* record_sigbus:
|
||||
* @cpu: cpu context
|
||||
* @addr: misaligned guest address
|
||||
* @access_type: access was read/write/execute
|
||||
* @ra: host pc for unwinding
|
||||
*
|
||||
* We are about to raise SIGBUS with si_code BUS_ADRALN,
|
||||
* and si_addr set for @addr. Record anything further needed
|
||||
* for the signal ucontext_t.
|
||||
*
|
||||
* If the emulated kernel does not provide the signal handler with
|
||||
* anything besides the user context registers, and the siginfo_t,
|
||||
* then this hook need do nothing and may be omitted.
|
||||
* Otherwise, record the data and return; the caller will raise
|
||||
* the signal, unwind the cpu state, and return to the main loop.
|
||||
*
|
||||
* If it is simpler to re-use the sysemu do_unaligned_access code,
|
||||
* @ra is provided so that a "normal" cpu exception can be raised.
|
||||
* In this case, the signal must be raised by the architecture cpu_loop.
|
||||
*/
|
||||
void (*record_sigbus)(CPUState *cpu, vaddr addr,
|
||||
MMUAccessType access_type, uintptr_t ra);
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
#endif /* NEED_CPU_H */
|
||||
|
||||
|
||||
@@ -70,5 +70,10 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
#else
|
||||
|
||||
void QEMU_NORETURN helper_unaligned_ld(CPUArchState *env, target_ulong addr);
|
||||
void QEMU_NORETURN helper_unaligned_st(CPUArchState *env, target_ulong addr);
|
||||
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
#endif /* TCG_LDST_H */
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
void cpu_loop(CPUARMState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr, ec, fsc, si_code;
|
||||
int trapnr, ec, fsc, si_code, si_signo;
|
||||
abi_long ret;
|
||||
|
||||
for (;;) {
|
||||
@@ -121,20 +121,26 @@ void cpu_loop(CPUARMState *env)
|
||||
fsc = extract32(env->exception.syndrome, 0, 6);
|
||||
switch (fsc) {
|
||||
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
||||
si_signo = TARGET_SIGSEGV;
|
||||
si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
||||
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
||||
si_signo = TARGET_SIGSEGV;
|
||||
si_code = TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
case 0x11: /* Synchronous Tag Check Fault */
|
||||
si_signo = TARGET_SIGSEGV;
|
||||
si_code = TARGET_SEGV_MTESERR;
|
||||
break;
|
||||
case 0x21: /* Alignment fault */
|
||||
si_signo = TARGET_SIGBUS;
|
||||
si_code = TARGET_BUS_ADRALN;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
force_sig_fault(TARGET_SIGSEGV, si_code, env->exception.vaddress);
|
||||
force_sig_fault(si_signo, si_code, env->exception.vaddress);
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
case EXCP_BKPT:
|
||||
|
||||
@@ -54,21 +54,6 @@ void cpu_loop(CPUAlphaState *env)
|
||||
fprintf(stderr, "External interrupt. Exit\n");
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
case EXCP_MMFAULT:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
|
||||
? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
|
||||
info._sifields._sigfault._addr = env->trap_arg0;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
break;
|
||||
case EXCP_UNALIGN:
|
||||
info.si_signo = TARGET_SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_BUS_ADRALN;
|
||||
info._sifields._sigfault._addr = env->trap_arg0;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
break;
|
||||
case EXCP_OPCDEC:
|
||||
do_sigill:
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "cpu_loop-common.h"
|
||||
#include "signal-common.h"
|
||||
#include "semihosting/common-semi.h"
|
||||
#include "target/arm/syndrome.h"
|
||||
|
||||
#define get_user_code_u32(x, gaddr, env) \
|
||||
({ abi_long __r = get_user_u32((x), (gaddr)); \
|
||||
@@ -280,7 +281,7 @@ static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode)
|
||||
void cpu_loop(CPUARMState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr;
|
||||
int trapnr, si_signo, si_code;
|
||||
unsigned int n, insn;
|
||||
abi_ulong ret;
|
||||
|
||||
@@ -423,9 +424,30 @@ void cpu_loop(CPUARMState *env)
|
||||
break;
|
||||
case EXCP_PREFETCH_ABORT:
|
||||
case EXCP_DATA_ABORT:
|
||||
/* XXX: check env->error_code */
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
|
||||
env->exception.vaddress);
|
||||
/* 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: /* Permision fault, level 1 */
|
||||
case 0xf: /* Permision 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_DEBUG:
|
||||
case EXCP_BKPT:
|
||||
|
||||
@@ -37,16 +37,6 @@ void cpu_loop(CPUCRISState *env)
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case 0xaa:
|
||||
{
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* XXX: check env->error_code */
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
info._sifields._sigfault._addr = env->pregs[PR_EDA];
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
void cpu_loop(CPUHexagonState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr, signum, sigcode;
|
||||
target_ulong sigaddr;
|
||||
int trapnr;
|
||||
target_ulong syscallnum;
|
||||
target_ulong ret;
|
||||
|
||||
@@ -39,10 +38,6 @@ void cpu_loop(CPUHexagonState *env)
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
signum = 0;
|
||||
sigcode = 0;
|
||||
sigaddr = 0;
|
||||
|
||||
switch (trapnr) {
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
@@ -65,12 +60,6 @@ void cpu_loop(CPUHexagonState *env)
|
||||
env->gpr[0] = ret;
|
||||
}
|
||||
break;
|
||||
case HEX_EXCP_FETCH_NO_UPAGE:
|
||||
case HEX_EXCP_PRIV_NO_UREAD:
|
||||
case HEX_EXCP_PRIV_NO_UWRITE:
|
||||
signum = TARGET_SIGSEGV;
|
||||
sigcode = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
@@ -79,17 +68,6 @@ void cpu_loop(CPUHexagonState *env)
|
||||
trapnr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (signum) {
|
||||
target_siginfo_t info = {
|
||||
.si_signo = signum,
|
||||
.si_errno = 0,
|
||||
.si_code = sigcode,
|
||||
._sifields._sigfault._addr = sigaddr
|
||||
};
|
||||
queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
|
||||
}
|
||||
|
||||
process_pending_signals(env);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef AARCH64_HOST_SIGNAL_H
|
||||
#define AARCH64_HOST_SIGNAL_H
|
||||
|
||||
/* Pre-3.16 kernel headers don't have these, so provide fallback definitions */
|
||||
#ifndef ESR_MAGIC
|
||||
#define ESR_MAGIC 0x45535201
|
||||
struct esr_context {
|
||||
struct _aarch64_ctx head;
|
||||
uint64_t esr;
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline struct _aarch64_ctx *first_ctx(ucontext_t *uc)
|
||||
{
|
||||
return (struct _aarch64_ctx *)&uc->uc_mcontext.__reserved;
|
||||
}
|
||||
|
||||
static inline struct _aarch64_ctx *next_ctx(struct _aarch64_ctx *hdr)
|
||||
{
|
||||
return (struct _aarch64_ctx *)((char *)hdr + hdr->size);
|
||||
}
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.pc;
|
||||
}
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
struct _aarch64_ctx *hdr;
|
||||
uint32_t insn;
|
||||
|
||||
/* Find the esr_context, which has the WnR bit in it */
|
||||
for (hdr = first_ctx(uc); hdr->magic; hdr = next_ctx(hdr)) {
|
||||
if (hdr->magic == ESR_MAGIC) {
|
||||
struct esr_context const *ec = (struct esr_context const *)hdr;
|
||||
uint64_t esr = ec->esr;
|
||||
|
||||
/* For data aborts ESR.EC is 0b10010x: then bit 6 is the WnR bit */
|
||||
return extract32(esr, 27, 5) == 0x12 && extract32(esr, 6, 1) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fall back to parsing instructions; will only be needed
|
||||
* for really ancient (pre-3.16) kernels.
|
||||
*/
|
||||
insn = *(uint32_t *)host_signal_pc(uc);
|
||||
|
||||
return (insn & 0xbfff0000) == 0x0c000000 /* C3.3.1 */
|
||||
|| (insn & 0xbfe00000) == 0x0c800000 /* C3.3.2 */
|
||||
|| (insn & 0xbfdf0000) == 0x0d000000 /* C3.3.3 */
|
||||
|| (insn & 0xbfc00000) == 0x0d800000 /* C3.3.4 */
|
||||
|| (insn & 0x3f400000) == 0x08000000 /* C3.3.6 */
|
||||
|| (insn & 0x3bc00000) == 0x39000000 /* C3.3.13 */
|
||||
|| (insn & 0x3fc00000) == 0x3d800000 /* ... 128bit */
|
||||
/* Ignore bits 10, 11 & 21, controlling indexing. */
|
||||
|| (insn & 0x3bc00000) == 0x38000000 /* C3.3.8-12 */
|
||||
|| (insn & 0x3fe00000) == 0x3c800000 /* ... 128bit */
|
||||
/* Ignore bits 23 & 24, controlling indexing. */
|
||||
|| (insn & 0x3a400000) == 0x28000000; /* C3.3.7,14-16 */
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef ALPHA_HOST_SIGNAL_H
|
||||
#define ALPHA_HOST_SIGNAL_H
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.sc_pc;
|
||||
}
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
uint32_t *pc = (uint32_t *)host_signal_pc(uc);
|
||||
uint32_t insn = *pc;
|
||||
|
||||
/* XXX: need kernel patch to get write flag faster */
|
||||
switch (insn >> 26) {
|
||||
case 0x0d: /* stw */
|
||||
case 0x0e: /* stb */
|
||||
case 0x0f: /* stq_u */
|
||||
case 0x24: /* stf */
|
||||
case 0x25: /* stg */
|
||||
case 0x26: /* sts */
|
||||
case 0x27: /* stt */
|
||||
case 0x2c: /* stl */
|
||||
case 0x2d: /* stq */
|
||||
case 0x2e: /* stl_c */
|
||||
case 0x2f: /* stq_c */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef ARM_HOST_SIGNAL_H
|
||||
#define ARM_HOST_SIGNAL_H
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.arm_pc;
|
||||
}
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
/*
|
||||
* In the FSR, bit 11 is WnR, assuming a v6 or
|
||||
* later processor. On v5 we will always report
|
||||
* this as a read, which will fail later.
|
||||
*/
|
||||
uint32_t fsr = uc->uc_mcontext.error_code;
|
||||
return extract32(fsr, 11, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef I386_HOST_SIGNAL_H
|
||||
#define I386_HOST_SIGNAL_H
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.gregs[REG_EIP];
|
||||
}
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe
|
||||
&& (uc->uc_mcontext.gregs[REG_ERR] & 0x2);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef MIPS_HOST_SIGNAL_H
|
||||
#define MIPS_HOST_SIGNAL_H
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.pc;
|
||||
}
|
||||
|
||||
#if defined(__misp16) || defined(__mips_micromips)
|
||||
#error "Unsupported encoding"
|
||||
#endif
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
uint32_t insn = *(uint32_t *)host_signal_pc(uc);
|
||||
|
||||
/* Detect all store instructions at program counter. */
|
||||
switch ((insn >> 26) & 077) {
|
||||
case 050: /* SB */
|
||||
case 051: /* SH */
|
||||
case 052: /* SWL */
|
||||
case 053: /* SW */
|
||||
case 054: /* SDL */
|
||||
case 055: /* SDR */
|
||||
case 056: /* SWR */
|
||||
case 070: /* SC */
|
||||
case 071: /* SWC1 */
|
||||
case 074: /* SCD */
|
||||
case 075: /* SDC1 */
|
||||
case 077: /* SD */
|
||||
#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
|
||||
case 072: /* SWC2 */
|
||||
case 076: /* SDC2 */
|
||||
#endif
|
||||
return true;
|
||||
case 023: /* COP1X */
|
||||
/*
|
||||
* Required in all versions of MIPS64 since
|
||||
* MIPS64r1 and subsequent versions of MIPS32r2.
|
||||
*/
|
||||
switch (insn & 077) {
|
||||
case 010: /* SWXC1 */
|
||||
case 011: /* SDXC1 */
|
||||
case 015: /* SUXC1 */
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef PPC_HOST_SIGNAL_H
|
||||
#define PPC_HOST_SIGNAL_H
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.regs->nip;
|
||||
}
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.regs->trap != 0x400
|
||||
&& (uc->uc_mcontext.regs->dsisr & 0x02000000);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
#include "../ppc/host-signal.h"
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* host-signal.h: signal info dependent on the host architecture
|
||||
*
|
||||
* Copyright (c) 2003-2005 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef RISCV_HOST_SIGNAL_H
|
||||
#define RISCV_HOST_SIGNAL_H
|
||||
|
||||
static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
||||
{
|
||||
return uc->uc_mcontext.__gregs[REG_PC];
|
||||
}
|
||||
|
||||
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||
{
|
||||
/*
|
||||
* Detect store by reading the instruction at the program counter.
|
||||
* Do not read more than 16 bits, because we have not yet determined
|
||||
* the size of the instruction.
|
||||
*/
|
||||
const uint16_t *pinsn = (const uint16_t *)host_signal_pc(uc);
|
||||
uint16_t insn = pinsn[0];
|
||||
|
||||
/* 16-bit instructions */
|
||||
switch (insn & 0xe003) {
|
||||
case 0xa000: /* c.fsd */
|
||||
case 0xc000: /* c.sw */
|
||||
case 0xe000: /* c.sd (rv64) / c.fsw (rv32) */
|
||||
case 0xa002: /* c.fsdsp */
|
||||
case 0xc002: /* c.swsp */
|
||||
case 0xe002: /* c.sdsp (rv64) / c.fswsp (rv32) */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 32-bit instructions, major opcodes */
|
||||
switch (insn & 0x7f) {
|
||||
case 0x23: /* store */
|
||||
case 0x27: /* store-fp */
|
||||
return true;
|
||||
case 0x2f: /* amo */
|
||||
/*
|
||||
* The AMO function code is in bits 25-31, unread as yet.
|
||||
* The AMO functions are LR (read), SC (write), and the
|
||||
* rest are all read-modify-write.
|
||||
*/
|
||||
insn = pinsn[1];
|
||||
return (insn >> 11) != 2; /* LR */
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,8 +5,8 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef RISCV64_HOSTDEP_H
|
||||
#define RISCV64_HOSTDEP_H
|
||||
#ifndef RISCV_HOSTDEP_H
|
||||
#define RISCV_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user