diff --git a/linux-user/aarch64/target_structs.h b/linux-user/aarch64/target_structs.h index 7c748344ca..3a06f373c3 100644 --- a/linux-user/aarch64/target_structs.h +++ b/linux-user/aarch64/target_structs.h @@ -1,58 +1 @@ -/* - * ARM AArch64 specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef AARCH64_TARGET_STRUCTS_H -#define AARCH64_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/alpha/cpu_loop.c b/linux-user/alpha/cpu_loop.c index 37c33f0ccd..de6e0c901c 100644 --- a/linux-user/alpha/cpu_loop.c +++ b/linux-user/alpha/cpu_loop.c @@ -27,8 +27,7 @@ void cpu_loop(CPUAlphaState *env) { CPUState *cs = env_cpu(env); - int trapnr; - target_siginfo_t info; + int trapnr, si_code; abi_long sysret; while (1) { @@ -56,18 +55,10 @@ void cpu_loop(CPUAlphaState *env) break; case EXCP_OPCDEC: do_sigill: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case EXCP_ARITH: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_FLTINV; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_FLTINV, env->pc); break; case EXCP_FEN: /* No-op. Linux simply re-enables the FPU. */ @@ -76,20 +67,10 @@ void cpu_loop(CPUAlphaState *env) switch (env->error_code) { case 0x80: /* BPT */ - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; + goto do_sigtrap_brkpt; case 0x81: /* BUGCHK */ - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = 0; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; + goto do_sigtrap_unk; case 0x83: /* CALLSYS */ trapnr = env->ir[IR_V0]; @@ -130,47 +111,43 @@ void cpu_loop(CPUAlphaState *env) abort(); case 0xAA: /* GENTRAP */ - info.si_signo = TARGET_SIGFPE; switch (env->ir[IR_A0]) { case TARGET_GEN_INTOVF: - info.si_code = TARGET_FPE_INTOVF; + si_code = TARGET_FPE_INTOVF; break; case TARGET_GEN_INTDIV: - info.si_code = TARGET_FPE_INTDIV; + si_code = TARGET_FPE_INTDIV; break; case TARGET_GEN_FLTOVF: - info.si_code = TARGET_FPE_FLTOVF; + si_code = TARGET_FPE_FLTOVF; break; case TARGET_GEN_FLTUND: - info.si_code = TARGET_FPE_FLTUND; + si_code = TARGET_FPE_FLTUND; break; case TARGET_GEN_FLTINV: - info.si_code = TARGET_FPE_FLTINV; + si_code = TARGET_FPE_FLTINV; break; case TARGET_GEN_FLTINE: - info.si_code = TARGET_FPE_FLTRES; + si_code = TARGET_FPE_FLTRES; break; case TARGET_GEN_ROPRAND: - info.si_code = 0; + si_code = TARGET_FPE_FLTUNK; break; default: - info.si_signo = TARGET_SIGTRAP; - info.si_code = 0; - break; + goto do_sigtrap_unk; } - info.si_errno = 0; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); break; default: goto do_sigill; } break; case 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); + do_sigtrap_brkpt: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + break; + do_sigtrap_unk: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_UNK, env->pc); break; case EXCP_INTERRUPT: /* Just indicate that signals should be handled asap. */ diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h index 339b070bf1..3a06f373c3 100644 --- a/linux-user/arm/target_structs.h +++ b/linux-user/arm/target_structs.h @@ -1,59 +1 @@ -/* - * ARM specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef ARM_TARGET_STRUCTS_H -#define ARM_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ - abi_ulong __unused1; - abi_ulong shm_dtime; /* time of last shmdt() */ - abi_ulong __unused2; - abi_ulong shm_ctime; /* time of last change by shmctl() */ - abi_ulong __unused3; - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -struct target_oabi_flock64 { - abi_short l_type; - abi_short l_whence; - abi_llong l_start; - abi_llong l_len; - abi_int l_pid; -} QEMU_PACKED; -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/cris/cpu_loop.c b/linux-user/cris/cpu_loop.c index 5213aebf55..0f46b3c1a8 100644 --- a/linux-user/cris/cpu_loop.c +++ b/linux-user/cris/cpu_loop.c @@ -28,8 +28,7 @@ void cpu_loop(CPUCRISState *env) { CPUState *cs = env_cpu(env); int trapnr, ret; - target_siginfo_t info; - + while (1) { cpu_exec_start(cs); trapnr = cpu_exec(cs); @@ -38,8 +37,8 @@ void cpu_loop(CPUCRISState *env) switch (trapnr) { case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ - break; + /* just indicate that signals should be handled asap */ + break; case EXCP_BREAK: ret = do_syscall(env, env->regs[9], @@ -57,10 +56,7 @@ void cpu_loop(CPUCRISState *env) } break; case 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->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/cris/target_structs.h b/linux-user/cris/target_structs.h index f949d2331e..3a06f373c3 100644 --- a/linux-user/cris/target_structs.h +++ b/linux-user/cris/target_structs.h @@ -1,58 +1 @@ -/* - * CRIS specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef CRIS_TARGET_STRUCTS_H -#define CRIS_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/generic/target_structs.h b/linux-user/generic/target_structs.h new file mode 100644 index 0000000000..09ff858b6e --- /dev/null +++ b/linux-user/generic/target_structs.h @@ -0,0 +1,58 @@ +/* + * Generic structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef GENERIC_TARGET_STRUCTS_H +#define GENERIC_TARGET_STRUCTS_H + +struct target_ipc_perm { + abi_int __key; /* Key. */ + abi_uint uid; /* Owner's user ID. */ + abi_uint gid; /* Owner's group ID. */ + abi_uint cuid; /* Creator's user ID. */ + abi_uint cgid; /* Creator's group ID. */ + abi_ushort mode; /* Read/write permission. */ + abi_ushort __pad1; + abi_ushort __seq; /* Sequence number. */ + abi_ushort __pad2; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* operation permission struct */ + abi_long shm_segsz; /* size of segment in bytes */ + abi_ulong shm_atime; /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong shm_dtime; /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong shm_ctime; /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + abi_int shm_cpid; /* pid of creator */ + abi_int shm_lpid; /* pid of last shmop */ + abi_ulong shm_nattch; /* number of current attaches */ + abi_ulong __unused4; + abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/hexagon/target_structs.h b/linux-user/hexagon/target_structs.h index c217d9442a..3a06f373c3 100644 --- a/linux-user/hexagon/target_structs.h +++ b/linux-user/hexagon/target_structs.h @@ -1,54 +1 @@ -/* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -/* - * Hexagon specific structures for linux-user - */ -#ifndef HEXAGON_TARGET_STRUCTS_H -#define HEXAGON_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ - abi_ulong __unused1; - abi_ulong shm_dtime; /* time of last shmdt() */ - abi_ulong __unused2; - abi_ulong shm_ctime; /* time of last change by shmctl() */ - abi_ulong __unused3; - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index a47a63176b..a576d1a249 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -110,7 +110,6 @@ static abi_ulong hppa_lws(CPUHPPAState *env) void cpu_loop(CPUHPPAState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; abi_ulong ret; int trapnr; @@ -145,28 +144,25 @@ void cpu_loop(CPUHPPAState *env) env->iaoq_b = env->gr[31] + 4; break; case EXCP_ILL: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f); + break; case EXCP_PRIV_OPR: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f); + break; case EXCP_PRIV_REG: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPN; - info._sifields._sigfault._addr = env->iaoq_f; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f); break; case EXCP_OVERFLOW: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->iaoq_f); + break; case EXCP_COND: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f); + break; case EXCP_ASSIST: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = 0; - info._sifields._sigfault._addr = env->iaoq_f; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f); break; case 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->iaoq_f); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 9aaae93e2f..29dfd7cd0c 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -84,17 +84,6 @@ static void set_idt(int n, unsigned int dpl) } #endif -static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr) -{ - target_siginfo_t info = { - .si_signo = sig, - .si_code = code, - ._sifields._sigfault._addr = addr - }; - - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); -} - #ifdef TARGET_X86_64 static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len) { @@ -107,7 +96,7 @@ static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len) } env->error_code = PG_ERROR_W_MASK | PG_ERROR_U_MASK; - gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr); + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr); return false; } @@ -193,11 +182,21 @@ static void emulate_vsyscall(CPUX86State *env) return; sigsegv: - /* Like force_sig(SIGSEGV). */ - gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGSEGV); } #endif +static bool maybe_handle_vm86_trap(CPUX86State *env, int trapnr) +{ +#ifndef TARGET_X86_64 + if (env->eflags & VM_MASK) { + handle_vm86_trap(env, trapnr); + return true; + } +#endif + return false; +} + void cpu_loop(CPUX86State *env) { CPUState *cs = env_cpu(env); @@ -255,65 +254,54 @@ void cpu_loop(CPUX86State *env) #endif case EXCP0B_NOSEG: case EXCP0C_STACK: - gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGBUS); break; case EXCP0D_GPF: /* XXX: potential problem if ABI32 */ -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_fault(env); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif - gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGSEGV); break; case EXCP0E_PAGE: - gen_signal(env, TARGET_SIGSEGV, - (env->error_code & 1 ? - TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR), - env->cr[2]); + force_sig_fault(TARGET_SIGSEGV, + (env->error_code & PG_ERROR_P_MASK ? + TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR), + env->cr[2]); break; case EXCP00_DIVZ: -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_trap(env, trapnr); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif - gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip); break; case EXCP01_DB: - case EXCP03_INT3: -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_trap(env, trapnr); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif - if (trapnr == EXCP01_DB) { - gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); - } else { - gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); + break; + case EXCP03_INT3: + if (maybe_handle_vm86_trap(env, trapnr)) { + break; } + force_sig(TARGET_SIGTRAP); break; case EXCP04_INTO: case EXCP05_BOUND: -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_trap(env, trapnr); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif - gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGSEGV); break; case EXCP06_ILLOP: - gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; case EXCP_DEBUG: - gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/i386/target_structs.h b/linux-user/i386/target_structs.h index e22847fd20..3a06f373c3 100644 --- a/linux-user/i386/target_structs.h +++ b/linux-user/i386/target_structs.h @@ -1,58 +1 @@ -/* - * i386 specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef I386_TARGET_STRUCTS_H -#define I386_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c index 3181594414..928a18e3cf 100644 --- a/linux-user/m68k/cpu_loop.c +++ b/linux-user/m68k/cpu_loop.c @@ -29,7 +29,6 @@ void cpu_loop(CPUM68KState *env) CPUState *cs = env_cpu(env); int trapnr; unsigned int n; - target_siginfo_t info; for(;;) { cpu_exec_start(cs); @@ -46,25 +45,13 @@ void cpu_loop(CPUM68KState *env) case EXCP_ILLEGAL: case EXCP_LINEA: case EXCP_LINEF: - 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_CHK: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_INTOVF; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->pc); break; case EXCP_DIV0: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_INTDIV; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc); break; case EXCP_TRAP0: { @@ -91,10 +78,7 @@ void cpu_loop(CPUM68KState *env) /* just indicate that signals should be handled asap */ break; case 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->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/m68k/target_structs.h b/linux-user/m68k/target_structs.h index e373d481e1..3a06f373c3 100644 --- a/linux-user/m68k/target_structs.h +++ b/linux-user/m68k/target_structs.h @@ -1,58 +1 @@ -/* - * m68k specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef M68K_TARGET_STRUCTS_H -#define M68K_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index ff1fb26c8b..1a2556be2c 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -27,9 +27,8 @@ void cpu_loop(CPUMBState *env) { CPUState *cs = env_cpu(env); - int trapnr, ret; - target_siginfo_t info; - + int trapnr, ret, si_code; + while (1) { cpu_exec_start(cs); trapnr = cpu_exec(cs); @@ -38,8 +37,8 @@ void cpu_loop(CPUMBState *env) switch (trapnr) { case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ - break; + /* just indicate that signals should be handled asap */ + break; case EXCP_SYSCALL: /* Return address is 4 bytes after the call. */ env->regs[14] += 4; @@ -67,6 +66,7 @@ void cpu_loop(CPUMBState *env) */ env->regs[14] = env->pc; break; + case EXCP_HW_EXCP: env->regs[17] = env->pc + 4; if (env->iflags & D_FLAG) { @@ -74,42 +74,41 @@ void cpu_loop(CPUMBState *env) env->pc -= 4; /* FIXME: if branch was immed, replay the imm as well. */ } - env->iflags &= ~(IMM_FLAG | D_FLAG); - switch (env->esr & 31) { - case ESR_EC_DIVZERO: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_FLTDIV; - info._sifields._sigfault._addr = 0; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; - case ESR_EC_FPU: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - if (env->fsr & FSR_IO) { - info.si_code = TARGET_FPE_FLTINV; - } - if (env->fsr & FSR_DZ) { - info.si_code = TARGET_FPE_FLTDIV; - } - info._sifields._sigfault._addr = 0; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; - default: - fprintf(stderr, "Unhandled hw-exception: 0x%x\n", - env->esr & ESR_EC_MASK); - cpu_dump_state(cs, stderr, 0); - exit(EXIT_FAILURE); - break; + case ESR_EC_DIVZERO: + si_code = TARGET_FPE_INTDIV; + break; + case ESR_EC_FPU: + /* + * Note that the kernel passes along fsr as si_code + * if there's no recognized bit set. Possibly this + * implies that si_code is 0, but follow the structure. + */ + si_code = env->fsr; + if (si_code & FSR_IO) { + si_code = TARGET_FPE_FLTINV; + } else if (si_code & FSR_OF) { + si_code = TARGET_FPE_FLTOVF; + } else if (si_code & FSR_UF) { + si_code = TARGET_FPE_FLTUND; + } else if (si_code & FSR_DZ) { + si_code = TARGET_FPE_FLTDIV; + } else if (si_code & FSR_DO) { + si_code = TARGET_FPE_FLTRES; + } + break; + default: + fprintf(stderr, "Unhandled hw-exception: 0x%x\n", + env->esr & ESR_EC_MASK); + cpu_dump_state(cs, stderr, 0); + exit(EXIT_FAILURE); } + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); break; + case 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->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/microblaze/target_structs.h b/linux-user/microblaze/target_structs.h index d08f6a53a8..3a06f373c3 100644 --- a/linux-user/microblaze/target_structs.h +++ b/linux-user/microblaze/target_structs.h @@ -1,58 +1 @@ -/* - * MicroBlaze specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef MICROBLAZE_TARGET_STRUCTS_H -#define MICROBLAZE_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 32f9fc1c1c..9bb12a07ba 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -40,36 +40,32 @@ enum { BRK_DIVZERO = 7 }; -static int do_break(CPUMIPSState *env, target_siginfo_t *info, - unsigned int code) +static void do_tr_or_bp(CPUMIPSState *env, unsigned int code, bool trap) { - int ret = -1; + target_ulong pc = env->active_tc.PC; switch (code) { case BRK_OVERFLOW: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, pc); + break; case BRK_DIVZERO: - info->si_signo = TARGET_SIGFPE; - info->si_errno = 0; - info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; - queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); - ret = 0; + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, pc); break; default: - info->si_signo = TARGET_SIGTRAP; - info->si_errno = 0; - queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); - ret = 0; + if (trap) { + force_sig(TARGET_SIGTRAP); + } else { + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, pc); + } break; } - - return ret; } void cpu_loop(CPUMIPSState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; - int trapnr; + int trapnr, si_code; + unsigned int code; abi_long ret; # ifdef TARGET_ABI_MIPSO32 unsigned int syscall_num; @@ -160,149 +156,53 @@ done_syscall: break; case EXCP_CpU: case EXCP_RI: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = 0; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + case EXCP_DSPDIS: + force_sig(TARGET_SIGILL); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; case 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); - break; - case EXCP_DSPDIS: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, + env->active_tc.PC); break; case EXCP_FPE: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_FLTUNK; + si_code = TARGET_FPE_FLTUNK; if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { - info.si_code = TARGET_FPE_FLTINV; + si_code = TARGET_FPE_FLTINV; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) { - info.si_code = TARGET_FPE_FLTDIV; + si_code = TARGET_FPE_FLTDIV; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) { - info.si_code = TARGET_FPE_FLTOVF; + si_code = TARGET_FPE_FLTOVF; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) { - info.si_code = TARGET_FPE_FLTUND; + si_code = TARGET_FPE_FLTUND; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) { - info.si_code = TARGET_FPE_FLTRES; + si_code = TARGET_FPE_FLTRES; } - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, si_code, env->active_tc.PC); break; + /* The code below was inspired by the MIPS Linux kernel trap * handling code in arch/mips/kernel/traps.c. */ case EXCP_BREAK: - { - abi_ulong trap_instr; - unsigned int code; - - if (env->hflags & MIPS_HFLAG_M16) { - if (env->insn_flags & ASE_MICROMIPS) { - /* microMIPS mode */ - ret = get_user_u16(trap_instr, env->active_tc.PC); - if (ret != 0) { - goto error; - } - - if ((trap_instr >> 10) == 0x11) { - /* 16-bit instruction */ - code = trap_instr & 0xf; - } else { - /* 32-bit instruction */ - abi_ulong instr_lo; - - ret = get_user_u16(instr_lo, - env->active_tc.PC + 2); - if (ret != 0) { - goto error; - } - trap_instr = (trap_instr << 16) | instr_lo; - code = ((trap_instr >> 6) & ((1 << 20) - 1)); - /* Unfortunately, microMIPS also suffers from - the old assembler bug... */ - if (code >= (1 << 10)) { - code >>= 10; - } - } - } else { - /* MIPS16e mode */ - ret = get_user_u16(trap_instr, env->active_tc.PC); - if (ret != 0) { - goto error; - } - code = (trap_instr >> 6) & 0x3f; - } - } else { - ret = get_user_u32(trap_instr, env->active_tc.PC); - if (ret != 0) { - goto error; - } - - /* As described in the original Linux kernel code, the - * below checks on 'code' are to work around an old - * assembly bug. - */ - code = ((trap_instr >> 6) & ((1 << 20) - 1)); - if (code >= (1 << 10)) { - code >>= 10; - } - } - - if (do_break(env, &info, code) != 0) { - goto error; - } + /* + * As described in the original Linux kernel code, the below + * checks on 'code' are to work around an old assembly bug. + */ + code = env->error_code; + if (code >= (1 << 10)) { + code >>= 10; } + do_tr_or_bp(env, code, false); break; case EXCP_TRAP: - { - abi_ulong trap_instr; - unsigned int code = 0; - - if (env->hflags & MIPS_HFLAG_M16) { - /* microMIPS mode */ - abi_ulong instr[2]; - - ret = get_user_u16(instr[0], env->active_tc.PC) || - get_user_u16(instr[1], env->active_tc.PC + 2); - - trap_instr = (instr[0] << 16) | instr[1]; - } else { - ret = get_user_u32(trap_instr, env->active_tc.PC); - } - - if (ret != 0) { - goto error; - } - - /* The immediate versions don't provide a code. */ - if (!(trap_instr & 0xFC000000)) { - if (env->hflags & MIPS_HFLAG_M16) { - /* microMIPS mode */ - code = ((trap_instr >> 12) & ((1 << 4) - 1)); - } else { - code = ((trap_instr >> 6) & ((1 << 10) - 1)); - } - } - - if (do_break(env, &info, code) != 0) { - goto error; - } - } + do_tr_or_bp(env, env->error_code, true); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); break; default: -error: EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); abort(); } diff --git a/linux-user/nios2/target_structs.h b/linux-user/nios2/target_structs.h index daa2886f98..3a06f373c3 100644 --- a/linux-user/nios2/target_structs.h +++ b/linux-user/nios2/target_structs.h @@ -1,58 +1 @@ -/* - * Nios2 specific structures for linux-user - * - * Copyright (c) 2016 Marek Vasut - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef NIOS2_TARGET_STRUCTS_H -#define NIOS2_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/openrisc/cpu_loop.c b/linux-user/openrisc/cpu_loop.c index 592901a68b..7683bea064 100644 --- a/linux-user/openrisc/cpu_loop.c +++ b/linux-user/openrisc/cpu_loop.c @@ -29,7 +29,6 @@ void cpu_loop(CPUOpenRISCState *env) CPUState *cs = env_cpu(env); int trapnr; abi_long ret; - target_siginfo_t info; for (;;) { cpu_exec_start(cs); @@ -55,27 +54,16 @@ void cpu_loop(CPUOpenRISCState *env) } break; case EXCP_ALIGN: - info.si_signo = TARGET_SIGBUS; - info.si_errno = 0; - info.si_code = TARGET_BUS_ADRALN; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, env->eear); break; case EXCP_ILLEGAL: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case EXCP_INTERRUPT: /* We processed the pending cpu work above. */ break; case 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->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/openrisc/target_structs.h b/linux-user/openrisc/target_structs.h index e98e2bc799..3a06f373c3 100644 --- a/linux-user/openrisc/target_structs.h +++ b/linux-user/openrisc/target_structs.h @@ -1,58 +1 @@ -/* - * OpenRISC specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef OPENRISC_TARGET_STRUCTS_H -#define OPENRISC_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c index 30c82f2354..46e6ffd6d3 100644 --- a/linux-user/ppc/cpu_loop.c +++ b/linux-user/ppc/cpu_loop.c @@ -76,8 +76,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) void cpu_loop(CPUPPCState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; - int trapnr; + int trapnr, si_signo, si_code; target_ulong ret; for(;;) { @@ -102,61 +101,10 @@ void cpu_loop(CPUPPCState *env) "Aborting\n"); break; case POWERPC_EXCP_DSI: /* Data storage exception */ - /* XXX: check this. Seems bugged */ - switch (env->error_code & 0xFF000000) { - case 0x40000000: - case 0x42000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - case 0x04000000: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLADR; - break; - case 0x08000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_ACCERR; - break; - default: - /* Let's send a regular segfault... */ - EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", - env->error_code); - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - } - info._sifields._sigfault._addr = env->spr[SPR_DAR]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_ISI: /* Instruction storage exception */ - /* XXX: check this */ - switch (env->error_code & 0xFF000000) { - case 0x40000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - case 0x10000000: - case 0x08000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_ACCERR; - break; - default: - /* Let's send a regular segfault... */ - EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", - env->error_code); - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - } - info._sifields._sigfault._addr = env->nip - 4; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */ + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, + env->spr[SPR_DAR]); break; case POWERPC_EXCP_EXTERNAL: /* External input */ cpu_abort(cs, "External interrupt while in user mode. " @@ -167,24 +115,23 @@ void cpu_loop(CPUPPCState *env) /* XXX: check this */ switch (env->error_code & ~0xF) { case POWERPC_EXCP_FP: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; + si_signo = TARGET_SIGFPE; switch (env->error_code & 0xF) { case POWERPC_EXCP_FP_OX: - info.si_code = TARGET_FPE_FLTOVF; + si_code = TARGET_FPE_FLTOVF; break; case POWERPC_EXCP_FP_UX: - info.si_code = TARGET_FPE_FLTUND; + si_code = TARGET_FPE_FLTUND; break; case POWERPC_EXCP_FP_ZX: case POWERPC_EXCP_FP_VXZDZ: - info.si_code = TARGET_FPE_FLTDIV; + si_code = TARGET_FPE_FLTDIV; break; case POWERPC_EXCP_FP_XX: - info.si_code = TARGET_FPE_FLTRES; + si_code = TARGET_FPE_FLTRES; break; case POWERPC_EXCP_FP_VXSOFT: - info.si_code = TARGET_FPE_FLTINV; + si_code = TARGET_FPE_FLTINV; break; case POWERPC_EXCP_FP_VXSNAN: case POWERPC_EXCP_FP_VXISI: @@ -193,51 +140,50 @@ void cpu_loop(CPUPPCState *env) case POWERPC_EXCP_FP_VXVC: case POWERPC_EXCP_FP_VXSQRT: case POWERPC_EXCP_FP_VXCVI: - info.si_code = TARGET_FPE_FLTSUB; + si_code = TARGET_FPE_FLTSUB; break; default: EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", env->error_code); + si_code = 0; break; } break; case POWERPC_EXCP_INVAL: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; + si_signo = TARGET_SIGILL; switch (env->error_code & 0xF) { case POWERPC_EXCP_INVAL_INVAL: - info.si_code = TARGET_ILL_ILLOPC; + si_code = TARGET_ILL_ILLOPC; break; case POWERPC_EXCP_INVAL_LSWX: - info.si_code = TARGET_ILL_ILLOPN; + si_code = TARGET_ILL_ILLOPN; break; case POWERPC_EXCP_INVAL_SPR: - info.si_code = TARGET_ILL_PRVREG; + si_code = TARGET_ILL_PRVREG; break; case POWERPC_EXCP_INVAL_FP: - info.si_code = TARGET_ILL_COPROC; + si_code = TARGET_ILL_COPROC; break; default: EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", env->error_code & 0xF); - info.si_code = TARGET_ILL_ILLADR; + si_code = TARGET_ILL_ILLADR; break; } break; case POWERPC_EXCP_PRIV: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; + si_signo = TARGET_SIGILL; switch (env->error_code & 0xF) { case POWERPC_EXCP_PRIV_OPC: - info.si_code = TARGET_ILL_PRVOPC; + si_code = TARGET_ILL_PRVOPC; break; case POWERPC_EXCP_PRIV_REG: - info.si_code = TARGET_ILL_PRVREG; + si_code = TARGET_ILL_PRVREG; break; default: EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", env->error_code & 0xF); - info.si_code = TARGET_ILL_PRVOPC; + si_code = TARGET_ILL_PRVOPC; break; } break; @@ -250,28 +196,19 @@ void cpu_loop(CPUPPCState *env) env->error_code); break; } - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(si_signo, si_code, env->nip); break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ + case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ + case POWERPC_EXCP_VPU: /* Vector unavailable exception */ + force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip); break; case POWERPC_EXCP_SYSCALL: /* System call exception */ case POWERPC_EXCP_SYSCALL_VECTORED: cpu_abort(cs, "Syscall exception while in user mode. " "Aborting\n"); break; - case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_DECR: /* Decrementer exception */ cpu_abort(cs, "Decrementer interrupt while in user mode. " "Aborting\n"); @@ -292,13 +229,6 @@ void cpu_loop(CPUPPCState *env) cpu_abort(cs, "Instruction TLB exception while in user mode. " "Aborting\n"); break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); break; @@ -355,13 +285,6 @@ void cpu_loop(CPUPPCState *env) cpu_abort(cs, "Hypervisor instruction segment exception " "while in user mode. Aborting\n"); break; - case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ cpu_abort(cs, "Programmable interval timer interrupt " "while in user mode. Aborting\n"); @@ -444,10 +367,7 @@ void cpu_loop(CPUPPCState *env) env->gpr[3] = ret; break; case 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->nip); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c index 0cd8985cb8..26d446f323 100644 --- a/linux-user/riscv/cpu_loop.c +++ b/linux-user/riscv/cpu_loop.c @@ -30,8 +30,7 @@ void cpu_loop(CPURISCVState *env) { CPUState *cs = env_cpu(env); - int trapnr, signum, sigcode; - target_ulong sigaddr; + int trapnr; target_ulong ret; for (;;) { @@ -40,10 +39,6 @@ void cpu_loop(CPURISCVState *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 */ @@ -79,39 +74,23 @@ void cpu_loop(CPURISCVState *env) } break; case RISCV_EXCP_ILLEGAL_INST: - signum = TARGET_SIGILL; - sigcode = TARGET_ILL_ILLOPC; + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case RISCV_EXCP_BREAKPOINT: - signum = TARGET_SIGTRAP; - sigcode = TARGET_TRAP_BRKPT; - sigaddr = env->pc; + case EXCP_DEBUG: + gdbstep: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case RISCV_EXCP_SEMIHOST: env->gpr[xA0] = do_common_semihosting(cs); env->pc += 4; break; - case EXCP_DEBUG: - gdbstep: - signum = TARGET_SIGTRAP; - sigcode = TARGET_TRAP_BRKPT; - break; default: EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", 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_FAULT, &info); - } - process_pending_signals(env); } } diff --git a/linux-user/riscv/target_structs.h b/linux-user/riscv/target_structs.h index ea3e5ed17e..3a06f373c3 100644 --- a/linux-user/riscv/target_structs.h +++ b/linux-user/riscv/target_structs.h @@ -1,46 +1 @@ -/* - * RISC-V specific structures for linux-user - * - * This is a copy of ../aarch64/target_structs.h atm. - * - */ -#ifndef RISCV_TARGET_STRUCTS_H -#define RISCV_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c index ad0c3cd263..7901dfe6f5 100644 --- a/linux-user/s390x/cpu_loop.c +++ b/linux-user/s390x/cpu_loop.c @@ -58,7 +58,6 @@ void cpu_loop(CPUS390XState *env) { CPUState *cs = env_cpu(env); int trapnr, n, sig; - target_siginfo_t info; target_ulong addr; abi_long ret; @@ -158,11 +157,7 @@ void cpu_loop(CPUS390XState *env) */ env->psw.addr += env->int_pgm_ilen; do_signal: - info.si_signo = sig; - info.si_errno = 0; - info.si_code = n; - info._sifields._sigfault._addr = addr; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(sig, n, addr); break; case EXCP_ATOMIC: diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c index 3290f6445c..1bd313cb19 100644 --- a/linux-user/sh4/cpu_loop.c +++ b/linux-user/sh4/cpu_loop.c @@ -28,7 +28,6 @@ void cpu_loop(CPUSH4State *env) { CPUState *cs = env_cpu(env); int trapnr, ret; - target_siginfo_t info; while (1) { bool arch_interrupt = true; @@ -60,10 +59,7 @@ void cpu_loop(CPUSH4State *env) /* just indicate that signals should be handled asap */ break; case 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->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/sh4/target_structs.h b/linux-user/sh4/target_structs.h index 00ac39478b..3a06f373c3 100644 --- a/linux-user/sh4/target_structs.h +++ b/linux-user/sh4/target_structs.h @@ -1,58 +1 @@ -/* - * SH4 specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef SH4_TARGET_STRUCTS_H -#define SH4_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index 8765ab6020..baf3d9ae01 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -155,7 +155,6 @@ void cpu_loop (CPUSPARCState *env) CPUState *cs = env_cpu(env); int trapnr; abi_long ret; - target_siginfo_t info; while (1) { cpu_exec_start(cs); @@ -241,19 +240,10 @@ void cpu_loop (CPUSPARCState *env) /* just indicate that signals should be handled asap */ break; case TT_ILL_INSN: - { - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - } + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case 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->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ce9d64896c..5950222a77 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6444,11 +6444,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, int deathsig; ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig, arg3, arg4, arg5)); - if (!is_error(ret) && arg2 && put_user_s32(deathsig, arg2)) { + if (!is_error(ret) && + put_user_s32(host_to_target_signal(deathsig), arg2)) { return -TARGET_EFAULT; } return ret; } + case PR_SET_PDEATHSIG: + return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2), + arg3, arg4, arg5)); case PR_GET_NAME: { void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); @@ -6500,10 +6504,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, case PR_SET_UNALIGN: return do_prctl_set_unalign(env, arg2); + case PR_CAP_AMBIENT: + case PR_CAPBSET_READ: + case PR_CAPBSET_DROP: case PR_GET_DUMPABLE: case PR_SET_DUMPABLE: case PR_GET_KEEPCAPS: case PR_SET_KEEPCAPS: + case PR_GET_SECUREBITS: + case PR_SET_SECUREBITS: case PR_GET_TIMING: case PR_SET_TIMING: case PR_GET_TIMERSLACK: @@ -6927,6 +6936,14 @@ typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr); typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl); #if defined(TARGET_ARM) && TARGET_ABI_BITS == 32 +struct target_oabi_flock64 { + abi_short l_type; + abi_short l_whence; + abi_llong l_start; + abi_llong l_len; + abi_int l_pid; +} QEMU_PACKED; + static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, abi_ulong target_flock_addr) { diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index cca561f622..f23f0a2178 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -688,7 +688,7 @@ typedef struct target_siginfo { #define TARGET_FPE_FLTINV (7) /* floating point invalid operation */ #define TARGET_FPE_FLTSUB (8) /* subscript out of range */ #define TARGET_FPE_FLTUNK (14) /* undiagnosed fp exception */ -#define TARGET_NSIGFPE 15 +#define TARGET_FPE_CONDTRAP (15) /* trap on condition */ /* * SIGSEGV si_codes @@ -715,6 +715,7 @@ typedef struct target_siginfo { #define TARGET_TRAP_TRACE (2) /* process trace trap */ #define TARGET_TRAP_BRANCH (3) /* process taken branch trap */ #define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */ +#define TARGET_TRAP_UNK (5) /* undiagnosed trap */ struct target_rlimit { abi_ulong rlim_cur; diff --git a/linux-user/x86_64/target_structs.h b/linux-user/x86_64/target_structs.h index ce367b253b..f1181383c4 100644 --- a/linux-user/x86_64/target_structs.h +++ b/linux-user/x86_64/target_structs.h @@ -19,41 +19,7 @@ #ifndef X86_64_TARGET_STRUCTS_H #define X86_64_TARGET_STRUCTS_H -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; +#include "../generic/target_structs.h" /* The x86 definition differs from the generic one in that the * two padding fields exist whether the ABI is 32 bits or 64 bits. diff --git a/linux-user/xtensa/cpu_loop.c b/linux-user/xtensa/cpu_loop.c index 6bc6d6dee6..d51ce05392 100644 --- a/linux-user/xtensa/cpu_loop.c +++ b/linux-user/xtensa/cpu_loop.c @@ -126,7 +126,6 @@ static void xtensa_underflow12(CPUXtensaState *env) void cpu_loop(CPUXtensaState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; abi_ulong ret; int trapnr; @@ -163,14 +162,12 @@ void cpu_loop(CPUXtensaState *env) case EXC_USER: switch (env->sregs[EXCCAUSE]) { case ILLEGAL_INSTRUCTION_CAUSE: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, + env->sregs[EPC1]); + break; case PRIVILEGED_CAUSE: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = - env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ? - TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC; - info._sifields._sigfault._addr = env->sregs[EPC1]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, + env->sregs[EPC1]); break; case SYSCALL_CAUSE: @@ -219,11 +216,8 @@ void cpu_loop(CPUXtensaState *env) break; case INTEGER_DIVIDE_BY_ZERO_CAUSE: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_INTDIV; - info._sifields._sigfault._addr = env->sregs[EPC1]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, + env->sregs[EPC1]); break; default: @@ -232,10 +226,8 @@ void cpu_loop(CPUXtensaState *env) } break; case 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->sregs[EPC1]); break; case EXC_DEBUG: default: diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc index 0760941431..fc6ede75b8 100644 --- a/target/mips/tcg/micromips_translate.c.inc +++ b/target/mips/tcg/micromips_translate.c.inc @@ -822,7 +822,7 @@ static void gen_pool16c_insn(DisasContext *ctx) gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); break; case BREAK16: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 0, 4)); break; case SDBBP16: if (is_uhi(extract32(ctx->opcode, 0, 4))) { @@ -937,7 +937,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx) break; case R6_BREAK16: /* BREAK16 */ - generate_exception(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 6, 4)); break; case R6_SDBBP16: /* SDBBP16 */ @@ -1047,7 +1047,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) case TNE: mips32_op = OPC_TNE; do_trap: - gen_trap(ctx, mips32_op, rs, rt, -1); + gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4)); break; #ifndef CONFIG_USER_ONLY case MFC0: @@ -1812,7 +1812,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) gen_pool32axf(env, ctx, rt, rs); break; case BREAK32: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 6, 20)); break; case SIGRIE: check_insn(ctx, ISA_MIPS_R6); @@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS_R6); mips32_op = OPC_TEQI; do_trapi: - gen_trap(ctx, mips32_op, rs, -1, imm); + gen_trap(ctx, mips32_op, rs, -1, imm, 0); break; case BNEZC: diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips16e_translate.c.inc index 84d816603a..f57e0a5f2a 100644 --- a/target/mips/tcg/mips16e_translate.c.inc +++ b/target/mips/tcg/mips16e_translate.c.inc @@ -969,7 +969,7 @@ static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx) gen_slt(ctx, OPC_SLTU, 24, rx, ry); break; case RR_BREAK: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 5, 6)); break; case RR_SLLV: gen_shift(ctx, OPC_SLLV, ry, rx, ry); diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 2c022a49f2..916cece4d2 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -1268,11 +1268,11 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) switch (extract32(ctx->opcode, 10, 1)) { case NM_TEQ: check_nms(ctx); - gen_trap(ctx, OPC_TEQ, rs, rt, -1); + gen_trap(ctx, OPC_TEQ, rs, rt, -1, rd); break; case NM_TNE: check_nms(ctx); - gen_trap(ctx, OPC_TNE, rs, rt, -1); + gen_trap(ctx, OPC_TNE, rs, rt, -1, rd); break; } break; diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 1c2264417c..b82a7ec6ad 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1367,6 +1367,16 @@ void generate_exception_end(DisasContext *ctx, int excp) generate_exception_err(ctx, excp, 0); } +void generate_exception_break(DisasContext *ctx, int code) +{ +#ifdef CONFIG_USER_ONLY + /* Pass the break code along to cpu_loop. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUMIPSState, error_code)); +#endif + generate_exception_end(ctx, EXCP_BREAK); +} + void gen_reserved_instruction(DisasContext *ctx) { generate_exception_end(ctx, EXCP_RI); @@ -4723,7 +4733,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt, /* Traps */ static void gen_trap(DisasContext *ctx, uint32_t opc, - int rs, int rt, int16_t imm) + int rs, int rt, int16_t imm, int code) { int cond; TCGv t0 = tcg_temp_new(); @@ -4768,6 +4778,11 @@ static void gen_trap(DisasContext *ctx, uint32_t opc, case OPC_TGEU: /* rs >= rs unsigned */ case OPC_TGEIU: /* r0 >= 0 unsigned */ /* Always trap */ +#ifdef CONFIG_USER_ONLY + /* Pass the break code along to cpu_loop. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUMIPSState, error_code)); +#endif generate_exception_end(ctx, EXCP_TRAP); break; case OPC_TLT: /* rs < rs */ @@ -4808,6 +4823,18 @@ static void gen_trap(DisasContext *ctx, uint32_t opc, tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1); break; } +#ifdef CONFIG_USER_ONLY + /* Pass the break code along to cpu_loop. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUMIPSState, error_code)); +#endif + /* Like save_cpu_state, only don't update saved values. */ + if (ctx->base.pc_next != ctx->saved_pc) { + gen_save_pc(ctx->base.pc_next); + } + if (ctx->hflags != ctx->saved_hflags) { + tcg_gen_movi_i32(hflags, ctx->hflags); + } generate_exception(ctx, EXCP_TRAP); gen_set_label(l1); } @@ -14145,7 +14172,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) case OPC_TEQ: case OPC_TNE: check_insn(ctx, ISA_MIPS2); - gen_trap(ctx, op1, rs, rt, -1); + gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10)); break; case OPC_PMON: /* Pmon entry point, also R4010 selsl */ @@ -14160,7 +14187,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) generate_exception_end(ctx, EXCP_SYSCALL); break; case OPC_BREAK: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 6, 20)); break; case OPC_SYNC: check_insn(ctx, ISA_MIPS2); @@ -15279,11 +15306,10 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_TLTI: case OPC_TLTIU: case OPC_TEQI: - case OPC_TNEI: check_insn(ctx, ISA_MIPS2); check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_trap(ctx, op1, rs, -1, imm); + gen_trap(ctx, op1, rs, -1, imm, 0); break; case OPC_SIGRIE: check_insn(ctx, ISA_MIPS_R6); diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 6111493651..ae01515efe 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -129,6 +129,7 @@ enum { void generate_exception(DisasContext *ctx, int excp); void generate_exception_err(DisasContext *ctx, int excp, int err); void generate_exception_end(DisasContext *ctx, int excp); +void generate_exception_break(DisasContext *ctx, int code); void gen_reserved_instruction(DisasContext *ctx); void check_insn(DisasContext *ctx, uint64_t flags);