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:
Peter Maydell 2021-09-24 15:05:12 +01:00
commit e749ea2479
4 changed files with 46 additions and 69 deletions

View File

@ -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);

View File

@ -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))

View File

@ -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);

View File

@ -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.