From e7070c0f0ec1df10d687eb1f3e480e6c37de27d9 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sun, 23 Feb 2003 18:47:09 -0800 Subject: [PATCH] [PATCH] s390: 31 bit compatability layer. Fixes for the 31 bit compatability layer: * add compat function for jiffies_to_timeval * convert parameters of clone system call * incorporate changes from setup_arg_pages to setup_arg_pages32 * incorporate changes from do_execve to do_execve32 * take care of nanosecond field in struct timespec * remove functions of old module system calls * add TIF_31BIT thread flag and replace S390_FLAG_31BIT with it * add arch_get_unmapped_area * add wrapper for sys_set_tid_address --- arch/s390x/kernel/binfmt_elf32.c | 30 ++- arch/s390x/kernel/entry.S | 10 +- arch/s390x/kernel/exec32.c | 18 +- arch/s390x/kernel/linux32.c | 349 ++++++------------------------- arch/s390x/kernel/process.c | 2 +- arch/s390x/kernel/ptrace.c | 11 +- arch/s390x/kernel/signal.c | 2 +- arch/s390x/kernel/signal32.c | 2 +- arch/s390x/kernel/sys_s390.c | 32 +++ arch/s390x/kernel/wrapper32.S | 5 + include/asm-s390x/compat.h | 6 +- include/asm-s390x/elf.h | 3 +- include/asm-s390x/pgtable.h | 2 + include/asm-s390x/processor.h | 6 +- include/asm-s390x/thread_info.h | 2 + 15 files changed, 161 insertions(+), 319 deletions(-) diff --git a/arch/s390x/kernel/binfmt_elf32.c b/arch/s390x/kernel/binfmt_elf32.c index a8762672720ba..6a3e3f21a2b27 100644 --- a/arch/s390x/kernel/binfmt_elf32.c +++ b/arch/s390x/kernel/binfmt_elf32.c @@ -9,9 +9,10 @@ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) */ - #define __ASMS390_ELF_H +#include + /* * These are used to set parameters in the core dumps. */ @@ -38,7 +39,7 @@ #define ELF_PLAT_INIT(_r) \ do { \ _r->gprs[14] = 0; \ - current->thread.flags |= S390_FLAG_31BIT; \ + set_thread_flag(TIF_31BIT); \ } while(0) #define USE_ELF_CORE_DUMP @@ -49,9 +50,7 @@ the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. */ -#define ELF_ET_DYN_BASE ((TASK31_SIZE & 0x80000000) \ - ? TASK31_SIZE / 3 * 2 \ - : 2 * TASK31_SIZE / 3) +#define ELF_ET_DYN_BASE (TASK31_SIZE / 3 * 2) /* Wow, the "main" arch needs arch dependent functions too.. :) */ @@ -86,7 +85,6 @@ #define ELF_PLATFORM (NULL) -#ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) \ do { \ if (ibcs2) \ @@ -94,7 +92,6 @@ do { \ else if (current->personality != PER_LINUX32) \ set_personality(PER_LINUX); \ } while (0) -#endif #include "linux32.h" @@ -186,6 +183,14 @@ MODULE_AUTHOR("Gerhard Tonn "); #undef MODULE_DESCRIPTION #undef MODULE_AUTHOR +#define jiffies_to_timeval jiffies_to_compat_timeval +static __inline__ void +jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +{ + value->tv_usec = (jiffies % HZ) * (1000000L / HZ); + value->tv_sec = jiffies / HZ; +} + #include "../../../fs/binfmt_elf.c" static unsigned long @@ -193,14 +198,17 @@ elf_map32 (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int p { unsigned long map_addr; - if(!addr) - addr = 0x40000000; + if (!addr) + addr = 0x40000000; + + if (prot & PROT_READ) + prot |= PROT_EXEC; down_write(¤t->mm->mmap_sem); map_addr = do_mmap(filep, ELF_PAGESTART(addr), - eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type, + eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), + prot, type, eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)); up_write(¤t->mm->mmap_sem); return(map_addr); } - diff --git a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S index b514bbad4066c..750950d2c35a0 100644 --- a/arch/s390x/kernel/entry.S +++ b/arch/s390x/kernel/entry.S @@ -280,6 +280,12 @@ sys_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_clone # branch to sys_clone +#ifdef CONFIG_S390_SUPPORT +sys32_clone_glue: + la %r2,SP_PTREGS(%r15) # load pt_regs + jg sys32_clone # branch to sys32_clone +#endif + sys_fork_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_fork # branch to sys_fork @@ -511,7 +517,7 @@ sys_call_table: .long SYSCALL(sys_ipc,sys32_ipc_wrapper) .long SYSCALL(sys_fsync,sys32_fsync_wrapper) .long SYSCALL(sys_sigreturn_glue,sys32_sigreturn_glue) - .long SYSCALL(sys_clone_glue,sys_clone_glue) /* 120 */ + .long SYSCALL(sys_clone_glue,sys32_clone_glue) /* 120 */ .long SYSCALL(sys_setdomainname,sys32_setdomainname_wrapper) .long SYSCALL(s390x_newuname,sys32_newuname_wrapper) .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* modify_ldt for i386 */ @@ -643,7 +649,7 @@ sys_call_table: .long SYSCALL(sys_epoll_create,sys_ni_syscall) .long SYSCALL(sys_epoll_ctl,sys_ni_syscall) .long SYSCALL(sys_epoll_wait,sys_ni_syscall) - .long SYSCALL(sys_set_tid_address,sys_ni_syscall) + .long SYSCALL(sys_set_tid_address,sys32_set_tid_address_wrapper) .long SYSCALL(sys_fadvise64,sys_ni_syscall) .rept 255-253 .long SYSCALL(sys_ni_syscall,sys_ni_syscall) diff --git a/arch/s390x/kernel/exec32.c b/arch/s390x/kernel/exec32.c index 61956d60ca1a9..62a0cd11eafd9 100644 --- a/arch/s390x/kernel/exec32.c +++ b/arch/s390x/kernel/exec32.c @@ -42,9 +42,11 @@ int setup_arg_pages32(struct linux_binprm *bprm) { unsigned long stack_base; struct vm_area_struct *mpnt; + struct mm_struct *mm = current->mm; int i; stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; + mm->arg_start = bprm->p + stack_base; bprm->p += stack_base; if (bprm->loader) @@ -55,9 +57,14 @@ int setup_arg_pages32(struct linux_binprm *bprm) if (!mpnt) return -ENOMEM; - down_write(¤t->mm->mmap_sem); + if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) { + kmem_cache_free(vm_area_cachep, mpnt); + return -ENOMEM; + } + + down_write(&mm->mmap_sem); { - mpnt->vm_mm = current->mm; + mpnt->vm_mm = mm; mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = STACK_TOP; mpnt->vm_page_prot = PAGE_COPY; @@ -65,9 +72,10 @@ int setup_arg_pages32(struct linux_binprm *bprm) mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; + INIT_LIST_HEAD(&mpnt->shared); mpnt->vm_private_data = (void *) 0; - insert_vm_struct(current->mm, mpnt); - current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + insert_vm_struct(mm, mpnt); + mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { @@ -78,7 +86,7 @@ int setup_arg_pages32(struct linux_binprm *bprm) } stack_base += PAGE_SIZE; } - up_write(¤t->mm->mmap_sem); + up_write(&mm->mmap_sem); return 0; } diff --git a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c index c3eb024425317..1f55e233c2f58 100644 --- a/arch/s390x/kernel/linux32.c +++ b/arch/s390x/kernel/linux32.c @@ -1328,12 +1328,12 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); err |= put_user(stat->rdev, &statbuf->st_rdev); err |= put_user(stat->size, &statbuf->st_size); - err |= put_user(stat->atime, &statbuf->st_atime); - err |= put_user(0, &statbuf->__unused1); - err |= put_user(stat->mtime, &statbuf->st_mtime); - err |= put_user(0, &statbuf->__unused2); - err |= put_user(stat->ctime, &statbuf->st_ctime); - err |= put_user(0, &statbuf->__unused3); + err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); + err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); + err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); + err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); + err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); + err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); err |= put_user(stat->blksize, &statbuf->st_blksize); err |= put_user(stat->blocks, &statbuf->st_blocks); /* fixme @@ -2700,8 +2700,7 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) int retval; int i; - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); + sched_balance_exec(); file = open_exec(filename); @@ -2709,21 +2708,32 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) if (IS_ERR(file)) return retval; + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); + bprm.file = file; bprm.filename = filename; bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; - if ((bprm.argc = count32(argv)) < 0) { - allow_write_access(file); - fput(file); - return bprm.argc; - } - if ((bprm.envc = count32(envp)) < 0) { - allow_write_access(file); - fput(file); - return bprm.envc; - } + bprm.mm = mm_alloc(); + retval = -ENOMEM; + if (!bprm.mm) + goto out_file; + + /* init_new_context is empty for s390x. */ + + bprm.argc = count32(argv); + if ((retval = bprm.argc) < 0) + goto out_mm; + + bprm.envc = count32(envp); + if ((retval = bprm.envc) < 0) + goto out_mm; + + retval = security_bprm_alloc(&bprm); + if (retval) + goto out; retval = prepare_binprm(&bprm); if (retval < 0) @@ -2743,19 +2753,31 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) goto out; retval = search_binary_handler(&bprm, regs); - if (retval >= 0) + if (retval >= 0) { /* execve success */ + security_bprm_free(&bprm); return retval; + } out: /* Something went wrong, return the inode and free the argument pages*/ - allow_write_access(bprm.file); - if (bprm.file) - fput(bprm.file); + for (i=0 ; i= TASK_SIZE - && !segment_eq(get_fs (), KERNEL_DS)) - return -EFAULT; - - page = __get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE); - if (retval > 0) { - if (retval < PAGE_SIZE) { - *buf = (char *)page; - return retval; - } - retval = -ENAMETOOLONG; - } else if (!retval) - retval = -EINVAL; - - free_page(page); - return retval; -} - -static inline void -put_mod_name(char *buf) -{ - free_page((unsigned long)buf); -} - -static __inline__ struct module *find_module(const char *name) -{ - struct module *mod; - - for (mod = module_list; mod ; mod = mod->next) { - if (mod->flags & MOD_DELETED) - continue; - if (!strcmp(mod->name, name)) - break; - } - - return mod; -} - -static int -qm_modules(char *buf, size_t bufsize, compat_size_t *ret) -{ - struct module *mod; - size_t nmod, space, len; - - nmod = space = 0; - - for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) { - len = strlen(mod->name)+1; - if (len > bufsize) - goto calc_space_needed; - if (copy_to_user(buf, mod->name, len)) - return -EFAULT; - buf += len; - bufsize -= len; - space += len; - } - - if (put_user(nmod, ret)) - return -EFAULT; - else - return 0; - -calc_space_needed: - space += len; - while ((mod = mod->next)->next != NULL) - space += strlen(mod->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static int -qm_deps(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret) -{ - size_t i, space, len; - - if (mod->next == NULL) - return -EINVAL; - if (!MOD_CAN_QUERY(mod)) - return put_user(0, ret); - - space = 0; - for (i = 0; i < mod->ndeps; ++i) { - const char *dep_name = mod->deps[i].dep->name; - - len = strlen(dep_name)+1; - if (len > bufsize) - goto calc_space_needed; - if (copy_to_user(buf, dep_name, len)) - return -EFAULT; - buf += len; - bufsize -= len; - space += len; - } - - return put_user(i, ret); - -calc_space_needed: - space += len; - while (++i < mod->ndeps) - space += strlen(mod->deps[i].dep->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static int -qm_refs(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret) -{ - size_t nrefs, space, len; - struct module_ref *ref; - - if (mod->next == NULL) - return -EINVAL; - if (!MOD_CAN_QUERY(mod)) - if (put_user(0, ret)) - return -EFAULT; - else - return 0; - - space = 0; - for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) { - const char *ref_name = ref->ref->name; - - len = strlen(ref_name)+1; - if (len > bufsize) - goto calc_space_needed; - if (copy_to_user(buf, ref_name, len)) - return -EFAULT; - buf += len; - bufsize -= len; - space += len; - } - - if (put_user(nrefs, ret)) - return -EFAULT; - else - return 0; - -calc_space_needed: - space += len; - while ((ref = ref->next_ref) != NULL) - space += strlen(ref->ref->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static inline int -qm_symbols(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret) -{ - size_t i, space, len; - struct module_symbol *s; - char *strings; - unsigned *vals; - - if (!MOD_CAN_QUERY(mod)) - if (put_user(0, ret)) - return -EFAULT; - else - return 0; - - space = mod->nsyms * 2*sizeof(u32); - - i = len = 0; - s = mod->syms; - - if (space > bufsize) - goto calc_space_needed; - - if (!access_ok(VERIFY_WRITE, buf, space)) - return -EFAULT; - - bufsize -= space; - vals = (unsigned *)buf; - strings = buf+space; - - for (; i < mod->nsyms ; ++i, ++s, vals += 2) { - len = strlen(s->name)+1; - if (len > bufsize) - goto calc_space_needed; - - if (copy_to_user(strings, s->name, len) - || __put_user(s->value, vals+0) - || __put_user(space, vals+1)) - return -EFAULT; - - strings += len; - bufsize -= len; - space += len; - } - - if (put_user(i, ret)) - return -EFAULT; - else - return 0; - -calc_space_needed: - for (; i < mod->nsyms; ++i, ++s) - space += strlen(s->name)+1; - - if (put_user(space, ret)) - return -EFAULT; - else - return -ENOSPC; -} - -static inline int -qm_info(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret) -{ - int error = 0; - - if (mod->next == NULL) - return -EINVAL; - - if (sizeof(struct module_info32) <= bufsize) { - struct module_info32 info; - info.addr = (unsigned long)mod; - info.size = mod->size; - info.flags = mod->flags; - info.usecount = - ((mod_member_present(mod, can_unload) - && mod->can_unload) - ? -1 : atomic_read(&mod->uc.usecount)); - - if (copy_to_user(buf, &info, sizeof(struct module_info32))) - return -EFAULT; - } else - error = -ENOSPC; - - if (put_user(sizeof(struct module_info32), ret)) - return -EFAULT; - - return error; -} - -struct kernel_sym32 { - u32 value; - char name[60]; -}; - #else /* CONFIG_MODULES */ asmlinkage int @@ -4069,3 +3832,21 @@ asmlinkage compat_ssize_t sys32_write(unsigned int fd, char * buf, size_t count) return sys_write(fd, buf, count); } + +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; + newsp = regs.orig_gpr2 & 0x7fffffffUL; + parent_tidptr = (int *) (regs.gprs[4] & 0x7fffffffUL); + 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; +} diff --git a/arch/s390x/kernel/process.c b/arch/s390x/kernel/process.c index 93c25e0d01266..e5aac6e59e770 100644 --- a/arch/s390x/kernel/process.c +++ b/arch/s390x/kernel/process.c @@ -206,7 +206,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) { - if (current->thread.flags & S390_FLAG_31BIT) { + if (test_thread_flag(TIF_31BIT)) { frame->childregs.acrs[0] = (unsigned int) regs->gprs[6]; } else { diff --git a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c index afd926812be3e..acc3583819fb1 100644 --- a/arch/s390x/kernel/ptrace.c +++ b/arch/s390x/kernel/ptrace.c @@ -58,7 +58,7 @@ static void FixPerRegisters(struct task_struct *task) if (per_info->single_step) { per_info->control_regs.bits.starting_addr = 0; #ifdef CONFIG_S390_SUPPORT - if (current->thread.flags & S390_FLAG_31BIT) + if (test_thread_flag(TIF_31BIT)) per_info->control_regs.bits.ending_addr = 0x7fffffffUL; else #endif @@ -290,7 +290,7 @@ static int peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data) addr_t offset; __u32 tmp; - if (!(child->thread.flags & S390_FLAG_31BIT) || + if (!test_thread_flag(TIF_31BIT) || (addr & 3) || addr > sizeof(struct user) - 3) return -EIO; @@ -349,9 +349,8 @@ static int poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) per_struct32 *dummy_per32 = NULL; addr_t offset; __u32 tmp; - int ret; - if (!(child->thread.flags & S390_FLAG_31BIT) || + if (!test_thread_flag(TIF_31BIT) || (addr & 3) || addr > sizeof(struct user32) - 3) return -EIO; @@ -382,7 +381,7 @@ static int poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) */ if (addr == (addr_t) &dummy32->regs.fp_regs.fpc && (tmp & ~FPC_VALID_MASK) != 0) - /* Invalid floating pointer control. */ + /* Invalid floating point control. */ return -EINVAL; offset = addr - (addr_t) &dummy32->regs.fp_regs; *(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp; @@ -542,7 +541,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) /* Do requests that differ for 31/64 bit */ default: #ifdef CONFIG_S390_SUPPORT - if (current->thread.flags & S390_FLAG_31BIT) + if (test_thread_flag(TIF_31BIT)) return do_ptrace_emu31(child, request, addr, data); #endif return do_ptrace_normal(child, request, addr, data); diff --git a/arch/s390x/kernel/signal.c b/arch/s390x/kernel/signal.c index 9981f1aba80f0..8ab3cc518536f 100644 --- a/arch/s390x/kernel/signal.c +++ b/arch/s390x/kernel/signal.c @@ -455,7 +455,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; #ifdef CONFIG_S390_SUPPORT - if (current->thread.flags & S390_FLAG_31BIT) { + if (test_thread_flag(TIF_31BIT)) { extern asmlinkage int do_signal32(struct pt_regs *regs, sigset_t *oldset); return do_signal32(regs, oldset); } diff --git a/arch/s390x/kernel/signal32.c b/arch/s390x/kernel/signal32.c index 3b1a0047e806e..cb63aa5739a10 100644 --- a/arch/s390x/kernel/signal32.c +++ b/arch/s390x/kernel/signal32.c @@ -556,7 +556,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sig->action[sig-1]; + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; /* Are we from a system call? */ if (regs->trap == __LC_SVC_OLD_PSW) { diff --git a/arch/s390x/kernel/sys_s390.c b/arch/s390x/kernel/sys_s390.c index efa2c33d4608f..19688fd669d00 100644 --- a/arch/s390x/kernel/sys_s390.c +++ b/arch/s390x/kernel/sys_s390.c @@ -117,6 +117,38 @@ out: return error; } +unsigned long +arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct vm_area_struct *vma; + unsigned long end; + + if (test_thread_flag(TIF_31BIT)) { + if (!addr) + addr = 0x40000000; + end = 0x80000000; + } else { + if (!addr) + addr = TASK_SIZE / 2; + end = TASK_SIZE; + } + + if (len > end) + return -ENOMEM; + addr = PAGE_ALIGN(addr); + + for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (end - len < addr) + return -ENOMEM; + if (!vma || addr + len <= vma->vm_start) + return addr; + addr = vma->vm_end; + } +} + extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); /* diff --git a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S index d255576722b0e..8b91acc29938e 100644 --- a/arch/s390x/kernel/wrapper32.S +++ b/arch/s390x/kernel/wrapper32.S @@ -1204,3 +1204,8 @@ sys32_sched_getaffinity_wrapper: sys32_exit_group_wrapper: lgfr %r2,%r2 # int jg sys_exit_group # branch to system call + + .globl sys32_set_tid_address_wrapper +sys32_set_tid_address_wrapper: + llgtr %r2,%r2 # int * + jg sys_set_tid_address # branch to system call diff --git a/include/asm-s390x/compat.h b/include/asm-s390x/compat.h index b960ee9fc0f81..8541cce5a7719 100644 --- a/include/asm-s390x/compat.h +++ b/include/asm-s390x/compat.h @@ -49,11 +49,11 @@ struct compat_stat { u32 st_blksize; u32 st_blocks; u32 st_atime; - u32 __unused1; + u32 st_atime_nsec; u32 st_mtime; - u32 __unused2; + u32 st_mtime_nsec; u32 st_ctime; - u32 __unused3; + u32 st_ctime_nsec; u32 __unused4; u32 __unused5; }; diff --git a/include/asm-s390x/elf.h b/include/asm-s390x/elf.h index 8d3e5ef5f124c..df7559584881a 100644 --- a/include/asm-s390x/elf.h +++ b/include/asm-s390x/elf.h @@ -39,7 +39,7 @@ typedef s390_regs elf_gregset_t; #define ELF_PLAT_INIT(_r) \ do { \ _r->gprs[14] = 0; \ - current->thread.flags = 0; \ + clear_thread_flag(TIF_31BIT); \ } while(0) #define USE_ELF_CORE_DUMP @@ -83,6 +83,7 @@ do { \ set_personality(PER_SVR4); \ else if (current->personality != PER_LINUX32) \ set_personality(PER_LINUX); \ + clear_thread_flag(TIF_31BIT); \ } while (0) #endif diff --git a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h index 8d9547c35c662..7bd5407576d38 100644 --- a/include/asm-s390x/pgtable.h +++ b/include/asm-s390x/pgtable.h @@ -544,5 +544,7 @@ typedef pte_t *pte_addr_t; */ #define pgtable_cache_init() do { } while (0) +#define HAVE_ARCH_UNMAPPED_AREA + #endif /* _S390_PAGE_H */ diff --git a/include/asm-s390x/processor.h b/include/asm-s390x/processor.h index a2b83517d616b..64a35797af7f2 100644 --- a/include/asm-s390x/processor.h +++ b/include/asm-s390x/processor.h @@ -55,8 +55,6 @@ extern void print_cpu_info(struct cpuinfo_S390 *); /* Lazy FPU handling on uni-processor */ extern struct task_struct *last_task_used_math; -#define S390_FLAG_31BIT 0x01UL - /* * User space process size: 4TB (default). */ @@ -66,8 +64,8 @@ extern struct task_struct *last_task_used_math; /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ -#define TASK_UNMAPPED_BASE ((current->thread.flags & S390_FLAG_31BIT) ? \ - (TASK31_SIZE / 2) : (TASK_SIZE / 2)) +#define TASK_UNMAPPED_BASE \ + (test_thread_flag(TIF_31BIT) ? (TASK31_SIZE / 2) : (TASK_SIZE / 2)) #define THREAD_SIZE (4*PAGE_SIZE) diff --git a/include/asm-s390x/thread_info.h b/include/asm-s390x/thread_info.h index 0bc09b5a2e9b7..a84effda06c9f 100644 --- a/include/asm-s390x/thread_info.h +++ b/include/asm-s390x/thread_info.h @@ -77,6 +77,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_31BIT 18 /* 32bit process */ #define _TIF_SYSCALL_TRACE (1<