diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 54 | ||||
-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/early.c | 125 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 43 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 69 | ||||
-rw-r--r-- | arch/s390/kernel/head31.S | 61 | ||||
-rw-r--r-- | arch/s390/kernel/head64.S | 64 | ||||
-rw-r--r-- | arch/s390/kernel/irq.c | 5 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 18 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 155 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 21 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 47 | ||||
-rw-r--r-- | arch/s390/kernel/sys_s390.c | 17 | ||||
-rw-r--r-- | arch/s390/kernel/topology.c | 35 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 26 |
17 files changed, 324 insertions, 440 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 77051cd2792..6302f508258 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -2,8 +2,6 @@ # Makefile for the linux kernel. # -EXTRA_AFLAGS := -traditional - # # Passing null pointers is ok for smp code, since we access the lowcore here. # diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 1375f8a4469..fa28ecae636 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -5,44 +5,38 @@ */ #include <linux/sched.h> - -/* Use marker if you need to separate the values later */ - -#define DEFINE(sym, val, marker) \ - asm volatile("\n->" #sym " %0 " #val " " #marker : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) +#include <linux/kbuild.h> int main(void) { - DEFINE(__THREAD_info, offsetof(struct task_struct, stack),); - DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),); - DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),); + DEFINE(__THREAD_info, offsetof(struct task_struct, stack)); + DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp)); + DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info)); DEFINE(__THREAD_mm_segment, - offsetof(struct task_struct, thread.mm_segment),); + offsetof(struct task_struct, thread.mm_segment)); BLANK(); - DEFINE(__TASK_pid, offsetof(struct task_struct, pid),); + DEFINE(__TASK_pid, offsetof(struct task_struct, pid)); BLANK(); - DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid),); - DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address),); - DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id),); + DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid)); + DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address)); + DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id)); BLANK(); - DEFINE(__TI_task, offsetof(struct thread_info, task),); - DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain),); - DEFINE(__TI_flags, offsetof(struct thread_info, flags),); - DEFINE(__TI_cpu, offsetof(struct thread_info, cpu),); - DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count),); + DEFINE(__TI_task, offsetof(struct thread_info, task)); + DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain)); + DEFINE(__TI_flags, offsetof(struct thread_info, flags)); + DEFINE(__TI_cpu, offsetof(struct thread_info, cpu)); + DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); BLANK(); - DEFINE(__PT_ARGS, offsetof(struct pt_regs, args),); - DEFINE(__PT_PSW, offsetof(struct pt_regs, psw),); - DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs),); - DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2),); - DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),); - DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),); - DEFINE(__PT_SIZE, sizeof(struct pt_regs),); + DEFINE(__PT_ARGS, offsetof(struct pt_regs, args)); + DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); + DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); + DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); + DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc)); + DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap)); + DEFINE(__PT_SIZE, sizeof(struct pt_regs)); BLANK(); - DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),); - DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),); - DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),); + DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); + DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs)); + DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1)); return 0; } diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 743d54f0b8d..d003a6e16af 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 dff0568e67e..c93d1296cc0 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/early.c b/arch/s390/kernel/early.c index 68ec4083bf7..d0e09684b9c 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -139,15 +139,15 @@ static noinline __init void detect_machine_type(void) /* Running under z/VM ? */ if (cpuinfo->cpu_id.version == 0xff) - machine_flags |= 1; + machine_flags |= MACHINE_FLAG_VM; /* Running on a P/390 ? */ if (cpuinfo->cpu_id.machine == 0x7490) - machine_flags |= 4; + machine_flags |= MACHINE_FLAG_P390; /* Running under KVM ? */ if (cpuinfo->cpu_id.version == 0xfe) - machine_flags |= 64; + machine_flags |= MACHINE_FLAG_KVM; } #ifdef CONFIG_64BIT @@ -268,6 +268,118 @@ static noinline __init void setup_lowcore_early(void) s390_base_pgm_handler_fn = early_pgm_check_handler; } +static noinline __init void setup_hpage(void) +{ +#ifndef CONFIG_DEBUG_PAGEALLOC + unsigned int facilities; + + facilities = stfl(); + if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29))) + return; + machine_flags |= MACHINE_FLAG_HPAGE; + __ctl_set_bit(0, 23); +#endif +} + +static __init void detect_mvpg(void) +{ +#ifndef CONFIG_64BIT + int rc; + + asm volatile( + " la 0,0\n" + " mvpg %2,%2\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "=d" (rc) : "0" (-EOPNOTSUPP), "a" (0) : "memory", "cc", "0"); + if (!rc) + machine_flags |= MACHINE_FLAG_MVPG; +#endif +} + +static __init void detect_ieee(void) +{ +#ifndef CONFIG_64BIT + int rc, tmp; + + asm volatile( + " efpc %1,0\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "=d" (rc), "=d" (tmp): "0" (-EOPNOTSUPP) : "cc"); + if (!rc) + machine_flags |= MACHINE_FLAG_IEEE; +#endif +} + +static __init void detect_csp(void) +{ +#ifndef CONFIG_64BIT + int rc; + + asm volatile( + " la 0,0\n" + " la 1,0\n" + " la 2,4\n" + " csp 0,2\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc", "0", "1", "2"); + if (!rc) + machine_flags |= MACHINE_FLAG_CSP; +#endif +} + +static __init void detect_diag9c(void) +{ + unsigned int cpu_address; + int rc; + + cpu_address = stap(); + asm volatile( + " diag %2,0,0x9c\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc"); + if (!rc) + machine_flags |= MACHINE_FLAG_DIAG9C; +} + +static __init void detect_diag44(void) +{ +#ifdef CONFIG_64BIT + int rc; + + asm volatile( + " diag 0,0,0x44\n" + "0: la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) + : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc"); + if (!rc) + machine_flags |= MACHINE_FLAG_DIAG44; +#endif +} + +static __init void detect_machine_facilities(void) +{ +#ifdef CONFIG_64BIT + unsigned int facilities; + + facilities = stfl(); + if (facilities & (1 << 28)) + machine_flags |= MACHINE_FLAG_IDTE; + if (facilities & (1 << 23)) + machine_flags |= MACHINE_FLAG_PFMF; + if (facilities & (1 << 4)) + machine_flags |= MACHINE_FLAG_MVCOS; +#endif +} + /* * Save ipl parameters, clear bss memory, initialize storage keys * and create a kernel NSS at startup if the SAVESYS= parm is defined @@ -285,6 +397,13 @@ void __init startup_init(void) create_kernel_nss(); sort_main_extable(); setup_lowcore_early(); + detect_mvpg(); + detect_ieee(); + detect_csp(); + detect_diag9c(); + detect_diag44(); + detect_machine_facilities(); + setup_hpage(); sclp_read_info_early(); sclp_facilities_detect(); memsize = sclp_memory_detect(); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 6766e37fe8e..708cf9cf9a3 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING) STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER @@ -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,11 +310,13 @@ 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 bo BASED(sysc_reschedule) - tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + tm __TI_flags+3(%r9),_TIF_SIGPENDING bnz BASED(sysc_sigpending) tm __TI_flags+3(%r9),_TIF_RESTART_SVC bo BASED(sysc_restart) @@ -342,7 +342,7 @@ sysc_mcck_pending: br %r1 # TIF bit will be cleared by handler # -# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal +# _TIF_SIGPENDING is set, call do_signal # sysc_sigpending: ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP @@ -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) @@ -657,7 +656,7 @@ io_work: lr %r15,%r1 # # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED +# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED # and _TIF_MCCK_PENDING # io_work_loop: @@ -665,7 +664,7 @@ io_work_loop: bo BASED(io_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bo BASED(io_reschedule) - tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + tm __TI_flags+3(%r9),_TIF_SIGPENDING bnz BASED(io_sigpending) b BASED(io_restore) io_work_done: @@ -693,7 +692,7 @@ io_reschedule: b BASED(io_work_loop) # -# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal +# _TIF_SIGPENDING is set, call do_signal # io_sigpending: TRACE_IRQS_ON diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index cd959c0b2e1..fee10177dbf 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER STACK_SIZE = 1 << STACK_SHIFT -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING) #define BASED(name) name-system_call(%r13) @@ -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,11 +302,13 @@ 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 jo sysc_reschedule - tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + tm __TI_flags+7(%r9),_TIF_SIGPENDING jnz sysc_sigpending tm __TI_flags+7(%r9),_TIF_RESTART_SVC jo sysc_restart @@ -332,7 +332,7 @@ sysc_mcck_pending: jg s390_handle_mcck # TIF bit will be cleared by handler # -# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal +# _TIF_SIGPENDING is set, call do_signal # sysc_sigpending: ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP @@ -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) @@ -648,11 +670,16 @@ io_work_loop: jo io_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jo io_reschedule - tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) + tm __TI_flags+7(%r9),_TIF_SIGPENDING jnz io_sigpending 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 # @@ -674,7 +701,7 @@ io_reschedule: j io_work_loop # -# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal +# _TIF_SIGPENDING or is set, call do_signal # io_sigpending: TRACE_IRQS_ON diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index dc364c1419a..a816e2de32b 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -57,61 +57,6 @@ startup_continue: # l %r14,.Lstartup_init-.LPG1(%r13) basr %r14,%r14 - - l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags -# -# find out if we have an IEEE fpu -# - mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) - efpc %r0,0 # test IEEE extract fpc instruction - oi 3(%r12),2 # set IEEE fpu flag -.Lchkfpu: - -# -# find out if we have the CSP instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13) - la %r0,0 - lr %r1,%r0 - la %r2,4 - csp %r0,%r2 # Test CSP instruction - oi 3(%r12),8 # set CSP flag -.Lchkcsp: - -# -# find out if we have the MVPG instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13) - sr %r0,%r0 - la %r1,0 - la %r2,0 - mvpg %r1,%r2 # Test CSP instruction - oi 3(%r12),16 # set MVPG flag -.Lchkmvpg: - -# -# find out if we have the IDTE instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) - .long 0xb2b10000 # store facility list - tm 0xc8,0x08 # check bit for clearing-by-ASCE - bno .Lchkidte-.LPG1(%r13) - lhi %r1,2094 - lhi %r2,0 - .long 0xb98e2001 - oi 3(%r12),0x80 # set IDTE flag -.Lchkidte: - -# -# find out if the diag 0x9c is available -# - mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13) - stap __LC_CPUID+4 # store cpu address - lh %r1,__LC_CPUID+4 - diag %r1,0,0x9c # test diag 0x9c - oi 2(%r12),1 # set diag9c flag -.Lchkdiag9c: - lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 8 @@ -132,13 +77,7 @@ startup_continue: .long 0 # cr13: home space segment table .long 0xc0000000 # cr14: machine check handling off .long 0 # cr15: linkage stack operations -.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu -.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp -.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg -.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte -.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c .Lmchunk:.long memory_chunk -.Lmflags:.long machine_flags .Lbss_bgn: .long __bss_start .Lbss_end: .long _end .Lparmaddr: .long PARMAREA diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 79dccd206a6..1d06961e87b 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -125,73 +125,11 @@ startup_continue: # and create a kernel NSS if the SAVESYS= parm is defined # brasl %r14,startup_init - # set program check new psw mask - mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) - larl %r12,machine_flags -# -# find out if we have the MVPG instruction -# - la %r1,0f-.LPG1(%r13) # set program check address - stg %r1,__LC_PGM_NEW_PSW+8 - sgr %r0,%r0 - lghi %r1,0 - lghi %r2,0 - mvpg %r1,%r2 # test MVPG instruction - oi 7(%r12),16 # set MVPG flag -0: - -# -# find out if the diag 0x44 works in 64 bit mode -# - la %r1,0f-.LPG1(%r13) # set program check address - stg %r1,__LC_PGM_NEW_PSW+8 - diag 0,0,0x44 # test diag 0x44 - oi 7(%r12),32 # set diag44 flag -0: - -# -# find out if we have the IDTE instruction -# - la %r1,0f-.LPG1(%r13) # set program check address - stg %r1,__LC_PGM_NEW_PSW+8 - .long 0xb2b10000 # store facility list - tm 0xc8,0x08 # check bit for clearing-by-ASCE - bno 0f-.LPG1(%r13) - lhi %r1,2048 - lhi %r2,0 - .long 0xb98e2001 - oi 7(%r12),0x80 # set IDTE flag -0: - -# -# find out if the diag 0x9c is available -# - la %r1,0f-.LPG1(%r13) # set program check address - stg %r1,__LC_PGM_NEW_PSW+8 - stap __LC_CPUID+4 # store cpu address - lh %r1,__LC_CPUID+4 - diag %r1,0,0x9c # test diag 0x9c - oi 6(%r12),1 # set diag9c flag -0: - -# -# find out if we have the MVCOS instruction -# - la %r1,0f-.LPG1(%r13) # set program check address - stg %r1,__LC_PGM_NEW_PSW+8 - .short 0xc800 # mvcos 0(%r0),0(%r0),%r0 - .short 0x0000 - .short 0x0000 -0: tm 0x8f,0x13 # special-operation exception? - bno 1f-.LPG1(%r13) # if yes, MVCOS is present - oi 6(%r12),2 # set MVCOS flag -1: - lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 16 .Lentry:.quad 0x0000000180000000,_stext -.Lctl: .quad 0x04b50002 # cr0: various things +.Lctl: .quad 0x04350002 # cr0: various things .quad 0 # cr1: primary space segment table .quad .Lduct # cr2: dispatchable unit control table .quad 0 # cr3: instruction authorization diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index c36d8123ca1..e7c5bfb7c75 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; } @@ -60,8 +61,6 @@ init_IRQ(void) /* * Switch to the asynchronous interrupt stack for softirq execution. */ -extern void __do_softirq(void); - asmlinkage void do_softirq(void) { unsigned long flags, old, new; diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index c1aff194141..7920861109d 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -180,24 +180,6 @@ void cpu_idle(void) } } -void show_regs(struct pt_regs *regs) -{ - print_modules(); - printk("CPU: %d %s %s %.*s\n", - task_thread_info(current)->cpu, print_tainted(), - init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); - printk("Process %s (pid: %d, task: %p, ksp: %p)\n", - current->comm, current->pid, current, - (void *) current->thread.ksp); - show_registers(regs); - /* Show stack backtrace if pt_regs is from kernel mode */ - if (!(regs->psw.mask & PSW_MASK_PSTATE)) - show_trace(NULL, (unsigned long *) regs->gprs[15]); - show_last_breaking_event(regs); -} - extern void kernel_thread_starter(void); asm( diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 58a06429698..35827b9bd4d 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,137 +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 -#define PT32_IEEE_IP 0x13c - -static int -do_ptrace(struct task_struct *child, long request, long addr, long data) -{ - int ret; - - if (request == PTRACE_ATTACH) - return ptrace_attach(child); - - /* - * Special cases to get/store the ieee instructions pointer. - */ - if (child == current) { - if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP) - return peek_user(child, addr, data); - if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP) - return poke_user(child, addr, data); -#ifdef CONFIG_COMPAT - if (request == PTRACE_PEEKUSR && - addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT)) - return peek_user_emu31(child, addr, data); - if (request == PTRACE_POKEUSR && - addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT)) - return poke_user_emu31(child, addr, data); -#endif - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - return ret; - - 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 long -sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - ret = do_ptrace(child, request, addr, data); - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index a9d18aafa5f..2bc70b6e876 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -73,7 +73,7 @@ EXPORT_SYMBOL(uaccess); unsigned int console_mode = 0; unsigned int console_devno = -1; unsigned int console_irq = -1; -unsigned long machine_flags = 0; +unsigned long machine_flags; unsigned long elf_hwcap = 0; char elf_platform[ELF_PLATFORM_SIZE]; @@ -683,15 +683,6 @@ setup_memory(void) #endif } -static __init unsigned int stfl(void) -{ - asm volatile( - " .insn s,0xb2b10000,0(0)\n" /* stfl */ - "0:\n" - EX_TABLE(0b,0b)); - return S390_lowcore.stfl_fac_list; -} - static int __init __stfle(unsigned long long *list, int doublewords) { typedef struct { unsigned long long _[doublewords]; } addrtype; @@ -758,6 +749,9 @@ static void __init setup_hwcaps(void) elf_hwcap |= 1UL << 6; } + if (MACHINE_HAS_HPAGE) + elf_hwcap |= 1UL << 7; + switch (cpuinfo->cpu_id.machine) { case 0x9672: #if !defined(CONFIG_64BIT) @@ -881,8 +875,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo) static int show_cpuinfo(struct seq_file *m, void *v) { - static const char *hwcap_str[7] = { - "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp" + static const char *hwcap_str[8] = { + "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", + "edat" }; struct cpuinfo_S390 *cpuinfo; unsigned long n = (unsigned long) v - 1; @@ -897,7 +892,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) num_online_cpus(), loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ))%100); seq_puts(m, "features\t: "); - for (i = 0; i < 7; i++) + for (i = 0; i < 8; i++) if (hwcap_str[i] && (elf_hwcap & (1UL << i))) seq_printf(m, "%s ", hwcap_str[i]); seq_puts(m, "\n"); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0dfa988c1b2..1f4228948dc 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); @@ -505,7 +503,7 @@ out: return rc; } -static int smp_rescan_cpus(void) +static int __smp_rescan_cpus(void) { cpumask_t avail; @@ -570,7 +568,7 @@ out: kfree(info); printk(KERN_INFO "CPUs: %d configured, %d standby\n", c_cpus, s_cpus); get_online_cpus(); - smp_rescan_cpus(); + __smp_rescan_cpus(); put_online_cpus(); } @@ -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 */ @@ -890,8 +890,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf, if (val != 0 && val != 1) return -EINVAL; - mutex_lock(&smp_cpu_state_mutex); get_online_cpus(); + mutex_lock(&smp_cpu_state_mutex); rc = -EBUSY; if (cpu_online(cpu)) goto out; @@ -919,8 +919,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf, break; } out: - put_online_cpus(); mutex_unlock(&smp_cpu_state_mutex); + put_online_cpus(); return rc ? rc : count; } static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); @@ -1088,17 +1088,17 @@ out: } #ifdef CONFIG_HOTPLUG_CPU -static ssize_t __ref rescan_store(struct sys_device *dev, - const char *buf, size_t count) + +int smp_rescan_cpus(void) { cpumask_t newcpus; int cpu; int rc; - mutex_lock(&smp_cpu_state_mutex); get_online_cpus(); + mutex_lock(&smp_cpu_state_mutex); newcpus = cpu_present_map; - rc = smp_rescan_cpus(); + rc = __smp_rescan_cpus(); if (rc) goto out; cpus_andnot(newcpus, cpu_present_map, newcpus); @@ -1109,10 +1109,19 @@ static ssize_t __ref rescan_store(struct sys_device *dev, } rc = 0; out: - put_online_cpus(); mutex_unlock(&smp_cpu_state_mutex); + put_online_cpus(); if (!cpus_empty(newcpus)) topology_schedule_update(); + return rc; +} + +static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf, + size_t count) +{ + int rc; + + rc = smp_rescan_cpus(); return rc ? rc : count; } static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); @@ -1139,16 +1148,16 @@ static ssize_t dispatching_store(struct sys_device *dev, const char *buf, if (val != 0 && val != 1) return -EINVAL; rc = 0; - mutex_lock(&smp_cpu_state_mutex); get_online_cpus(); + mutex_lock(&smp_cpu_state_mutex); if (cpu_management == val) goto out; rc = topology_set_cpu_management(val); if (!rc) cpu_management = val; out: - put_online_cpus(); mutex_unlock(&smp_cpu_state_mutex); + put_online_cpus(); return rc ? rc : count; } static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store); diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index 988d0d64c2c..5fdb799062b 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, diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 12b39b3d9c3..661a0721705 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -9,6 +9,7 @@ #include <linux/device.h> #include <linux/bootmem.h> #include <linux/sched.h> +#include <linux/kthread.h> #include <linux/workqueue.h> #include <linux/cpu.h> #include <linux/smp.h> @@ -66,6 +67,8 @@ static struct timer_list topology_timer; static void set_topology_timer(void); static DECLARE_WORK(topology_work, topology_work_fn); +cpumask_t cpu_core_map[NR_CPUS]; + cpumask_t cpu_coregroup_map(unsigned int cpu) { struct core_info *core = &core_info; @@ -199,6 +202,14 @@ int topology_set_cpu_management(int fc) return rc; } +static void update_cpu_core_map(void) +{ + int cpu; + + for_each_present_cpu(cpu) + cpu_core_map[cpu] = cpu_coregroup_map(cpu); +} + void arch_update_cpu_topology(void) { struct tl_info *info = tl_info; @@ -206,20 +217,33 @@ void arch_update_cpu_topology(void) int cpu; if (!machine_has_topology) { + update_cpu_core_map(); topology_update_polarization_simple(); return; } stsi(info, 15, 1, 2); tl_to_cores(info); + update_cpu_core_map(); for_each_online_cpu(cpu) { sysdev = get_cpu_sysdev(cpu); kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); } } -static void topology_work_fn(struct work_struct *work) +static int topology_kthread(void *data) { arch_reinit_sched_domains(); + return 0; +} + +static void topology_work_fn(struct work_struct *work) +{ + /* We can't call arch_reinit_sched_domains() from a multi-threaded + * workqueue context since it may deadlock in case of cpu hotplug. + * So we have to create a kernel thread in order to call + * arch_reinit_sched_domains(). + */ + kthread_run(topology_kthread, NULL, "topology_update"); } void topology_schedule_update(void) @@ -251,20 +275,23 @@ static int __init init_topology_update(void) { int rc; + rc = 0; if (!machine_has_topology) { topology_update_polarization_simple(); - return 0; + goto out; } init_timer_deferrable(&topology_timer); if (machine_has_topology_irq) { rc = register_external_interrupt(0x2005, topology_interrupt); if (rc) - return rc; + goto out; ctl_set_bit(0, 8); } else set_topology_timer(); - return 0; +out: + update_cpu_core_map(); + return rc; } __initcall(init_topology_update); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 57b607b6110..4584d81984c 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -113,7 +113,7 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high) } } -void show_trace(struct task_struct *task, unsigned long *stack) +static void show_trace(struct task_struct *task, unsigned long *stack) { register unsigned long __r15 asm ("15"); unsigned long sp; @@ -161,14 +161,14 @@ void show_stack(struct task_struct *task, unsigned long *sp) show_trace(task, sp); } -#ifdef CONFIG_64BIT -void show_last_breaking_event(struct pt_regs *regs) +static void show_last_breaking_event(struct pt_regs *regs) { +#ifdef CONFIG_64BIT printk("Last Breaking-Event-Address:\n"); printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN); print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN); -} #endif +} /* * The architecture-independent dump_stack generator @@ -223,6 +223,24 @@ void show_registers(struct pt_regs *regs) show_code(regs); } +void show_regs(struct pt_regs *regs) +{ + print_modules(); + printk("CPU: %d %s %s %.*s\n", + task_thread_info(current)->cpu, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); + printk("Process %s (pid: %d, task: %p, ksp: %p)\n", + current->comm, current->pid, current, + (void *) current->thread.ksp); + show_registers(regs); + /* Show stack backtrace if pt_regs is from kernel mode */ + if (!(regs->psw.mask & PSW_MASK_PSTATE)) + show_trace(NULL, (unsigned long *) regs->gprs[15]); + show_last_breaking_event(regs); +} + /* This is called from fs/proc/array.c */ void task_show_regs(struct seq_file *m, struct task_struct *task) { |