diff options
48 files changed, 842 insertions, 1653 deletions
diff --git a/default-configs/targets/sparc64-linux-user.mak b/default-configs/targets/sparc64-linux-user.mak index 8469242..9d23ab4 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/aarch64/signal.c b/linux-user/aarch64/signal.c index b591790..662bcd1 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, 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 c5c27ce..1129ffe 100644 --- a/linux-user/alpha/signal.c +++ b/linux-user/alpha/signal.c @@ -138,8 +138,8 @@ void setup_frame(int sig, struct target_sigaction *ka, setup_sigcontext(&frame->sc, env, frame_addr, set); - if (ka->sa_restorer) { - r26 = ka->sa_restorer; + if (ka->ka_restorer) { + r26 = ka->ka_restorer; } else { __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, @@ -192,15 +192,15 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); } - if (ka->sa_restorer) { - r26 = ka->sa_restorer; + if (ka->ka_restorer) { + r26 = ka->ka_restorer; } else { __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, &frame->retcode[1]); __put_user(INSN_CALLSYS, &frame->retcode[2]); /* imb(); */ - r26 = frame_addr + offsetof(struct target_sigframe, retcode); + r26 = frame_addr + offsetof(struct target_rt_sigframe, retcode); } if (err) { @@ -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); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h index 0b90d3a..2506429 100644 --- a/linux-user/alpha/target_signal.h +++ b/linux-user/alpha/target_signal.h @@ -92,6 +92,7 @@ typedef struct target_sigaltstack { #define TARGET_GEN_SUBRNG7 -25 #define TARGET_ARCH_HAS_SETUP_FRAME +#define TARGET_ARCH_HAS_KA_RESTORER /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 989d03c..69632d1 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -224,6 +224,64 @@ 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); + int raise, enabled; + + if (rc == 0) { + /* Illegal instruction */ + return false; + } + if (rc > 0) { + /* Everything ok. */ + env->regs[15] += 4; + return true; + } + + /* FP exception */ + rc = -rc; + raise = 0; + + /* Translate softfloat flags to FPSR flags */ + if (rc & float_flag_invalid) { + raise |= BIT_IOC; + } + if (rc & float_flag_divbyzero) { + raise |= BIT_DZC; + } + if (rc & float_flag_overflow) { + raise |= BIT_OFC; + } + if (rc & float_flag_underflow) { + raise |= BIT_UFC; + } + if (rc & float_flag_inexact) { + raise |= BIT_IXC; + } + + /* Accumulate unenabled exceptions */ + enabled = ts->fpa.fpsr >> 16; + ts->fpa.fpsr |= raise & ~enabled; + + if (raise & enabled) { + target_siginfo_t info = { }; + + /* + * The kernel's nwfpe emulator does not pass a real si_code. + * It merely uses send_sig(SIGFPE, current, 1). + */ + info.si_signo = TARGET_SIGFPE; + info.si_code = TARGET_SI_KERNEL; + + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + } else { + env->regs[15] += 4; + } + return true; +} + void cpu_loop(CPUARMState *env) { CPUState *cs = env_cpu(env); @@ -244,9 +302,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 +319,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 (!env->thumb && 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: diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index f21d153..32b68ee 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, 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, env); #if 0 /* Send SIGTRAP if we're single-stepping */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index fc9c4f1..0e832b2 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 @@ -1398,6 +1375,39 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i regs->gprs[15] = infop->start_stack; } +/* See linux kernel: arch/s390/include/uapi/asm/ptrace.h (s390_regs). */ +#define ELF_NREG 27 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +enum { + TARGET_REG_PSWM = 0, + TARGET_REG_PSWA = 1, + TARGET_REG_GPRS = 2, + TARGET_REG_ARS = 18, + TARGET_REG_ORIG_R2 = 26, +}; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, + const CPUS390XState *env) +{ + int i; + uint32_t *aregs; + + (*regs)[TARGET_REG_PSWM] = tswapreg(env->psw.mask); + (*regs)[TARGET_REG_PSWA] = tswapreg(env->psw.addr); + for (i = 0; i < 16; i++) { + (*regs)[TARGET_REG_GPRS + i] = tswapreg(env->regs[i]); + } + aregs = (uint32_t *)&((*regs)[TARGET_REG_ARS]); + for (i = 0; i < 16; i++) { + aregs[i] = tswap32(env->aregs[i]); + } + (*regs)[TARGET_REG_ORIG_R2] = 0; +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + #endif /* TARGET_S390X */ #ifdef TARGET_RISCV @@ -3399,7 +3409,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); @@ -3642,11 +3651,12 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) (void) memset(psinfo, 0, sizeof (*psinfo)); - len = ts->info->arg_end - ts->info->arg_start; + len = ts->info->env_strings - ts->info->arg_strings; if (len >= ELF_PRARGSZ) len = ELF_PRARGSZ - 1; - if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len)) + if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_strings, len)) { return -EFAULT; + } for (i = 0; i < len; i++) if (psinfo->pr_psargs[i] == 0) psinfo->pr_psargs[i] = ' '; @@ -3698,32 +3708,16 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) * for the name: * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core * - * Returns 0 in case of success, -1 otherwise (errno is set). + * Returns the filename */ -static int core_dump_filename(const TaskState *ts, char *buf, - size_t bufsize) +static char *core_dump_filename(const TaskState *ts) { - char timestamp[64]; - char *base_filename = NULL; - struct timeval tv; - struct tm tm; - - assert(bufsize >= PATH_MAX); - - if (gettimeofday(&tv, NULL) < 0) { - (void) fprintf(stderr, "unable to get current timestamp: %s", - strerror(errno)); - return (-1); - } + g_autoptr(GDateTime) now = g_date_time_new_now_local(); + g_autofree char *nowstr = g_date_time_format(now, "%Y%m%d-%H%M%S"); + g_autofree char *base_filename = g_path_get_basename(ts->bprm->filename); - base_filename = g_path_get_basename(ts->bprm->filename); - (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", - localtime_r(&tv.tv_sec, &tm)); - (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", - base_filename, timestamp, (int)getpid()); - g_free(base_filename); - - return (0); + return g_strdup_printf("qemu_%s_%s_%d.core", + base_filename, nowstr, (int)getpid()); } static int dump_write(int fd, const void *ptr, size_t size) @@ -3951,7 +3945,7 @@ static int elf_core_dump(int signr, const CPUArchState *env) const CPUState *cpu = env_cpu((CPUArchState *)env); const TaskState *ts = (const TaskState *)cpu->opaque; struct vm_area_struct *vma = NULL; - char corefile[PATH_MAX]; + g_autofree char *corefile = NULL; struct elf_note_info info; struct elfhdr elf; struct elf_phdr phdr; @@ -3968,8 +3962,7 @@ static int elf_core_dump(int signr, const CPUArchState *env) if (dumpsize.rlim_cur == 0) return 0; - if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0) - return (-errno); + corefile = core_dump_filename(ts); if ((fd = open(corefile, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c index fde8dc9..85eab5e 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, 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 d1a58fe..0e266f4 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); 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 9320e1d..8701774 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, 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 49ff87c..d062306 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, env); unlock_user_struct(frame, frame_addr, 0); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/main.c b/linux-user/main.c index 7995b6e..4dfc47a 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; } diff --git a/linux-user/meson.build b/linux-user/meson.build index 7fe28d6..9549f81 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/microblaze/signal.c b/linux-user/microblaze/signal.c index cf0707b..4c483bd 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, 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 455a8a2..e6be807 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, 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 7d53506..cc3872f 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, env); *pr2 = env->regs[2]; return 0; diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c index 232ad82..5c5640a 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, 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 bad38f8..edfad28 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); unlock_user_struct(rt_sf, rt_sf_addr, 1); return -TARGET_QEMU_ESIGRETURN; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 74e06e7..3b0b6b7 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/riscv/signal.c b/linux-user/riscv/signal.c index 67a95db..9405c7f 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, 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 7107c5f..ef136da 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -25,25 +25,24 @@ #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 #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 { 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,30 +50,41 @@ typedef struct { target_s390_fp_regs fpregs; } target_sigregs; -struct target_sigcontext { - target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS]; - target_sigregs *sregs; -}; +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; +} 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]; + target_sigregs_ext sregs_ext; + uint16_t retcode; } sigframe; +#define TARGET_UC_VXRS 2 + 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 */ + target_sigset_t tuc_sigmask; + uint8_t reserved[128 - sizeof(target_sigset_t)]; + target_sigregs_ext tuc_mcontext_ext; }; 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; @@ -105,151 +115,191 @@ 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]); } } +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) { sigframe *frame; abi_ulong frame_addr; + abi_ulong restorer; 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; } + /* 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]); + __put_user(frame_addr + offsetof(sigframe, sregs), &frame->sc.sregs); + /* Create _sigregs on the signal stack */ save_sigregs(env, &frame->sregs); - __put_user((abi_ulong)(unsigned long)&frame->sregs, - (abi_ulong *)&frame->sc.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. */ + /* 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. + */ if (ka->sa_flags & TARGET_SA_RESTORER) { - env->regs[14] = (unsigned long) - ka->sa_restorer | PSW_ADDR_AMODE; + restorer = ka->sa_restorer; } else { - env->regs[14] = (frame_addr + offsetof(sigframe, retcode)) - | PSW_ADDR_AMODE; + restorer = frame_addr + offsetof(sigframe, retcode); __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, - (uint16_t *)(frame->retcode)); + &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; - env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; + /* 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); - env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); + 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); unlock_user_struct(frame, frame_addr, 1); - return; - -give_sigsegv: - force_sigsegv(sig); } 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; + abi_ulong restorer; + abi_ulong uc_flags; 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); - - /* 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); - for (i = 0; i < TARGET_NSIG_WORDS; i++) { - __put_user((abi_ulong)set->sig[i], - (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); - } + /* Set up backchain. */ + __put_user(env->regs[15], (abi_ulong *) frame); - /* 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 | PSW_ADDR_AMODE; + restorer = ka->sa_restorer; } else { - env->regs[14] = (frame_addr + offsetof(typeof(*frame), retcode)) - | PSW_ADDR_AMODE; + restorer = frame_addr + offsetof(typeof(*frame), retcode); __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, - (uint16_t *)(frame->retcode)); + &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. */ + 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 */ + env->regs[14] = restorer; env->regs[15] = frame_addr; - env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; + /* 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); + env->regs[2] = 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); + env->regs[5] = 0; /* FIXME: current->thread.last_break */ } -static int -restore_sigregs(CPUS390XState *env, target_sigregs *sc) +static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) { - int err = 0; + 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); - /* FIXME: 31-bit -> | PSW_ADDR_AMODE */ + 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]); @@ -257,8 +307,24 @@ restore_sigregs(CPUS390XState *env, target_sigregs *sc) for (i = 0; i < 16; i++) { __get_user(*get_freg(env, i), &sc->fpregs.fprs[i]); } +} + +static void restore_sigregs_ext(CPUS390XState *env, target_sigregs_ext *ext) +{ + int i; - return err; + /* + * 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) @@ -270,23 +336,22 @@ 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; } + + /* 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); set_sigmask(&set); /* ~_BLOCKABLE? */ - if (restore_sigregs(env, &frame->sregs)) { - goto badframe; - } + restore_sigregs(env, &frame->sregs); + restore_sigregs_ext(env, &frame->sregs_ext); 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) @@ -297,25 +362,18 @@ 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); set_sigmask(&set); /* ~_BLOCKABLE? */ - if (restore_sigregs(env, &frame->uc.tuc_mcontext)) { - goto badframe; - } + restore_sigregs(env, &frame->uc.tuc_mcontext); + restore_sigregs_ext(env, &frame->uc.tuc_mcontext_ext); - if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0, - get_sp_from_cpustate(env)) == -EFAULT) { - goto badframe; - } - unlock_user_struct(frame, frame_addr, 0); - return -TARGET_QEMU_ESIGRETURN; + target_restore_altstack(&frame->uc.tuc_stack, env); -badframe: unlock_user_struct(frame, frame_addr, 0); - force_sig(TARGET_SIGSEGV); return -TARGET_QEMU_ESIGRETURN; } diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c index 29c1ee3..0451e65 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, 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 1df1068..ea86328 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, CPUArchState *env); static inline void target_sigemptyset(target_sigset_t *set) { diff --git a/linux-user/signal.c b/linux-user/signal.c index 7eecec4..9016896 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, CPUArchState *env) +{ + 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(get_sp_from_cpustate(env))) { + 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, @@ -756,81 +800,49 @@ 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) { - 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) - { - __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 (uoss_addr) { + /* Verify writability now, but do not alter user memory yet. */ + if (!lock_user_struct(VERIFY_WRITE, uoss, uoss_addr, 0)) { + goto out; + } + target_save_altstack(&oss, env); } - 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, env); + 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; } /* do_sigaction() return target values and host errnos */ int do_sigaction(int sig, const struct target_sigaction *act, - struct target_sigaction *oact) + struct target_sigaction *oact, abi_ulong ka_restorer) { struct target_sigaction *k; struct sigaction act1; @@ -864,6 +876,9 @@ int do_sigaction(int sig, const struct target_sigaction *act, #ifdef TARGET_ARCH_HAS_SA_RESTORER __get_user(k->sa_restorer, &act->sa_restorer); #endif +#ifdef TARGET_ARCH_HAS_KA_RESTORER + k->ka_restorer = ka_restorer; +#endif /* To be swapped in target_to_host_sigset. */ k->sa_mask = act->sa_mask; diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index d27b7a3..0cc3db5 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -21,107 +21,96 @@ #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 { +/* 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]; }; -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; +/* 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 { - abi_ulong si_float_regs[32]; - unsigned long si_fsr; - unsigned long si_fpqdepth; +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; + 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; - +#endif +}; +#ifdef TARGET_ARCH_HAS_SETUP_FRAME struct target_signal_frame { - struct sparc_stackf ss; - __siginfo_t info; - 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; + 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 */ + abi_ulong rwin_save; }; +#endif + 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; + 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; }; -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 @@ -132,175 +121,310 @@ 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 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], ®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]); + } +} + +static void save_reg_win(struct target_reg_window *win, 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]); + 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[WREG_O0 + i], &si->si_regs.u_regs[i + 8]); + for (i = 0; i < 8; i++) { + __put_user(env->regwptr[i + WREG_I0], &win->ins[i]); } - __put_user(mask, &si->si_mask); - return err; } -#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7))) +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 +} + +#ifdef TARGET_ARCH_HAS_SETUP_FRAME 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, err, i; - - /* 1. Make sure everything is clean */ - //synchronize_user_stack(); + size_t sf_size = sizeof(*sf) + sizeof(struct target_siginfo_fpu); + int i; - 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; + force_sigsegv(sig); + return; } -#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); + 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->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]); } - for (i = 0; i < 8; i++) { - __put_user(env->regwptr[i + WREG_L0], &sf->ss.locals[i]); - } - for (i = 0; i < 8; i++) { - __put_user(env->regwptr[i + WREG_I0], &sf->ss.ins[i]); - } - if (err) - goto sigsegv; + save_reg_win(&sf->ss.win, env); /* 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; - 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, sizeof(struct target_signal_frame)); - 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); + 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, 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); + +#ifdef TARGET_ABI32 + __put_user(0, &sf->extra_size); +#endif + + /* 3. signal handler back-trampoline and parameters */ + 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 { + 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]); + } +#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; - abi_ulong up_psr, pc, npc; + struct target_signal_frame *sf = NULL; + abi_ulong pc, npc, ptr; target_sigset_t set; sigset_t host_set; int i; sf_addr = env->regwptr[WREG_SP]; trace_user_do_sigreturn(env, sf_addr); - if (!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) + if ((sf_addr & 15) || !lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) { goto segv_and_exit; + } - __get_user(pc, &sf->info.si_regs.pc); - __get_user(npc, &sf->info.si_regs.npc); + /* Make sure stack pointer is aligned. */ + __get_user(ptr, &sf->regs.u_regs[14]); + if (ptr & 7) { + goto segv_and_exit; + } + /* 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; } /* 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]); + + __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); } - /* 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->rwin_save); + if (ptr) { + goto segv_and_exit; /* TODO: restore_rwin */ + } - /* 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]); } @@ -310,17 +434,74 @@ 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; +#else + return -TARGET_ENOSYS; +#endif } 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) @@ -388,14 +569,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]; -}; - -#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 1fa1011..1f4bed5 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 diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h index 911a3f5..34f9a12 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 */ diff --git a/linux-user/sparc/target_structs.h b/linux-user/sparc/target_structs.h index 9953540..beeace8 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 __pad0; +#endif abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad2; -#else - abi_ushort mode; abi_ushort __pad1; -#endif 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/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h index d8ea04e..15d531f 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/cpu_loop.c b/linux-user/sparc64/cpu_loop.c deleted file mode 100644 index 4fd44e1..0000000 --- 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 <http://www.gnu.org/licenses/>. - */ - -#include "../sparc/cpu_loop.c" diff --git a/linux-user/sparc64/meson.build b/linux-user/sparc64/meson.build deleted file mode 100644 index 9527a40..0000000 --- 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 170ebac..0000000 --- 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 <http://www.gnu.org/licenses/>. - */ -#include "../sparc/signal.c" diff --git a/linux-user/sparc64/sockbits.h b/linux-user/sparc64/sockbits.h deleted file mode 100644 index 658899e..0000000 --- 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 4af114e..0000000 --- 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: -# <number> <abi> <name> <entry point> <compat entry point> -# -# The <abi> 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 08c7e39..0000000 --- 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 b22263d..0000000 --- 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 d6e388f..0000000 --- a/linux-user/sparc64/target_elf.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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 diff --git a/linux-user/sparc64/target_fcntl.h b/linux-user/sparc64/target_fcntl.h deleted file mode 100644 index 053c774..0000000 --- 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 6a7d57d..0000000 --- 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 4a8ed48..0000000 --- a/linux-user/sparc64/target_structs.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ -#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 diff --git a/linux-user/sparc64/target_syscall.h b/linux-user/sparc64/target_syscall.h deleted file mode 100644 index 696a68b..0000000 --- a/linux-user/sparc64/target_syscall.h +++ /dev/null @@ -1,35 +0,0 @@ -#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 */ diff --git a/linux-user/sparc64/termbits.h b/linux-user/sparc64/termbits.h deleted file mode 100644 index 1ab1e80..0000000 --- a/linux-user/sparc64/termbits.h +++ /dev/null @@ -1,291 +0,0 @@ -/* 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 diff --git a/linux-user/strace.c b/linux-user/strace.c index e969121..cce0a5d 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 @@ -2335,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, @@ -2355,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 @@ -3467,6 +3474,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 084048a..278596a 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 @@ -1573,7 +1576,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 }, @@ -1665,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 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 95d79dd..c9f8120 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8980,29 +8980,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_sigaction case TARGET_NR_sigaction: { -#if defined(TARGET_ALPHA) - struct target_sigaction act, oact, *pact = 0; - struct target_old_sigaction *old_act; - if (arg2) { - if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) - return -TARGET_EFAULT; - act._sa_handler = old_act->_sa_handler; - target_siginitset(&act.sa_mask, old_act->sa_mask); - act.sa_flags = old_act->sa_flags; - act.sa_restorer = 0; - unlock_user_struct(old_act, arg2, 0); - pact = &act; - } - ret = get_errno(do_sigaction(arg1, pact, &oact)); - if (!is_error(ret) && arg3) { - if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) - return -TARGET_EFAULT; - old_act->_sa_handler = oact._sa_handler; - old_act->sa_mask = oact.sa_mask.sig[0]; - old_act->sa_flags = oact.sa_flags; - unlock_user_struct(old_act, arg3, 1); - } -#elif defined(TARGET_MIPS) +#if defined(TARGET_MIPS) struct target_sigaction act, oact, *pact, *old_act; if (arg2) { @@ -9017,7 +8995,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, pact = NULL; } - ret = get_errno(do_sigaction(arg1, pact, &oact)); + ret = get_errno(do_sigaction(arg1, pact, &oact, 0)); if (!is_error(ret) && arg3) { if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) @@ -9039,23 +9017,24 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, act._sa_handler = old_act->_sa_handler; target_siginitset(&act.sa_mask, old_act->sa_mask); act.sa_flags = old_act->sa_flags; +#ifdef TARGET_ARCH_HAS_SA_RESTORER act.sa_restorer = old_act->sa_restorer; -#ifdef TARGET_ARCH_HAS_KA_RESTORER - act.ka_restorer = 0; #endif unlock_user_struct(old_act, arg2, 0); pact = &act; } else { pact = NULL; } - ret = get_errno(do_sigaction(arg1, pact, &oact)); + ret = get_errno(do_sigaction(arg1, pact, &oact, 0)); if (!is_error(ret) && arg3) { if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) return -TARGET_EFAULT; old_act->_sa_handler = oact._sa_handler; old_act->sa_mask = oact.sa_mask.sig[0]; old_act->sa_flags = oact.sa_flags; +#ifdef TARGET_ARCH_HAS_SA_RESTORER old_act->sa_restorer = oact.sa_restorer; +#endif unlock_user_struct(old_act, arg3, 1); } #endif @@ -9064,77 +9043,43 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif case TARGET_NR_rt_sigaction: { -#if defined(TARGET_ALPHA) - /* For Alpha and SPARC this is a 5 argument syscall, with + /* + * For Alpha and SPARC this is a 5 argument syscall, with * a 'restorer' parameter which must be copied into the * sa_restorer field of the sigaction struct. * For Alpha that 'restorer' is arg5; for SPARC it is arg4, * and arg5 is the sigsetsize. - * Alpha also has a separate rt_sigaction struct that it uses - * here; SPARC uses the usual sigaction struct. */ - struct target_rt_sigaction *rt_act; - struct target_sigaction act, oact, *pact = 0; - - if (arg4 != sizeof(target_sigset_t)) { - return -TARGET_EINVAL; - } - if (arg2) { - if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) - return -TARGET_EFAULT; - act._sa_handler = rt_act->_sa_handler; - act.sa_mask = rt_act->sa_mask; - act.sa_flags = rt_act->sa_flags; - act.sa_restorer = arg5; - unlock_user_struct(rt_act, arg2, 0); - pact = &act; - } - ret = get_errno(do_sigaction(arg1, pact, &oact)); - if (!is_error(ret) && arg3) { - if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0)) - return -TARGET_EFAULT; - rt_act->_sa_handler = oact._sa_handler; - rt_act->sa_mask = oact.sa_mask; - rt_act->sa_flags = oact.sa_flags; - unlock_user_struct(rt_act, arg3, 1); - } -#else -#ifdef TARGET_SPARC +#if defined(TARGET_ALPHA) + target_ulong sigsetsize = arg4; + target_ulong restorer = arg5; +#elif defined(TARGET_SPARC) target_ulong restorer = arg4; target_ulong sigsetsize = arg5; #else target_ulong sigsetsize = arg4; + target_ulong restorer = 0; #endif - struct target_sigaction *act; - struct target_sigaction *oact; + struct target_sigaction *act = NULL; + struct target_sigaction *oact = NULL; if (sigsetsize != sizeof(target_sigset_t)) { return -TARGET_EINVAL; } - if (arg2) { - if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) { - return -TARGET_EFAULT; - } -#ifdef TARGET_ARCH_HAS_KA_RESTORER - act->ka_restorer = restorer; -#endif - } else { - act = NULL; + if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) { + return -TARGET_EFAULT; } - if (arg3) { - if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) { - ret = -TARGET_EFAULT; - goto rt_sigaction_fail; + if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) { + ret = -TARGET_EFAULT; + } else { + ret = get_errno(do_sigaction(arg1, act, oact, restorer)); + if (oact) { + unlock_user_struct(oact, arg3, 1); } - } else - oact = NULL; - ret = get_errno(do_sigaction(arg1, act, oact)); - rt_sigaction_fail: - if (act) + } + if (act) { unlock_user_struct(act, arg2, 0); - if (oact) - unlock_user_struct(oact, arg3, 1); -#endif + } } return ret; #ifdef TARGET_NR_sgetmask /* not on alpha */ @@ -11195,8 +11140,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 @@ -13245,8 +13189,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)) { diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 25be414..18b031a 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -492,7 +492,7 @@ void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset); struct target_sigaction; int do_sigaction(int sig, const struct target_sigaction *act, - struct target_sigaction *oact); + struct target_sigaction *oact, abi_ulong ka_restorer); #include "target_signal.h" @@ -501,27 +501,12 @@ int do_sigaction(int sig, const struct target_sigaction *act, #endif #if defined(TARGET_ALPHA) -struct target_old_sigaction { - abi_ulong _sa_handler; - abi_ulong sa_mask; - int32_t sa_flags; -}; - -struct target_rt_sigaction { - abi_ulong _sa_handler; - abi_ulong sa_flags; - target_sigset_t sa_mask; -}; +typedef int32_t target_old_sa_flags; +#else +typedef abi_ulong target_old_sa_flags; +#endif -/* This is the struct used inside the kernel. The ka_restorer - field comes from the 5th argument to sys_rt_sigaction. */ -struct target_sigaction { - abi_ulong _sa_handler; - abi_ulong sa_flags; - target_sigset_t sa_mask; - abi_ulong sa_restorer; -}; -#elif defined(TARGET_MIPS) +#if defined(TARGET_MIPS) struct target_sigaction { uint32_t sa_flags; #if defined(TARGET_ABI_MIPSN32) @@ -539,7 +524,7 @@ struct target_sigaction { struct target_old_sigaction { abi_ulong _sa_handler; abi_ulong sa_mask; - abi_ulong sa_flags; + target_old_sa_flags sa_flags; #ifdef TARGET_ARCH_HAS_SA_RESTORER abi_ulong sa_restorer; #endif diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 590f031..72771e1 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, 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; diff --git a/tests/tcg/sparc64/Makefile.target b/tests/tcg/sparc64/Makefile.target index 5bd7f90..408dace 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 |