Pull request linux-user 20210924
Clean up siginfo_t handling for arm, aarch64 -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmFN2PwSHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748HUYP/Rk46UwLoiTl+OvJ6HtcUssMDR8os1On UDL4Bh3ioZ0If6qX98iUHuwgrEHRy0wqTzrwQ44t4Afer+i116O8Otn+Tk4DGDv/ gvYxtVQ0HUuC5Er6rvqcfAmRlY5afD8DKmmRhHBP2bHulT0BHeRf3JOPZ16esuXU VTdQZdD21Szh+33T8EfMOdxFvcDWKrNwJOMF7diyYe8wgXETe2LS4MQshw+O9m/t +2w2PbK0PFLwbQQIs3DldpIMrCcvClKNRb0SDhIa6Yf7Jkmfb/WSoODxhLXTtuTn o7kS4Eyv25nMqpOzQM71/+Rb06y9kkL0/LEgYy9Sveq1+lqbDdO1VloyuVjH6a1e N0VJTT2szRCXMQvaLceaoPj85qGAV5zNmEC9fAAUlAGVeUc4GVS/bAchHbBDJNur t0AtlbmXKFae2QOKp4UMv1pFwUR8B9f2Ua8Gia3UmwpyWgivBsv0U6sWdaAzGx/N 6F1HvPmHJSt4wSMkUJ26cJ72kMbx4KeABHyB2lUKZ87iUuHuqv4AzmZJMuS9YByG slREahJPyBfxOottbK9jEb2OBKcKAgLoyiM9GkG66uPDywzKHFyZGr01zk5EZN2k scTL8xzDg5QkQsbkvSKvnmfaRdLVQP/zw2pjEZS+YBYUK2vD9e8mLUEMH2CrjmZ5 +Adga/+9vKFx =i8W/ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-6.2-pull-request' into staging Pull request linux-user 20210924 Clean up siginfo_t handling for arm, aarch64 # gpg: Signature made Fri 24 Sep 2021 14:56:12 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-6.2-pull-request: linux-user/aarch64: Use force_sig_fault() linux-user/arm: Use force_sig_fault() linux-user: Provide new force_sig_fault() function linux-user: Zero out target_siginfo_t in force_sig() linux-user/arm: Use force_sig() to deliver fpa11 emulation SIGFPE linux-user/arm: Set siginfo_t addr field for SIGTRAP signals linux-user/aarch64: Set siginfo_t addr field for SIGTRAP signals Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e749ea2479
@ -79,9 +79,8 @@
|
||||
void cpu_loop(CPUARMState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr, ec, fsc;
|
||||
int trapnr, ec, fsc, si_code;
|
||||
abi_long ret;
|
||||
target_siginfo_t info;
|
||||
|
||||
for (;;) {
|
||||
cpu_exec_start(cs);
|
||||
@ -110,18 +109,10 @@ void cpu_loop(CPUARMState *env)
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
case EXCP_UDEF:
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLOPN;
|
||||
info._sifields._sigfault._addr = env->pc;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
|
||||
break;
|
||||
case EXCP_PREFETCH_ABORT:
|
||||
case EXCP_DATA_ABORT:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info._sifields._sigfault._addr = env->exception.vaddress;
|
||||
|
||||
/* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
|
||||
ec = syn_get_ec(env->exception.syndrome);
|
||||
assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
|
||||
@ -130,27 +121,24 @@ void cpu_loop(CPUARMState *env)
|
||||
fsc = extract32(env->exception.syndrome, 0, 6);
|
||||
switch (fsc) {
|
||||
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
||||
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
||||
info.si_code = TARGET_SEGV_ACCERR;
|
||||
si_code = TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
case 0x11: /* Synchronous Tag Check Fault */
|
||||
info.si_code = TARGET_SEGV_MTESERR;
|
||||
si_code = TARGET_SEGV_MTESERR;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGSEGV, si_code, env->exception.vaddress);
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
case EXCP_BKPT:
|
||||
info.si_signo = TARGET_SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_TRAP_BRKPT;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
break;
|
||||
case EXCP_SEMIHOST:
|
||||
env->xregs[0] = do_common_semihosting(cs);
|
||||
@ -170,11 +158,7 @@ void cpu_loop(CPUARMState *env)
|
||||
/* Check for MTE asynchronous faults */
|
||||
if (unlikely(env->cp15.tfsr_el[0])) {
|
||||
env->cp15.tfsr_el[0] = 0;
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info._sifields._sigfault._addr = 0;
|
||||
info.si_code = TARGET_SEGV_MTEAERR;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MTEAERR, 0);
|
||||
}
|
||||
|
||||
process_pending_signals(env);
|
||||
|
@ -94,7 +94,6 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
||||
{
|
||||
uint64_t oldval, newval, val;
|
||||
uint32_t addr, cpsr;
|
||||
target_siginfo_t info;
|
||||
|
||||
/* Based on the 32 bit code in do_kernel_trap */
|
||||
|
||||
@ -143,12 +142,9 @@ segv:
|
||||
end_exclusive();
|
||||
/* We get the PC of the entry address - which is as good as anything,
|
||||
on a real kernel what you get depends on which mode it uses. */
|
||||
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->exception.vaddress;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
|
||||
env->exception.vaddress);
|
||||
}
|
||||
|
||||
/* Handle a jump to the kernel code page. */
|
||||
@ -268,16 +264,13 @@ static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode)
|
||||
ts->fpa.fpsr |= raise & ~enabled;
|
||||
|
||||
if (raise & enabled) {
|
||||
target_siginfo_t info = { };
|
||||
|
||||
/*
|
||||
* The kernel's nwfpe emulator does not pass a real si_code.
|
||||
* It merely uses send_sig(SIGFPE, current, 1).
|
||||
* It merely uses send_sig(SIGFPE, current, 1), which results in
|
||||
* __send_signal() filling out SI_KERNEL with pid and uid 0 (under
|
||||
* the "SEND_SIG_PRIV" case). That's what our force_sig() does.
|
||||
*/
|
||||
info.si_signo = TARGET_SIGFPE;
|
||||
info.si_code = TARGET_SI_KERNEL;
|
||||
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig(TARGET_SIGFPE);
|
||||
} else {
|
||||
env->regs[15] += 4;
|
||||
}
|
||||
@ -289,8 +282,6 @@ void cpu_loop(CPUARMState *env)
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr;
|
||||
unsigned int n, insn;
|
||||
target_siginfo_t info;
|
||||
uint32_t addr;
|
||||
abi_ulong ret;
|
||||
|
||||
for(;;) {
|
||||
@ -325,11 +316,8 @@ void cpu_loop(CPUARMState *env)
|
||||
break;
|
||||
}
|
||||
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLOPN;
|
||||
info._sifields._sigfault._addr = env->regs[15];
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN,
|
||||
env->regs[15]);
|
||||
}
|
||||
break;
|
||||
case EXCP_SWI:
|
||||
@ -397,18 +385,14 @@ void cpu_loop(CPUARMState *env)
|
||||
* Otherwise SIGILL. This includes any SWI with
|
||||
* immediate not originally 0x9fxxxx, because
|
||||
* of the earlier XOR.
|
||||
* Like the real kernel, we report the addr of the
|
||||
* SWI in the siginfo si_addr but leave the PC
|
||||
* pointing at the insn after the SWI.
|
||||
*/
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLTRP;
|
||||
info._sifields._sigfault._addr = env->regs[15];
|
||||
if (env->thumb) {
|
||||
info._sifields._sigfault._addr -= 2;
|
||||
} else {
|
||||
info._sifields._sigfault._addr -= 4;
|
||||
}
|
||||
queue_signal(env, info.si_signo,
|
||||
QEMU_SI_FAULT, &info);
|
||||
abi_ulong faultaddr = env->regs[15];
|
||||
faultaddr -= env->thumb ? 2 : 4;
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
|
||||
faultaddr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -439,23 +423,14 @@ void cpu_loop(CPUARMState *env)
|
||||
break;
|
||||
case EXCP_PREFETCH_ABORT:
|
||||
case EXCP_DATA_ABORT:
|
||||
addr = env->exception.vaddress;
|
||||
{
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* XXX: check env->error_code */
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
info._sifields._sigfault._addr = addr;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
/* XXX: check env->error_code */
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
|
||||
env->exception.vaddress);
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
case EXCP_BKPT:
|
||||
excp_debug:
|
||||
info.si_signo = TARGET_SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_TRAP_BRKPT;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[15]);
|
||||
break;
|
||||
case EXCP_KERNEL_TRAP:
|
||||
if (do_kernel_trap(env))
|
||||
|
@ -40,6 +40,7 @@ void tswap_siginfo(target_siginfo_t *tinfo,
|
||||
void set_sigmask(const sigset_t *set);
|
||||
void force_sig(int sig);
|
||||
void force_sigsegv(int oldsig);
|
||||
void force_sig_fault(int sig, int code, abi_ulong addr);
|
||||
#if defined(TARGET_ARCH_HAS_SETUP_FRAME)
|
||||
void setup_frame(int sig, struct target_sigaction *ka,
|
||||
target_sigset_t *set, CPUArchState *env);
|
||||
|
@ -641,7 +641,7 @@ void force_sig(int sig)
|
||||
{
|
||||
CPUState *cpu = thread_cpu;
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
target_siginfo_t info;
|
||||
target_siginfo_t info = {};
|
||||
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
@ -651,6 +651,23 @@ void force_sig(int sig)
|
||||
queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Force a synchronously taken QEMU_SI_FAULT signal. For QEMU the
|
||||
* 'force' part is handled in process_pending_signals().
|
||||
*/
|
||||
void force_sig_fault(int sig, int code, abi_ulong addr)
|
||||
{
|
||||
CPUState *cpu = thread_cpu;
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
target_siginfo_t info = {};
|
||||
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info._sifields._sigfault._addr = addr;
|
||||
queue_signal(env, sig, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
|
||||
/* Force a SIGSEGV if we couldn't write to memory trying to set
|
||||
* up the signal frame. oldsig is the signal we were trying to handle
|
||||
* at the point of failure.
|
||||
|
Loading…
Reference in New Issue
Block a user