diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/compat_linux.c | 84 | ||||
-rw-r--r-- | arch/s390/kernel/compat_linux.h | 4 | ||||
-rw-r--r-- | arch/s390/kernel/compat_wrapper.S | 35 | ||||
-rw-r--r-- | arch/s390/kernel/debug.c | 12 | ||||
-rw-r--r-- | arch/s390/kernel/entry.h | 6 | ||||
-rw-r--r-- | arch/s390/kernel/init_task.c | 5 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 41 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 19 | ||||
-rw-r--r-- | arch/s390/kernel/sclp.S | 5 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 54 | ||||
-rw-r--r-- | arch/s390/kernel/suspend.c | 24 | ||||
-rw-r--r-- | arch/s390/kernel/swsusp_asm64.S | 102 | ||||
-rw-r--r-- | arch/s390/kernel/sys_s390.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/syscalls.S | 10 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 39 | ||||
-rw-r--r-- | arch/s390/kernel/vdso.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/vdso32/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/vdso32/vdso32_wrapper.S | 3 | ||||
-rw-r--r-- | arch/s390/kernel/vdso64/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/vdso64/vdso64_wrapper.S | 3 | ||||
-rw-r--r-- | arch/s390/kernel/vmlinux.lds.S | 9 |
22 files changed, 206 insertions, 263 deletions
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index fa9905ce7d0..63e46433e81 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -7,6 +7,7 @@ #include <linux/sched.h> #include <linux/kbuild.h> #include <asm/vdso.h> +#include <asm/sigp.h> int main(void) { @@ -59,6 +60,10 @@ int main(void) DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); - + /* constants for SIGP */ + DEFINE(__SIGP_STOP, sigp_stop); + DEFINE(__SIGP_RESTART, sigp_restart); + DEFINE(__SIGP_SENSE, sigp_sense); + DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset); return 0; } diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 9ab188d67a3..0debcec23a3 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -24,7 +24,6 @@ #include <linux/signal.h> #include <linux/resource.h> #include <linux/times.h> -#include <linux/utsname.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/sem.h> @@ -443,66 +442,28 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) * sys32_execve() executes a new program after the asm stub has set * things up for us. This should basically do what I want it to. */ -asmlinkage long sys32_execve(void) +asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, + compat_uptr_t __user *envp) { struct pt_regs *regs = task_pt_regs(current); char *filename; - unsigned long result; - int rc; - - filename = getname(compat_ptr(regs->orig_gpr2)); - if (IS_ERR(filename)) { - result = PTR_ERR(filename); - goto out; - } - rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), - compat_ptr(regs->gprs[4]), regs); - if (rc) { - result = rc; - goto out_putname; - } + long rc; + + filename = getname(name); + rc = PTR_ERR(filename); + if (IS_ERR(filename)) + return rc; + rc = compat_do_execve(filename, argv, envp, regs); + if (rc) + goto out; current->thread.fp_regs.fpc=0; asm volatile("sfpc %0,0" : : "d" (0)); - result = regs->gprs[2]; -out_putname: - putname(filename); + rc = regs->gprs[2]; out: - return result; -} - - -#ifdef CONFIG_MODULES - -asmlinkage long -sys32_init_module(void __user *umod, unsigned long len, - const char __user *uargs) -{ - return sys_init_module(umod, len, uargs); -} - -asmlinkage long -sys32_delete_module(const char __user *name_user, unsigned int flags) -{ - return sys_delete_module(name_user, flags); -} - -#else /* CONFIG_MODULES */ - -asmlinkage long -sys32_init_module(void __user *umod, unsigned long len, - const char __user *uargs) -{ - return -ENOSYS; + putname(filename); + return rc; } -asmlinkage long -sys32_delete_module(const char __user *name_user, unsigned int flags) -{ - return -ENOSYS; -} - -#endif /* CONFIG_MODULES */ - asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo) { @@ -801,23 +762,6 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) return sys_write(fd, buf, count); } -asmlinkage long sys32_clone(void) -{ - struct pt_regs *regs = task_pt_regs(current); - unsigned long clone_flags; - unsigned long newsp; - int __user *parent_tidptr, *child_tidptr; - - clone_flags = regs->gprs[3] & 0xffffffffUL; - newsp = regs->orig_gpr2 & 0x7fffffffUL; - parent_tidptr = compat_ptr(regs->gprs[4]); - child_tidptr = compat_ptr(regs->gprs[5]); - if (!newsp) - newsp = regs->gprs[15]; - return do_fork(clone_flags, newsp, regs, 0, - parent_tidptr, child_tidptr); -} - /* * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 836a2884290..c07f9ca05ad 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h @@ -198,7 +198,8 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, size_t sigsetsize); long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); -long sys32_execve(void); +long sys32_execve(char __user *name, compat_uptr_t __user *argv, + compat_uptr_t __user *envp); long sys32_init_module(void __user *umod, unsigned long len, const char __user *uargs); long sys32_delete_module(const char __user *name_user, unsigned int flags); @@ -222,7 +223,6 @@ unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg); long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg); long sys32_read(unsigned int fd, char __user * buf, size_t count); long sys32_write(unsigned int fd, char __user * buf, size_t count); -long sys32_clone(void); long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise); long sys32_fadvise64_64(struct fadvise64_64_args __user *args); long sys32_sigaction(int sig, const struct old_sigaction32 __user *act, diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 88a83366819..682fb69dba2 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -568,18 +568,18 @@ compat_sys_sigprocmask_wrapper: llgtr %r4,%r4 # compat_old_sigset_t * jg compat_sys_sigprocmask # branch to system call - .globl sys32_init_module_wrapper -sys32_init_module_wrapper: + .globl sys_init_module_wrapper +sys_init_module_wrapper: llgtr %r2,%r2 # void * llgfr %r3,%r3 # unsigned long llgtr %r4,%r4 # char * - jg sys32_init_module # branch to system call + jg sys_init_module # branch to system call - .globl sys32_delete_module_wrapper -sys32_delete_module_wrapper: + .globl sys_delete_module_wrapper +sys_delete_module_wrapper: llgtr %r2,%r2 # const char * llgfr %r3,%r3 # unsigned int - jg sys32_delete_module # branch to system call + jg sys_delete_module # branch to system call .globl sys32_quotactl_wrapper sys32_quotactl_wrapper: @@ -1832,11 +1832,26 @@ compat_sys_rt_tgsigqueueinfo_wrapper: llgtr %r5,%r5 # struct compat_siginfo * jg compat_sys_rt_tgsigqueueinfo_wrapper # branch to system call - .globl sys_perf_counter_open_wrapper -sys_perf_counter_open_wrapper: - llgtr %r2,%r2 # const struct perf_counter_attr * + .globl sys_perf_event_open_wrapper +sys_perf_event_open_wrapper: + llgtr %r2,%r2 # const struct perf_event_attr * lgfr %r3,%r3 # pid_t lgfr %r4,%r4 # int lgfr %r5,%r5 # int llgfr %r6,%r6 # unsigned long - jg sys_perf_counter_open # branch to system call + jg sys_perf_event_open # branch to system call + + .globl sys_clone_wrapper +sys_clone_wrapper: + llgfr %r2,%r2 # unsigned long + llgfr %r3,%r3 # unsigned long + llgtr %r4,%r4 # int * + llgtr %r5,%r5 # int * + jg sys_clone # branch to system call + + .globl sys32_execve_wrapper +sys32_execve_wrapper: + llgtr %r2,%r2 # char * + llgtr %r3,%r3 # compat_uptr_t * + llgtr %r4,%r4 # compat_uptr_t * + jg sys32_execve # branch to system call diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index be8bceaf37d..20f282c911c 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -63,8 +63,6 @@ typedef struct } debug_sprintf_entry_t; -extern void tod_to_timeval(uint64_t todval, struct timespec *xtime); - /* internal function prototyes */ static int debug_init(void); @@ -883,11 +881,11 @@ static int debug_active=1; * if debug_active is already off */ static int -s390dbf_procactive(ctl_table *table, int write, struct file *filp, +s390dbf_procactive(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { if (!write || debug_stoppable || !debug_active) - return proc_dointvec(table, write, filp, buffer, lenp, ppos); + return proc_dointvec(table, write, buffer, lenp, ppos); else return 0; } @@ -1450,17 +1448,13 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, int area, debug_entry_t * entry, char *out_buf) { struct timespec time_spec; - unsigned long long time; char *except_str; unsigned long caller; int rc = 0; unsigned int level; level = entry->id.fields.level; - time = entry->id.stck; - /* adjust todclock to 1970 */ - time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); - tod_to_timeval(time, &time_spec); + stck_to_timespec(entry->id.stck, &time_spec); if (entry->id.fields.exception) except_str = "*"; diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index 950c59c6688..e1e5e767ab5 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -42,10 +42,12 @@ long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args); long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, u32 len_low); long sys_fork(void); -long sys_clone(void); +long sys_clone(unsigned long newsp, unsigned long clone_flags, + int __user *parent_tidptr, int __user *child_tidptr); long sys_vfork(void); void execve_tail(void); -long sys_execve(void); +long sys_execve(char __user *name, char __user * __user *argv, + char __user * __user *envp); long sys_sigsuspend(int history0, int history1, old_sigset_t mask); long sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact); diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c index fe787f9e5f3..4d1c9fb0b54 100644 --- a/arch/s390/kernel/init_task.c +++ b/arch/s390/kernel/init_task.c @@ -25,9 +25,8 @@ static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = - { INIT_THREAD_INFO(init_task) }; +union thread_union init_thread_union __init_task_data = + { INIT_THREAD_INFO(init_task) }; /* * Initial task structure. diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5a43f27eec1..5417eb57271 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -27,11 +27,11 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/notifier.h> -#include <linux/utsname.h> #include <linux/tick.h> #include <linux/elfcore.h> #include <linux/kernel_stat.h> #include <linux/syscalls.h> +#include <linux/compat.h> #include <asm/compat.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -230,17 +230,11 @@ SYSCALL_DEFINE0(fork) return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } -SYSCALL_DEFINE0(clone) +SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags, + int __user *, parent_tidptr, int __user *, child_tidptr) { struct pt_regs *regs = task_pt_regs(current); - unsigned long clone_flags; - unsigned long newsp; - int __user *parent_tidptr, *child_tidptr; - clone_flags = regs->gprs[3]; - newsp = regs->orig_gpr2; - parent_tidptr = (int __user *) regs->gprs[4]; - child_tidptr = (int __user *) regs->gprs[5]; if (!newsp) newsp = regs->gprs[15]; return do_fork(clone_flags, newsp, regs, 0, @@ -274,30 +268,25 @@ asmlinkage void execve_tail(void) /* * sys_execve() executes a new program. */ -SYSCALL_DEFINE0(execve) +SYSCALL_DEFINE3(execve, char __user *, name, char __user * __user *, argv, + char __user * __user *, envp) { struct pt_regs *regs = task_pt_regs(current); char *filename; - unsigned long result; - int rc; + long rc; - filename = getname((char __user *) regs->orig_gpr2); - if (IS_ERR(filename)) { - result = PTR_ERR(filename); + filename = getname(name); + rc = PTR_ERR(filename); + if (IS_ERR(filename)) + return rc; + rc = do_execve(filename, argv, envp, regs); + if (rc) goto out; - } - rc = do_execve(filename, (char __user * __user *) regs->gprs[3], - (char __user * __user *) regs->gprs[4], regs); - if (rc) { - result = rc; - goto out_putname; - } execve_tail(); - result = regs->gprs[2]; -out_putname: - putname(filename); + rc = regs->gprs[2]; out: - return result; + putname(filename); + return rc; } /* diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index f3ddd7ac06c..a8738676b26 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -339,24 +339,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied, ret; switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - /* Remove high order bit from address (only for 31 bit). */ - addr &= PSW_ADDR_INSN; - /* read word at location addr. */ - return generic_ptrace_peekdata(child, addr, data); - case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ return peek_user(child, addr, data); - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - /* Remove high order bit from address (only for 31 bit). */ - addr &= PSW_ADDR_INSN; - /* write the word at location addr. */ - return generic_ptrace_pokedata(child, addr, data); - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ return poke_user(child, addr, data); @@ -386,8 +372,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned long); } return 0; + default: + /* Removing high order bit from addr (only for 31 bit). */ + addr &= PSW_ADDR_INSN; + return ptrace_request(child, request, addr, data); } - return ptrace_request(child, request, addr, data); } #ifdef CONFIG_COMPAT diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index 20639dfe0c4..e27ca63076d 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S @@ -24,8 +24,6 @@ LC_EXT_INT_CODE = 0x86 # addr of ext int code # R3 = external interruption parameter if R2=0 # -.section ".init.text","ax" - _sclp_wait_int: stm %r6,%r15,24(%r15) # save registers basr %r13,0 # get base register @@ -318,9 +316,8 @@ _sclp_print_early: .long _sclp_work_area .Lascebc: .long _ascebc -.previous -.section ".init.data","a" +.section .data,"aw",@progbits .balign 4096 _sclp_work_area: .fill 4096 diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 56c16876b91..c932caa5e85 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -147,11 +147,11 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig) udelay(10); } -void arch_send_call_function_ipi(cpumask_t mask) +void arch_send_call_function_ipi_mask(const struct cpumask *mask) { int cpu; - for_each_cpu_mask(cpu, mask) + for_each_cpu(cpu, mask) smp_ext_bitcall(cpu, ec_call_function); } @@ -475,10 +475,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu) { unsigned long async_stack, panic_stack; struct _lowcore *lowcore; - int lc_order; - lc_order = sizeof(long) == 8 ? 1 : 0; - lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); + lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); if (!lowcore) return -ENOMEM; async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); @@ -509,16 +507,14 @@ static int __cpuinit smp_alloc_lowcore(int cpu) out: free_page(panic_stack); free_pages(async_stack, ASYNC_ORDER); - free_pages((unsigned long) lowcore, lc_order); + free_pages((unsigned long) lowcore, LC_ORDER); return -ENOMEM; } static void smp_free_lowcore(int cpu) { struct _lowcore *lowcore; - int lc_order; - lc_order = sizeof(long) == 8 ? 1 : 0; lowcore = lowcore_ptr[cpu]; #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) @@ -528,7 +524,7 @@ static void smp_free_lowcore(int cpu) #endif free_page(lowcore->panic_stack - PAGE_SIZE); free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER); - free_pages((unsigned long) lowcore, lc_order); + free_pages((unsigned long) lowcore, LC_ORDER); lowcore_ptr[cpu] = NULL; } @@ -664,7 +660,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) unsigned long async_stack, panic_stack; struct _lowcore *lowcore; unsigned int cpu; - int lc_order; smp_detect_cpus(); @@ -674,8 +669,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) print_cpu_info(); /* Reallocate current lowcore, but keep its contents. */ - lc_order = sizeof(long) == 8 ? 1 : 0; - lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); + lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); panic_stack = __get_free_page(GFP_KERNEL); async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); BUG_ON(!lowcore || !panic_stack || !async_stack); @@ -1047,42 +1041,6 @@ out: static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, dispatching_store); -/* - * If the resume kernel runs on another cpu than the suspended kernel, - * we have to switch the cpu IDs in the logical map. - */ -void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id, - struct _lowcore *suspend_lowcore) -{ - int cpu, suspend_cpu_id, resume_cpu_id; - u32 suspend_phys_cpu_id; - - suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr]; - suspend_cpu_id = suspend_lowcore->cpu_nr; - - for_each_present_cpu(cpu) { - if (__cpu_logical_map[cpu] == resume_phys_cpu_id) { - resume_cpu_id = cpu; - goto found; - } - } - panic("Could not find resume cpu in logical map.\n"); - -found: - printk("Resume cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id); - printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id); - - __cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id; - __cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id; - - lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id; -} - -u32 smp_get_phys_cpu_id(void) -{ - return __cpu_logical_map[smp_processor_id()]; -} - static int __init topology_init(void) { int cpu; diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c index 086bee970ca..cf9e5c6d552 100644 --- a/arch/s390/kernel/suspend.c +++ b/arch/s390/kernel/suspend.c @@ -6,36 +6,26 @@ * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com> */ -#include <linux/suspend.h> -#include <linux/reboot.h> #include <linux/pfn.h> -#include <linux/mm.h> -#include <asm/sections.h> #include <asm/system.h> -#include <asm/ipl.h> /* * References to section boundaries */ extern const void __nosave_begin, __nosave_end; -/* - * check if given pfn is in the 'nosave' or in the read only NSS section - */ int pfn_is_nosave(unsigned long pfn) { - unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; - unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) - >> PAGE_SHIFT; - unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1; - unsigned long stext_pfn = PFN_DOWN(__pa(&_stext)); + unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); + unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end)); + /* Always save lowcore pages (LC protection might be enabled). */ + if (pfn <= LC_PAGES) + return 0; if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) return 1; - if (pfn >= stext_pfn && pfn <= eshared_pfn) { - if (ipl_info.type == IPL_TYPE_NSS) - return 1; - } else if ((tprot(pfn * PAGE_SIZE) && pfn > 0)) + /* Skip memory holes and read-only pages (NSS, DCSS, ...). */ + if (tprot(PFN_PHYS(pfn))) return 1; return 0; } diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 7cd6b096f0d..fe927d0bc20 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S @@ -9,6 +9,7 @@ #include <asm/page.h> #include <asm/ptrace.h> +#include <asm/thread_info.h> #include <asm/asm-offsets.h> /* @@ -41,6 +42,9 @@ swsusp_arch_suspend: /* Get pointer to save area */ lghi %r1,0x1000 + /* Save CPU address */ + stap __LC_CPU_ADDRESS(%r1) + /* Store registers */ mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ stfpc 0x31c(%r1) /* store fpu control */ @@ -102,11 +106,10 @@ swsusp_arch_resume: aghi %r15,-STACK_FRAME_OVERHEAD stg %r1,__SF_BACKCHAIN(%r15) -#ifdef CONFIG_SMP - /* Save boot cpu number */ - brasl %r14,smp_get_phys_cpu_id - lgr %r10,%r2 -#endif + /* Make all free pages stable */ + lghi %r2,1 + brasl %r14,arch_set_page_states + /* Deactivate DAT */ stnsm __SF_EMPTY(%r15),0xfb @@ -133,6 +136,69 @@ swsusp_arch_resume: 2: ptlb /* flush tlb */ + /* Reset System */ + larl %r1,restart_entry + larl %r2,.Lrestart_diag308_psw + og %r1,0(%r2) + stg %r1,0(%r0) + larl %r1,.Lnew_pgm_check_psw + epsw %r2,%r3 + stm %r2,%r3,0(%r1) + mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) + lghi %r0,0 + diag %r0,%r0,0x308 +restart_entry: + lhi %r1,1 + sigp %r1,%r0,0x12 + sam64 + larl %r1,.Lnew_pgm_check_psw + lpswe 0(%r1) +pgm_check_entry: + + /* Switch to original suspend CPU */ + larl %r1,.Lresume_cpu /* Resume CPU address: r2 */ + stap 0(%r1) + llgh %r2,0(%r1) + lghi %r3,0x1000 + llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */ + cgr %r1,%r2 + je restore_registers /* r1 = r2 -> nothing to do */ + larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */ + mvc __LC_RESTART_PSW(16,%r0),0(%r4) +3: + sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET + brc 8,4f /* accepted */ + brc 2,3b /* busy, try again */ + + /* Suspend CPU not available -> panic */ + larl %r15,init_thread_union + ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) + larl %r2,.Lpanic_string + larl %r3,_sclp_print_early + lghi %r1,0 + sam31 + sigp %r1,%r0,0x12 + basr %r14,%r3 + larl %r3,.Ldisabled_wait_31 + lpsw 0(%r3) +4: + /* Switch to suspend CPU */ + sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */ + brc 2,4b /* busy, try again */ +5: + sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ +6: j 6b + +restart_suspend: + larl %r1,.Lresume_cpu + llgh %r2,0(%r1) +7: + sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */ + brc 2,7b /* busy, try again */ + tmll %r9,0x40 /* Test if resume CPU is stopped */ + jz 7b + +restore_registers: /* Restore registers */ lghi %r13,0x1000 /* %r1 = pointer to save arae */ @@ -166,19 +232,33 @@ swsusp_arch_resume: /* Pointer to save area */ lghi %r13,0x1000 -#ifdef CONFIG_SMP - /* Switch CPUs */ - lgr %r2,%r10 /* get cpu id */ - llgf %r3,0x318(%r13) - brasl %r14,smp_switch_boot_cpu_in_resume -#endif /* Restore prefix register */ spx 0x318(%r13) /* Activate DAT */ stosm __SF_EMPTY(%r15),0x04 + /* Make all free pages unstable */ + lghi %r2,0 + brasl %r14,arch_set_page_states + /* Return 0 */ lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) lghi %r2,0 br %r14 + + .section .data.nosave,"aw",@progbits + .align 8 +.Ldisabled_wait_31: + .long 0x000a0000,0x00000000 +.Lpanic_string: + .asciz "Resume not possible because suspend CPU is no longer available" + .align 8 +.Lrestart_diag308_psw: + .long 0x00080000,0x80000000 +.Lrestart_suspend_psw: + .quad 0x0000000180000000,restart_suspend +.Lnew_pgm_check_psw: + .quad 0,pgm_check_entry +.Lresume_cpu: + .byte 0,0 diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index c7ae4b17e0e..e9d94f61d50 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -29,7 +29,6 @@ #include <linux/personality.h> #include <linux/unistd.h> #include <linux/ipc.h> -#include <linux/syscalls.h> #include <asm/uaccess.h> #include "entry.h" diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index ad1acd20038..30eca070d42 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) SYSCALL(sys_link,sys_link,sys32_link_wrapper) SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ -SYSCALL(sys_execve,sys_execve,sys32_execve) +SYSCALL(sys_execve,sys_execve,sys32_execve_wrapper) SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) @@ -128,7 +128,7 @@ SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) -SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */ +SYSCALL(sys_clone,sys_clone,sys_clone_wrapper) /* 120 */ SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper) NI_SYSCALL /* modify_ldt for i386 */ @@ -136,8 +136,8 @@ SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper) SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */ SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask_wrapper) NI_SYSCALL /* old "create module" */ -SYSCALL(sys_init_module,sys_init_module,sys32_init_module_wrapper) -SYSCALL(sys_delete_module,sys_delete_module,sys32_delete_module_wrapper) +SYSCALL(sys_init_module,sys_init_module,sys_init_module_wrapper) +SYSCALL(sys_delete_module,sys_delete_module,sys_delete_module_wrapper) NI_SYSCALL /* 130: old get_kernel_syms */ SYSCALL(sys_quotactl,sys_quotactl,sys32_quotactl_wrapper) SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper) @@ -339,4 +339,4 @@ SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper) SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper) SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper) SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper) /* 330 */ -SYSCALL(sys_perf_counter_open,sys_perf_counter_open,sys_perf_counter_open_wrapper) +SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 54e327e9af0..34162a0b2ca 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -91,6 +91,7 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime) todval -= (sec * 1000000) << 12; xtime->tv_nsec = ((todval * 1000) >> 12); } +EXPORT_SYMBOL(tod_to_timeval); void clock_comparator_work(void) { @@ -183,12 +184,14 @@ static void timing_alert_interrupt(__u16 code) static void etr_reset(void); static void stp_reset(void); -unsigned long read_persistent_clock(void) +void read_persistent_clock(struct timespec *ts) { - struct timespec ts; + tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, ts); +} - tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, &ts); - return ts.tv_sec; +void read_boot_clock(struct timespec *ts) +{ + tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, ts); } static cycle_t read_tod_clock(struct clocksource *cs) @@ -206,6 +209,10 @@ static struct clocksource clocksource_tod = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +struct clocksource * __init clocksource_default_clock(void) +{ + return &clocksource_tod; +} void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) { @@ -243,10 +250,6 @@ void update_vsyscall_tz(void) */ void __init time_init(void) { - struct timespec ts; - unsigned long flags; - cycle_t now; - /* Reset time synchronization interfaces. */ etr_reset(); stp_reset(); @@ -262,26 +265,6 @@ void __init time_init(void) if (clocksource_register(&clocksource_tod) != 0) panic("Could not register TOD clock source"); - /* - * The TOD clock is an accurate clock. The xtime should be - * initialized in a way that the difference between TOD and - * xtime is reasonably small. Too bad that timekeeping_init - * sets xtime.tv_nsec to zero. In addition the clock source - * change from the jiffies clock source to the TOD clock - * source add another error of up to 1/HZ second. The same - * function sets wall_to_monotonic to a value that is too - * small for /proc/uptime to be accurate. - * Reset xtime and wall_to_monotonic to sane values. - */ - write_seqlock_irqsave(&xtime_lock, flags); - now = get_clock(); - tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime); - clocksource_tod.cycle_last = now; - clocksource_tod.raw_time = xtime; - tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts); - set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec); - write_sequnlock_irqrestore(&xtime_lock, flags); - /* Enable TOD clock interrupts on the boot cpu. */ init_cpu_timer(); diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 45e1708b70f..45a3e9a7ae2 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -75,7 +75,7 @@ __setup("vdso=", vdso_setup); static union { struct vdso_data data; u8 page[PAGE_SIZE]; -} vdso_data_store __attribute__((__section__(".data.page_aligned"))); +} vdso_data_store __page_aligned_data; struct vdso_data *vdso_data = &vdso_data_store.data; /* diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile index ca78ad60ba2..d13e8755a8c 100644 --- a/arch/s390/kernel/vdso32/Makefile +++ b/arch/s390/kernel/vdso32/Makefile @@ -13,7 +13,7 @@ KBUILD_AFLAGS_31 += -m31 -s KBUILD_CFLAGS_31 := $(filter-out -m64,$(KBUILD_CFLAGS)) KBUILD_CFLAGS_31 += -m31 -fPIC -shared -fno-common -fno-builtin KBUILD_CFLAGS_31 += -nostdlib -Wl,-soname=linux-vdso32.so.1 \ - $(call ld-option, -Wl$(comma)--hash-style=sysv) + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_31) $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_31) diff --git a/arch/s390/kernel/vdso32/vdso32_wrapper.S b/arch/s390/kernel/vdso32/vdso32_wrapper.S index 61639a89e70..ae42f8ce350 100644 --- a/arch/s390/kernel/vdso32/vdso32_wrapper.S +++ b/arch/s390/kernel/vdso32/vdso32_wrapper.S @@ -1,7 +1,8 @@ #include <linux/init.h> +#include <linux/linkage.h> #include <asm/page.h> - .section ".data.page_aligned" + __PAGE_ALIGNED_DATA .globl vdso32_start, vdso32_end .balign PAGE_SIZE diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile index 6fc8e829258..449352dda9c 100644 --- a/arch/s390/kernel/vdso64/Makefile +++ b/arch/s390/kernel/vdso64/Makefile @@ -13,7 +13,7 @@ KBUILD_AFLAGS_64 += -m64 -s KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS)) KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ - $(call ld-option, -Wl$(comma)--hash-style=sysv) + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64) $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64) diff --git a/arch/s390/kernel/vdso64/vdso64_wrapper.S b/arch/s390/kernel/vdso64/vdso64_wrapper.S index d8e2ac14d56..c245842b516 100644 --- a/arch/s390/kernel/vdso64/vdso64_wrapper.S +++ b/arch/s390/kernel/vdso64/vdso64_wrapper.S @@ -1,7 +1,8 @@ #include <linux/init.h> +#include <linux/linkage.h> #include <asm/page.h> - .section ".data.page_aligned" + __PAGE_ALIGNED_DATA .globl vdso64_start, vdso64_end .balign PAGE_SIZE diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 7315f9e67e1..bc15ef93e65 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -84,13 +84,10 @@ SECTIONS _end = . ; - /* Sections to be discarded */ - /DISCARD/ : { - EXIT_DATA - *(.exitcall.exit) - } - /* Debugging sections. */ STABS_DEBUG DWARF_DEBUG + + /* Sections to be discarded */ + DISCARDS } |