From 48c8c5e8862431235ec5ab553977ee5fe6ffbba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 3 Mar 2021 22:46:57 +0100 Subject: [PATCH 01/59] linux-user: Remove dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can not use watchpoints in user-mode emulation because we need the softmmu slow path to detect accesses to watchpointed memory. This code is expanded as empty stub in "hw/core/cpu.h" anyway, so we can drop it. Reviewed-by: Laurent Vivier Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210303214708.1727801-18-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/main.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 7995b6e7a6..4dfc47ad3b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -205,7 +205,6 @@ CPUArchState *cpu_copy(CPUArchState *env) CPUState *new_cpu = cpu_create(cpu_type); CPUArchState *new_env = new_cpu->env_ptr; CPUBreakpoint *bp; - CPUWatchpoint *wp; /* Reset non arch specific state */ cpu_reset(new_cpu); @@ -217,13 +216,9 @@ CPUArchState *cpu_copy(CPUArchState *env) Note: Once we support ptrace with hw-debug register access, make sure BP_CPU break/watchpoints are handled correctly on clone. */ QTAILQ_INIT(&new_cpu->breakpoints); - QTAILQ_INIT(&new_cpu->watchpoints); QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); } - QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { - cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); - } return new_env; } From 5847d3098d92851015e0f0c868e1305103feae02 Mon Sep 17 00:00:00 2001 From: Matus Kysel Date: Tue, 6 Apr 2021 14:42:03 +0000 Subject: [PATCH 02/59] linux-user: strace now handles unshare syscall args correctly Syscall unshare did not have custom print function for strace, but it's argument is same as flags in clone syscall, so it can be easily implemented. Also updated missing flags from clone_flags. Signed-off-by: Matus Kysel Reviewed-by: Laurent Vivier Message-Id: <20210406144203.1020598-1-mkysel@tachyum.com> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 18 ++++++++++++++++++ linux-user/strace.list | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index e969121b6c..1cadb6d50f 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1109,6 +1109,12 @@ UNUSED static struct flags clone_flags[] = { #if defined(CLONE_NEWNET) FLAG_GENERIC(CLONE_NEWNET), #endif +#if defined(CLONE_NEWCGROUP) + FLAG_GENERIC(CLONE_NEWCGROUP), +#endif +#if defined(CLONE_NEWTIME) + FLAG_GENERIC(CLONE_NEWTIME), +#endif #if defined(CLONE_IO) FLAG_GENERIC(CLONE_IO), #endif @@ -3467,6 +3473,18 @@ print_unlinkat(void *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_unshare +static void +print_unshare(void *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_flags(clone_flags, arg0, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_utime static void print_utime(void *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index 084048ab96..3b7c15578c 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1573,7 +1573,7 @@ { TARGET_NR_unlinkat, "unlinkat" , NULL, print_unlinkat, NULL }, #endif #ifdef TARGET_NR_unshare -{ TARGET_NR_unshare, "unshare" , NULL, NULL, NULL }, +{ TARGET_NR_unshare, "unshare" , NULL, print_unshare, NULL }, #endif #ifdef TARGET_NR_userfaultfd { TARGET_NR_userfaultfd, "userfaultfd" , NULL, NULL, NULL }, From c1438d6c02eae03cc387dbdf2f30c11f45894954 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 23 Apr 2021 09:54:10 -0700 Subject: [PATCH 03/59] linux-user/arm: Split out emulate_arm_fpa11 Pull out the fpa11 emulation to a helper function. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-Id: <20210423165413.338259-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/arm/cpu_loop.c | 153 +++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 59 deletions(-) diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 989d03cd89..106909c7d8 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -224,6 +224,92 @@ static bool insn_is_linux_bkpt(uint32_t opcode, bool is_thumb) } } +static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) +{ + TaskState *ts = env_cpu(env)->opaque; + int rc = EmulateAll(opcode, &ts->fpa, env); + + if (rc == 0) { + /* Illegal instruction */ + return false; + } + if (rc > 0) { + /* Everything ok. */ + env->regs[15] += 4; + return true; + } + + /* FP exception */ + int arm_fpe = 0; + + /* Translate softfloat flags to FPSR flags */ + if (-rc & float_flag_invalid) { + arm_fpe |= BIT_IOC; + } + if (-rc & float_flag_divbyzero) { + arm_fpe |= BIT_DZC; + } + if (-rc & float_flag_overflow) { + arm_fpe |= BIT_OFC; + } + if (-rc & float_flag_underflow) { + arm_fpe |= BIT_UFC; + } + if (-rc & float_flag_inexact) { + arm_fpe |= BIT_IXC; + } + + /* Exception enabled? */ + FPSR fpsr = ts->fpa.fpsr; + if (fpsr & (arm_fpe << 16)) { + target_siginfo_t info; + + info.si_signo = TARGET_SIGFPE; + info.si_errno = 0; + + /* ordered by priority, least first */ + if (arm_fpe & BIT_IXC) { + info.si_code = TARGET_FPE_FLTRES; + } + if (arm_fpe & BIT_UFC) { + info.si_code = TARGET_FPE_FLTUND; + } + if (arm_fpe & BIT_OFC) { + info.si_code = TARGET_FPE_FLTOVF; + } + if (arm_fpe & BIT_DZC) { + info.si_code = TARGET_FPE_FLTDIV; + } + if (arm_fpe & BIT_IOC) { + info.si_code = TARGET_FPE_FLTINV; + } + + info._sifields._sigfault._addr = env->regs[15]; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + } else { + env->regs[15] += 4; + } + + /* Accumulate unenabled exceptions */ + if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) { + fpsr |= BIT_IXC; + } + if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) { + fpsr |= BIT_UFC; + } + if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) { + fpsr |= BIT_OFC; + } + if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) { + fpsr |= BIT_DZC; + } + if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) { + fpsr |= BIT_IOC; + } + ts->fpa.fpsr = fpsr; + return true; +} + void cpu_loop(CPUARMState *env) { CPUState *cs = env_cpu(env); @@ -244,9 +330,7 @@ void cpu_loop(CPUARMState *env) case EXCP_NOCP: case EXCP_INVSTATE: { - TaskState *ts = cs->opaque; uint32_t opcode; - int rc; /* we handle the FPU emulation here, as Linux */ /* we get the opcode */ @@ -263,64 +347,15 @@ void cpu_loop(CPUARMState *env) goto excp_debug; } - rc = EmulateAll(opcode, &ts->fpa, env); - if (rc == 0) { /* illegal instruction */ - 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); - } else if (rc < 0) { /* FP exception */ - int arm_fpe=0; - - /* translate softfloat flags to FPSR flags */ - if (-rc & float_flag_invalid) - arm_fpe |= BIT_IOC; - if (-rc & float_flag_divbyzero) - arm_fpe |= BIT_DZC; - if (-rc & float_flag_overflow) - arm_fpe |= BIT_OFC; - if (-rc & float_flag_underflow) - arm_fpe |= BIT_UFC; - if (-rc & float_flag_inexact) - arm_fpe |= BIT_IXC; - - FPSR fpsr = ts->fpa.fpsr; - //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); - - if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - - /* ordered by priority, least first */ - if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; - if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; - if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; - if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; - if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; - - info._sifields._sigfault._addr = env->regs[15]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - } else { - env->regs[15] += 4; - } - - /* accumulate unenabled exceptions */ - if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) - fpsr |= BIT_IXC; - if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) - fpsr |= BIT_UFC; - if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) - fpsr |= BIT_OFC; - if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) - fpsr |= BIT_DZC; - if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) - fpsr |= BIT_IOC; - ts->fpa.fpsr=fpsr; - } else { /* everything OK */ - /* increment PC */ - env->regs[15] += 4; + if (emulate_arm_fpa11(env, opcode)) { + 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); } break; case EXCP_SWI: From d827f6d5fdb0826e17c80f63547c5c2dee3f0fac Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 23 Apr 2021 09:54:11 -0700 Subject: [PATCH 04/59] linux-user/arm: Do not emulate fpa11 in thumb mode These antiquated instructions are arm-mode only. Buglink: https://bugs.launchpad.net/bugs/1925512 Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-Id: <20210423165413.338259-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/arm/cpu_loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 106909c7d8..e2a1496b9f 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -347,7 +347,7 @@ void cpu_loop(CPUARMState *env) goto excp_debug; } - if (emulate_arm_fpa11(env, opcode)) { + if (!env->thumb && emulate_arm_fpa11(env, opcode)) { break; } From 0a50285ee8bf471936325f5ccd870752d2a038cb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 23 Apr 2021 09:54:12 -0700 Subject: [PATCH 05/59] linux-user/arm: Do not fill in si_code for fpa11 exceptions There is no such decoding in linux/arch/arm/nwfpe/fpmodule.c. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-Id: <20210423165413.338259-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/arm/cpu_loop.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index e2a1496b9f..5f61d25717 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -262,29 +262,15 @@ static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) /* Exception enabled? */ FPSR fpsr = ts->fpa.fpsr; if (fpsr & (arm_fpe << 16)) { - target_siginfo_t info; + target_siginfo_t info = { }; + /* + * The kernel's nwfpe emulator does not pass a real si_code. + * It merely uses send_sig(SIGFPE, current, 1). + */ info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; + info.si_code = TARGET_SI_KERNEL; - /* ordered by priority, least first */ - if (arm_fpe & BIT_IXC) { - info.si_code = TARGET_FPE_FLTRES; - } - if (arm_fpe & BIT_UFC) { - info.si_code = TARGET_FPE_FLTUND; - } - if (arm_fpe & BIT_OFC) { - info.si_code = TARGET_FPE_FLTOVF; - } - if (arm_fpe & BIT_DZC) { - info.si_code = TARGET_FPE_FLTDIV; - } - if (arm_fpe & BIT_IOC) { - info.si_code = TARGET_FPE_FLTINV; - } - - info._sifields._sigfault._addr = env->regs[15]; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); } else { env->regs[15] += 4; From 74081ae0ff4aea6ad0db0427ed31ac5250a58b3f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 23 Apr 2021 09:54:13 -0700 Subject: [PATCH 06/59] linux-user/arm: Simplify accumulating and raising fpa11 exceptions Use bit masking instead of an if tree. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-Id: <20210423165413.338259-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/arm/cpu_loop.c | 50 ++++++++++++++------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 5f61d25717..69632d15be 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -228,6 +228,7 @@ static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) { TaskState *ts = env_cpu(env)->opaque; int rc = EmulateAll(opcode, &ts->fpa, env); + int raise, enabled; if (rc == 0) { /* Illegal instruction */ @@ -240,28 +241,31 @@ static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) } /* FP exception */ - int arm_fpe = 0; + rc = -rc; + raise = 0; /* Translate softfloat flags to FPSR flags */ - if (-rc & float_flag_invalid) { - arm_fpe |= BIT_IOC; + if (rc & float_flag_invalid) { + raise |= BIT_IOC; } - if (-rc & float_flag_divbyzero) { - arm_fpe |= BIT_DZC; + if (rc & float_flag_divbyzero) { + raise |= BIT_DZC; } - if (-rc & float_flag_overflow) { - arm_fpe |= BIT_OFC; + if (rc & float_flag_overflow) { + raise |= BIT_OFC; } - if (-rc & float_flag_underflow) { - arm_fpe |= BIT_UFC; + if (rc & float_flag_underflow) { + raise |= BIT_UFC; } - if (-rc & float_flag_inexact) { - arm_fpe |= BIT_IXC; + if (rc & float_flag_inexact) { + raise |= BIT_IXC; } - /* Exception enabled? */ - FPSR fpsr = ts->fpa.fpsr; - if (fpsr & (arm_fpe << 16)) { + /* Accumulate unenabled exceptions */ + enabled = ts->fpa.fpsr >> 16; + ts->fpa.fpsr |= raise & ~enabled; + + if (raise & enabled) { target_siginfo_t info = { }; /* @@ -275,24 +279,6 @@ static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) } else { env->regs[15] += 4; } - - /* Accumulate unenabled exceptions */ - if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) { - fpsr |= BIT_IXC; - } - if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) { - fpsr |= BIT_UFC; - } - if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) { - fpsr |= BIT_OFC; - } - if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) { - fpsr |= BIT_DZC; - } - if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) { - fpsr |= BIT_IOC; - } - ts->fpa.fpsr = fpsr; return true; } From 9f771ad8399d5832a99564919379ab29c1bbbdce Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Wed, 12 May 2021 18:13:58 +0800 Subject: [PATCH 07/59] linux-user: Add strace support for printing arguments of llseek Some target are using llseek instead of _llseek like riscv, nios2, hexagon, and openrisc. Signed-off-by: Kito Cheng Reviewed-by: Laurent Vivier Message-Id: <20210512101358.122781-1-kito.cheng@sifive.com> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 3 ++- linux-user/strace.list | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 1cadb6d50f..cce0a5d1e3 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -2341,7 +2341,7 @@ print_linkat(void *cpu_env, const struct syscallname *name, } #endif -#ifdef TARGET_NR__llseek +#if defined(TARGET_NR__llseek) || defined(TARGET_NR_llseek) static void print__llseek(void *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, @@ -2361,6 +2361,7 @@ print__llseek(void *cpu_env, const struct syscallname *name, qemu_log("%s", whence); print_syscall_epilogue(name); } +#define print_llseek print__llseek #endif #ifdef TARGET_NR_lseek diff --git a/linux-user/strace.list b/linux-user/strace.list index 3b7c15578c..18f7217275 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -511,6 +511,9 @@ #ifdef TARGET_NR__llseek { TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL }, #endif +#ifdef TARGET_NR_llseek +{ TARGET_NR_llseek, "llseek" , NULL, print_llseek, NULL }, +#endif #ifdef TARGET_NR_lock { TARGET_NR_lock, "lock" , NULL, NULL, NULL }, #endif From 92bad948367c4b8a58f6bb81b45750f1d583f274 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:10 -0700 Subject: [PATCH 08/59] linux-user: Split out target_restore_altstack Create a function to match target_save_altstack. Fix some style and unlock issues in do_sigaltstack. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/signal-common.h | 1 + linux-user/signal.c | 115 +++++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 1df1068552..34b963af9a 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -24,6 +24,7 @@ int on_sig_stack(unsigned long sp); int sas_ss_flags(unsigned long sp); abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka); void target_save_altstack(target_stack_t *uss, CPUArchState *env); +abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp); static inline void target_sigemptyset(target_sigset_t *set) { diff --git a/linux-user/signal.c b/linux-user/signal.c index 7eecec46c4..9daa89eac5 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -297,6 +297,50 @@ void target_save_altstack(target_stack_t *uss, CPUArchState *env) __put_user(ts->sigaltstack_used.ss_size, &uss->ss_size); } +abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp) +{ + TaskState *ts = (TaskState *)thread_cpu->opaque; + size_t minstacksize = TARGET_MINSIGSTKSZ; + target_stack_t ss; + +#if defined(TARGET_PPC64) + /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */ + struct image_info *image = ts->info; + if (get_ppc64_abi(image) > 1) { + minstacksize = 4096; + } +#endif + + __get_user(ss.ss_sp, &uss->ss_sp); + __get_user(ss.ss_size, &uss->ss_size); + __get_user(ss.ss_flags, &uss->ss_flags); + + if (on_sig_stack(sp)) { + return -TARGET_EPERM; + } + + switch (ss.ss_flags) { + default: + return -TARGET_EINVAL; + + case TARGET_SS_DISABLE: + ss.ss_size = 0; + ss.ss_sp = 0; + break; + + case TARGET_SS_ONSTACK: + case 0: + if (ss.ss_size < minstacksize) { + return -TARGET_ENOMEM; + } + break; + } + + ts->sigaltstack_used.ss_sp = ss.ss_sp; + ts->sigaltstack_used.ss_size = ss.ss_size; + return 0; +} + /* siginfo conversion */ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, @@ -758,73 +802,44 @@ static void host_signal_handler(int host_signum, siginfo_t *info, /* compare linux/kernel/signal.c:do_sigaltstack() */ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) { - int ret; - struct target_sigaltstack oss; - TaskState *ts = (TaskState *)thread_cpu->opaque; + target_stack_t oss, *uoss = NULL; + abi_long ret = -TARGET_EFAULT; - /* XXX: test errors */ - if(uoss_addr) - { + if (uoss_addr) { + TaskState *ts = (TaskState *)thread_cpu->opaque; + + /* Verify writability now, but do not alter user memory yet. */ + if (!lock_user_struct(VERIFY_WRITE, uoss, uoss_addr, 0)) { + goto out; + } __put_user(ts->sigaltstack_used.ss_sp, &oss.ss_sp); __put_user(ts->sigaltstack_used.ss_size, &oss.ss_size); __put_user(sas_ss_flags(sp), &oss.ss_flags); } - if(uss_addr) - { - struct target_sigaltstack *uss; - struct target_sigaltstack ss; - size_t minstacksize = TARGET_MINSIGSTKSZ; + if (uss_addr) { + target_stack_t *uss; -#if defined(TARGET_PPC64) - /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */ - struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; - if (get_ppc64_abi(image) > 1) { - minstacksize = 4096; - } -#endif - - ret = -TARGET_EFAULT; if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { goto out; } - __get_user(ss.ss_sp, &uss->ss_sp); - __get_user(ss.ss_size, &uss->ss_size); - __get_user(ss.ss_flags, &uss->ss_flags); - unlock_user_struct(uss, uss_addr, 0); - - ret = -TARGET_EPERM; - if (on_sig_stack(sp)) + ret = target_restore_altstack(uss, sp); + if (ret) { goto out; - - ret = -TARGET_EINVAL; - if (ss.ss_flags != TARGET_SS_DISABLE - && ss.ss_flags != TARGET_SS_ONSTACK - && ss.ss_flags != 0) - goto out; - - if (ss.ss_flags == TARGET_SS_DISABLE) { - ss.ss_size = 0; - ss.ss_sp = 0; - } else { - ret = -TARGET_ENOMEM; - if (ss.ss_size < minstacksize) { - goto out; - } } - - ts->sigaltstack_used.ss_sp = ss.ss_sp; - ts->sigaltstack_used.ss_size = ss.ss_size; } if (uoss_addr) { - ret = -TARGET_EFAULT; - if (copy_to_user(uoss_addr, &oss, sizeof(oss))) - goto out; + memcpy(uoss, &oss, sizeof(oss)); + unlock_user_struct(uoss, uoss_addr, 1); + uoss = NULL; } - ret = 0; -out: + + out: + if (uoss) { + unlock_user_struct(uoss, uoss_addr, 0); + } return ret; } From 56384cf3adaeb15bab479be328605e301ae253f2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:11 -0700 Subject: [PATCH 09/59] linux-user: Use target_restore_altstack in all sigreturn Note that target_restore_altstack uses the host memory pointer that we have already verified, so TARGET_EFAULT is not a possible return value. Note that using -EFAULT was a bug. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/aarch64/signal.c | 6 +----- linux-user/alpha/signal.c | 6 +----- linux-user/arm/signal.c | 9 ++------- linux-user/hexagon/signal.c | 6 +----- linux-user/hppa/signal.c | 8 +------- linux-user/i386/signal.c | 5 +---- linux-user/m68k/signal.c | 5 +---- linux-user/microblaze/signal.c | 6 +----- linux-user/mips/signal.c | 6 +----- linux-user/nios2/signal.c | 8 +------- linux-user/openrisc/signal.c | 5 +---- linux-user/ppc/signal.c | 4 +--- linux-user/riscv/signal.c | 6 +----- linux-user/s390x/signal.c | 6 ++---- linux-user/sh4/signal.c | 7 +------ linux-user/xtensa/signal.c | 6 +----- 16 files changed, 18 insertions(+), 81 deletions(-) diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index b591790c22..2a1b7dbcdc 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -561,11 +561,7 @@ long do_rt_sigreturn(CPUARMState *env) goto badframe; } - if (do_sigaltstack(frame_addr + - offsetof(struct target_rt_sigframe, uc.tuc_stack), - 0, get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/alpha/signal.c b/linux-user/alpha/signal.c index c5c27ce084..0af0227118 100644 --- a/linux-user/alpha/signal.c +++ b/linux-user/alpha/signal.c @@ -257,11 +257,7 @@ long do_rt_sigreturn(CPUAlphaState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, - uc.tuc_stack), - 0, env->ir[IR_SP]) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, env->ir[IR_SP]); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index f21d1535e4..b7a772302f 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -685,11 +685,7 @@ static int do_sigframe_return_v2(CPUARMState *env, } } - if (do_sigaltstack(context_addr - + offsetof(struct target_ucontext_v2, tuc_stack), - 0, get_sp_from_cpustate(env)) == -EFAULT) { - return 1; - } + target_restore_altstack(&uc->tuc_stack, get_sp_from_cpustate(env)); #if 0 /* Send SIGTRAP if we're single-stepping */ @@ -773,8 +769,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env) goto badframe; } - if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) - goto badframe; + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); #if 0 /* Send SIGTRAP if we're single-stepping */ diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c index fde8dc93b7..3854eb4709 100644 --- a/linux-user/hexagon/signal.c +++ b/linux-user/hexagon/signal.c @@ -260,11 +260,7 @@ long do_rt_sigreturn(CPUHexagonState *env) } restore_ucontext(env, &frame->uc); - - if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, - uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.uc_stack, get_sp_from_cpustate(env)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index d1a58feeb3..578874cf27 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -187,13 +187,7 @@ long do_rt_sigreturn(CPUArchState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - unlock_user_struct(frame, frame_addr, 0); - - if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, - uc.tuc_stack), - 0, env->gr[30]) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, env->gr[30]); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c index 9320e1d472..3a0a1546a6 100644 --- a/linux-user/i386/signal.c +++ b/linux-user/i386/signal.c @@ -581,10 +581,7 @@ long do_rt_sigreturn(CPUX86State *env) goto badframe; } - if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, - get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/m68k/signal.c b/linux-user/m68k/signal.c index 49ff87c77b..004b59fb61 100644 --- a/linux-user/m68k/signal.c +++ b/linux-user/m68k/signal.c @@ -400,10 +400,7 @@ long do_rt_sigreturn(CPUM68KState *env) if (target_rt_restore_ucontext(env, &frame->uc)) goto badframe; - if (do_sigaltstack(frame_addr + - offsetof(struct target_rt_sigframe, uc.tuc_stack), - 0, get_sp_from_cpustate(env)) == -EFAULT) - goto badframe; + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c index cf0707b556..f59a1faf47 100644 --- a/linux-user/microblaze/signal.c +++ b/linux-user/microblaze/signal.c @@ -209,11 +209,7 @@ long do_rt_sigreturn(CPUMBState *env) restore_sigcontext(&frame->uc.tuc_mcontext, env); - if (do_sigaltstack(frame_addr + - offsetof(struct target_rt_sigframe, uc.tuc_stack), - 0, get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c index 455a8a229a..456fa64f41 100644 --- a/linux-user/mips/signal.c +++ b/linux-user/mips/signal.c @@ -368,11 +368,7 @@ long do_rt_sigreturn(CPUMIPSState *env) set_sigmask(&blocked); restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); - - if (do_sigaltstack(frame_addr + - offsetof(struct target_rt_sigframe, rs_uc.tuc_stack), - 0, get_sp_from_cpustate(env)) == -EFAULT) - goto badframe; + target_restore_altstack(&frame->rs_uc.tuc_stack, get_sp_from_cpustate(env)); env->active_tc.PC = env->CP0_EPC; mips_set_hflags_isa_mode_from_pc(env); diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index 7d535065ed..751ea88811 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -82,9 +82,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, int *pr2) { int temp; - abi_ulong off, frame_addr = env->regs[R_SP]; unsigned long *gregs = uc->tuc_mcontext.gregs; - int err; /* Always make any pending restarted system calls return -EINTR */ /* current->restart_block.fn = do_no_restart_syscall; */ @@ -130,11 +128,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, __get_user(env->regs[R_RA], &gregs[23]); __get_user(env->regs[R_SP], &gregs[28]); - off = offsetof(struct target_rt_sigframe, uc.tuc_stack); - err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env)); - if (err == -EFAULT) { - return 1; - } + target_restore_altstack(&uc->tuc_stack, get_sp_from_cpustate(env)); *pr2 = env->regs[2]; return 0; diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c index 232ad82b98..86f94d7f76 100644 --- a/linux-user/openrisc/signal.c +++ b/linux-user/openrisc/signal.c @@ -158,10 +158,7 @@ long do_rt_sigreturn(CPUOpenRISCState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - if (do_sigaltstack(frame_addr + offsetof(target_rt_sigframe, uc.tuc_stack), - 0, frame_addr) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, frame_addr); unlock_user_struct(frame, frame_addr, 0); return cpu_get_gpr(env, 11); diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c index bad38f8ed9..b44d5ce73c 100644 --- a/linux-user/ppc/signal.c +++ b/linux-user/ppc/signal.c @@ -655,9 +655,7 @@ long do_rt_sigreturn(CPUPPCState *env) if (do_setcontext(&rt_sf->uc, env, 1)) goto sigsegv; - do_sigaltstack(rt_sf_addr - + offsetof(struct target_rt_sigframe, uc.tuc_stack), - 0, env->gpr[1]); + target_restore_altstack(&rt_sf->uc.tuc_stack, env->gpr[1]); unlock_user_struct(rt_sf, rt_sf_addr, 1); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index 67a95dbc7b..81d1129da3 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -192,11 +192,7 @@ long do_rt_sigreturn(CPURISCVState *env) } restore_ucontext(env, &frame->uc); - - if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, - uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.uc_stack, get_sp_from_cpustate(env)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 7107c5fb53..73806f5472 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -307,10 +307,8 @@ long do_rt_sigreturn(CPUS390XState *env) goto badframe; } - if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0, - get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c index 29c1ee30e6..684f18da58 100644 --- a/linux-user/sh4/signal.c +++ b/linux-user/sh4/signal.c @@ -323,12 +323,7 @@ long do_rt_sigreturn(CPUSH4State *regs) set_sigmask(&blocked); restore_sigcontext(regs, &frame->uc.tuc_mcontext); - - if (do_sigaltstack(frame_addr + - offsetof(struct target_rt_sigframe, uc.tuc_stack), - 0, get_sp_from_cpustate(regs)) == -EFAULT) { - goto badframe; - } + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(regs)); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 590f0313ff..22ec6cdeb9 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -253,12 +253,8 @@ long do_rt_sigreturn(CPUXtensaState *env) set_sigmask(&set); restore_sigcontext(env, frame); + target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); - if (do_sigaltstack(frame_addr + - offsetof(struct target_rt_sigframe, uc.tuc_stack), - 0, get_sp_from_cpustate(env)) == -TARGET_EFAULT) { - goto badframe; - } unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; From 6b2087550345e87320f777c4db8254323d0d4123 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:12 -0700 Subject: [PATCH 10/59] linux-user: Pass CPUArchState to do_sigaltstack Now that we have exactly one call, it's easy to pass in env instead of passing in the sp value. Use target_save_altstack, which required env. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/qemu.h | 3 ++- linux-user/signal.c | 11 ++++------- linux-user/syscall.c | 3 +-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 74e06e7121..3b0b6b75fe 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -432,7 +432,8 @@ int target_to_host_signal(int sig); int host_to_target_signal(int sig); long do_sigreturn(CPUArchState *env); long do_rt_sigreturn(CPUArchState *env); -abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, + CPUArchState *env); int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx, abi_ulong unew_ctx, abi_long ctx_size); diff --git a/linux-user/signal.c b/linux-user/signal.c index 9daa89eac5..2e1095055b 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -800,21 +800,18 @@ static void host_signal_handler(int host_signum, siginfo_t *info, /* do_sigaltstack() returns target values and errnos. */ /* compare linux/kernel/signal.c:do_sigaltstack() */ -abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, + CPUArchState *env) { target_stack_t oss, *uoss = NULL; abi_long ret = -TARGET_EFAULT; if (uoss_addr) { - TaskState *ts = (TaskState *)thread_cpu->opaque; - /* Verify writability now, but do not alter user memory yet. */ if (!lock_user_struct(VERIFY_WRITE, uoss, uoss_addr, 0)) { goto out; } - __put_user(ts->sigaltstack_used.ss_sp, &oss.ss_sp); - __put_user(ts->sigaltstack_used.ss_size, &oss.ss_size); - __put_user(sas_ss_flags(sp), &oss.ss_flags); + target_save_altstack(&oss, env); } if (uss_addr) { @@ -823,7 +820,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { goto out; } - ret = target_restore_altstack(uss, sp); + ret = target_restore_altstack(uss, get_sp_from_cpustate(env)); if (ret) { goto out; } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 95d79ddc43..4d52b2cfe3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11195,8 +11195,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } case TARGET_NR_sigaltstack: - return do_sigaltstack(arg1, arg2, - get_sp_from_cpustate((CPUArchState *)cpu_env)); + return do_sigaltstack(arg1, arg2, cpu_env); #ifdef CONFIG_SENDFILE #ifdef TARGET_NR_sendfile From ddc3e74d9c5ac76562ce8abe9e5908c4ff7cb8f0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:13 -0700 Subject: [PATCH 11/59] linux-user: Pass CPUArchState to target_restore_altstack In most cases we were already passing get_sp_from_cpustate directly to the function. In other cases, we were passing a local variable which already contained the same value. In the rest of the cases, we were passing the stack pointer out of env directly. Reviewed by: Warner Losh Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/aarch64/signal.c | 2 +- linux-user/alpha/signal.c | 2 +- linux-user/arm/signal.c | 4 ++-- linux-user/hexagon/signal.c | 2 +- linux-user/hppa/signal.c | 2 +- linux-user/i386/signal.c | 2 +- linux-user/m68k/signal.c | 2 +- linux-user/microblaze/signal.c | 2 +- linux-user/mips/signal.c | 2 +- linux-user/nios2/signal.c | 2 +- linux-user/openrisc/signal.c | 2 +- linux-user/ppc/signal.c | 2 +- linux-user/riscv/signal.c | 2 +- linux-user/s390x/signal.c | 2 +- linux-user/sh4/signal.c | 2 +- linux-user/signal-common.h | 2 +- linux-user/signal.c | 6 +++--- linux-user/xtensa/signal.c | 2 +- 18 files changed, 21 insertions(+), 21 deletions(-) diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index 2a1b7dbcdc..662bcd1c4e 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -561,7 +561,7 @@ long do_rt_sigreturn(CPUARMState *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/alpha/signal.c b/linux-user/alpha/signal.c index 0af0227118..d4e4666874 100644 --- a/linux-user/alpha/signal.c +++ b/linux-user/alpha/signal.c @@ -257,7 +257,7 @@ long do_rt_sigreturn(CPUAlphaState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, env->ir[IR_SP]); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index b7a772302f..32b68ee302 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -685,7 +685,7 @@ static int do_sigframe_return_v2(CPUARMState *env, } } - target_restore_altstack(&uc->tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&uc->tuc_stack, env); #if 0 /* Send SIGTRAP if we're single-stepping */ @@ -769,7 +769,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); #if 0 /* Send SIGTRAP if we're single-stepping */ diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c index 3854eb4709..85eab5e943 100644 --- a/linux-user/hexagon/signal.c +++ b/linux-user/hexagon/signal.c @@ -260,7 +260,7 @@ long do_rt_sigreturn(CPUHexagonState *env) } restore_ucontext(env, &frame->uc); - target_restore_altstack(&frame->uc.uc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.uc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index 578874cf27..0e266f472d 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -187,7 +187,7 @@ long do_rt_sigreturn(CPUArchState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, env->gr[30]); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c index 3a0a1546a6..8701774e37 100644 --- a/linux-user/i386/signal.c +++ b/linux-user/i386/signal.c @@ -581,7 +581,7 @@ long do_rt_sigreturn(CPUX86State *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/m68k/signal.c b/linux-user/m68k/signal.c index 004b59fb61..d06230655e 100644 --- a/linux-user/m68k/signal.c +++ b/linux-user/m68k/signal.c @@ -400,7 +400,7 @@ long do_rt_sigreturn(CPUM68KState *env) if (target_rt_restore_ucontext(env, &frame->uc)) goto badframe; - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c index f59a1faf47..4c483bd8c6 100644 --- a/linux-user/microblaze/signal.c +++ b/linux-user/microblaze/signal.c @@ -209,7 +209,7 @@ long do_rt_sigreturn(CPUMBState *env) restore_sigcontext(&frame->uc.tuc_mcontext, env); - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c index 456fa64f41..e6be807a81 100644 --- a/linux-user/mips/signal.c +++ b/linux-user/mips/signal.c @@ -368,7 +368,7 @@ long do_rt_sigreturn(CPUMIPSState *env) set_sigmask(&blocked); restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); - target_restore_altstack(&frame->rs_uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->rs_uc.tuc_stack, env); env->active_tc.PC = env->CP0_EPC; mips_set_hflags_isa_mode_from_pc(env); diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index 751ea88811..cc3872f11d 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -128,7 +128,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, __get_user(env->regs[R_RA], &gregs[23]); __get_user(env->regs[R_SP], &gregs[28]); - target_restore_altstack(&uc->tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&uc->tuc_stack, env); *pr2 = env->regs[2]; return 0; diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c index 86f94d7f76..5c5640a284 100644 --- a/linux-user/openrisc/signal.c +++ b/linux-user/openrisc/signal.c @@ -158,7 +158,7 @@ long do_rt_sigreturn(CPUOpenRISCState *env) set_sigmask(&set); restore_sigcontext(env, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, frame_addr); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return cpu_get_gpr(env, 11); diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c index b44d5ce73c..edfad28a37 100644 --- a/linux-user/ppc/signal.c +++ b/linux-user/ppc/signal.c @@ -655,7 +655,7 @@ long do_rt_sigreturn(CPUPPCState *env) if (do_setcontext(&rt_sf->uc, env, 1)) goto sigsegv; - target_restore_altstack(&rt_sf->uc.tuc_stack, env->gpr[1]); + target_restore_altstack(&rt_sf->uc.tuc_stack, env); unlock_user_struct(rt_sf, rt_sf_addr, 1); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index 81d1129da3..9405c7fd9a 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -192,7 +192,7 @@ long do_rt_sigreturn(CPURISCVState *env) } restore_ucontext(env, &frame->uc); - target_restore_altstack(&frame->uc.uc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.uc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 73806f5472..b68b44ae7e 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -307,7 +307,7 @@ long do_rt_sigreturn(CPUS390XState *env) goto badframe; } - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c index 684f18da58..0451e65806 100644 --- a/linux-user/sh4/signal.c +++ b/linux-user/sh4/signal.c @@ -323,7 +323,7 @@ long do_rt_sigreturn(CPUSH4State *regs) set_sigmask(&blocked); restore_sigcontext(regs, &frame->uc.tuc_mcontext); - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(regs)); + target_restore_altstack(&frame->uc.tuc_stack, regs); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 34b963af9a..ea86328b28 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -24,7 +24,7 @@ int on_sig_stack(unsigned long sp); int sas_ss_flags(unsigned long sp); abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka); void target_save_altstack(target_stack_t *uss, CPUArchState *env); -abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp); +abi_long target_restore_altstack(target_stack_t *uss, CPUArchState *env); static inline void target_sigemptyset(target_sigset_t *set) { diff --git a/linux-user/signal.c b/linux-user/signal.c index 2e1095055b..cbd80b28cf 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -297,7 +297,7 @@ void target_save_altstack(target_stack_t *uss, CPUArchState *env) __put_user(ts->sigaltstack_used.ss_size, &uss->ss_size); } -abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp) +abi_long target_restore_altstack(target_stack_t *uss, CPUArchState *env) { TaskState *ts = (TaskState *)thread_cpu->opaque; size_t minstacksize = TARGET_MINSIGSTKSZ; @@ -315,7 +315,7 @@ abi_long target_restore_altstack(target_stack_t *uss, abi_ulong sp) __get_user(ss.ss_size, &uss->ss_size); __get_user(ss.ss_flags, &uss->ss_flags); - if (on_sig_stack(sp)) { + if (on_sig_stack(get_sp_from_cpustate(env))) { return -TARGET_EPERM; } @@ -820,7 +820,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { goto out; } - ret = target_restore_altstack(uss, get_sp_from_cpustate(env)); + ret = target_restore_altstack(uss, env); if (ret) { goto out; } diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 22ec6cdeb9..72771e1294 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -253,7 +253,7 @@ long do_rt_sigreturn(CPUXtensaState *env) set_sigmask(&set); restore_sigcontext(env, frame); - target_restore_altstack(&frame->uc.tuc_stack, get_sp_from_cpustate(env)); + target_restore_altstack(&frame->uc.tuc_stack, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; From eb215f40c2b4cbb12e97197db5fb06bd73b8324e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:14 -0700 Subject: [PATCH 12/59] linux-user/sparc: Include TARGET_STACK_BIAS in get_sp_from_cpustate Move TARGET_STACK_BIAS from signal.c. Generic code cares about the logical stack pointer, not the physical one that has a bias applied for sparc64. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 2 -- linux-user/sparc/target_cpu.h | 9 ++++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index d27b7a3af7..76579093a8 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -394,8 +394,6 @@ struct target_reg_window { abi_ulong ins[8]; }; -#define TARGET_STACK_BIAS 2047 - /* {set, get}context() needed for 64-bit SparcLinux userland. */ void sparc64_set_context(CPUSPARCState *env) { diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h index 1fa1011775..1f4bed50f4 100644 --- a/linux-user/sparc/target_cpu.h +++ b/linux-user/sparc/target_cpu.h @@ -20,6 +20,12 @@ #ifndef SPARC_TARGET_CPU_H #define SPARC_TARGET_CPU_H +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +# define TARGET_STACK_BIAS 2047 +#else +# define TARGET_STACK_BIAS 0 +#endif + static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp, unsigned flags) { @@ -40,6 +46,7 @@ static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp, #endif /* ??? The kernel appears to copy one stack frame to the new stack. */ /* ??? The kernel force aligns the new stack. */ + /* Userspace provides a biased stack pointer value. */ env->regwptr[WREG_SP] = newsp; } @@ -77,7 +84,7 @@ static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls) static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) { - return state->regwptr[WREG_SP]; + return state->regwptr[WREG_SP] + TARGET_STACK_BIAS; } #endif From 089a2256eec34f56db88977bf5bf8d566c4f24ad Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:15 -0700 Subject: [PATCH 13/59] linux-user/sparc: Clean up init_thread Share code between sparc32 and sparc64, removing a bit of pointless difference wrt psr/tstate. Use sizeof(abi_ulong) for allocating initial register window. Use TARGET_STACK_BIAS. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-7-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index fc9c4f12be..ffc03d72f9 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -676,48 +676,25 @@ static uint32_t get_elf_hwcap2(void) #define ELF_CLASS ELFCLASS64 #define ELF_ARCH EM_SPARCV9 - -#define STACK_BIAS 2047 - -static inline void init_thread(struct target_pt_regs *regs, - struct image_info *infop) -{ -#ifndef TARGET_ABI32 - regs->tstate = 0; -#endif - regs->pc = infop->entry; - regs->npc = regs->pc + 4; - regs->y = 0; -#ifdef TARGET_ABI32 - regs->u_regs[14] = infop->start_stack - 16 * 4; -#else - if (personality(infop->personality) == PER_LINUX32) - regs->u_regs[14] = infop->start_stack - 16 * 4; - else - regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; -#endif -} - #else #define ELF_START_MMAP 0x80000000 #define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ | HWCAP_SPARC_MULDIV) - #define ELF_CLASS ELFCLASS32 #define ELF_ARCH EM_SPARC +#endif /* TARGET_SPARC64 */ static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { - regs->psr = 0; + /* Note that target_cpu_copy_regs does not read psr/tstate. */ regs->pc = infop->entry; regs->npc = regs->pc + 4; regs->y = 0; - regs->u_regs[14] = infop->start_stack - 16 * 4; + regs->u_regs[14] = (infop->start_stack - 16 * sizeof(abi_ulong) + - TARGET_STACK_BIAS); } - -#endif -#endif +#endif /* TARGET_SPARC */ #ifdef TARGET_PPC From 2f23eec6bd9e25d6d66a819a2bd7432f84dc101c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:16 -0700 Subject: [PATCH 14/59] linux-user/sparc: Merge sparc64 target_syscall.h There are only a few differences in sparc32 vs sparc64. This fixes target_shmlba for sparc32plus, which is v9. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-8-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/target_syscall.h | 42 +++++++++++++++++++++-------- linux-user/sparc64/target_syscall.h | 36 +------------------------ 2 files changed, 32 insertions(+), 46 deletions(-) diff --git a/linux-user/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h index d8ea04ea83..15d531f389 100644 --- a/linux-user/sparc/target_syscall.h +++ b/linux-user/sparc/target_syscall.h @@ -3,18 +3,34 @@ #include "target_errno.h" +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) struct target_pt_regs { - abi_ulong psr; - abi_ulong pc; - abi_ulong npc; - abi_ulong y; - abi_ulong u_regs[16]; + abi_ulong u_regs[16]; + abi_ulong tstate; + abi_ulong pc; + abi_ulong npc; + uint32_t y; + uint32_t magic; }; +#else +struct target_pt_regs { + abi_ulong psr; + abi_ulong pc; + abi_ulong npc; + abi_ulong y; + abi_ulong u_regs[16]; +}; +#endif -#define UNAME_MACHINE "sparc" +#ifdef TARGET_SPARC64 +# define UNAME_MACHINE "sparc64" +#else +# define UNAME_MACHINE "sparc" +#endif #define UNAME_MINIMUM_RELEASE "2.6.32" -/* SPARC kernels don't define this in their Kconfig, but they have the +/* + * SPARC kernels don't define this in their Kconfig, but they have the * same ABI as if they did, implemented by sparc-specific code which fishes * directly in the u_regs() struct for half the parameters in sparc_do_fork() * and copy_thread(). @@ -25,20 +41,24 @@ struct target_pt_regs { #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 -/* For SPARC SHMLBA is determined at runtime in the kernel, and - * libc has to runtime-detect it using the hwcaps (see glibc - * sysdeps/unix/sysv/linux/sparc/getshmlba; we follow the same - * logic here, though we know we're not the sparc v9 64-bit case). +/* + * For SPARC SHMLBA is determined at runtime in the kernel, and + * libc has to runtime-detect it using the hwcaps. + * See glibc sysdeps/unix/sysv/linux/sparc/getshmlba. */ #define TARGET_FORCE_SHMLBA static inline abi_ulong target_shmlba(CPUSPARCState *env) { +#ifdef TARGET_SPARC64 + return MAX(TARGET_PAGE_SIZE, 16 * 1024); +#else if (!(env->def.features & CPU_FEATURE_FLUSH)) { return 64 * 1024; } else { return 256 * 1024; } +#endif } #endif /* SPARC_TARGET_SYSCALL_H */ diff --git a/linux-user/sparc64/target_syscall.h b/linux-user/sparc64/target_syscall.h index 696a68b1ed..164a5fc632 100644 --- a/linux-user/sparc64/target_syscall.h +++ b/linux-user/sparc64/target_syscall.h @@ -1,35 +1 @@ -#ifndef SPARC64_TARGET_SYSCALL_H -#define SPARC64_TARGET_SYSCALL_H - -#include "../sparc/target_errno.h" - -struct target_pt_regs { - abi_ulong u_regs[16]; - abi_ulong tstate; - abi_ulong pc; - abi_ulong npc; - abi_ulong y; - abi_ulong fprs; -}; - -#define UNAME_MACHINE "sparc64" -#define UNAME_MINIMUM_RELEASE "2.6.32" - -/* SPARC kernels don't define this in their Kconfig, but they have the - * same ABI as if they did, implemented by sparc-specific code which fishes - * directly in the u_regs() struct for half the parameters in sparc_do_fork() - * and copy_thread(). - */ -#define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 4096 -#define TARGET_MCL_CURRENT 0x2000 -#define TARGET_MCL_FUTURE 0x4000 -#define TARGET_MCL_ONFAULT 0x8000 - -#define TARGET_FORCE_SHMLBA - -static inline abi_ulong target_shmlba(CPUSPARCState *env) -{ - return MAX(TARGET_PAGE_SIZE, 16 * 1024); -} -#endif /* SPARC64_TARGET_SYSCALL_H */ +#include "../sparc/target_syscall.h" From b136c211dadc8957b7e3cbb6de4031e3a69a2cfd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:17 -0700 Subject: [PATCH 15/59] linux-user/sparc: Merge sparc64 target_elf.h Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-9-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc64/target_elf.h | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/linux-user/sparc64/target_elf.h b/linux-user/sparc64/target_elf.h index d6e388f1cf..023b49b743 100644 --- a/linux-user/sparc64/target_elf.h +++ b/linux-user/sparc64/target_elf.h @@ -1,14 +1 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation, or (at your option) any - * later version. See the COPYING file in the top-level directory. - */ - -#ifndef SPARC64_TARGET_ELF_H -#define SPARC64_TARGET_ELF_H -static inline const char *cpu_get_model(uint32_t eflags) -{ - return "TI UltraSparc II"; -} -#endif +#include "../sparc/target_elf.h" From 6175783bfa2189f774f1ae8ccd0e6d19e5407e79 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:18 -0700 Subject: [PATCH 16/59] linux-user/sparc: Merge sparc64 target_structs.h Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-10-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/target_structs.h | 36 +++++++----------- linux-user/sparc64/target_structs.h | 59 +---------------------------- 2 files changed, 15 insertions(+), 80 deletions(-) diff --git a/linux-user/sparc/target_structs.h b/linux-user/sparc/target_structs.h index 9953540759..beeace8fb2 100644 --- a/linux-user/sparc/target_structs.h +++ b/linux-user/sparc/target_structs.h @@ -26,13 +26,10 @@ struct target_ipc_perm { abi_uint cuid; /* Creator's user ID. */ abi_uint cgid; /* Creator's group ID. */ #if TARGET_ABI_BITS == 32 - abi_ushort __pad1; - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad2; -#else - abi_ushort mode; - abi_ushort __pad1; + abi_ushort __pad0; #endif + abi_ushort mode; /* Read/write permission. */ + abi_ushort __pad1; abi_ushort __seq; /* Sequence number. */ uint64_t __unused1; uint64_t __unused2; @@ -40,22 +37,17 @@ struct target_ipc_perm { struct target_shmid_ds { struct target_ipc_perm shm_perm; /* operation permission struct */ -#if TARGET_ABI_BITS == 32 - abi_uint __pad1; -#endif - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_uint __pad2; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_uint __pad3; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_cpid; /* pid of creator */ - abi_ulong shm_lpid; /* pid of last shmop */ - abi_long shm_nattch; /* number of current attaches */ + /* + * Note that sparc32 splits these into hi/lo parts. + * For simplicity in qemu, always use a 64-bit type. + */ + int64_t shm_atime; /* last attach time */ + int64_t shm_dtime; /* last detach time */ + int64_t shm_ctime; /* last change time */ + abi_ulong shm_segsz; /* size of segment in bytes */ + 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 __unused1; abi_ulong __unused2; }; diff --git a/linux-user/sparc64/target_structs.h b/linux-user/sparc64/target_structs.h index 4a8ed48df7..cbcbc4602a 100644 --- a/linux-user/sparc64/target_structs.h +++ b/linux-user/sparc64/target_structs.h @@ -1,58 +1 @@ -/* - * SPARC64 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 SPARC64_TARGET_STRUCTS_H -#define SPARC64_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 "../sparc/target_structs.h" From 0de9081b2369e372a6bdee5192102badad552bfb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:19 -0700 Subject: [PATCH 17/59] linux-user/sparc: Merge sparc64 termbits.h Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-11-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc64/termbits.h | 292 +--------------------------------- 1 file changed, 1 insertion(+), 291 deletions(-) diff --git a/linux-user/sparc64/termbits.h b/linux-user/sparc64/termbits.h index 1ab1e80db5..54ddfee3ba 100644 --- a/linux-user/sparc64/termbits.h +++ b/linux-user/sparc64/termbits.h @@ -1,291 +1 @@ -/* from asm/termbits.h */ - -#ifndef LINUX_USER_SPARC64_TERMBITS_H -#define LINUX_USER_SPARC64_TERMBITS_H - -#define TARGET_NCCS 19 - -typedef unsigned char target_cc_t; /* cc_t */ -typedef unsigned int target_speed_t; /* speed_t */ -typedef unsigned int target_tcflag_t; /* tcflag_t */ - -struct target_termios { - target_tcflag_t c_iflag; /* input mode flags */ - target_tcflag_t c_oflag; /* output mode flags */ - target_tcflag_t c_cflag; /* control mode flags */ - target_tcflag_t c_lflag; /* local mode flags */ - target_cc_t c_line; /* line discipline */ - target_cc_t c_cc[TARGET_NCCS]; /* control characters */ -}; - - -/* c_cc characters */ -#define TARGET_VINTR 0 -#define TARGET_VQUIT 1 -#define TARGET_VERASE 2 -#define TARGET_VKILL 3 -#define TARGET_VEOF 4 -#define TARGET_VEOL 5 -#define TARGET_VEOL2 6 -#define TARGET_VSWTC 7 -#define TARGET_VSTART 8 -#define TARGET_VSTOP 9 - -#define TARGET_VSUSP 10 -#define TARGET_VDSUSP 11 /* SunOS POSIX nicety I do believe... */ -#define TARGET_VREPRINT 12 -#define TARGET_VDISCARD 13 -#define TARGET_VWERASE 14 -#define TARGET_VLNEXT 15 - -/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is - * shared with eof/eol - */ -#define TARGET_VMIN TARGET_VEOF -#define TARGET_VTIME TARGET_VEOL - -/* c_iflag bits */ -#define TARGET_IGNBRK 0x00000001 -#define TARGET_BRKINT 0x00000002 -#define TARGET_IGNPAR 0x00000004 -#define TARGET_PARMRK 0x00000008 -#define TARGET_INPCK 0x00000010 -#define TARGET_ISTRIP 0x00000020 -#define TARGET_INLCR 0x00000040 -#define TARGET_IGNCR 0x00000080 -#define TARGET_ICRNL 0x00000100 -#define TARGET_IUCLC 0x00000200 -#define TARGET_IXON 0x00000400 -#define TARGET_IXANY 0x00000800 -#define TARGET_IXOFF 0x00001000 -#define TARGET_IMAXBEL 0x00002000 -#define TARGET_IUTF8 0x00004000 - -/* c_oflag bits */ -#define TARGET_OPOST 0x00000001 -#define TARGET_OLCUC 0x00000002 -#define TARGET_ONLCR 0x00000004 -#define TARGET_OCRNL 0x00000008 -#define TARGET_ONOCR 0x00000010 -#define TARGET_ONLRET 0x00000020 -#define TARGET_OFILL 0x00000040 -#define TARGET_OFDEL 0x00000080 -#define TARGET_NLDLY 0x00000100 -#define TARGET_NL0 0x00000000 -#define TARGET_NL1 0x00000100 -#define TARGET_CRDLY 0x00000600 -#define TARGET_CR0 0x00000000 -#define TARGET_CR1 0x00000200 -#define TARGET_CR2 0x00000400 -#define TARGET_CR3 0x00000600 -#define TARGET_TABDLY 0x00001800 -#define TARGET_TAB0 0x00000000 -#define TARGET_TAB1 0x00000800 -#define TARGET_TAB2 0x00001000 -#define TARGET_TAB3 0x00001800 -#define TARGET_XTABS 0x00001800 -#define TARGET_BSDLY 0x00002000 -#define TARGET_BS0 0x00000000 -#define TARGET_BS1 0x00002000 -#define TARGET_VTDLY 0x00004000 -#define TARGET_VT0 0x00000000 -#define TARGET_VT1 0x00004000 -#define TARGET_FFDLY 0x00008000 -#define TARGET_FF0 0x00000000 -#define TARGET_FF1 0x00008000 -#define TARGET_PAGEOUT 0x00010000 /* SUNOS specific */ -#define TARGET_WRAP 0x00020000 /* SUNOS specific */ - -/* c_cflag bit meaning */ -#define TARGET_CBAUD 0x0000100f -#define TARGET_B0 0x00000000 /* hang up */ -#define TARGET_B50 0x00000001 -#define TARGET_B75 0x00000002 -#define TARGET_B110 0x00000003 -#define TARGET_B134 0x00000004 -#define TARGET_B150 0x00000005 -#define TARGET_B200 0x00000006 -#define TARGET_B300 0x00000007 -#define TARGET_B600 0x00000008 -#define TARGET_B1200 0x00000009 -#define TARGET_B1800 0x0000000a -#define TARGET_B2400 0x0000000b -#define TARGET_B4800 0x0000000c -#define TARGET_B9600 0x0000000d -#define TARGET_B19200 0x0000000e -#define TARGET_B38400 0x0000000f -#define TARGET_EXTA B19200 -#define TARGET_EXTB B38400 -#define TARGET_CSIZE 0x00000030 -#define TARGET_CS5 0x00000000 -#define TARGET_CS6 0x00000010 -#define TARGET_CS7 0x00000020 -#define TARGET_CS8 0x00000030 -#define TARGET_CSTOPB 0x00000040 -#define TARGET_CREAD 0x00000080 -#define TARGET_PARENB 0x00000100 -#define TARGET_PARODD 0x00000200 -#define TARGET_HUPCL 0x00000400 -#define TARGET_CLOCAL 0x00000800 -#define TARGET_CBAUDEX 0x00001000 -/* We'll never see these speeds with the Zilogs, but for completeness... */ -#define TARGET_B57600 0x00001001 -#define TARGET_B115200 0x00001002 -#define TARGET_B230400 0x00001003 -#define TARGET_B460800 0x00001004 -/* This is what we can do with the Zilogs. */ -#define TARGET_B76800 0x00001005 -/* This is what we can do with the SAB82532. */ -#define TARGET_B153600 0x00001006 -#define TARGET_B307200 0x00001007 -#define TARGET_B614400 0x00001008 -#define TARGET_B921600 0x00001009 -/* And these are the rest... */ -#define TARGET_B500000 0x0000100a -#define TARGET_B576000 0x0000100b -#define TARGET_B1000000 0x0000100c -#define TARGET_B1152000 0x0000100d -#define TARGET_B1500000 0x0000100e -#define TARGET_B2000000 0x0000100f -/* These have totally bogus values and nobody uses them - so far. Later on we'd have to use say 0x10000x and - adjust CBAUD constant and drivers accordingly. -#define B2500000 0x00001010 -#define B3000000 0x00001011 -#define B3500000 0x00001012 -#define B4000000 0x00001013 */ -#define TARGET_CIBAUD 0x100f0000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 0x40000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 0x80000000 /* flow control */ - -/* c_lflag bits */ -#define TARGET_ISIG 0x00000001 -#define TARGET_ICANON 0x00000002 -#define TARGET_XCASE 0x00000004 -#define TARGET_ECHO 0x00000008 -#define TARGET_ECHOE 0x00000010 -#define TARGET_ECHOK 0x00000020 -#define TARGET_ECHONL 0x00000040 -#define TARGET_NOFLSH 0x00000080 -#define TARGET_TOSTOP 0x00000100 -#define TARGET_ECHOCTL 0x00000200 -#define TARGET_ECHOPRT 0x00000400 -#define TARGET_ECHOKE 0x00000800 -#define TARGET_DEFECHO 0x00001000 /* SUNOS thing, what is it? */ -#define TARGET_FLUSHO 0x00002000 -#define TARGET_PENDIN 0x00004000 -#define TARGET_IEXTEN 0x00008000 -#define TARGET_EXTPROC 0x00010000 - -/* ioctls */ - -/* Big T */ -#define TARGET_TCGETA TARGET_IOR('T', 1, struct target_termio) -#define TARGET_TCSETA TARGET_IOW('T', 2, struct target_termio) -#define TARGET_TCSETAW TARGET_IOW('T', 3, struct target_termio) -#define TARGET_TCSETAF TARGET_IOW('T', 4, struct target_termio) -#define TARGET_TCSBRK TARGET_IO('T', 5) -#define TARGET_TCXONC TARGET_IO('T', 6) -#define TARGET_TCFLSH TARGET_IO('T', 7) -#define TARGET_TCGETS TARGET_IOR('T', 8, struct target_termios) -#define TARGET_TCSETS TARGET_IOW('T', 9, struct target_termios) -#define TARGET_TCSETSW TARGET_IOW('T', 10, struct target_termios) -#define TARGET_TCSETSF TARGET_IOW('T', 11, struct target_termios) - -/* Note that all the ioctls that are not available in Linux have a - * double underscore on the front to: a) avoid some programs to - * thing we support some ioctls under Linux (autoconfiguration stuff) - */ -/* Little t */ -#define TARGET_TIOCGETD TARGET_IOR('t', 0, int) -#define TARGET_TIOCSETD TARGET_IOW('t', 1, int) -//#define __TIOCHPCL _IO('t', 2) /* SunOS Specific */ -//#define __TIOCMODG _IOR('t', 3, int) /* SunOS Specific */ -//#define __TIOCMODS _IOW('t', 4, int) /* SunOS Specific */ -//#define __TIOCGETP _IOR('t', 8, struct sgttyb) /* SunOS Specific */ -//#define __TIOCSETP _IOW('t', 9, struct sgttyb) /* SunOS Specific */ -//#define __TIOCSETN _IOW('t', 10, struct sgttyb) /* SunOS Specific */ -#define TARGET_TIOCEXCL TARGET_IO('t', 13) -#define TARGET_TIOCNXCL TARGET_IO('t', 14) -//#define __TIOCFLUSH _IOW('t', 16, int) /* SunOS Specific */ -//#define __TIOCSETC _IOW('t', 17, struct tchars) /* SunOS Specific */ -//#define __TIOCGETC _IOR('t', 18, struct tchars) /* SunOS Specific */ -//#define __TIOCTCNTL _IOW('t', 32, int) /* SunOS Specific */ -//#define __TIOCSIGNAL _IOW('t', 33, int) /* SunOS Specific */ -//#define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */ -//#define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */ -#define TARGET_TIOCCONS TARGET_IO('t', 36) -//#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */ -//#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */ -#define TARGET_TIOCGSOFTCAR TARGET_IOR('t', 100, int) -#define TARGET_TIOCSSOFTCAR TARGET_IOW('t', 101, int) -//#define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */ -#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct winsize) -#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct winsize) -//#define __TIOCREMOTE _IOW('t', 105, int) /* SunOS Specific */ -#define TARGET_TIOCMGET TARGET_IOR('t', 106, int) -#define TARGET_TIOCMBIC TARGET_IOW('t', 107, int) -#define TARGET_TIOCMBIS TARGET_IOW('t', 108, int) -#define TARGET_TIOCMSET TARGET_IOW('t', 109, int) -#define TARGET_TIOCSTART TARGET_IO('t', 110) -#define TARGET_TIOCSTOP TARGET_IO('t', 111) -#define TARGET_TIOCPKT TARGET_IOW('t', 112, int) -#define TARGET_TIOCNOTTY TARGET_IO('t', 113) -#define TARGET_TIOCSTI TARGET_IOW('t', 114, char) -#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int) -//#define __TIOCGLTC _IOR('t', 116, struct ltchars) /* SunOS Specific */ -//#define __TIOCSLTC _IOW('t', 117, struct ltchars) /* SunOS Specific */ -/* 118 is the non-posix setpgrp tty ioctl */ -/* 119 is the non-posix getpgrp tty ioctl */ -//#define __TIOCCDTR TARGET_IO('t', 120) /* SunOS Specific */ -//#define __TIOCSDTR TARGET_IO('t', 121) /* SunOS Specific */ -#define TARGET_TIOCCBRK TARGET_IO('t', 122) -#define TARGET_TIOCSBRK TARGET_IO('t', 123) -//#define __TIOCLGET TARGET_IOW('t', 124, int) /* SunOS Specific */ -//#define __TIOCLSET TARGET_IOW('t', 125, int) /* SunOS Specific */ -//#define __TIOCLBIC TARGET_IOW('t', 126, int) /* SunOS Specific */ -//#define __TIOCLBIS TARGET_IOW('t', 127, int) /* SunOS Specific */ -//#define __TIOCISPACE TARGET_IOR('t', 128, int) /* SunOS Specific */ -//#define __TIOCISIZE TARGET_IOR('t', 129, int) /* SunOS Specific */ -#define TARGET_TIOCSPGRP TARGET_IOW('t', 130, int) -#define TARGET_TIOCGPGRP TARGET_IOR('t', 131, int) -#define TARGET_TIOCSCTTY TARGET_IO('t', 132) -#define TARGET_TIOCGSID TARGET_IOR('t', 133, int) -/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */ -#define TARGET_TIOCGPTN TARGET_IOR('t', 134, unsigned int) /* Get Pty Number */ -#define TARGET_TIOCSPTLCK TARGET_IOW('t', 135, int) /* Lock/unlock PTY */ -#define TARGET_TIOCGPTPEER TARGET_IO('t', 137) /* Safely open the slave */ - -/* Little f */ -#define TARGET_FIOCLEX TARGET_IO('f', 1) -#define TARGET_FIONCLEX TARGET_IO('f', 2) -#define TARGET_FIOASYNC TARGET_IOW('f', 125, int) -#define TARGET_FIONBIO TARGET_IOW('f', 126, int) -#define TARGET_FIONREAD TARGET_IOR('f', 127, int) -#define TARGET_TIOCINQ TARGET_FIONREAD - -/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it - * someday. This is completely bogus, I know... - */ -//#define __TCGETSTAT TARGET_IO('T', 200) /* Rutgers specific */ -//#define __TCSETSTAT TARGET_IO('T', 201) /* Rutgers specific */ - -/* Linux specific, no SunOS equivalent. */ -#define TARGET_TIOCLINUX 0x541C -#define TARGET_TIOCGSERIAL 0x541E -#define TARGET_TIOCSSERIAL 0x541F -#define TARGET_TCSBRKP 0x5425 -#define TARGET_TIOCTTYGSTRUCT 0x5426 -#define TARGET_TIOCSERCONFIG 0x5453 -#define TARGET_TIOCSERGWILD 0x5454 -#define TARGET_TIOCSERSWILD 0x5455 -#define TARGET_TIOCGLCKTRMIOS 0x5456 -#define TARGET_TIOCSLCKTRMIOS 0x5457 -#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ -#define TARGET_TIOCMIWAIT 0x545C /* Wait input */ -#define TARGET_TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ - -#endif +#include "../sparc/termbits.h" From 921c16268dc599180390d73bd6432a03ccc5918f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:20 -0700 Subject: [PATCH 18/59] linux-user/sparc: Merge sparc64/ into sparc/ All of the source and header files already defer to sparc via #include. The syscall.tbl and syscallhdr.sh files could not do the same, but are identical. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-12-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- .../targets/sparc64-linux-user.mak | 1 + linux-user/meson.build | 1 - linux-user/sparc64/cpu_loop.c | 20 - linux-user/sparc64/meson.build | 5 - linux-user/sparc64/signal.c | 19 - linux-user/sparc64/sockbits.h | 1 - linux-user/sparc64/syscall.tbl | 487 ------------------ linux-user/sparc64/syscallhdr.sh | 32 -- linux-user/sparc64/target_cpu.h | 1 - linux-user/sparc64/target_elf.h | 1 - linux-user/sparc64/target_fcntl.h | 1 - linux-user/sparc64/target_signal.h | 1 - linux-user/sparc64/target_structs.h | 1 - linux-user/sparc64/target_syscall.h | 1 - linux-user/sparc64/termbits.h | 1 - 15 files changed, 1 insertion(+), 572 deletions(-) delete mode 100644 linux-user/sparc64/cpu_loop.c delete mode 100644 linux-user/sparc64/meson.build delete mode 100644 linux-user/sparc64/signal.c delete mode 100644 linux-user/sparc64/sockbits.h delete mode 100644 linux-user/sparc64/syscall.tbl delete mode 100644 linux-user/sparc64/syscallhdr.sh delete mode 100644 linux-user/sparc64/target_cpu.h delete mode 100644 linux-user/sparc64/target_elf.h delete mode 100644 linux-user/sparc64/target_fcntl.h delete mode 100644 linux-user/sparc64/target_signal.h delete mode 100644 linux-user/sparc64/target_structs.h delete mode 100644 linux-user/sparc64/target_syscall.h delete mode 100644 linux-user/sparc64/termbits.h diff --git a/default-configs/targets/sparc64-linux-user.mak b/default-configs/targets/sparc64-linux-user.mak index 846924201a..9d23ab4a26 100644 --- a/default-configs/targets/sparc64-linux-user.mak +++ b/default-configs/targets/sparc64-linux-user.mak @@ -1,5 +1,6 @@ TARGET_ARCH=sparc64 TARGET_BASE_ARCH=sparc +TARGET_ABI_DIR=sparc TARGET_SYSTBL_ABI=common,64 TARGET_SYSTBL=syscall.tbl TARGET_ALIGNED_ONLY=y diff --git a/linux-user/meson.build b/linux-user/meson.build index 7fe28d659e..9549f81682 100644 --- a/linux-user/meson.build +++ b/linux-user/meson.build @@ -32,7 +32,6 @@ subdir('mips') subdir('ppc') subdir('s390x') subdir('sh4') -subdir('sparc64') subdir('sparc') subdir('x86_64') subdir('xtensa') diff --git a/linux-user/sparc64/cpu_loop.c b/linux-user/sparc64/cpu_loop.c deleted file mode 100644 index 4fd44e1b1e..0000000000 --- a/linux-user/sparc64/cpu_loop.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * qemu user cpu loop - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * 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 . - */ - -#include "../sparc/cpu_loop.c" diff --git a/linux-user/sparc64/meson.build b/linux-user/sparc64/meson.build deleted file mode 100644 index 9527a40ed4..0000000000 --- a/linux-user/sparc64/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -syscall_nr_generators += { - 'sparc64': generator(sh, - arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ], - output: '@BASENAME@_nr.h') -} diff --git a/linux-user/sparc64/signal.c b/linux-user/sparc64/signal.c deleted file mode 100644 index 170ebac232..0000000000 --- a/linux-user/sparc64/signal.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Emulation of Linux signals - * - * Copyright (c) 2003 Fabrice Bellard - * - * 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 . - */ -#include "../sparc/signal.c" diff --git a/linux-user/sparc64/sockbits.h b/linux-user/sparc64/sockbits.h deleted file mode 100644 index 658899e4d3..0000000000 --- a/linux-user/sparc64/sockbits.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/sockbits.h" diff --git a/linux-user/sparc64/syscall.tbl b/linux-user/sparc64/syscall.tbl deleted file mode 100644 index 4af114e84f..0000000000 --- a/linux-user/sparc64/syscall.tbl +++ /dev/null @@ -1,487 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -# -# system call numbers and entry vectors for sparc -# -# The format is: -# -# -# The can be common, 64, or 32 for this file. -# -0 common restart_syscall sys_restart_syscall -1 32 exit sys_exit sparc_exit -1 64 exit sparc_exit -2 common fork sys_fork -3 common read sys_read -4 common write sys_write -5 common open sys_open compat_sys_open -6 common close sys_close -7 common wait4 sys_wait4 compat_sys_wait4 -8 common creat sys_creat -9 common link sys_link -10 common unlink sys_unlink -11 32 execv sunos_execv -11 64 execv sys_nis_syscall -12 common chdir sys_chdir -13 32 chown sys_chown16 -13 64 chown sys_chown -14 common mknod sys_mknod -15 common chmod sys_chmod -16 32 lchown sys_lchown16 -16 64 lchown sys_lchown -17 common brk sys_brk -18 common perfctr sys_nis_syscall -19 common lseek sys_lseek compat_sys_lseek -20 common getpid sys_getpid -21 common capget sys_capget -22 common capset sys_capset -23 32 setuid sys_setuid16 -23 64 setuid sys_setuid -24 32 getuid sys_getuid16 -24 64 getuid sys_getuid -25 common vmsplice sys_vmsplice compat_sys_vmsplice -26 common ptrace sys_ptrace compat_sys_ptrace -27 common alarm sys_alarm -28 common sigaltstack sys_sigaltstack compat_sys_sigaltstack -29 32 pause sys_pause -29 64 pause sys_nis_syscall -30 32 utime sys_utime32 -30 64 utime sys_utime -31 32 lchown32 sys_lchown -32 32 fchown32 sys_fchown -33 common access sys_access -34 common nice sys_nice -35 32 chown32 sys_chown -36 common sync sys_sync -37 common kill sys_kill -38 common stat sys_newstat compat_sys_newstat -39 32 sendfile sys_sendfile compat_sys_sendfile -39 64 sendfile sys_sendfile64 -40 common lstat sys_newlstat compat_sys_newlstat -41 common dup sys_dup -42 common pipe sys_sparc_pipe -43 common times sys_times compat_sys_times -44 32 getuid32 sys_getuid -45 common umount2 sys_umount -46 32 setgid sys_setgid16 -46 64 setgid sys_setgid -47 32 getgid sys_getgid16 -47 64 getgid sys_getgid -48 common signal sys_signal -49 32 geteuid sys_geteuid16 -49 64 geteuid sys_geteuid -50 32 getegid sys_getegid16 -50 64 getegid sys_getegid -51 common acct sys_acct -52 64 memory_ordering sys_memory_ordering -53 32 getgid32 sys_getgid -54 common ioctl sys_ioctl compat_sys_ioctl -55 common reboot sys_reboot -56 32 mmap2 sys_mmap2 sys32_mmap2 -57 common symlink sys_symlink -58 common readlink sys_readlink -59 32 execve sys_execve sys32_execve -59 64 execve sys64_execve -60 common umask sys_umask -61 common chroot sys_chroot -62 common fstat sys_newfstat compat_sys_newfstat -63 common fstat64 sys_fstat64 compat_sys_fstat64 -64 common getpagesize sys_getpagesize -65 common msync sys_msync -66 common vfork sys_vfork -67 common pread64 sys_pread64 compat_sys_pread64 -68 common pwrite64 sys_pwrite64 compat_sys_pwrite64 -69 32 geteuid32 sys_geteuid -70 32 getegid32 sys_getegid -71 common mmap sys_mmap -72 32 setreuid32 sys_setreuid -73 32 munmap sys_munmap -73 64 munmap sys_64_munmap -74 common mprotect sys_mprotect -75 common madvise sys_madvise -76 common vhangup sys_vhangup -77 32 truncate64 sys_truncate64 compat_sys_truncate64 -78 common mincore sys_mincore -79 32 getgroups sys_getgroups16 -79 64 getgroups sys_getgroups -80 32 setgroups sys_setgroups16 -80 64 setgroups sys_setgroups -81 common getpgrp sys_getpgrp -82 32 setgroups32 sys_setgroups -83 common setitimer sys_setitimer compat_sys_setitimer -84 32 ftruncate64 sys_ftruncate64 compat_sys_ftruncate64 -85 common swapon sys_swapon -86 common getitimer sys_getitimer compat_sys_getitimer -87 32 setuid32 sys_setuid -88 common sethostname sys_sethostname -89 32 setgid32 sys_setgid -90 common dup2 sys_dup2 -91 32 setfsuid32 sys_setfsuid -92 common fcntl sys_fcntl compat_sys_fcntl -93 common select sys_select -94 32 setfsgid32 sys_setfsgid -95 common fsync sys_fsync -96 common setpriority sys_setpriority -97 common socket sys_socket -98 common connect sys_connect -99 common accept sys_accept -100 common getpriority sys_getpriority -101 common rt_sigreturn sys_rt_sigreturn sys32_rt_sigreturn -102 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction -103 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask -104 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending -105 32 rt_sigtimedwait sys_rt_sigtimedwait_time32 compat_sys_rt_sigtimedwait_time32 -105 64 rt_sigtimedwait sys_rt_sigtimedwait -106 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo -107 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend -108 32 setresuid32 sys_setresuid -108 64 setresuid sys_setresuid -109 32 getresuid32 sys_getresuid -109 64 getresuid sys_getresuid -110 32 setresgid32 sys_setresgid -110 64 setresgid sys_setresgid -111 32 getresgid32 sys_getresgid -111 64 getresgid sys_getresgid -112 32 setregid32 sys_setregid -113 common recvmsg sys_recvmsg compat_sys_recvmsg -114 common sendmsg sys_sendmsg compat_sys_sendmsg -115 32 getgroups32 sys_getgroups -116 common gettimeofday sys_gettimeofday compat_sys_gettimeofday -117 common getrusage sys_getrusage compat_sys_getrusage -118 common getsockopt sys_getsockopt sys_getsockopt -119 common getcwd sys_getcwd -120 common readv sys_readv compat_sys_readv -121 common writev sys_writev compat_sys_writev -122 common settimeofday sys_settimeofday compat_sys_settimeofday -123 32 fchown sys_fchown16 -123 64 fchown sys_fchown -124 common fchmod sys_fchmod -125 common recvfrom sys_recvfrom -126 32 setreuid sys_setreuid16 -126 64 setreuid sys_setreuid -127 32 setregid sys_setregid16 -127 64 setregid sys_setregid -128 common rename sys_rename -129 common truncate sys_truncate compat_sys_truncate -130 common ftruncate sys_ftruncate compat_sys_ftruncate -131 common flock sys_flock -132 common lstat64 sys_lstat64 compat_sys_lstat64 -133 common sendto sys_sendto -134 common shutdown sys_shutdown -135 common socketpair sys_socketpair -136 common mkdir sys_mkdir -137 common rmdir sys_rmdir -138 32 utimes sys_utimes_time32 -138 64 utimes sys_utimes -139 common stat64 sys_stat64 compat_sys_stat64 -140 common sendfile64 sys_sendfile64 -141 common getpeername sys_getpeername -142 32 futex sys_futex_time32 -142 64 futex sys_futex -143 common gettid sys_gettid -144 common getrlimit sys_getrlimit compat_sys_getrlimit -145 common setrlimit sys_setrlimit compat_sys_setrlimit -146 common pivot_root sys_pivot_root -147 common prctl sys_prctl -148 common pciconfig_read sys_pciconfig_read -149 common pciconfig_write sys_pciconfig_write -150 common getsockname sys_getsockname -151 common inotify_init sys_inotify_init -152 common inotify_add_watch sys_inotify_add_watch -153 common poll sys_poll -154 common getdents64 sys_getdents64 -155 32 fcntl64 sys_fcntl64 compat_sys_fcntl64 -156 common inotify_rm_watch sys_inotify_rm_watch -157 common statfs sys_statfs compat_sys_statfs -158 common fstatfs sys_fstatfs compat_sys_fstatfs -159 common umount sys_oldumount -160 common sched_set_affinity sys_sched_setaffinity compat_sys_sched_setaffinity -161 common sched_get_affinity sys_sched_getaffinity compat_sys_sched_getaffinity -162 common getdomainname sys_getdomainname -163 common setdomainname sys_setdomainname -164 64 utrap_install sys_utrap_install -165 common quotactl sys_quotactl -166 common set_tid_address sys_set_tid_address -167 common mount sys_mount compat_sys_mount -168 common ustat sys_ustat compat_sys_ustat -169 common setxattr sys_setxattr -170 common lsetxattr sys_lsetxattr -171 common fsetxattr sys_fsetxattr -172 common getxattr sys_getxattr -173 common lgetxattr sys_lgetxattr -174 common getdents sys_getdents compat_sys_getdents -175 common setsid sys_setsid -176 common fchdir sys_fchdir -177 common fgetxattr sys_fgetxattr -178 common listxattr sys_listxattr -179 common llistxattr sys_llistxattr -180 common flistxattr sys_flistxattr -181 common removexattr sys_removexattr -182 common lremovexattr sys_lremovexattr -183 32 sigpending sys_sigpending compat_sys_sigpending -183 64 sigpending sys_nis_syscall -184 common query_module sys_ni_syscall -185 common setpgid sys_setpgid -186 common fremovexattr sys_fremovexattr -187 common tkill sys_tkill -188 32 exit_group sys_exit_group sparc_exit_group -188 64 exit_group sparc_exit_group -189 common uname sys_newuname -190 common init_module sys_init_module -191 32 personality sys_personality sys_sparc64_personality -191 64 personality sys_sparc64_personality -192 32 remap_file_pages sys_sparc_remap_file_pages sys_remap_file_pages -192 64 remap_file_pages sys_remap_file_pages -193 common epoll_create sys_epoll_create -194 common epoll_ctl sys_epoll_ctl -195 common epoll_wait sys_epoll_wait -196 common ioprio_set sys_ioprio_set -197 common getppid sys_getppid -198 32 sigaction sys_sparc_sigaction compat_sys_sparc_sigaction -198 64 sigaction sys_nis_syscall -199 common sgetmask sys_sgetmask -200 common ssetmask sys_ssetmask -201 32 sigsuspend sys_sigsuspend -201 64 sigsuspend sys_nis_syscall -202 common oldlstat sys_newlstat compat_sys_newlstat -203 common uselib sys_uselib -204 32 readdir sys_old_readdir compat_sys_old_readdir -204 64 readdir sys_nis_syscall -205 common readahead sys_readahead compat_sys_readahead -206 common socketcall sys_socketcall sys32_socketcall -207 common syslog sys_syslog -208 common lookup_dcookie sys_lookup_dcookie compat_sys_lookup_dcookie -209 common fadvise64 sys_fadvise64 compat_sys_fadvise64 -210 common fadvise64_64 sys_fadvise64_64 compat_sys_fadvise64_64 -211 common tgkill sys_tgkill -212 common waitpid sys_waitpid -213 common swapoff sys_swapoff -214 common sysinfo sys_sysinfo compat_sys_sysinfo -215 32 ipc sys_ipc compat_sys_ipc -215 64 ipc sys_sparc_ipc -216 32 sigreturn sys_sigreturn sys32_sigreturn -216 64 sigreturn sys_nis_syscall -217 common clone sys_clone -218 common ioprio_get sys_ioprio_get -219 32 adjtimex sys_adjtimex_time32 -219 64 adjtimex sys_sparc_adjtimex -220 32 sigprocmask sys_sigprocmask compat_sys_sigprocmask -220 64 sigprocmask sys_nis_syscall -221 common create_module sys_ni_syscall -222 common delete_module sys_delete_module -223 common get_kernel_syms sys_ni_syscall -224 common getpgid sys_getpgid -225 common bdflush sys_bdflush -226 common sysfs sys_sysfs -227 common afs_syscall sys_nis_syscall -228 common setfsuid sys_setfsuid16 -229 common setfsgid sys_setfsgid16 -230 common _newselect sys_select compat_sys_select -231 32 time sys_time32 -232 common splice sys_splice -233 32 stime sys_stime32 -233 64 stime sys_stime -234 common statfs64 sys_statfs64 compat_sys_statfs64 -235 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64 -236 common _llseek sys_llseek -237 common mlock sys_mlock -238 common munlock sys_munlock -239 common mlockall sys_mlockall -240 common munlockall sys_munlockall -241 common sched_setparam sys_sched_setparam -242 common sched_getparam sys_sched_getparam -243 common sched_setscheduler sys_sched_setscheduler -244 common sched_getscheduler sys_sched_getscheduler -245 common sched_yield sys_sched_yield -246 common sched_get_priority_max sys_sched_get_priority_max -247 common sched_get_priority_min sys_sched_get_priority_min -248 32 sched_rr_get_interval sys_sched_rr_get_interval_time32 -248 64 sched_rr_get_interval sys_sched_rr_get_interval -249 32 nanosleep sys_nanosleep_time32 -249 64 nanosleep sys_nanosleep -250 32 mremap sys_mremap -250 64 mremap sys_64_mremap -251 common _sysctl sys_ni_syscall -252 common getsid sys_getsid -253 common fdatasync sys_fdatasync -254 32 nfsservctl sys_ni_syscall sys_nis_syscall -254 64 nfsservctl sys_nis_syscall -255 common sync_file_range sys_sync_file_range compat_sys_sync_file_range -256 32 clock_settime sys_clock_settime32 -256 64 clock_settime sys_clock_settime -257 32 clock_gettime sys_clock_gettime32 -257 64 clock_gettime sys_clock_gettime -258 32 clock_getres sys_clock_getres_time32 -258 64 clock_getres sys_clock_getres -259 32 clock_nanosleep sys_clock_nanosleep_time32 -259 64 clock_nanosleep sys_clock_nanosleep -260 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity -261 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity -262 32 timer_settime sys_timer_settime32 -262 64 timer_settime sys_timer_settime -263 32 timer_gettime sys_timer_gettime32 -263 64 timer_gettime sys_timer_gettime -264 common timer_getoverrun sys_timer_getoverrun -265 common timer_delete sys_timer_delete -266 common timer_create sys_timer_create compat_sys_timer_create -# 267 was vserver -267 common vserver sys_nis_syscall -268 common io_setup sys_io_setup compat_sys_io_setup -269 common io_destroy sys_io_destroy -270 common io_submit sys_io_submit compat_sys_io_submit -271 common io_cancel sys_io_cancel -272 32 io_getevents sys_io_getevents_time32 -272 64 io_getevents sys_io_getevents -273 common mq_open sys_mq_open compat_sys_mq_open -274 common mq_unlink sys_mq_unlink -275 32 mq_timedsend sys_mq_timedsend_time32 -275 64 mq_timedsend sys_mq_timedsend -276 32 mq_timedreceive sys_mq_timedreceive_time32 -276 64 mq_timedreceive sys_mq_timedreceive -277 common mq_notify sys_mq_notify compat_sys_mq_notify -278 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr -279 common waitid sys_waitid compat_sys_waitid -280 common tee sys_tee -281 common add_key sys_add_key -282 common request_key sys_request_key -283 common keyctl sys_keyctl compat_sys_keyctl -284 common openat sys_openat compat_sys_openat -285 common mkdirat sys_mkdirat -286 common mknodat sys_mknodat -287 common fchownat sys_fchownat -288 32 futimesat sys_futimesat_time32 -288 64 futimesat sys_futimesat -289 common fstatat64 sys_fstatat64 compat_sys_fstatat64 -290 common unlinkat sys_unlinkat -291 common renameat sys_renameat -292 common linkat sys_linkat -293 common symlinkat sys_symlinkat -294 common readlinkat sys_readlinkat -295 common fchmodat sys_fchmodat -296 common faccessat sys_faccessat -297 32 pselect6 sys_pselect6_time32 compat_sys_pselect6_time32 -297 64 pselect6 sys_pselect6 -298 32 ppoll sys_ppoll_time32 compat_sys_ppoll_time32 -298 64 ppoll sys_ppoll -299 common unshare sys_unshare -300 common set_robust_list sys_set_robust_list compat_sys_set_robust_list -301 common get_robust_list sys_get_robust_list compat_sys_get_robust_list -302 common migrate_pages sys_migrate_pages compat_sys_migrate_pages -303 common mbind sys_mbind compat_sys_mbind -304 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy -305 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy -306 common kexec_load sys_kexec_load compat_sys_kexec_load -307 common move_pages sys_move_pages compat_sys_move_pages -308 common getcpu sys_getcpu -309 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait -310 32 utimensat sys_utimensat_time32 -310 64 utimensat sys_utimensat -311 common signalfd sys_signalfd compat_sys_signalfd -312 common timerfd_create sys_timerfd_create -313 common eventfd sys_eventfd -314 common fallocate sys_fallocate compat_sys_fallocate -315 32 timerfd_settime sys_timerfd_settime32 -315 64 timerfd_settime sys_timerfd_settime -316 32 timerfd_gettime sys_timerfd_gettime32 -316 64 timerfd_gettime sys_timerfd_gettime -317 common signalfd4 sys_signalfd4 compat_sys_signalfd4 -318 common eventfd2 sys_eventfd2 -319 common epoll_create1 sys_epoll_create1 -320 common dup3 sys_dup3 -321 common pipe2 sys_pipe2 -322 common inotify_init1 sys_inotify_init1 -323 common accept4 sys_accept4 -324 common preadv sys_preadv compat_sys_preadv -325 common pwritev sys_pwritev compat_sys_pwritev -326 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo -327 common perf_event_open sys_perf_event_open -328 32 recvmmsg sys_recvmmsg_time32 compat_sys_recvmmsg_time32 -328 64 recvmmsg sys_recvmmsg -329 common fanotify_init sys_fanotify_init -330 common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark -331 common prlimit64 sys_prlimit64 -332 common name_to_handle_at sys_name_to_handle_at -333 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at -334 32 clock_adjtime sys_clock_adjtime32 -334 64 clock_adjtime sys_sparc_clock_adjtime -335 common syncfs sys_syncfs -336 common sendmmsg sys_sendmmsg compat_sys_sendmmsg -337 common setns sys_setns -338 common process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv -339 common process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev -340 32 kern_features sys_ni_syscall sys_kern_features -340 64 kern_features sys_kern_features -341 common kcmp sys_kcmp -342 common finit_module sys_finit_module -343 common sched_setattr sys_sched_setattr -344 common sched_getattr sys_sched_getattr -345 common renameat2 sys_renameat2 -346 common seccomp sys_seccomp -347 common getrandom sys_getrandom -348 common memfd_create sys_memfd_create -349 common bpf sys_bpf -350 32 execveat sys_execveat sys32_execveat -350 64 execveat sys64_execveat -351 common membarrier sys_membarrier -352 common userfaultfd sys_userfaultfd -353 common bind sys_bind -354 common listen sys_listen -355 common setsockopt sys_setsockopt sys_setsockopt -356 common mlock2 sys_mlock2 -357 common copy_file_range sys_copy_file_range -358 common preadv2 sys_preadv2 compat_sys_preadv2 -359 common pwritev2 sys_pwritev2 compat_sys_pwritev2 -360 common statx sys_statx -361 32 io_pgetevents sys_io_pgetevents_time32 compat_sys_io_pgetevents -361 64 io_pgetevents sys_io_pgetevents -362 common pkey_mprotect sys_pkey_mprotect -363 common pkey_alloc sys_pkey_alloc -364 common pkey_free sys_pkey_free -365 common rseq sys_rseq -# room for arch specific syscalls -392 64 semtimedop sys_semtimedop -393 common semget sys_semget -394 common semctl sys_semctl compat_sys_semctl -395 common shmget sys_shmget -396 common shmctl sys_shmctl compat_sys_shmctl -397 common shmat sys_shmat compat_sys_shmat -398 common shmdt sys_shmdt -399 common msgget sys_msgget -400 common msgsnd sys_msgsnd compat_sys_msgsnd -401 common msgrcv sys_msgrcv compat_sys_msgrcv -402 common msgctl sys_msgctl compat_sys_msgctl -403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime -404 32 clock_settime64 sys_clock_settime sys_clock_settime -405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime -406 32 clock_getres_time64 sys_clock_getres sys_clock_getres -407 32 clock_nanosleep_time64 sys_clock_nanosleep sys_clock_nanosleep -408 32 timer_gettime64 sys_timer_gettime sys_timer_gettime -409 32 timer_settime64 sys_timer_settime sys_timer_settime -410 32 timerfd_gettime64 sys_timerfd_gettime sys_timerfd_gettime -411 32 timerfd_settime64 sys_timerfd_settime sys_timerfd_settime -412 32 utimensat_time64 sys_utimensat sys_utimensat -413 32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64 -414 32 ppoll_time64 sys_ppoll compat_sys_ppoll_time64 -416 32 io_pgetevents_time64 sys_io_pgetevents sys_io_pgetevents -417 32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64 -418 32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend -419 32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive -420 32 semtimedop_time64 sys_semtimedop sys_semtimedop -421 32 rt_sigtimedwait_time64 sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time64 -422 32 futex_time64 sys_futex sys_futex -423 32 sched_rr_get_interval_time64 sys_sched_rr_get_interval sys_sched_rr_get_interval -424 common pidfd_send_signal sys_pidfd_send_signal -425 common io_uring_setup sys_io_uring_setup -426 common io_uring_enter sys_io_uring_enter -427 common io_uring_register sys_io_uring_register -428 common open_tree sys_open_tree -429 common move_mount sys_move_mount -430 common fsopen sys_fsopen -431 common fsconfig sys_fsconfig -432 common fsmount sys_fsmount -433 common fspick sys_fspick -434 common pidfd_open sys_pidfd_open -# 435 reserved for clone3 -436 common close_range sys_close_range -437 common openat2 sys_openat2 -438 common pidfd_getfd sys_pidfd_getfd -439 common faccessat2 sys_faccessat2 diff --git a/linux-user/sparc64/syscallhdr.sh b/linux-user/sparc64/syscallhdr.sh deleted file mode 100644 index 08c7e39bb3..0000000000 --- a/linux-user/sparc64/syscallhdr.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -in="$1" -out="$2" -my_abis=`echo "($3)" | tr ',' '|'` -prefix="$4" -offset="$5" - -fileguard=LINUX_USER_SPARC64_`basename "$out" | sed \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ - -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'` -grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | ( - printf "#ifndef %s\n" "${fileguard}" - printf "#define %s\n" "${fileguard}" - printf "\n" - - nxt=0 - while read nr abi name entry compat ; do - if [ -z "$offset" ]; then - printf "#define TARGET_NR_%s%s\t%s\n" \ - "${prefix}" "${name}" "${nr}" - else - printf "#define TARGET_NR_%s%s\t(%s + %s)\n" \ - "${prefix}" "${name}" "${offset}" "${nr}" - fi - nxt=$((nr+1)) - done - - printf "\n" - printf "#endif /* %s */" "${fileguard}" -) > "$out" diff --git a/linux-user/sparc64/target_cpu.h b/linux-user/sparc64/target_cpu.h deleted file mode 100644 index b22263d2db..0000000000 --- a/linux-user/sparc64/target_cpu.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/target_cpu.h" diff --git a/linux-user/sparc64/target_elf.h b/linux-user/sparc64/target_elf.h deleted file mode 100644 index 023b49b743..0000000000 --- a/linux-user/sparc64/target_elf.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/target_elf.h" diff --git a/linux-user/sparc64/target_fcntl.h b/linux-user/sparc64/target_fcntl.h deleted file mode 100644 index 053c774257..0000000000 --- a/linux-user/sparc64/target_fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/target_fcntl.h" diff --git a/linux-user/sparc64/target_signal.h b/linux-user/sparc64/target_signal.h deleted file mode 100644 index 6a7d57d024..0000000000 --- a/linux-user/sparc64/target_signal.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/target_signal.h" diff --git a/linux-user/sparc64/target_structs.h b/linux-user/sparc64/target_structs.h deleted file mode 100644 index cbcbc4602a..0000000000 --- a/linux-user/sparc64/target_structs.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/target_structs.h" diff --git a/linux-user/sparc64/target_syscall.h b/linux-user/sparc64/target_syscall.h deleted file mode 100644 index 164a5fc632..0000000000 --- a/linux-user/sparc64/target_syscall.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/target_syscall.h" diff --git a/linux-user/sparc64/termbits.h b/linux-user/sparc64/termbits.h deleted file mode 100644 index 54ddfee3ba..0000000000 --- a/linux-user/sparc64/termbits.h +++ /dev/null @@ -1 +0,0 @@ -#include "../sparc/termbits.h" From 743f99e1176b175ff2698d0dc36b834c6cef7f24 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:21 -0700 Subject: [PATCH 19/59] linux-user/sparc: Remove target_sigcontext as unused Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-13-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 76579093a8..3d068e0955 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -21,34 +21,6 @@ #include "signal-common.h" #include "linux-user/trace.h" -#define __SUNOS_MAXWIN 31 - -/* This is what SunOS does, so shall I. */ -struct target_sigcontext { - abi_ulong sigc_onstack; /* state to restore */ - - abi_ulong sigc_mask; /* sigmask to restore */ - abi_ulong sigc_sp; /* stack pointer */ - abi_ulong sigc_pc; /* program counter */ - abi_ulong sigc_npc; /* next program counter */ - abi_ulong sigc_psr; /* for condition codes etc */ - abi_ulong sigc_g1; /* User uses these two registers */ - abi_ulong sigc_o0; /* within the trampoline code. */ - - /* Now comes information regarding the users window set - * at the time of the signal. - */ - abi_ulong sigc_oswins; /* outstanding windows */ - - /* stack ptrs for each regwin buf */ - char *sigc_spbuf[__SUNOS_MAXWIN]; - - /* Windows to restore after signal */ - struct { - abi_ulong locals[8]; - abi_ulong ins[8]; - } sigc_wbuf[__SUNOS_MAXWIN]; -}; /* A Sparc stack frame */ struct sparc_stackf { abi_ulong locals[8]; From 4f4fdec308d1b840d34056a0f100e14b317e1c44 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:22 -0700 Subject: [PATCH 20/59] linux-user/sparc: Remove target_rt_signal_frame as unused It's wrong anyway. Remove it for now. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-14-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 3d068e0955..29c5e3b0c0 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -64,17 +64,6 @@ struct target_signal_frame { abi_ulong extra_size; /* Should be 0 */ qemu_siginfo_fpu_t fpu_state; }; -struct target_rt_signal_frame { - struct sparc_stackf ss; - siginfo_t info; - abi_ulong regs[20]; - sigset_t mask; - abi_ulong fpu_save; - uint32_t insns[2]; - stack_t stack; - unsigned int extra_size; /* Should be 0 */ - qemu_siginfo_fpu_t fpu_state; -}; static inline abi_ulong get_sigframe(struct target_sigaction *sa, CPUSPARCState *env, From f8ea624e7456b10bee8e82b788885a438af8084d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:23 -0700 Subject: [PATCH 21/59] linux-user/sparc: Fix the stackframe structure Move target_reg_window up and use it. Fold structptr and xxargs into xargs -- the use of a host pointer was incorrect anyway. Rename the structure to target_stackf for consistency. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-15-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 29c5e3b0c0..3474098641 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -21,16 +21,26 @@ #include "signal-common.h" #include "linux-user/trace.h" -/* A Sparc stack frame */ -struct sparc_stackf { +/* A Sparc register window */ +struct target_reg_window { abi_ulong locals[8]; abi_ulong ins[8]; - /* It's simpler to treat fp and callers_pc as elements of ins[] - * since we never need to access them ourselves. - */ - char *structptr; - abi_ulong xargs[6]; - abi_ulong xxargs[1]; +}; + +/* A Sparc stack frame. */ +struct target_stackf { + /* + * Since qemu does not reference fp or callers_pc directly, + * it's simpler to treat fp and callers_pc as elements of ins[], + * and then bundle locals[] and ins[] into reg_window. + */ + struct target_reg_window win; + /* + * Similarly, bundle structptr and xxargs into xargs[]. + * This portion of the struct is part of the function call abi, + * and belongs to the callee for spilling argument registers. + */ + abi_ulong xargs[8]; }; typedef struct { @@ -56,7 +66,7 @@ typedef struct { struct target_signal_frame { - struct sparc_stackf ss; + struct target_stackf ss; __siginfo_t info; abi_ulong fpu_save; uint32_t insns[2] QEMU_ALIGNED(8); @@ -150,10 +160,10 @@ void setup_frame(int sig, struct target_sigaction *ka, } for (i = 0; i < 8; i++) { - __put_user(env->regwptr[i + WREG_L0], &sf->ss.locals[i]); + __put_user(env->regwptr[i + WREG_L0], &sf->ss.win.locals[i]); } for (i = 0; i < 8; i++) { - __put_user(env->regwptr[i + WREG_I0], &sf->ss.ins[i]); + __put_user(env->regwptr[i + WREG_I0], &sf->ss.win.ins[i]); } if (err) goto sigsegv; @@ -349,12 +359,6 @@ struct target_ucontext { target_mcontext_t tuc_mcontext; }; -/* A V9 register window */ -struct target_reg_window { - abi_ulong locals[8]; - abi_ulong ins[8]; -}; - /* {set, get}context() needed for 64-bit SparcLinux userland. */ void sparc64_set_context(CPUSPARCState *env) { From a1181d53a97dbed24b68fd04d700679cf9d6af65 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:24 -0700 Subject: [PATCH 22/59] linux-user/sparc: Use target_pt_regs Replace __siginfo_t with target_pt_regs, and move si_mask into target_signal_frame directly. Extract save/restore functions for target_pt_regs. Adjust for sparc64 tstate. Use proper get/put functions for psr. Turns out we were already writing to si_mask twice, so no need to handle that in the new functions. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-16-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 121 ++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 57 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 3474098641..0d9305818f 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -43,17 +43,6 @@ struct target_stackf { abi_ulong xargs[8]; }; -typedef struct { - struct { - abi_ulong psr; - abi_ulong pc; - abi_ulong npc; - abi_ulong y; - abi_ulong u_regs[16]; /* globals and ins */ - } si_regs; - int si_mask; -} __siginfo_t; - typedef struct { abi_ulong si_float_regs[32]; unsigned long si_fsr; @@ -67,7 +56,8 @@ typedef struct { struct target_signal_frame { struct target_stackf ss; - __siginfo_t info; + struct target_pt_regs regs; + uint32_t si_mask; abi_ulong fpu_save; uint32_t insns[2] QEMU_ALIGNED(8); abi_ulong extramask[TARGET_NSIG_WORDS - 1]; @@ -103,23 +93,61 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa, return sp; } -static int -setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask) +static void save_pt_regs(struct target_pt_regs *regs, CPUSPARCState *env) { - int err = 0, i; + int i; - __put_user(env->psr, &si->si_regs.psr); - __put_user(env->pc, &si->si_regs.pc); - __put_user(env->npc, &si->si_regs.npc); - __put_user(env->y, &si->si_regs.y); - for (i=0; i < 8; i++) { - __put_user(env->gregs[i], &si->si_regs.u_regs[i]); +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) + __put_user(sparc64_tstate(env), ®s->tstate); + /* TODO: magic should contain PT_REG_MAGIC + %tt. */ + __put_user(0, ®s->magic); +#else + __put_user(cpu_get_psr(env), ®s->psr); +#endif + + __put_user(env->pc, ®s->pc); + __put_user(env->npc, ®s->npc); + __put_user(env->y, ®s->y); + + for (i = 0; i < 8; i++) { + __put_user(env->gregs[i], ®s->u_regs[i]); } - for (i=0; i < 8; i++) { - __put_user(env->regwptr[WREG_O0 + i], &si->si_regs.u_regs[i + 8]); + for (i = 0; i < 8; i++) { + __put_user(env->regwptr[WREG_O0 + i], ®s->u_regs[i + 8]); + } +} + +static void restore_pt_regs(struct target_pt_regs *regs, CPUSPARCState *env) +{ + int i; + +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) + /* User can only change condition codes and %asi in %tstate. */ + uint64_t tstate; + __get_user(tstate, ®s->tstate); + cpu_put_ccr(env, tstate >> 32); + env->asi = extract64(tstate, 24, 8); +#else + /* + * User can only change condition codes and FPU enabling in %psr. + * But don't bother with FPU enabling, since a real kernel would + * just re-enable the FPU upon the next fpu trap. + */ + uint32_t psr; + __get_user(psr, ®s->psr); + env->psr = (psr & PSR_ICC) | (env->psr & ~PSR_ICC); +#endif + + /* Note that pc and npc are handled in the caller. */ + + __get_user(env->y, ®s->y); + + for (i = 0; i < 8; i++) { + __get_user(env->gregs[i], ®s->u_regs[i]); + } + for (i = 0; i < 8; i++) { + __get_user(env->regwptr[WREG_O0 + i], ®s->u_regs[i + 8]); } - __put_user(mask, &si->si_mask); - return err; } #define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7))) @@ -129,7 +157,7 @@ void setup_frame(int sig, struct target_sigaction *ka, { abi_ulong sf_addr; struct target_signal_frame *sf; - int sigframe_size, err, i; + int sigframe_size, i; /* 1. Make sure everything is clean */ //synchronize_user_stack(); @@ -143,18 +171,14 @@ void setup_frame(int sig, struct target_sigaction *ka, if (!sf) { goto sigsegv; } -#if 0 - if (invalid_frame_pointer(sf, sigframe_size)) - goto sigill_and_return; -#endif /* 2. Save the current process state */ - err = setup___siginfo(&sf->info, env, set->sig[0]); + save_pt_regs(&sf->regs, env); __put_user(0, &sf->extra_size); //save_fpu_state(regs, &sf->fpu_state); //__put_user(&sf->fpu_state, &sf->fpu_save); - __put_user(set->sig[0], &sf->info.si_mask); + __put_user(set->sig[0], &sf->si_mask); for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) { __put_user(set->sig[i + 1], &sf->extramask[i]); } @@ -165,16 +189,14 @@ void setup_frame(int sig, struct target_sigaction *ka, for (i = 0; i < 8; i++) { __put_user(env->regwptr[i + WREG_I0], &sf->ss.win.ins[i]); } - if (err) - goto sigsegv; /* 3. signal handler back-trampoline and parameters */ env->regwptr[WREG_SP] = sf_addr; env->regwptr[WREG_O0] = sig; env->regwptr[WREG_O1] = sf_addr + - offsetof(struct target_signal_frame, info); + offsetof(struct target_signal_frame, regs); env->regwptr[WREG_O2] = sf_addr + - offsetof(struct target_signal_frame, info); + offsetof(struct target_signal_frame, regs); /* 4. signal handler */ env->pc = ka->_sa_handler; @@ -218,7 +240,7 @@ long do_sigreturn(CPUSPARCState *env) { abi_ulong sf_addr; struct target_signal_frame *sf; - abi_ulong up_psr, pc, npc; + abi_ulong pc, npc; target_sigset_t set; sigset_t host_set; int i; @@ -234,29 +256,17 @@ long do_sigreturn(CPUSPARCState *env) if (sf_addr & 3) goto segv_and_exit; - __get_user(pc, &sf->info.si_regs.pc); - __get_user(npc, &sf->info.si_regs.npc); + __get_user(pc, &sf->regs.pc); + __get_user(npc, &sf->regs.npc); if ((pc | npc) & 3) { goto segv_and_exit; } /* 2. Restore the state */ - __get_user(up_psr, &sf->info.si_regs.psr); - - /* User can only change condition codes and FPU enabling in %psr. */ - env->psr = (up_psr & (PSR_ICC /* | PSR_EF */)) - | (env->psr & ~(PSR_ICC /* | PSR_EF */)); - + restore_pt_regs(&sf->regs, env); env->pc = pc; env->npc = npc; - __get_user(env->y, &sf->info.si_regs.y); - for (i=0; i < 8; i++) { - __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]); - } - for (i=0; i < 8; i++) { - __get_user(env->regwptr[i + WREG_O0], &sf->info.si_regs.u_regs[i + 8]); - } /* FIXME: implement FPU save/restore: * __get_user(fpu_save, &sf->fpu_save); @@ -267,11 +277,8 @@ long do_sigreturn(CPUSPARCState *env) * } */ - /* This is pretty much atomic, no amount locking would prevent - * the races which exist anyways. - */ - __get_user(set.sig[0], &sf->info.si_mask); - for(i = 1; i < TARGET_NSIG_WORDS; i++) { + __get_user(set.sig[0], &sf->si_mask); + for (i = 1; i < TARGET_NSIG_WORDS; i++) { __get_user(set.sig[i], &sf->extramask[i - 1]); } From 44a5f861718caeb6f7b1ac7a6c279d32fc84041a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:25 -0700 Subject: [PATCH 23/59] linux-user/sparc: Split out save_reg_win Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-17-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 0d9305818f..69fee5a76a 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -150,6 +150,18 @@ static void restore_pt_regs(struct target_pt_regs *regs, CPUSPARCState *env) } } +static void save_reg_win(struct target_reg_window *win, CPUSPARCState *env) +{ + int i; + + for (i = 0; i < 8; i++) { + __put_user(env->regwptr[i + WREG_L0], &win->locals[i]); + } + for (i = 0; i < 8; i++) { + __put_user(env->regwptr[i + WREG_I0], &win->ins[i]); + } +} + #define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7))) void setup_frame(int sig, struct target_sigaction *ka, @@ -183,12 +195,7 @@ void setup_frame(int sig, struct target_sigaction *ka, __put_user(set->sig[i + 1], &sf->extramask[i]); } - for (i = 0; i < 8; i++) { - __put_user(env->regwptr[i + WREG_L0], &sf->ss.win.locals[i]); - } - for (i = 0; i < 8; i++) { - __put_user(env->regwptr[i + WREG_I0], &sf->ss.win.ins[i]); - } + save_reg_win(&sf->ss.win, env); /* 3. signal handler back-trampoline and parameters */ env->regwptr[WREG_SP] = sf_addr; From a0774ec4d4934b375a118a65104f658ef3b5b834 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:26 -0700 Subject: [PATCH 24/59] linux-user/sparc: Clean up get_sigframe Remove inline; fix spacing and comment format. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-18-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 69fee5a76a..57dbc72c99 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -65,24 +65,25 @@ struct target_signal_frame { qemu_siginfo_fpu_t fpu_state; }; -static inline abi_ulong get_sigframe(struct target_sigaction *sa, - CPUSPARCState *env, - unsigned long framesize) +static abi_ulong get_sigframe(struct target_sigaction *sa, + CPUSPARCState *env, + size_t framesize) { abi_ulong sp = get_sp_from_cpustate(env); /* * If we are on the alternate signal stack and would overflow it, don't. * Return an always-bogus address instead so we will die with SIGSEGV. - */ + */ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) { - return -1; + return -1; } /* This is the X/Open sanctioned signal stack switching. */ sp = target_sigsp(sp, sa) - framesize; - /* Always align the stack frame. This handles two cases. First, + /* + * Always align the stack frame. This handles two cases. First, * sigaltstack need not be mindful of platform specific stack * alignment. Second, if we took this signal because the stack * is not aligned properly, we'd like to take the signal cleanly From 71cda6e9128d3f47634ebc8cda7125d5039e43ac Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:27 -0700 Subject: [PATCH 25/59] linux-user/sparc: Save and restore fpu in signal frame Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-19-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 84 ++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 57dbc72c99..59bb449512 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -43,26 +43,25 @@ struct target_stackf { abi_ulong xargs[8]; }; -typedef struct { - abi_ulong si_float_regs[32]; - unsigned long si_fsr; - unsigned long si_fpqdepth; +struct target_siginfo_fpu { + /* It is more convenient for qemu to move doubles, not singles. */ + uint64_t si_double_regs[16]; + uint32_t si_fsr; + uint32_t si_fpqdepth; struct { - unsigned long *insn_addr; - unsigned long insn; + uint32_t insn_addr; + uint32_t insn; } si_fpqueue [16]; -} qemu_siginfo_fpu_t; - +}; struct target_signal_frame { struct target_stackf ss; struct target_pt_regs regs; - uint32_t si_mask; - abi_ulong fpu_save; - uint32_t insns[2] QEMU_ALIGNED(8); - abi_ulong extramask[TARGET_NSIG_WORDS - 1]; - abi_ulong extra_size; /* Should be 0 */ - qemu_siginfo_fpu_t fpu_state; + uint32_t si_mask; + abi_ulong fpu_save; + uint32_t insns[2] QEMU_ALIGNED(8); + abi_ulong extramask[TARGET_NSIG_WORDS - 1]; + abi_ulong extra_size; /* Should be 0 */ }; static abi_ulong get_sigframe(struct target_sigaction *sa, @@ -163,33 +162,51 @@ static void save_reg_win(struct target_reg_window *win, CPUSPARCState *env) } } -#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7))) +static void save_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) +{ + int i; + + for (i = 0; i < 16; ++i) { + __put_user(env->fpr[i].ll, &fpu->si_double_regs[i]); + } + __put_user(env->fsr, &fpu->si_fsr); + __put_user(0, &fpu->si_fpqdepth); +} + +static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) +{ + int i; + + for (i = 0; i < 16; ++i) { + __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]); + } + __get_user(env->fsr, &fpu->si_fsr); +} void setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUSPARCState *env) { abi_ulong sf_addr; struct target_signal_frame *sf; - int sigframe_size, i; + size_t sf_size = sizeof(*sf) + sizeof(struct target_siginfo_fpu); + int i; /* 1. Make sure everything is clean */ - //synchronize_user_stack(); - sigframe_size = NF_ALIGNEDSZ; - sf_addr = get_sigframe(ka, env, sigframe_size); + sf_addr = get_sigframe(ka, env, sf_size); trace_user_setup_frame(env, sf_addr); - sf = lock_user(VERIFY_WRITE, sf_addr, - sizeof(struct target_signal_frame), 0); + sf = lock_user(VERIFY_WRITE, sf_addr, sf_size, 0); if (!sf) { goto sigsegv; } + /* 2. Save the current process state */ save_pt_regs(&sf->regs, env); __put_user(0, &sf->extra_size); - //save_fpu_state(regs, &sf->fpu_state); - //__put_user(&sf->fpu_state, &sf->fpu_save); + save_fpu((struct target_siginfo_fpu *)(sf + 1), env); + __put_user(sf_addr + sizeof(*sf), &sf->fpu_save); __put_user(set->sig[0], &sf->si_mask); for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) { @@ -226,7 +243,7 @@ void setup_frame(int sig, struct target_sigaction *ka, val32 = 0x91d02010; __put_user(val32, &sf->insns[1]); } - unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); + unlock_user(sf, sf_addr, sf_size); return; #if 0 sigill_and_return: @@ -248,7 +265,7 @@ long do_sigreturn(CPUSPARCState *env) { abi_ulong sf_addr; struct target_signal_frame *sf; - abi_ulong pc, npc; + abi_ulong pc, npc, ptr; target_sigset_t set; sigset_t host_set; int i; @@ -276,14 +293,15 @@ long do_sigreturn(CPUSPARCState *env) env->pc = pc; env->npc = npc; - /* FIXME: implement FPU save/restore: - * __get_user(fpu_save, &sf->fpu_save); - * if (fpu_save) { - * if (restore_fpu_state(env, fpu_save)) { - * goto segv_and_exit; - * } - * } - */ + __get_user(ptr, &sf->fpu_save); + if (ptr) { + struct target_siginfo_fpu *fpu; + if ((ptr & 3) || !lock_user_struct(VERIFY_READ, fpu, ptr, 1)) { + goto segv_and_exit; + } + restore_fpu(fpu, env); + unlock_user_struct(fpu, ptr, 0); + } __get_user(set.sig[0], &sf->si_mask); for (i = 1; i < TARGET_NSIG_WORDS; i++) { From 819f6df1ef83385e59e182dc6223d1ad533d393c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:28 -0700 Subject: [PATCH 26/59] linux-user/sparc: Add rwin_save to signal frame Stub it out to zero, but at least include it. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-20-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 59bb449512..4a0578ebf3 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -62,6 +62,7 @@ struct target_signal_frame { uint32_t insns[2] QEMU_ALIGNED(8); abi_ulong extramask[TARGET_NSIG_WORDS - 1]; abi_ulong extra_size; /* Should be 0 */ + abi_ulong rwin_save; }; static abi_ulong get_sigframe(struct target_sigaction *sa, @@ -208,6 +209,8 @@ void setup_frame(int sig, struct target_sigaction *ka, save_fpu((struct target_siginfo_fpu *)(sf + 1), env); __put_user(sf_addr + sizeof(*sf), &sf->fpu_save); + __put_user(0, &sf->rwin_save); /* TODO: save_rwin_state */ + __put_user(set->sig[0], &sf->si_mask); for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) { __put_user(set->sig[i + 1], &sf->extramask[i]); @@ -303,6 +306,11 @@ long do_sigreturn(CPUSPARCState *env) unlock_user_struct(fpu, ptr, 0); } + __get_user(ptr, &sf->rwin_save); + if (ptr) { + goto segv_and_exit; /* TODO: restore_rwin */ + } + __get_user(set.sig[0], &sf->si_mask); for (i = 1; i < TARGET_NSIG_WORDS; i++) { __get_user(set.sig[i], &sf->extramask[i - 1]); From 757d260143488d1d0b4016020969ab28259b854b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:29 -0700 Subject: [PATCH 27/59] linux-user/sparc: Clean up setup_frame Clean up a goto label with a single use. Remove #if 0. Remove useless parentheses. Fold constants into __put_user. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-21-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 4a0578ebf3..f0f614a3af 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -192,14 +192,13 @@ void setup_frame(int sig, struct target_sigaction *ka, size_t sf_size = sizeof(*sf) + sizeof(struct target_siginfo_fpu); int i; - /* 1. Make sure everything is clean */ - sf_addr = get_sigframe(ka, env, sf_size); trace_user_setup_frame(env, sf_addr); sf = lock_user(VERIFY_WRITE, sf_addr, sf_size, 0); if (!sf) { - goto sigsegv; + force_sigsegv(sig); + return; } /* 2. Save the current process state */ @@ -228,33 +227,21 @@ void setup_frame(int sig, struct target_sigaction *ka, /* 4. signal handler */ env->pc = ka->_sa_handler; - env->npc = (env->pc + 4); + env->npc = env->pc + 4; + /* 5. return to kernel instructions */ if (ka->ka_restorer) { env->regwptr[WREG_O7] = ka->ka_restorer; } else { - uint32_t val32; - env->regwptr[WREG_O7] = sf_addr + offsetof(struct target_signal_frame, insns) - 2 * 4; /* mov __NR_sigreturn, %g1 */ - val32 = 0x821020d8; - __put_user(val32, &sf->insns[0]); - + __put_user(0x821020d8u, &sf->insns[0]); /* t 0x10 */ - val32 = 0x91d02010; - __put_user(val32, &sf->insns[1]); + __put_user(0x91d02010u, &sf->insns[1]); } unlock_user(sf, sf_addr, sf_size); - return; -#if 0 -sigill_and_return: - force_sig(TARGET_SIGILL); -#endif -sigsegv: - unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); - force_sigsegv(sig); } void setup_rt_frame(int sig, struct target_sigaction *ka, From 1176e57a8b34c845a89b2b0f86e424a825d40faa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:30 -0700 Subject: [PATCH 28/59] linux-user/sparc: Minor corrections to do_sigreturn Check that the input sp is 16 byte aligned, not 4. Do that before the lock_user_struct check. Validate the saved sp is 8 byte aligned. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-22-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index f0f614a3af..0ff57af43d 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -254,7 +254,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, long do_sigreturn(CPUSPARCState *env) { abi_ulong sf_addr; - struct target_signal_frame *sf; + struct target_signal_frame *sf = NULL; abi_ulong pc, npc, ptr; target_sigset_t set; sigset_t host_set; @@ -262,18 +262,21 @@ long do_sigreturn(CPUSPARCState *env) sf_addr = env->regwptr[WREG_SP]; trace_user_do_sigreturn(env, sf_addr); - if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) { + + /* 1. Make sure we are not getting garbage from the user */ + if ((sf_addr & 15) || !lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) { goto segv_and_exit; } - /* 1. Make sure we are not getting garbage from the user */ - - if (sf_addr & 3) + /* Make sure stack pointer is aligned. */ + __get_user(ptr, &sf->regs.u_regs[14]); + if (ptr & 7) { goto segv_and_exit; + } - __get_user(pc, &sf->regs.pc); + /* Make sure instruction pointers are aligned. */ + __get_user(pc, &sf->regs.pc); __get_user(npc, &sf->regs.npc); - if ((pc | npc) & 3) { goto segv_and_exit; } @@ -309,7 +312,7 @@ long do_sigreturn(CPUSPARCState *env) unlock_user_struct(sf, sf_addr, 0); return -TARGET_QEMU_ESIGRETURN; -segv_and_exit: + segv_and_exit: unlock_user_struct(sf, sf_addr, 0); force_sig(TARGET_SIGSEGV); return -TARGET_QEMU_ESIGRETURN; From 11670e849227890e7ab3f1413bae28bf6a0f6707 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:31 -0700 Subject: [PATCH 29/59] linux-user/sparc: Add 64-bit support to fpu save/restore The shape of the kernel's __siginfo_fpu_t is dependent on the cpu type, not the abi. Which is weird, but there ya go. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-23-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 0ff57af43d..41a8b33bac 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -44,6 +44,12 @@ struct target_stackf { }; struct target_siginfo_fpu { +#ifdef TARGET_SPARC64 + uint64_t si_double_regs[32]; + uint64_t si_fsr; + uint64_t si_gsr; + uint64_t si_fprs; +#else /* It is more convenient for qemu to move doubles, not singles. */ uint64_t si_double_regs[16]; uint32_t si_fsr; @@ -52,6 +58,7 @@ struct target_siginfo_fpu { uint32_t insn_addr; uint32_t insn; } si_fpqueue [16]; +#endif }; struct target_signal_frame { @@ -167,21 +174,50 @@ static void save_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) { int i; +#ifdef TARGET_SPARC64 + for (i = 0; i < 32; ++i) { + __put_user(env->fpr[i].ll, &fpu->si_double_regs[i]); + } + __put_user(env->fsr, &fpu->si_fsr); + __put_user(env->gsr, &fpu->si_gsr); + __put_user(env->fprs, &fpu->si_fprs); +#else for (i = 0; i < 16; ++i) { __put_user(env->fpr[i].ll, &fpu->si_double_regs[i]); } __put_user(env->fsr, &fpu->si_fsr); __put_user(0, &fpu->si_fpqdepth); +#endif } static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) { int i; +#ifdef TARGET_SPARC64 + uint64_t fprs; + __get_user(fprs, &fpu->si_fprs); + + /* In case the user mucks about with FPRS, restore as directed. */ + if (fprs & FPRS_DL) { + for (i = 0; i < 16; ++i) { + __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]); + } + } + if (fprs & FPRS_DU) { + for (i = 16; i < 32; ++i) { + __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]); + } + } + __get_user(env->fsr, &fpu->si_fsr); + __get_user(env->gsr, &fpu->si_gsr); + env->fprs |= fprs; +#else for (i = 0; i < 16; ++i) { __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]); } __get_user(env->fsr, &fpu->si_fsr); +#endif } void setup_frame(int sig, struct target_sigaction *ka, From e76f2f847d6e09e948ccb74657567535c5dfa398 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:32 -0700 Subject: [PATCH 30/59] linux-user/sparc: Implement sparc32 rt signals Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-24-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 126 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 4 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 41a8b33bac..362993da02 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -72,6 +72,18 @@ struct target_signal_frame { abi_ulong rwin_save; }; +struct target_rt_signal_frame { + struct target_stackf ss; + target_siginfo_t info; + struct target_pt_regs regs; + target_sigset_t mask; + abi_ulong fpu_save; + uint32_t insns[2]; + target_stack_t stack; + abi_ulong extra_size; /* Should be 0 */ + abi_ulong rwin_save; +}; + static abi_ulong get_sigframe(struct target_sigaction *sa, CPUSPARCState *env, size_t framesize) @@ -284,7 +296,59 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUSPARCState *env) { - qemu_log_mask(LOG_UNIMP, "setup_rt_frame: not implemented\n"); + abi_ulong sf_addr; + struct target_rt_signal_frame *sf; + size_t sf_size = sizeof(*sf) + sizeof(struct target_siginfo_fpu); + + sf_addr = get_sigframe(ka, env, sf_size); + trace_user_setup_rt_frame(env, sf_addr); + + sf = lock_user(VERIFY_WRITE, sf_addr, sf_size, 0); + if (!sf) { + force_sigsegv(sig); + return; + } + + /* 2. Save the current process state */ + save_reg_win(&sf->ss.win, env); + save_pt_regs(&sf->regs, env); + + save_fpu((struct target_siginfo_fpu *)(sf + 1), env); + __put_user(sf_addr + sizeof(*sf), &sf->fpu_save); + + __put_user(0, &sf->rwin_save); /* TODO: save_rwin_state */ + + tswap_siginfo(&sf->info, info); + tswap_sigset(&sf->mask, set); + target_save_altstack(&sf->stack, env); + + __put_user(0, &sf->extra_size); + + /* 3. signal handler back-trampoline and parameters */ + env->regwptr[WREG_SP] = sf_addr; + env->regwptr[WREG_O0] = sig; + env->regwptr[WREG_O1] = + sf_addr + offsetof(struct target_rt_signal_frame, info); + env->regwptr[WREG_O2] = + sf_addr + offsetof(struct target_rt_signal_frame, regs); + + /* 4. signal handler */ + env->pc = ka->_sa_handler; + env->npc = env->pc + 4; + + /* 5. return to kernel instructions */ + if (ka->ka_restorer) { + env->regwptr[WREG_O7] = ka->ka_restorer; + } else { + env->regwptr[WREG_O7] = + sf_addr + offsetof(struct target_rt_signal_frame, insns) - 2 * 4; + + /* mov __NR_rt_sigreturn, %g1 */ + __put_user(0x82102065u, &sf->insns[0]); + /* t 0x10 */ + __put_user(0x91d02010u, &sf->insns[1]); + } + unlock_user(sf, sf_addr, sf_size); } long do_sigreturn(CPUSPARCState *env) @@ -356,9 +420,63 @@ long do_sigreturn(CPUSPARCState *env) long do_rt_sigreturn(CPUSPARCState *env) { - trace_user_do_rt_sigreturn(env, 0); - qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n"); - return -TARGET_ENOSYS; + abi_ulong sf_addr, tpc, tnpc, ptr; + struct target_rt_signal_frame *sf = NULL; + sigset_t set; + + sf_addr = get_sp_from_cpustate(env); + trace_user_do_rt_sigreturn(env, sf_addr); + + /* 1. Make sure we are not getting garbage from the user */ + if ((sf_addr & 15) || !lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) { + goto segv_and_exit; + } + + /* Validate SP alignment. */ + __get_user(ptr, &sf->regs.u_regs[8 + WREG_SP]); + if ((ptr + TARGET_STACK_BIAS) & 7) { + goto segv_and_exit; + } + + /* Validate PC and NPC alignment. */ + __get_user(tpc, &sf->regs.pc); + __get_user(tnpc, &sf->regs.npc); + if ((tpc | tnpc) & 3) { + goto segv_and_exit; + } + + /* 2. Restore the state */ + restore_pt_regs(&sf->regs, env); + + __get_user(ptr, &sf->fpu_save); + if (ptr) { + struct target_siginfo_fpu *fpu; + if ((ptr & 7) || !lock_user_struct(VERIFY_READ, fpu, ptr, 1)) { + goto segv_and_exit; + } + restore_fpu(fpu, env); + unlock_user_struct(fpu, ptr, 0); + } + + __get_user(ptr, &sf->rwin_save); + if (ptr) { + goto segv_and_exit; /* TODO: restore_rwin_state */ + } + + target_restore_altstack(&sf->stack, env); + target_to_host_sigset(&set, &sf->mask); + set_sigmask(&set); + + env->pc = tpc; + env->npc = tnpc; + + unlock_user_struct(sf, sf_addr, 0); + return -TARGET_QEMU_ESIGRETURN; + + segv_and_exit: + unlock_user_struct(sf, sf_addr, 0); + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; } #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) From bb3347f80f98df3935d7018a74a6dd777f2849fa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:33 -0700 Subject: [PATCH 31/59] linux-user/sparc: Implement sparc64 rt signals Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-25-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/signal.c | 27 ++++++++++++++++++++++++++- linux-user/sparc/target_signal.h | 2 ++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 362993da02..0cc3db5570 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -61,6 +61,7 @@ struct target_siginfo_fpu { #endif }; +#ifdef TARGET_ARCH_HAS_SETUP_FRAME struct target_signal_frame { struct target_stackf ss; struct target_pt_regs regs; @@ -71,16 +72,23 @@ struct target_signal_frame { abi_ulong extra_size; /* Should be 0 */ abi_ulong rwin_save; }; +#endif struct target_rt_signal_frame { struct target_stackf ss; target_siginfo_t info; struct target_pt_regs regs; +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) + abi_ulong fpu_save; + target_stack_t stack; + target_sigset_t mask; +#else target_sigset_t mask; abi_ulong fpu_save; uint32_t insns[2]; target_stack_t stack; abi_ulong extra_size; /* Should be 0 */ +#endif abi_ulong rwin_save; }; @@ -232,6 +240,7 @@ static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env) #endif } +#ifdef TARGET_ARCH_HAS_SETUP_FRAME void setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUSPARCState *env) { @@ -291,6 +300,7 @@ void setup_frame(int sig, struct target_sigaction *ka, } unlock_user(sf, sf_addr, sf_size); } +#endif /* TARGET_ARCH_HAS_SETUP_FRAME */ void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, @@ -322,21 +332,28 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, tswap_sigset(&sf->mask, set); target_save_altstack(&sf->stack, env); +#ifdef TARGET_ABI32 __put_user(0, &sf->extra_size); +#endif /* 3. signal handler back-trampoline and parameters */ - env->regwptr[WREG_SP] = sf_addr; + env->regwptr[WREG_SP] = sf_addr - TARGET_STACK_BIAS; env->regwptr[WREG_O0] = sig; env->regwptr[WREG_O1] = sf_addr + offsetof(struct target_rt_signal_frame, info); +#ifdef TARGET_ABI32 env->regwptr[WREG_O2] = sf_addr + offsetof(struct target_rt_signal_frame, regs); +#else + env->regwptr[WREG_O2] = env->regwptr[WREG_O1]; +#endif /* 4. signal handler */ env->pc = ka->_sa_handler; env->npc = env->pc + 4; /* 5. return to kernel instructions */ +#ifdef TARGET_ABI32 if (ka->ka_restorer) { env->regwptr[WREG_O7] = ka->ka_restorer; } else { @@ -348,11 +365,16 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, /* t 0x10 */ __put_user(0x91d02010u, &sf->insns[1]); } +#else + env->regwptr[WREG_O7] = ka->ka_restorer; +#endif + unlock_user(sf, sf_addr, sf_size); } long do_sigreturn(CPUSPARCState *env) { +#ifdef TARGET_ARCH_HAS_SETUP_FRAME abi_ulong sf_addr; struct target_signal_frame *sf = NULL; abi_ulong pc, npc, ptr; @@ -416,6 +438,9 @@ long do_sigreturn(CPUSPARCState *env) unlock_user_struct(sf, sf_addr, 0); force_sig(TARGET_SIGSEGV); return -TARGET_QEMU_ESIGRETURN; +#else + return -TARGET_ENOSYS; +#endif } long do_rt_sigreturn(CPUSPARCState *env) diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h index 911a3f5af5..34f9a12519 100644 --- a/linux-user/sparc/target_signal.h +++ b/linux-user/sparc/target_signal.h @@ -67,7 +67,9 @@ typedef struct target_sigaltstack { #define TARGET_MINSIGSTKSZ 4096 #define TARGET_SIGSTKSZ 16384 +#ifdef TARGET_ABI32 #define TARGET_ARCH_HAS_SETUP_FRAME +#endif /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ From 4cce45df712650e494784415167a9e6a3f3d5136 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 25 Apr 2021 19:53:34 -0700 Subject: [PATCH 32/59] tests/tcg/sparc64: Re-enable linux-test It passes now that we support signals properly. Signed-off-by: Richard Henderson Message-Id: <20210426025334.1168495-26-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- tests/tcg/sparc64/Makefile.target | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/tcg/sparc64/Makefile.target b/tests/tcg/sparc64/Makefile.target index 5bd7f90583..408dace783 100644 --- a/tests/tcg/sparc64/Makefile.target +++ b/tests/tcg/sparc64/Makefile.target @@ -1,11 +1,6 @@ # -*- Mode: makefile -*- # -# sparc specific tweaks and masking out broken tests - -# different from the other hangs: -# tests/tcg/multiarch/linux-test.c:264: Value too large for defined data type (ret=-1, errno=92/Value too large for defined data type) -run-linux-test: linux-test - $(call skip-test, $<, "BROKEN") +# sparc specific tweaks # On Sparc64 Linux support 8k pages EXTRA_RUNS+=run-test-mmap-8192 From 5d79bd111ff4f9ed0b19c20f6708a770651a9048 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:33:54 -0700 Subject: [PATCH 33/59] linux-user/s390x: Fix sigframe types Noticed via gitlab clang-user job: TEST signals on s390x ../linux-user/s390x/signal.c:258:9: runtime error: \ 1.84467e+19 is outside the range of representable values of \ type 'unsigned long' Which points to the fact that we were performing a double-to-uint64_t conversion while storing the fp registers, instead of just copying the data across. Turns out there are several errors: target_ulong is the size of the target register, whereas abi_ulong is the target 'unsigned long' type. Not a big deal here, since we only support 64-bit s390x, but not correct either. In target_sigcontext and target ucontext, we used a host pointer instead of a target pointer, aka abi_ulong. Fixing this allows the removal of a cast to __put_user. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index b68b44ae7e..707fb603d7 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -37,13 +37,14 @@ typedef struct { target_psw_t psw; - target_ulong gprs[__NUM_GPRS]; - unsigned int acrs[__NUM_ACRS]; + abi_ulong gprs[__NUM_GPRS]; + abi_uint acrs[__NUM_ACRS]; } target_s390_regs_common; typedef struct { - unsigned int fpc; - double fprs[__NUM_FPRS]; + uint32_t fpc; + uint32_t pad; + uint64_t fprs[__NUM_FPRS]; } target_s390_fp_regs; typedef struct { @@ -51,22 +52,22 @@ typedef struct { target_s390_fp_regs fpregs; } target_sigregs; -struct target_sigcontext { - target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS]; - target_sigregs *sregs; -}; +typedef struct { + abi_ulong oldmask[_SIGCONTEXT_NSIG_WORDS]; + abi_ulong sregs; +} target_sigcontext; typedef struct { uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; - struct target_sigcontext sc; + target_sigcontext sc; target_sigregs sregs; int signo; uint8_t retcode[S390_SYSCALL_SIZE]; } sigframe; struct target_ucontext { - target_ulong tuc_flags; - struct target_ucontext *tuc_link; + abi_ulong tuc_flags; + abi_ulong tuc_link; target_stack_t tuc_stack; target_sigregs tuc_mcontext; target_sigset_t tuc_sigmask; /* mask last for extensibility */ @@ -143,8 +144,7 @@ void setup_frame(int sig, struct target_sigaction *ka, save_sigregs(env, &frame->sregs); - __put_user((abi_ulong)(unsigned long)&frame->sregs, - (abi_ulong *)&frame->sc.sregs); + __put_user((abi_ulong)(unsigned long)&frame->sregs, &frame->sc.sregs); /* Set up to return from userspace. If provided, use a stub already in userspace. */ From cb1f198296dd9d7787328eab5beb2e31f550ba63 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:33:55 -0700 Subject: [PATCH 34/59] linux-user/s390x: Use uint16_t for signal retcode Using the right type simplifies the frame setup. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 707fb603d7..fece8ab97b 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -25,7 +25,6 @@ #define __NUM_FPRS 16 #define __NUM_ACRS 16 -#define S390_SYSCALL_SIZE 2 #define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */ #define _SIGCONTEXT_NSIG 64 @@ -62,7 +61,7 @@ typedef struct { target_sigcontext sc; target_sigregs sregs; int signo; - uint8_t retcode[S390_SYSCALL_SIZE]; + uint16_t retcode; } sigframe; struct target_ucontext { @@ -75,7 +74,7 @@ struct target_ucontext { typedef struct { uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; - uint8_t retcode[S390_SYSCALL_SIZE]; + uint16_t retcode; struct target_siginfo info; struct target_ucontext uc; } rt_sigframe; @@ -155,7 +154,7 @@ void setup_frame(int sig, struct target_sigaction *ka, env->regs[14] = (frame_addr + offsetof(sigframe, retcode)) | PSW_ADDR_AMODE; __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, - (uint16_t *)(frame->retcode)); + &frame->retcode); } /* Set up backchain. */ @@ -216,7 +215,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, env->regs[14] = (frame_addr + offsetof(typeof(*frame), retcode)) | PSW_ADDR_AMODE; __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, - (uint16_t *)(frame->retcode)); + &frame->retcode); } /* Set up backchain. */ From 915c69dc029e0fe509f8e4870993977068b66eaf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:33:56 -0700 Subject: [PATCH 35/59] linux-user/s390x: Remove PSW_ADDR_AMODE This is an unnecessary complication since we only support 64-bit mode. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index fece8ab97b..1dfca71fa9 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -31,7 +31,6 @@ #define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */ #define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW) #define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS) -#define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */ #define S390_SYSCALL_OPCODE ((uint16_t)0x0a00) typedef struct { @@ -148,11 +147,9 @@ void setup_frame(int sig, struct target_sigaction *ka, /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa_flags & TARGET_SA_RESTORER) { - env->regs[14] = (unsigned long) - ka->sa_restorer | PSW_ADDR_AMODE; + env->regs[14] = ka->sa_restorer; } else { - env->regs[14] = (frame_addr + offsetof(sigframe, retcode)) - | PSW_ADDR_AMODE; + env->regs[14] = frame_addr + offsetof(sigframe, retcode); __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, &frame->retcode); } @@ -162,7 +159,7 @@ void setup_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler */ env->regs[15] = frame_addr; - env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; + env->psw.addr = ka->_sa_handler; env->regs[2] = sig; //map_signal(sig); env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); @@ -210,10 +207,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa_flags & TARGET_SA_RESTORER) { - env->regs[14] = ka->sa_restorer | PSW_ADDR_AMODE; + env->regs[14] = ka->sa_restorer; } else { - env->regs[14] = (frame_addr + offsetof(typeof(*frame), retcode)) - | PSW_ADDR_AMODE; + env->regs[14] = frame_addr + offsetof(typeof(*frame), retcode); __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, &frame->retcode); } @@ -223,7 +219,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler */ env->regs[15] = frame_addr; - env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; + env->psw.addr = ka->_sa_handler; env->regs[2] = sig; //map_signal(sig); env->regs[3] = frame_addr + offsetof(typeof(*frame), info); @@ -248,7 +244,6 @@ restore_sigregs(CPUS390XState *env, target_sigregs *sc) trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr, (unsigned long long)env->psw.addr); __get_user(env->psw.addr, &sc->regs.psw.addr); - /* FIXME: 31-bit -> | PSW_ADDR_AMODE */ for (i = 0; i < 16; i++) { __get_user(env->aregs[i], &sc->regs.acrs[i]); From e6f960fcbe0d2ecd72d7f7d10a2ed510701db35e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:33:57 -0700 Subject: [PATCH 36/59] linux-user/s390x: Remove restore_sigregs return value The function cannot fail. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 1dfca71fa9..e455a9818d 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -230,10 +230,8 @@ give_sigsegv: force_sigsegv(sig); } -static int -restore_sigregs(CPUS390XState *env, target_sigregs *sc) +static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) { - int err = 0; int i; for (i = 0; i < 16; i++) { @@ -251,8 +249,6 @@ restore_sigregs(CPUS390XState *env, target_sigregs *sc) for (i = 0; i < 16; i++) { __get_user(*get_freg(env, i), &sc->fpregs.fprs[i]); } - - return err; } long do_sigreturn(CPUS390XState *env) @@ -271,9 +267,7 @@ long do_sigreturn(CPUS390XState *env) target_to_host_sigset_internal(&set, &target_set); set_sigmask(&set); /* ~_BLOCKABLE? */ - if (restore_sigregs(env, &frame->sregs)) { - goto badframe; - } + restore_sigregs(env, &frame->sregs); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; @@ -297,9 +291,7 @@ long do_rt_sigreturn(CPUS390XState *env) set_sigmask(&set); /* ~_BLOCKABLE? */ - if (restore_sigregs(env, &frame->uc.tuc_mcontext)) { - goto badframe; - } + restore_sigregs(env, &frame->uc.tuc_mcontext); target_restore_altstack(&frame->uc.tuc_stack, env); From bd45be9f5ffcaae68d2d0de2962cdc9fa20cb832 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:33:58 -0700 Subject: [PATCH 37/59] linux-user/s390x: Fix trace in restore_regs Directly reading sc->regs.psw.addr misses the bswap that may be performed by __get_user. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index e455a9818d..dcc6f7bc02 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -232,16 +232,17 @@ give_sigsegv: static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) { + target_ulong prev_addr; int i; for (i = 0; i < 16; i++) { __get_user(env->regs[i], &sc->regs.gprs[i]); } + prev_addr = env->psw.addr; __get_user(env->psw.mask, &sc->regs.psw.mask); - trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr, - (unsigned long long)env->psw.addr); __get_user(env->psw.addr, &sc->regs.psw.addr); + trace_user_s390x_restore_sigregs(env, env->psw.addr, prev_addr); for (i = 0; i < 16; i++) { __get_user(env->aregs[i], &sc->regs.acrs[i]); From 4e4a08200b6ed60055c45a0f05f4515365785a92 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:33:59 -0700 Subject: [PATCH 38/59] linux-user/s390x: Fix sigcontext sregs value Using the host address of &frame->sregs is incorrect. We need the guest address. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-7-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index dcc6f7bc02..f8515dd332 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -142,7 +142,7 @@ void setup_frame(int sig, struct target_sigaction *ka, save_sigregs(env, &frame->sregs); - __put_user((abi_ulong)(unsigned long)&frame->sregs, &frame->sc.sregs); + __put_user(frame_addr + offsetof(sigframe, sregs), &frame->sc.sregs); /* Set up to return from userspace. If provided, use a stub already in userspace. */ From bb17fc5b47af674ee429d4fca95485f9211aef4d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:00 -0700 Subject: [PATCH 39/59] linux-user/s390x: Use tswap_sigset in setup_rt_frame Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-8-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index f8515dd332..4dde55d4d5 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -182,7 +182,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUS390XState *env) { - int i; rt_sigframe *frame; abi_ulong frame_addr; @@ -199,10 +198,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link); target_save_altstack(&frame->uc.tuc_stack, env); save_sigregs(env, &frame->uc.tuc_mcontext); - for (i = 0; i < TARGET_NSIG_WORDS; i++) { - __put_user((abi_ulong)set->sig[i], - (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); - } + tswap_sigset(&frame->uc.tuc_sigmask, set); /* Set up to return from userspace. If provided, use a stub already in userspace. */ From 82839490e458a7e5022d6a0137c2a6a3eee0e9fc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:01 -0700 Subject: [PATCH 40/59] linux-user/s390x: Tidy save_sigregs The "save" routines copied from the kernel, which are currently commented out, are unnecessary in qemu. We can copy from env where the kernel needs special instructions. Fix comment style. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-9-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 4dde55d4d5..eabfe4293f 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -104,23 +104,25 @@ get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size) static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) { int i; - //save_access_regs(current->thread.acrs); FIXME - /* Copy a 'clean' PSW mask to the user to avoid leaking - information about whether PER is currently on. */ + /* + * Copy a 'clean' PSW mask to the user to avoid leaking + * information about whether PER is currently on. + */ __put_user(env->psw.mask, &sregs->regs.psw.mask); __put_user(env->psw.addr, &sregs->regs.psw.addr); + for (i = 0; i < 16; i++) { __put_user(env->regs[i], &sregs->regs.gprs[i]); } for (i = 0; i < 16; i++) { __put_user(env->aregs[i], &sregs->regs.acrs[i]); } + /* * We have to store the fp registers to current->thread.fp_regs * to merge them with the emulated registers. */ - //save_fp_regs(¤t->thread.fp_regs); FIXME for (i = 0; i < 16; i++) { __put_user(*get_freg(env, i), &sregs->fpregs.fprs[i]); } From 20807348806e12141347d87badd34e358971e7d5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:02 -0700 Subject: [PATCH 41/59] linux-user/s390x: Clean up single-use gotos in signal.c Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-10-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index eabfe4293f..64a9eab097 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -137,7 +137,8 @@ void setup_frame(int sig, struct target_sigaction *ka, frame_addr = get_sigframe(ka, env, sizeof(*frame)); trace_user_setup_frame(env, frame_addr); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { - goto give_sigsegv; + force_sigsegv(sig); + return; } __put_user(set->sig[0], &frame->sc.oldmask[0]); @@ -174,10 +175,6 @@ void setup_frame(int sig, struct target_sigaction *ka, /* Place signal number on stack to allow backtrace from handler. */ __put_user(env->regs[2], &frame->signo); unlock_user_struct(frame, frame_addr, 1); - return; - -give_sigsegv: - force_sigsegv(sig); } void setup_rt_frame(int sig, struct target_sigaction *ka, @@ -190,7 +187,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, frame_addr = get_sigframe(ka, env, sizeof *frame); trace_user_setup_rt_frame(env, frame_addr); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { - goto give_sigsegv; + force_sigsegv(sig); + return; } tswap_siginfo(&frame->info, info); @@ -222,10 +220,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, env->regs[2] = sig; //map_signal(sig); env->regs[3] = frame_addr + offsetof(typeof(*frame), info); env->regs[4] = frame_addr + offsetof(typeof(*frame), uc); - return; - -give_sigsegv: - force_sigsegv(sig); } static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) @@ -259,7 +253,8 @@ long do_sigreturn(CPUS390XState *env) trace_user_do_sigreturn(env, frame_addr); if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { - goto badframe; + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; } __get_user(target_set.sig[0], &frame->sc.oldmask[0]); @@ -270,10 +265,6 @@ long do_sigreturn(CPUS390XState *env) unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; - -badframe: - force_sig(TARGET_SIGSEGV); - return -TARGET_QEMU_ESIGRETURN; } long do_rt_sigreturn(CPUS390XState *env) @@ -284,7 +275,8 @@ long do_rt_sigreturn(CPUS390XState *env) trace_user_do_rt_sigreturn(env, frame_addr); if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { - goto badframe; + force_sig(TARGET_SIGSEGV); + return -TARGET_QEMU_ESIGRETURN; } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); @@ -296,9 +288,4 @@ long do_rt_sigreturn(CPUS390XState *env) unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; - -badframe: - unlock_user_struct(frame, frame_addr, 0); - force_sig(TARGET_SIGSEGV); - return -TARGET_QEMU_ESIGRETURN; } From 7e5355578eef26ece8a783f336b2c06a1f5a083a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:03 -0700 Subject: [PATCH 42/59] linux-user/s390x: Set psw.mask properly for the signal handler Note that PSW_ADDR_{64,32} are called PSW_MASK_{EA,BA} in the kernel source. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-11-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 64a9eab097..17f617c655 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -162,6 +162,9 @@ void setup_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler */ env->regs[15] = frame_addr; + /* Force default amode and default user address space control. */ + env->psw.mask = PSW_MASK_64 | PSW_MASK_32 | PSW_ASC_PRIMARY + | (env->psw.mask & ~PSW_MASK_ASC); env->psw.addr = ka->_sa_handler; env->regs[2] = sig; //map_signal(sig); @@ -215,6 +218,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, /* Set up registers for signal handler */ env->regs[15] = frame_addr; + /* Force default amode and default user address space control. */ + env->psw.mask = PSW_MASK_64 | PSW_MASK_32 | PSW_ASC_PRIMARY + | (env->psw.mask & ~PSW_MASK_ASC); env->psw.addr = ka->_sa_handler; env->regs[2] = sig; //map_signal(sig); From 6c18757dc55f0a47d926cec1aaab8c349a65a0c6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:04 -0700 Subject: [PATCH 43/59] linux-user/s390x: Add stub sigframe argument for last_break In order to properly present these arguments, we need to add code to target/s390x to record LowCore parameters for user-only. But in the meantime, at least zero the missing last_break argument, and fixup the comment style in the vicinity. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-12-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 17f617c655..bc41b01c5d 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -167,13 +167,16 @@ void setup_frame(int sig, struct target_sigaction *ka, | (env->psw.mask & ~PSW_MASK_ASC); env->psw.addr = ka->_sa_handler; - env->regs[2] = sig; //map_signal(sig); + env->regs[2] = sig; env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); - /* We forgot to include these in the sigcontext. - To avoid breaking binary compatibility, they are passed as args. */ - env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no; - env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr; + /* + * We forgot to include these in the sigcontext. + * To avoid breaking binary compatibility, they are passed as args. + */ + env->regs[4] = 0; /* FIXME: regs->int_code & 127 */ + env->regs[5] = 0; /* FIXME: regs->int_parm_long */ + env->regs[6] = 0; /* FIXME: current->thread.last_break */ /* Place signal number on stack to allow backtrace from handler. */ __put_user(env->regs[2], &frame->signo); @@ -223,9 +226,10 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, | (env->psw.mask & ~PSW_MASK_ASC); env->psw.addr = ka->_sa_handler; - env->regs[2] = sig; //map_signal(sig); + env->regs[2] = sig; env->regs[3] = frame_addr + offsetof(typeof(*frame), info); env->regs[4] = frame_addr + offsetof(typeof(*frame), uc); + env->regs[5] = 0; /* FIXME: current->thread.last_break */ } static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) From ac1a92ec8f1328141707965bb1df4252fdb76b68 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:05 -0700 Subject: [PATCH 44/59] linux-user/s390x: Fix frame_addr corruption in setup_frame The original value of frame_addr is still required for its use in the call to unlock_user_struct below. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-13-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index bc41b01c5d..81ba59b46a 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -168,7 +168,7 @@ void setup_frame(int sig, struct target_sigaction *ka, env->psw.addr = ka->_sa_handler; env->regs[2] = sig; - env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); + env->regs[3] = frame_addr + offsetof(typeof(*frame), sc); /* * We forgot to include these in the sigcontext. From 9e0fb648b259981350777020717bba8365957b0f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:06 -0700 Subject: [PATCH 45/59] linux-user/s390x: Add build asserts for sigset sizes At point of usage, it's not immediately obvious that we don't need a loop to copy these arrays. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-14-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 81ba59b46a..839a7ae4b3 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -141,6 +141,8 @@ void setup_frame(int sig, struct target_sigaction *ka, return; } + /* Make sure that we're initializing all of oldmask. */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(frame->sc.oldmask) != 1); __put_user(set->sig[0], &frame->sc.oldmask[0]); save_sigregs(env, &frame->sregs); @@ -266,6 +268,9 @@ long do_sigreturn(CPUS390XState *env) force_sig(TARGET_SIGSEGV); return -TARGET_QEMU_ESIGRETURN; } + + /* Make sure that we're initializing all of target_set. */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(target_set.sig) != 1); __get_user(target_set.sig[0], &frame->sc.oldmask[0]); target_to_host_sigset_internal(&set, &target_set); From 79d6f2baa4b738bb223a0ad382661fe501b0c867 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:07 -0700 Subject: [PATCH 46/59] linux-user/s390x: Clean up signal.c Reorder the function bodies to correspond to the kernel source. Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-15-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 67 ++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 839a7ae4b3..9d470e4ca0 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -133,6 +133,7 @@ void setup_frame(int sig, struct target_sigaction *ka, { sigframe *frame; abi_ulong frame_addr; + abi_ulong restorer; frame_addr = get_sigframe(ka, env, sizeof(*frame)); trace_user_setup_frame(env, frame_addr); @@ -141,28 +142,39 @@ void setup_frame(int sig, struct target_sigaction *ka, return; } + /* Set up backchain. */ + __put_user(env->regs[15], (abi_ulong *) frame); + + /* Create struct sigcontext on the signal stack. */ /* Make sure that we're initializing all of oldmask. */ QEMU_BUILD_BUG_ON(ARRAY_SIZE(frame->sc.oldmask) != 1); __put_user(set->sig[0], &frame->sc.oldmask[0]); - - save_sigregs(env, &frame->sregs); - __put_user(frame_addr + offsetof(sigframe, sregs), &frame->sc.sregs); - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ + /* Create _sigregs on the signal stack */ + save_sigregs(env, &frame->sregs); + + /* + * ??? The kernel uses regs->gprs[2] here, which is not yet the signo. + * Moreover the comment talks about allowing backtrace, which is really + * done by the r15 copy above. + */ + __put_user(sig, &frame->signo); + + /* + * Set up to return from userspace. + * If provided, use a stub already in userspace. + */ if (ka->sa_flags & TARGET_SA_RESTORER) { - env->regs[14] = ka->sa_restorer; + restorer = ka->sa_restorer; } else { - env->regs[14] = frame_addr + offsetof(sigframe, retcode); + restorer = frame_addr + offsetof(sigframe, retcode); __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, &frame->retcode); } - /* Set up backchain. */ - __put_user(env->regs[15], (abi_ulong *) frame); - /* Set up registers for signal handler */ + env->regs[14] = restorer; env->regs[15] = frame_addr; /* Force default amode and default user address space control. */ env->psw.mask = PSW_MASK_64 | PSW_MASK_32 | PSW_ASC_PRIMARY @@ -180,8 +192,6 @@ void setup_frame(int sig, struct target_sigaction *ka, env->regs[5] = 0; /* FIXME: regs->int_parm_long */ env->regs[6] = 0; /* FIXME: current->thread.last_break */ - /* Place signal number on stack to allow backtrace from handler. */ - __put_user(env->regs[2], &frame->signo); unlock_user_struct(frame, frame_addr, 1); } @@ -191,6 +201,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, { rt_sigframe *frame; abi_ulong frame_addr; + abi_ulong restorer; frame_addr = get_sigframe(ka, env, sizeof *frame); trace_user_setup_rt_frame(env, frame_addr); @@ -199,29 +210,33 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, return; } - tswap_siginfo(&frame->info, info); + /* Set up backchain. */ + __put_user(env->regs[15], (abi_ulong *) frame); - /* Create the ucontext. */ - __put_user(0, &frame->uc.tuc_flags); - __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link); - target_save_altstack(&frame->uc.tuc_stack, env); - save_sigregs(env, &frame->uc.tuc_mcontext); - tswap_sigset(&frame->uc.tuc_sigmask, set); - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ + /* + * Set up to return from userspace. + * If provided, use a stub already in userspace. + */ if (ka->sa_flags & TARGET_SA_RESTORER) { - env->regs[14] = ka->sa_restorer; + restorer = ka->sa_restorer; } else { - env->regs[14] = frame_addr + offsetof(typeof(*frame), retcode); + restorer = frame_addr + offsetof(typeof(*frame), retcode); __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, &frame->retcode); } - /* Set up backchain. */ - __put_user(env->regs[15], (abi_ulong *) frame); + /* Create siginfo on the signal stack. */ + tswap_siginfo(&frame->info, info); + + /* Create ucontext on the signal stack. */ + __put_user(0, &frame->uc.tuc_flags); + __put_user(0, &frame->uc.tuc_link); + target_save_altstack(&frame->uc.tuc_stack, env); + save_sigregs(env, &frame->uc.tuc_mcontext); + tswap_sigset(&frame->uc.tuc_sigmask, set); /* Set up registers for signal handler */ + env->regs[14] = restorer; env->regs[15] = frame_addr; /* Force default amode and default user address space control. */ env->psw.mask = PSW_MASK_64 | PSW_MASK_32 | PSW_ASC_PRIMARY From 0b16f04c1fa3f4f2abc538154c77b06c2aba52df Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 28 Apr 2021 12:34:08 -0700 Subject: [PATCH 47/59] linux-user/s390x: Handle vector regs in signal stack Signed-off-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20210428193408.233706-16-richard.henderson@linaro.org> [lv: fix indentation] Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 62 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 9d470e4ca0..ef136dae33 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -50,6 +50,12 @@ typedef struct { target_s390_fp_regs fpregs; } target_sigregs; +typedef struct { + uint64_t vxrs_low[16]; + uint64_t vxrs_high[16][2]; + uint8_t reserved[128]; +} target_sigregs_ext; + typedef struct { abi_ulong oldmask[_SIGCONTEXT_NSIG_WORDS]; abi_ulong sregs; @@ -60,15 +66,20 @@ typedef struct { target_sigcontext sc; target_sigregs sregs; int signo; + target_sigregs_ext sregs_ext; uint16_t retcode; } sigframe; +#define TARGET_UC_VXRS 2 + struct target_ucontext { abi_ulong tuc_flags; abi_ulong tuc_link; target_stack_t tuc_stack; target_sigregs tuc_mcontext; - target_sigset_t tuc_sigmask; /* mask last for extensibility */ + target_sigset_t tuc_sigmask; + uint8_t reserved[128 - sizeof(target_sigset_t)]; + target_sigregs_ext tuc_mcontext_ext; }; typedef struct { @@ -128,6 +139,24 @@ static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) } } +static void save_sigregs_ext(CPUS390XState *env, target_sigregs_ext *ext) +{ + int i; + + /* + * if (MACHINE_HAS_VX) ... + * That said, we always allocate the stack storage and the + * space is always available in env. + */ + for (i = 0; i < 16; ++i) { + __put_user(env->vregs[i][1], &ext->vxrs_low[i]); + } + for (i = 0; i < 16; ++i) { + __put_user(env->vregs[i + 16][0], &ext->vxrs_high[i][0]); + __put_user(env->vregs[i + 16][1], &ext->vxrs_high[i][1]); + } +} + void setup_frame(int sig, struct target_sigaction *ka, target_sigset_t *set, CPUS390XState *env) { @@ -161,6 +190,9 @@ void setup_frame(int sig, struct target_sigaction *ka, */ __put_user(sig, &frame->signo); + /* Create sigregs_ext on the signal stack. */ + save_sigregs_ext(env, &frame->sregs_ext); + /* * Set up to return from userspace. * If provided, use a stub already in userspace. @@ -202,6 +234,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, rt_sigframe *frame; abi_ulong frame_addr; abi_ulong restorer; + abi_ulong uc_flags; frame_addr = get_sigframe(ka, env, sizeof *frame); trace_user_setup_rt_frame(env, frame_addr); @@ -229,10 +262,15 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, tswap_siginfo(&frame->info, info); /* Create ucontext on the signal stack. */ - __put_user(0, &frame->uc.tuc_flags); + uc_flags = 0; + if (s390_has_feat(S390_FEAT_VECTOR)) { + uc_flags |= TARGET_UC_VXRS; + } + __put_user(uc_flags, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_link); target_save_altstack(&frame->uc.tuc_stack, env); save_sigregs(env, &frame->uc.tuc_mcontext); + save_sigregs_ext(env, &frame->uc.tuc_mcontext_ext); tswap_sigset(&frame->uc.tuc_sigmask, set); /* Set up registers for signal handler */ @@ -271,6 +309,24 @@ static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) } } +static void restore_sigregs_ext(CPUS390XState *env, target_sigregs_ext *ext) +{ + int i; + + /* + * if (MACHINE_HAS_VX) ... + * That said, we always allocate the stack storage and the + * space is always available in env. + */ + for (i = 0; i < 16; ++i) { + __get_user(env->vregs[i][1], &ext->vxrs_low[i]); + } + for (i = 0; i < 16; ++i) { + __get_user(env->vregs[i + 16][0], &ext->vxrs_high[i][0]); + __get_user(env->vregs[i + 16][1], &ext->vxrs_high[i][1]); + } +} + long do_sigreturn(CPUS390XState *env) { sigframe *frame; @@ -292,6 +348,7 @@ long do_sigreturn(CPUS390XState *env) set_sigmask(&set); /* ~_BLOCKABLE? */ restore_sigregs(env, &frame->sregs); + restore_sigregs_ext(env, &frame->sregs_ext); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; @@ -313,6 +370,7 @@ long do_rt_sigreturn(CPUS390XState *env) set_sigmask(&set); /* ~_BLOCKABLE? */ restore_sigregs(env, &frame->uc.tuc_mcontext); + restore_sigregs_ext(env, &frame->uc.tuc_mcontext_ext); target_restore_altstack(&frame->uc.tuc_stack, env); From db3221454d6b242c248cc4c33c60b9016e153516 Mon Sep 17 00:00:00 2001 From: Giuseppe Musacchio Date: Mon, 3 May 2021 19:41:58 +0200 Subject: [PATCH 48/59] linux-user: Add copy_file_range to strace.list Signed-off-by: Giuseppe Musacchio Reviewed-by: Laurent Vivier Message-Id: <20210503174159.54302-2-thatlemon@gmail.com> Signed-off-by: Laurent Vivier --- linux-user/strace.list | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/strace.list b/linux-user/strace.list index 18f7217275..278596acd1 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1668,3 +1668,6 @@ #ifdef TARGET_NR_statx { TARGET_NR_statx, "statx", NULL, print_statx, NULL }, #endif +#ifdef TARGET_NR_copy_file_range +{ TARGET_NR_copy_file_range, "copy_file_range", "%s(%d,%p,%d,%p,"TARGET_ABI_FMT_lu",%u)", NULL, NULL }, +#endif From 0fa259dd7986d152294f31a6483272a4cb627b6d Mon Sep 17 00:00:00 2001 From: Giuseppe Musacchio Date: Mon, 3 May 2021 19:41:59 +0200 Subject: [PATCH 49/59] linux-user: Fix erroneous conversion in copy_file_range The implicit cast from abi_long to size_t may introduce an intermediate unwanted sign-extension of the value for 32bit targets running on 64bit hosts. Signed-off-by: Giuseppe Musacchio Reviewed-by: Laurent Vivier Message-Id: <20210503174159.54302-3-thatlemon@gmail.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4d52b2cfe3..e05870c338 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -13244,8 +13244,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } poutoff = &outoff; } + /* Do not sign-extend the count parameter. */ ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff, - arg5, arg6)); + (abi_ulong)arg5, arg6)); if (!is_error(ret) && ret > 0) { if (arg2) { if (put_user_u64(inoff, arg2)) { From 68af19ad72630f00d1b92635334050826e4b6f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 May 2021 11:37:01 +0100 Subject: [PATCH 50/59] linux-user: use GDateTime for formatting timestamp for core file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GDateTime APIs provided by GLib avoid portability pitfalls, such as some platforms where 'struct timeval.tv_sec' field is still 'long' instead of 'time_t'. When combined with automatic cleanup, GDateTime often results in simpler code too. Signed-off-by: Daniel P. Berrangé Reviewed-by: Laurent Vivier Message-Id: <20210505103702.521457-7-berrange@redhat.com> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ffc03d72f9..015eed1a27 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -3376,7 +3376,6 @@ static size_t note_size(const struct memelfnote *); static void free_note_info(struct elf_note_info *); static int fill_note_info(struct elf_note_info *, long, const CPUArchState *); static void fill_thread_info(struct elf_note_info *, const CPUArchState *); -static int core_dump_filename(const TaskState *, char *, size_t); static int dump_write(int, const void *, size_t); static int write_note(struct memelfnote *, int); @@ -3675,32 +3674,16 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) * for the name: * qemu__-