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)
|
void cpu_loop(CPUARMState *env)
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
int trapnr, ec, fsc;
|
int trapnr, ec, fsc, si_code;
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
target_siginfo_t info;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cpu_exec_start(cs);
|
cpu_exec_start(cs);
|
||||||
@ -110,18 +109,10 @@ void cpu_loop(CPUARMState *env)
|
|||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
break;
|
break;
|
||||||
case EXCP_UDEF:
|
case EXCP_UDEF:
|
||||||
info.si_signo = TARGET_SIGILL;
|
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
case EXCP_DATA_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}. */
|
/* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
|
||||||
ec = syn_get_ec(env->exception.syndrome);
|
ec = syn_get_ec(env->exception.syndrome);
|
||||||
assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
|
assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
|
||||||
@ -130,27 +121,24 @@ void cpu_loop(CPUARMState *env)
|
|||||||
fsc = extract32(env->exception.syndrome, 0, 6);
|
fsc = extract32(env->exception.syndrome, 0, 6);
|
||||||
switch (fsc) {
|
switch (fsc) {
|
||||||
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
||||||
info.si_code = TARGET_SEGV_MAPERR;
|
si_code = TARGET_SEGV_MAPERR;
|
||||||
break;
|
break;
|
||||||
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
||||||
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
||||||
info.si_code = TARGET_SEGV_ACCERR;
|
si_code = TARGET_SEGV_ACCERR;
|
||||||
break;
|
break;
|
||||||
case 0x11: /* Synchronous Tag Check Fault */
|
case 0x11: /* Synchronous Tag Check Fault */
|
||||||
info.si_code = TARGET_SEGV_MTESERR;
|
si_code = TARGET_SEGV_MTESERR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
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;
|
break;
|
||||||
case EXCP_DEBUG:
|
case EXCP_DEBUG:
|
||||||
case EXCP_BKPT:
|
case EXCP_BKPT:
|
||||||
info.si_signo = TARGET_SIGTRAP;
|
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||||
info.si_errno = 0;
|
|
||||||
info.si_code = TARGET_TRAP_BRKPT;
|
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
|
||||||
break;
|
break;
|
||||||
case EXCP_SEMIHOST:
|
case EXCP_SEMIHOST:
|
||||||
env->xregs[0] = do_common_semihosting(cs);
|
env->xregs[0] = do_common_semihosting(cs);
|
||||||
@ -170,11 +158,7 @@ void cpu_loop(CPUARMState *env)
|
|||||||
/* Check for MTE asynchronous faults */
|
/* Check for MTE asynchronous faults */
|
||||||
if (unlikely(env->cp15.tfsr_el[0])) {
|
if (unlikely(env->cp15.tfsr_el[0])) {
|
||||||
env->cp15.tfsr_el[0] = 0;
|
env->cp15.tfsr_el[0] = 0;
|
||||||
info.si_signo = TARGET_SIGSEGV;
|
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MTEAERR, 0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
process_pending_signals(env);
|
process_pending_signals(env);
|
||||||
|
@ -94,7 +94,6 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
|
|||||||
{
|
{
|
||||||
uint64_t oldval, newval, val;
|
uint64_t oldval, newval, val;
|
||||||
uint32_t addr, cpsr;
|
uint32_t addr, cpsr;
|
||||||
target_siginfo_t info;
|
|
||||||
|
|
||||||
/* Based on the 32 bit code in do_kernel_trap */
|
/* Based on the 32 bit code in do_kernel_trap */
|
||||||
|
|
||||||
@ -143,12 +142,9 @@ segv:
|
|||||||
end_exclusive();
|
end_exclusive();
|
||||||
/* We get the PC of the entry address - which is as good as anything,
|
/* 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. */
|
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 */
|
/* XXX: check env->error_code */
|
||||||
info.si_code = TARGET_SEGV_MAPERR;
|
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
|
||||||
info._sifields._sigfault._addr = env->exception.vaddress;
|
env->exception.vaddress);
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a jump to the kernel code page. */
|
/* 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;
|
ts->fpa.fpsr |= raise & ~enabled;
|
||||||
|
|
||||||
if (raise & enabled) {
|
if (raise & enabled) {
|
||||||
target_siginfo_t info = { };
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The kernel's nwfpe emulator does not pass a real si_code.
|
* 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;
|
force_sig(TARGET_SIGFPE);
|
||||||
info.si_code = TARGET_SI_KERNEL;
|
|
||||||
|
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
|
||||||
} else {
|
} else {
|
||||||
env->regs[15] += 4;
|
env->regs[15] += 4;
|
||||||
}
|
}
|
||||||
@ -289,8 +282,6 @@ void cpu_loop(CPUARMState *env)
|
|||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
int trapnr;
|
int trapnr;
|
||||||
unsigned int n, insn;
|
unsigned int n, insn;
|
||||||
target_siginfo_t info;
|
|
||||||
uint32_t addr;
|
|
||||||
abi_ulong ret;
|
abi_ulong ret;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -325,11 +316,8 @@ void cpu_loop(CPUARMState *env)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.si_signo = TARGET_SIGILL;
|
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN,
|
||||||
info.si_errno = 0;
|
env->regs[15]);
|
||||||
info.si_code = TARGET_ILL_ILLOPN;
|
|
||||||
info._sifields._sigfault._addr = env->regs[15];
|
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXCP_SWI:
|
case EXCP_SWI:
|
||||||
@ -397,18 +385,14 @@ void cpu_loop(CPUARMState *env)
|
|||||||
* Otherwise SIGILL. This includes any SWI with
|
* Otherwise SIGILL. This includes any SWI with
|
||||||
* immediate not originally 0x9fxxxx, because
|
* immediate not originally 0x9fxxxx, because
|
||||||
* of the earlier XOR.
|
* 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;
|
abi_ulong faultaddr = env->regs[15];
|
||||||
info.si_errno = 0;
|
faultaddr -= env->thumb ? 2 : 4;
|
||||||
info.si_code = TARGET_ILL_ILLTRP;
|
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
|
||||||
info._sifields._sigfault._addr = env->regs[15];
|
faultaddr);
|
||||||
if (env->thumb) {
|
|
||||||
info._sifields._sigfault._addr -= 2;
|
|
||||||
} else {
|
|
||||||
info._sifields._sigfault._addr -= 4;
|
|
||||||
}
|
|
||||||
queue_signal(env, info.si_signo,
|
|
||||||
QEMU_SI_FAULT, &info);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -439,23 +423,14 @@ void cpu_loop(CPUARMState *env)
|
|||||||
break;
|
break;
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
addr = env->exception.vaddress;
|
/* XXX: check env->error_code */
|
||||||
{
|
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
|
||||||
info.si_signo = TARGET_SIGSEGV;
|
env->exception.vaddress);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case EXCP_DEBUG:
|
case EXCP_DEBUG:
|
||||||
case EXCP_BKPT:
|
case EXCP_BKPT:
|
||||||
excp_debug:
|
excp_debug:
|
||||||
info.si_signo = TARGET_SIGTRAP;
|
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[15]);
|
||||||
info.si_errno = 0;
|
|
||||||
info.si_code = TARGET_TRAP_BRKPT;
|
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
|
||||||
break;
|
break;
|
||||||
case EXCP_KERNEL_TRAP:
|
case EXCP_KERNEL_TRAP:
|
||||||
if (do_kernel_trap(env))
|
if (do_kernel_trap(env))
|
||||||
|
@ -40,6 +40,7 @@ void tswap_siginfo(target_siginfo_t *tinfo,
|
|||||||
void set_sigmask(const sigset_t *set);
|
void set_sigmask(const sigset_t *set);
|
||||||
void force_sig(int sig);
|
void force_sig(int sig);
|
||||||
void force_sigsegv(int oldsig);
|
void force_sigsegv(int oldsig);
|
||||||
|
void force_sig_fault(int sig, int code, abi_ulong addr);
|
||||||
#if defined(TARGET_ARCH_HAS_SETUP_FRAME)
|
#if defined(TARGET_ARCH_HAS_SETUP_FRAME)
|
||||||
void setup_frame(int sig, struct target_sigaction *ka,
|
void setup_frame(int sig, struct target_sigaction *ka,
|
||||||
target_sigset_t *set, CPUArchState *env);
|
target_sigset_t *set, CPUArchState *env);
|
||||||
|
@ -641,7 +641,7 @@ void force_sig(int sig)
|
|||||||
{
|
{
|
||||||
CPUState *cpu = thread_cpu;
|
CPUState *cpu = thread_cpu;
|
||||||
CPUArchState *env = cpu->env_ptr;
|
CPUArchState *env = cpu->env_ptr;
|
||||||
target_siginfo_t info;
|
target_siginfo_t info = {};
|
||||||
|
|
||||||
info.si_signo = sig;
|
info.si_signo = sig;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
@ -651,6 +651,23 @@ void force_sig(int sig)
|
|||||||
queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
|
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
|
/* 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
|
* up the signal frame. oldsig is the signal we were trying to handle
|
||||||
* at the point of failure.
|
* at the point of failure.
|
||||||
|
Loading…
Reference in New Issue
Block a user