From 5df799ac4ec2259bcc50cc39a4108d67fd31ff0e Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 25 Sep 2003 18:01:19 -0700 Subject: [PATCH] [PATCH] s390: 31 bit compat. - Fix emulation of sys_sysinfo and sys_clone. - Add code for -ERESTART_RESTARTBLOCK in signal emulation. - Fix ptrace peek/poke for 31 bit programs under a 64 bit kernel. - Fix typos in cp_stat64. --- arch/s390/kernel/compat_ioctl.c | 1 + arch/s390/kernel/compat_linux.c | 23 +++++++++++++++-------- arch/s390/kernel/compat_signal.c | 4 ++++ arch/s390/kernel/ptrace.c | 21 +++++++++++++++++++-- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c index 2f58414cc9604..5f74503818d4a 100644 --- a/arch/s390/kernel/compat_ioctl.c +++ b/arch/s390/kernel/compat_ioctl.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 62d0d764dab8f..1b03d2709b8d8 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -1554,7 +1554,11 @@ struct sysinfo32 { u32 totalswap; u32 freeswap; unsigned short procs; - char _f[22]; + unsigned short pads; + u32 totalhigh; + u32 freehigh; + unsigned int mem_unit; + char _f[8]; }; extern asmlinkage int sys_sysinfo(struct sysinfo *info); @@ -1579,6 +1583,9 @@ asmlinkage int sys32_sysinfo(struct sysinfo32 *info) err |= __put_user (s.totalswap, &info->totalswap); err |= __put_user (s.freeswap, &info->freeswap); err |= __put_user (s.procs, &info->procs); + err |= __put_user (s.totalhigh, &info->totalhigh); + err |= __put_user (s.freehigh, &info->freehigh); + err |= __put_user (s.mem_unit, &info->mem_unit); if (err) return -EFAULT; return ret; @@ -2581,10 +2588,10 @@ static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat) tmp.__st_ino = (u32)stat->ino; tmp.st_mode = stat->mode; tmp.st_nlink = (unsigned int)stat->nlink; - tmp.uid = stat->uid; - tmp.gid = stat->gid; + tmp.st_uid = stat->uid; + tmp.st_gid = stat->gid; tmp.st_rdev = huge_encode_dev(stat->rdev); - tmp.st_size = stat->st_size; + tmp.st_size = stat->size; tmp.st_blksize = (u32)stat->blksize; tmp.st_blocks = (u32)stat->blocks; tmp.st_atime = (u32)stat->atime.tv_sec; @@ -2773,7 +2780,6 @@ asmlinkage int sys32_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; - struct task_struct *p; int *parent_tidptr, *child_tidptr; clone_flags = regs.gprs[3] & 0xffffffffUL; @@ -2782,7 +2788,8 @@ asmlinkage int sys32_clone(struct pt_regs regs) child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL); if (!newsp) newsp = regs.gprs[15]; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, - parent_tidptr, child_tidptr); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + parent_tidptr, child_tidptr); } + + diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 836319402664e..a128403e4d98a 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -563,6 +563,10 @@ handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, if (regs->trap == __LC_SVC_OLD_PSW) { /* If so, check system call restarting.. */ switch (regs->gprs[2]) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = + do_no_restart_syscall; + clear_thread_flag(TIF_RESTART_SVC); case -ERESTARTNOHAND: regs->gprs[2] = -EINTR; break; diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index c81e2e13fc6f2..73cb7e8136e30 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -321,9 +321,18 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) /* Fake a 31 bit psw address. */ tmp = (__u32) __KSTK_PTREGS(child)->psw.addr | PSW32_ADDR_AMODE31; - } else + } else if (addr < (addr_t) &dummy32->regs.acrs[0]) { + /* gpr 0-15 */ tmp = *(__u32 *)((addr_t) __KSTK_PTREGS(child) + addr*2 + 4); + } else if (addr < (addr_t) &dummy32->regs.orig_gpr2) { + offset = PT_ACR0 + addr - (addr_t) &dummy32->regs.acrs; + tmp = *(__u32*)((addr_t) __KSTK_PTREGS(child) + offset); + } else { + /* orig gpr 2 */ + offset = PT_ORIGGPR2 + 4; + tmp = *(__u32*)((addr_t) __KSTK_PTREGS(child) + offset); + } } else if (addr >= (addr_t) &dummy32->regs.fp_regs && addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* @@ -387,9 +396,17 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) /* Build a 64 bit psw address from 31 bit address. */ __KSTK_PTREGS(child)->psw.addr = (__u64) tmp & PSW32_ADDR_INSN; - } else + } else if (addr < (addr_t) &dummy32->regs.acrs[0]) { + /* gpr 0-15 */ *(__u32*)((addr_t) __KSTK_PTREGS(child) + addr*2 + 4) = tmp; + } else if (addr < (addr_t) &dummy32->regs.orig_gpr2) { + offset = PT_ACR0 + addr - (addr_t) &dummy32->regs.acrs; + *(__u32*)((addr_t) __KSTK_PTREGS(child) + offset) = tmp; + } else { + offset = PT_ORIGGPR2 + 4; + *(__u32*)((addr_t) __KSTK_PTREGS(child) + offset) = tmp; + } } else if (addr >= (addr_t) &dummy32->regs.fp_regs && addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* -- 2.53.0