diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/compat_wrapper.S | 2 | ||||
-rw-r--r-- | arch/s390/kernel/debug.c | 20 | ||||
-rw-r--r-- | arch/s390/kernel/dis.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 29 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 57 | ||||
-rw-r--r-- | arch/s390/kernel/init_task.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/irq.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 100 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 20 | ||||
-rw-r--r-- | arch/s390/kernel/sys_s390.c | 17 |
10 files changed, 86 insertions, 165 deletions
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 743d54f0b8db..d003a6e16afb 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -121,7 +121,7 @@ sys32_ptrace_wrapper: lgfr %r3,%r3 # long llgtr %r4,%r4 # long llgfr %r5,%r5 # long - jg sys_ptrace # branch to system call + jg compat_sys_ptrace # branch to system call .globl sys32_alarm_wrapper sys32_alarm_wrapper: diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index dff0568e67ec..c93d1296cc0a 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -71,7 +71,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf, size_t user_len, loff_t * offset); static int debug_open(struct inode *inode, struct file *file); static int debug_close(struct inode *inode, struct file *file); -static debug_info_t* debug_info_create(char *name, int pages_per_area, +static debug_info_t *debug_info_create(const char *name, int pages_per_area, int nr_areas, int buf_size, mode_t mode); static void debug_info_get(debug_info_t *); static void debug_info_put(debug_info_t *); @@ -234,8 +234,8 @@ fail_malloc_areas: */ static debug_info_t* -debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size, - int level, int mode) +debug_info_alloc(const char *name, int pages_per_area, int nr_areas, + int buf_size, int level, int mode) { debug_info_t* rc; @@ -326,8 +326,8 @@ debug_info_free(debug_info_t* db_info){ */ static debug_info_t* -debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size, - mode_t mode) +debug_info_create(const char *name, int pages_per_area, int nr_areas, + int buf_size, mode_t mode) { debug_info_t* rc; @@ -684,9 +684,9 @@ debug_close(struct inode *inode, struct file *file) * - Returns handle for debug area */ -debug_info_t *debug_register_mode(char *name, int pages_per_area, int nr_areas, - int buf_size, mode_t mode, uid_t uid, - gid_t gid) +debug_info_t *debug_register_mode(const char *name, int pages_per_area, + int nr_areas, int buf_size, mode_t mode, + uid_t uid, gid_t gid) { debug_info_t *rc = NULL; @@ -722,8 +722,8 @@ EXPORT_SYMBOL(debug_register_mode); * - returns handle for debug area */ -debug_info_t *debug_register(char *name, int pages_per_area, int nr_areas, - int buf_size) +debug_info_t *debug_register(const char *name, int pages_per_area, + int nr_areas, int buf_size) { return debug_register_mode(name, pages_per_area, nr_areas, buf_size, S_IRUSR | S_IWUSR, 0, 0); diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index c14a336f6300..d2f270c995d9 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -208,7 +208,7 @@ static const unsigned char formats[][7] = { [INSTR_RRF_F0FF] = { 0xff, F_16,F_24,F_28,0,0,0 }, /* e.g. madbr */ [INSTR_RRF_FUFF] = { 0xff, F_24,F_16,F_28,U4_20,0,0 },/* e.g. didbr */ [INSTR_RRF_RURR] = { 0xff, R_24,R_28,R_16,U4_20,0,0 },/* e.g. .insn */ - [INSTR_RRF_R0RR] = { 0xff, R_24,R_28,R_16,0,0,0 }, /* e.g. idte */ + [INSTR_RRF_R0RR] = { 0xff, R_24,R_16,R_28,0,0,0 }, /* e.g. idte */ [INSTR_RRF_U0FF] = { 0xff, F_24,U4_16,F_28,0,0,0 }, /* e.g. fixr */ [INSTR_RRF_U0RF] = { 0xff, R_24,U4_16,F_28,0,0,0 }, /* e.g. cfebr */ [INSTR_RRF_M0RR] = { 0xff, R_24,R_28,M_16,0,0,0 }, /* e.g. sske */ diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index bdbb3bcd78a5..708cf9cf9a35 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -279,8 +279,6 @@ sysc_do_restart: st %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? - bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_WORK_SVC bnz BASED(sysc_work) # there is work to do (signals etc.) sysc_restore: @@ -312,6 +310,8 @@ sysc_work_loop: # One of the work bits is on. Find out which one. # sysc_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? + bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(sysc_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED @@ -602,12 +602,6 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler io_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifdef CONFIG_PREEMPT - bno BASED(io_preempt) # no -> check for preemptive scheduling -#else - bno BASED(io_restore) # no-> skip resched & signal -#endif tm __TI_flags+3(%r9),_TIF_WORK_INT bnz BASED(io_work) # there is work to do (signals etc.) io_restore: @@ -629,10 +623,18 @@ io_restore_trace_psw: .long 0, io_restore_trace + 0x80000000 #endif -#ifdef CONFIG_PREEMPT -io_preempt: +# +# switch to kernel stack, then check the TIF bits +# +io_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? +#ifndef CONFIG_PREEMPT + bno BASED(io_restore) # no-> skip resched & signal +#else + bnz BASED(io_work_user) # no -> check for preemptive scheduling + # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) - bnz BASED(io_restore) + bnz BASED(io_restore) # preemption disabled l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -646,10 +648,7 @@ io_resume_loop: br %r1 # call schedule #endif -# -# switch to kernel stack, then check the TIF bits -# -io_work: +io_work_user: l %r1,__LC_KERNEL_STACK s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 5a4a7bcd2bba..fee10177dbfc 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -271,8 +271,6 @@ sysc_noemu: stg %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? - jno sysc_restore tm __TI_flags+7(%r9),_TIF_WORK_SVC jnz sysc_work # there is work to do (signals etc.) sysc_restore: @@ -304,6 +302,8 @@ sysc_work_loop: # One of the work bits is on. Find out which one. # sysc_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? + jno sysc_restore tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo sysc_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED @@ -585,12 +585,6 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler io_return: - tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifdef CONFIG_PREEMPT - jno io_preempt # no -> check for preemptive scheduling -#else - jno io_restore # no-> skip resched & signal -#endif tm __TI_flags+7(%r9),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.) io_restore: @@ -612,10 +606,41 @@ io_restore_trace_psw: .quad 0, io_restore_trace #endif -#ifdef CONFIG_PREEMPT -io_preempt: +# +# There is work todo, we need to check if we return to userspace, then +# check, if we are in SIE, if yes leave it +# +io_work: + tm SP_PSW+1(%r15),0x01 # returning to user ? +#ifndef CONFIG_PREEMPT +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + jnz io_work_user # yes -> no need to check for SIE + la %r1, BASED(sie_opcode) # we return to kernel here + lg %r2, SP_PSW+8(%r15) + clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + jne io_restore # no-> return to kernel + lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE + aghi %r1, 4 + stg %r1, SP_PSW+8(%r15) + j io_restore # return to kernel +#else + jno io_restore # no-> skip resched & signal +#endif +#else + jnz io_work_user # yes -> do resched & signal +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + la %r1, BASED(sie_opcode) + lg %r2, SP_PSW+8(%r15) + clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + jne 0f # no -> leave PSW alone + lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE + aghi %r1, 4 + stg %r1, SP_PSW+8(%r15) +0: +#endif + # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) - jnz io_restore + jnz io_restore # preemption is disabled # switch to kernel stack lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE @@ -629,10 +654,7 @@ io_resume_loop: jg preempt_schedule_irq #endif -# -# switch to kernel stack, then check TIF bits -# -io_work: +io_work_user: lg %r1,__LC_KERNEL_STACK aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -653,6 +675,11 @@ io_work_loop: j io_restore io_work_done: +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) +sie_opcode: + .long 0xb2140000 +#endif + # # _TIF_MCCK_PENDING is set, call handler # diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c index d494161b05b4..7ad003969251 100644 --- a/arch/s390/kernel/init_task.c +++ b/arch/s390/kernel/init_task.c @@ -17,7 +17,6 @@ #include <asm/pgtable.h> static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index c59a86dca584..e7c5bfb7c755 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -25,6 +25,7 @@ int show_interrupts(struct seq_file *p, void *v) static const char *intrclass_names[] = { "EXT", "I/O", }; int i = *(loff_t *) v, j; + get_online_cpus(); if (i == 0) { seq_puts(p, " "); for_each_online_cpu(j) @@ -43,7 +44,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); } - + put_online_cpus(); return 0; } diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 7f4270163744..35827b9bd4d1 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -292,8 +292,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) return 0; } -static int -do_ptrace_normal(struct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { ptrace_area parea; int copied, ret; @@ -529,35 +528,19 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data) return 0; } -static int -do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - unsigned int tmp; /* 4 bytes !! */ + unsigned long addr = caddr; + unsigned long data = cdata; ptrace_area_emu31 parea; int copied, ret; switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - /* read word at location addr. */ - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned int __force __user *) data); - case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ return peek_user_emu31(child, addr, data); - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - /* write the word at location addr. */ - tmp = data; - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1); - if (copied != sizeof(tmp)) - return -EIO; - return 0; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ return poke_user_emu31(child, addr, data); @@ -587,82 +570,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned int); } return 0; - case PTRACE_GETEVENTMSG: - return put_user((__u32) child->ptrace_message, - (unsigned int __force __user *) data); - case PTRACE_GETSIGINFO: - if (child->last_siginfo == NULL) - return -EINVAL; - return copy_siginfo_to_user32((compat_siginfo_t - __force __user *) data, - child->last_siginfo); - case PTRACE_SETSIGINFO: - if (child->last_siginfo == NULL) - return -EINVAL; - return copy_siginfo_from_user32(child->last_siginfo, - (compat_siginfo_t - __force __user *) data); } - return ptrace_request(child, request, addr, data); + return compat_ptrace_request(child, request, addr, data); } #endif -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - switch (request) { - case PTRACE_SYSCALL: - /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: - /* restart after signal. */ - if (!valid_signal(data)) - return -EIO; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - /* make sure the single step bit is not set. */ - user_disable_single_step(child); - wake_up_process(child); - return 0; - - case PTRACE_KILL: - /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - return 0; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - user_disable_single_step(child); - wake_up_process(child); - return 0; - - case PTRACE_SINGLESTEP: - /* set the trap flag. */ - if (!valid_signal(data)) - return -EIO; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - user_enable_single_step(child); - /* give it a chance to run. */ - wake_up_process(child); - return 0; - - /* Do requests that differ for 31/64 bit */ - default: -#ifdef CONFIG_COMPAT - if (test_thread_flag(TIF_31BIT)) - return do_ptrace_emu31(child, request, addr, data); -#endif - return do_ptrace_normal(child, request, addr, data); - } - /* Not reached. */ - return -EIO; -} - asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0aeb290060d9..5d4fa4b1c74c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -139,7 +139,6 @@ static void __smp_call_function_map(void (*func) (void *info), void *info, if (wait) data.finished = CPU_MASK_NONE; - spin_lock(&call_lock); call_data = &data; for_each_cpu_mask(cpu, map) @@ -151,7 +150,6 @@ static void __smp_call_function_map(void (*func) (void *info), void *info, if (wait) while (!cpus_equal(map, data.finished)) cpu_relax(); - spin_unlock(&call_lock); out: if (local) { local_irq_disable(); @@ -177,11 +175,11 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, { cpumask_t map; - preempt_disable(); + spin_lock(&call_lock); map = cpu_online_map; cpu_clear(smp_processor_id(), map); __smp_call_function_map(func, info, nonatomic, wait, map); - preempt_enable(); + spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function); @@ -202,10 +200,10 @@ EXPORT_SYMBOL(smp_call_function); int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, int wait) { - preempt_disable(); + spin_lock(&call_lock); __smp_call_function_map(func, info, nonatomic, wait, cpumask_of_cpu(cpu)); - preempt_enable(); + spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function_single); @@ -228,10 +226,10 @@ EXPORT_SYMBOL(smp_call_function_single); int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info, int wait) { - preempt_disable(); + spin_lock(&call_lock); cpu_clear(smp_processor_id(), mask); __smp_call_function_map(func, info, 0, wait, mask); - preempt_enable(); + spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function_mask); @@ -592,7 +590,9 @@ int __cpuinit start_secondary(void *cpuvoid) pfault_init(); /* Mark this cpu as online */ + spin_lock(&call_lock); cpu_set(smp_processor_id(), cpu_online_map); + spin_unlock(&call_lock); /* Switch on interrupts */ local_irq_enable(); /* Print info about this processor */ @@ -711,7 +711,7 @@ int __cpuinit __cpu_up(unsigned int cpu) memset(sf, 0, sizeof(struct stack_frame)); sf->gprs[9] = (unsigned long) sf; cpu_lowcore->save_area[15] = (unsigned long) sf; - __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15); + __ctl_store(cpu_lowcore->cregs_save_area, 0, 15); asm volatile( " stam 0,15,0(%0)" : : "a" (&cpu_lowcore->access_regs_save_area) : "memory"); @@ -1089,7 +1089,7 @@ out: #ifdef CONFIG_HOTPLUG_CPU -int smp_rescan_cpus(void) +int __ref smp_rescan_cpus(void) { cpumask_t newcpus; int cpu; diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 988d0d64c2c8..5fdb799062b7 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -32,23 +32,6 @@ #include <asm/uaccess.h> #include "entry.h" -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage long sys_pipe(unsigned long __user *fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} - /* common code for old and new mmaps */ static inline long do_mmap2( unsigned long addr, unsigned long len, |