aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:38:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:38:30 -0400
commitd67c6f869c0a7f275689855161c93d714197e052 (patch)
tree17024af84087d216c62144d21a41beb74eca80dc /arch/s390/kernel
parentec31b2124158f60c515ed84bd5e40db1a883c7b6 (diff)
parent1175cdc670f2d4197b033f823b32435031a6daa8 (diff)
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: [S390] Update default configuration. [S390] use generic sys_ptrace [S390] Remove self ptrace IEEE_IP hack. [S390] Convert to SPARSEMEM & SPARSEMEM_VMEMMAP [S390] System z large page support. [S390] Convert machine feature detection code to C. [S390] vmemmap: use clear_table to initialise page tables. [S390] Move stfl to system.h and delete duplicated version. [S390] uaccess_mvcos: #ifdef config dependent code. [S390] cpu topology: Fix possible deadlock. [S390] Add topology_core_siblings to topology.h [S390] cio: Make isc handling more robust. [S390] remove -traditional [S390] Automatically detect added cpus. [S390] smp: Fix locking order. [S390] Add missing ifndef/define to include/asm-s390/sysinfo.h. [S390] Move show_regs to traps.c. [S390] cio: Use strict_strtoul() for attributes.
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/early.c125
-rw-r--r--arch/s390/kernel/head31.S61
-rw-r--r--arch/s390/kernel/head64.S64
-rw-r--r--arch/s390/kernel/process.c18
-rw-r--r--arch/s390/kernel/ptrace.c57
-rw-r--r--arch/s390/kernel/setup.c21
-rw-r--r--arch/s390/kernel/smp.c31
-rw-r--r--arch/s390/kernel/topology.c35
-rw-r--r--arch/s390/kernel/traps.c26
10 files changed, 205 insertions, 235 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 77051cd27925..6302f5082588 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -2,8 +2,6 @@
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4 4
5EXTRA_AFLAGS := -traditional
6
7# 5#
8# Passing null pointers is ok for smp code, since we access the lowcore here. 6# Passing null pointers is ok for smp code, since we access the lowcore here.
9# 7#
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 68ec4083bf73..d0e09684b9ce 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)
139 139
140 /* Running under z/VM ? */ 140 /* Running under z/VM ? */
141 if (cpuinfo->cpu_id.version == 0xff) 141 if (cpuinfo->cpu_id.version == 0xff)
142 machine_flags |= 1; 142 machine_flags |= MACHINE_FLAG_VM;
143 143
144 /* Running on a P/390 ? */ 144 /* Running on a P/390 ? */
145 if (cpuinfo->cpu_id.machine == 0x7490) 145 if (cpuinfo->cpu_id.machine == 0x7490)
146 machine_flags |= 4; 146 machine_flags |= MACHINE_FLAG_P390;
147 147
148 /* Running under KVM ? */ 148 /* Running under KVM ? */
149 if (cpuinfo->cpu_id.version == 0xfe) 149 if (cpuinfo->cpu_id.version == 0xfe)
150 machine_flags |= 64; 150 machine_flags |= MACHINE_FLAG_KVM;
151} 151}
152 152
153#ifdef CONFIG_64BIT 153#ifdef CONFIG_64BIT
@@ -268,6 +268,118 @@ static noinline __init void setup_lowcore_early(void)
268 s390_base_pgm_handler_fn = early_pgm_check_handler; 268 s390_base_pgm_handler_fn = early_pgm_check_handler;
269} 269}
270 270
271static noinline __init void setup_hpage(void)
272{
273#ifndef CONFIG_DEBUG_PAGEALLOC
274 unsigned int facilities;
275
276 facilities = stfl();
277 if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29)))
278 return;
279 machine_flags |= MACHINE_FLAG_HPAGE;
280 __ctl_set_bit(0, 23);
281#endif
282}
283
284static __init void detect_mvpg(void)
285{
286#ifndef CONFIG_64BIT
287 int rc;
288
289 asm volatile(
290 " la 0,0\n"
291 " mvpg %2,%2\n"
292 "0: la %0,0\n"
293 "1:\n"
294 EX_TABLE(0b,1b)
295 : "=d" (rc) : "0" (-EOPNOTSUPP), "a" (0) : "memory", "cc", "0");
296 if (!rc)
297 machine_flags |= MACHINE_FLAG_MVPG;
298#endif
299}
300
301static __init void detect_ieee(void)
302{
303#ifndef CONFIG_64BIT
304 int rc, tmp;
305
306 asm volatile(
307 " efpc %1,0\n"
308 "0: la %0,0\n"
309 "1:\n"
310 EX_TABLE(0b,1b)
311 : "=d" (rc), "=d" (tmp): "0" (-EOPNOTSUPP) : "cc");
312 if (!rc)
313 machine_flags |= MACHINE_FLAG_IEEE;
314#endif
315}
316
317static __init void detect_csp(void)
318{
319#ifndef CONFIG_64BIT
320 int rc;
321
322 asm volatile(
323 " la 0,0\n"
324 " la 1,0\n"
325 " la 2,4\n"
326 " csp 0,2\n"
327 "0: la %0,0\n"
328 "1:\n"
329 EX_TABLE(0b,1b)
330 : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc", "0", "1", "2");
331 if (!rc)
332 machine_flags |= MACHINE_FLAG_CSP;
333#endif
334}
335
336static __init void detect_diag9c(void)
337{
338 unsigned int cpu_address;
339 int rc;
340
341 cpu_address = stap();
342 asm volatile(
343 " diag %2,0,0x9c\n"
344 "0: la %0,0\n"
345 "1:\n"
346 EX_TABLE(0b,1b)
347 : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc");
348 if (!rc)
349 machine_flags |= MACHINE_FLAG_DIAG9C;
350}
351
352static __init void detect_diag44(void)
353{
354#ifdef CONFIG_64BIT
355 int rc;
356
357 asm volatile(
358 " diag 0,0,0x44\n"
359 "0: la %0,0\n"
360 "1:\n"
361 EX_TABLE(0b,1b)
362 : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc");
363 if (!rc)
364 machine_flags |= MACHINE_FLAG_DIAG44;
365#endif
366}
367
368static __init void detect_machine_facilities(void)
369{
370#ifdef CONFIG_64BIT
371 unsigned int facilities;
372
373 facilities = stfl();
374 if (facilities & (1 << 28))
375 machine_flags |= MACHINE_FLAG_IDTE;
376 if (facilities & (1 << 23))
377 machine_flags |= MACHINE_FLAG_PFMF;
378 if (facilities & (1 << 4))
379 machine_flags |= MACHINE_FLAG_MVCOS;
380#endif
381}
382
271/* 383/*
272 * Save ipl parameters, clear bss memory, initialize storage keys 384 * Save ipl parameters, clear bss memory, initialize storage keys
273 * and create a kernel NSS at startup if the SAVESYS= parm is defined 385 * and create a kernel NSS at startup if the SAVESYS= parm is defined
@@ -285,6 +397,13 @@ void __init startup_init(void)
285 create_kernel_nss(); 397 create_kernel_nss();
286 sort_main_extable(); 398 sort_main_extable();
287 setup_lowcore_early(); 399 setup_lowcore_early();
400 detect_mvpg();
401 detect_ieee();
402 detect_csp();
403 detect_diag9c();
404 detect_diag44();
405 detect_machine_facilities();
406 setup_hpage();
288 sclp_read_info_early(); 407 sclp_read_info_early();
289 sclp_facilities_detect(); 408 sclp_facilities_detect();
290 memsize = sclp_memory_detect(); 409 memsize = sclp_memory_detect();
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index dc364c1419af..a816e2de32b9 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -57,61 +57,6 @@ startup_continue:
57# 57#
58 l %r14,.Lstartup_init-.LPG1(%r13) 58 l %r14,.Lstartup_init-.LPG1(%r13)
59 basr %r14,%r14 59 basr %r14,%r14
60
61 l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
62#
63# find out if we have an IEEE fpu
64#
65 mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
66 efpc %r0,0 # test IEEE extract fpc instruction
67 oi 3(%r12),2 # set IEEE fpu flag
68.Lchkfpu:
69
70#
71# find out if we have the CSP instruction
72#
73 mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
74 la %r0,0
75 lr %r1,%r0
76 la %r2,4
77 csp %r0,%r2 # Test CSP instruction
78 oi 3(%r12),8 # set CSP flag
79.Lchkcsp:
80
81#
82# find out if we have the MVPG instruction
83#
84 mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
85 sr %r0,%r0
86 la %r1,0
87 la %r2,0
88 mvpg %r1,%r2 # Test CSP instruction
89 oi 3(%r12),16 # set MVPG flag
90.Lchkmvpg:
91
92#
93# find out if we have the IDTE instruction
94#
95 mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
96 .long 0xb2b10000 # store facility list
97 tm 0xc8,0x08 # check bit for clearing-by-ASCE
98 bno .Lchkidte-.LPG1(%r13)
99 lhi %r1,2094
100 lhi %r2,0
101 .long 0xb98e2001
102 oi 3(%r12),0x80 # set IDTE flag
103.Lchkidte:
104
105#
106# find out if the diag 0x9c is available
107#
108 mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13)
109 stap __LC_CPUID+4 # store cpu address
110 lh %r1,__LC_CPUID+4
111 diag %r1,0,0x9c # test diag 0x9c
112 oi 2(%r12),1 # set diag9c flag
113.Lchkdiag9c:
114
115 lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, 60 lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space,
116 # virtual and never return ... 61 # virtual and never return ...
117 .align 8 62 .align 8
@@ -132,13 +77,7 @@ startup_continue:
132 .long 0 # cr13: home space segment table 77 .long 0 # cr13: home space segment table
133 .long 0xc0000000 # cr14: machine check handling off 78 .long 0xc0000000 # cr14: machine check handling off
134 .long 0 # cr15: linkage stack operations 79 .long 0 # cr15: linkage stack operations
135.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
136.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
137.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
138.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
139.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
140.Lmchunk:.long memory_chunk 80.Lmchunk:.long memory_chunk
141.Lmflags:.long machine_flags
142.Lbss_bgn: .long __bss_start 81.Lbss_bgn: .long __bss_start
143.Lbss_end: .long _end 82.Lbss_end: .long _end
144.Lparmaddr: .long PARMAREA 83.Lparmaddr: .long PARMAREA
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 79dccd206a6e..1d06961e87b3 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -125,73 +125,11 @@ startup_continue:
125# and create a kernel NSS if the SAVESYS= parm is defined 125# and create a kernel NSS if the SAVESYS= parm is defined
126# 126#
127 brasl %r14,startup_init 127 brasl %r14,startup_init
128 # set program check new psw mask
129 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
130 larl %r12,machine_flags
131#
132# find out if we have the MVPG instruction
133#
134 la %r1,0f-.LPG1(%r13) # set program check address
135 stg %r1,__LC_PGM_NEW_PSW+8
136 sgr %r0,%r0
137 lghi %r1,0
138 lghi %r2,0
139 mvpg %r1,%r2 # test MVPG instruction
140 oi 7(%r12),16 # set MVPG flag
1410:
142
143#
144# find out if the diag 0x44 works in 64 bit mode
145#
146 la %r1,0f-.LPG1(%r13) # set program check address
147 stg %r1,__LC_PGM_NEW_PSW+8
148 diag 0,0,0x44 # test diag 0x44
149 oi 7(%r12),32 # set diag44 flag
1500:
151
152#
153# find out if we have the IDTE instruction
154#
155 la %r1,0f-.LPG1(%r13) # set program check address
156 stg %r1,__LC_PGM_NEW_PSW+8
157 .long 0xb2b10000 # store facility list
158 tm 0xc8,0x08 # check bit for clearing-by-ASCE
159 bno 0f-.LPG1(%r13)
160 lhi %r1,2048
161 lhi %r2,0
162 .long 0xb98e2001
163 oi 7(%r12),0x80 # set IDTE flag
1640:
165
166#
167# find out if the diag 0x9c is available
168#
169 la %r1,0f-.LPG1(%r13) # set program check address
170 stg %r1,__LC_PGM_NEW_PSW+8
171 stap __LC_CPUID+4 # store cpu address
172 lh %r1,__LC_CPUID+4
173 diag %r1,0,0x9c # test diag 0x9c
174 oi 6(%r12),1 # set diag9c flag
1750:
176
177#
178# find out if we have the MVCOS instruction
179#
180 la %r1,0f-.LPG1(%r13) # set program check address
181 stg %r1,__LC_PGM_NEW_PSW+8
182 .short 0xc800 # mvcos 0(%r0),0(%r0),%r0
183 .short 0x0000
184 .short 0x0000
1850: tm 0x8f,0x13 # special-operation exception?
186 bno 1f-.LPG1(%r13) # if yes, MVCOS is present
187 oi 6(%r12),2 # set MVCOS flag
1881:
189
190 lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, 128 lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
191 # virtual and never return ... 129 # virtual and never return ...
192 .align 16 130 .align 16
193.Lentry:.quad 0x0000000180000000,_stext 131.Lentry:.quad 0x0000000180000000,_stext
194.Lctl: .quad 0x04b50002 # cr0: various things 132.Lctl: .quad 0x04350002 # cr0: various things
195 .quad 0 # cr1: primary space segment table 133 .quad 0 # cr1: primary space segment table
196 .quad .Lduct # cr2: dispatchable unit control table 134 .quad .Lduct # cr2: dispatchable unit control table
197 .quad 0 # cr3: instruction authorization 135 .quad 0 # cr3: instruction authorization
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index c1aff194141d..7920861109d2 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -180,24 +180,6 @@ void cpu_idle(void)
180 } 180 }
181} 181}
182 182
183void show_regs(struct pt_regs *regs)
184{
185 print_modules();
186 printk("CPU: %d %s %s %.*s\n",
187 task_thread_info(current)->cpu, print_tainted(),
188 init_utsname()->release,
189 (int)strcspn(init_utsname()->version, " "),
190 init_utsname()->version);
191 printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
192 current->comm, current->pid, current,
193 (void *) current->thread.ksp);
194 show_registers(regs);
195 /* Show stack backtrace if pt_regs is from kernel mode */
196 if (!(regs->psw.mask & PSW_MASK_PSTATE))
197 show_trace(NULL, (unsigned long *) regs->gprs[15]);
198 show_last_breaking_event(regs);
199}
200
201extern void kernel_thread_starter(void); 183extern void kernel_thread_starter(void);
202 184
203asm( 185asm(
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 58a064296987..7f4270163744 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -607,38 +607,8 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
607} 607}
608#endif 608#endif
609 609
610#define PT32_IEEE_IP 0x13c 610long arch_ptrace(struct task_struct *child, long request, long addr, long data)
611
612static int
613do_ptrace(struct task_struct *child, long request, long addr, long data)
614{ 611{
615 int ret;
616
617 if (request == PTRACE_ATTACH)
618 return ptrace_attach(child);
619
620 /*
621 * Special cases to get/store the ieee instructions pointer.
622 */
623 if (child == current) {
624 if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP)
625 return peek_user(child, addr, data);
626 if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
627 return poke_user(child, addr, data);
628#ifdef CONFIG_COMPAT
629 if (request == PTRACE_PEEKUSR &&
630 addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
631 return peek_user_emu31(child, addr, data);
632 if (request == PTRACE_POKEUSR &&
633 addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
634 return poke_user_emu31(child, addr, data);
635#endif
636 }
637
638 ret = ptrace_check_attach(child, request == PTRACE_KILL);
639 if (ret < 0)
640 return ret;
641
642 switch (request) { 612 switch (request) {
643 case PTRACE_SYSCALL: 613 case PTRACE_SYSCALL:
644 /* continue and stop at next (return from) syscall */ 614 /* continue and stop at next (return from) syscall */
@@ -693,31 +663,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
693 return -EIO; 663 return -EIO;
694} 664}
695 665
696asmlinkage long
697sys_ptrace(long request, long pid, long addr, long data)
698{
699 struct task_struct *child;
700 int ret;
701
702 lock_kernel();
703 if (request == PTRACE_TRACEME) {
704 ret = ptrace_traceme();
705 goto out;
706 }
707
708 child = ptrace_get_task_struct(pid);
709 if (IS_ERR(child)) {
710 ret = PTR_ERR(child);
711 goto out;
712 }
713
714 ret = do_ptrace(child, request, addr, data);
715 put_task_struct(child);
716out:
717 unlock_kernel();
718 return ret;
719}
720
721asmlinkage void 666asmlinkage void
722syscall_trace(struct pt_regs *regs, int entryexit) 667syscall_trace(struct pt_regs *regs, int entryexit)
723{ 668{
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index a9d18aafa5f4..2bc70b6e876a 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(uaccess);
73unsigned int console_mode = 0; 73unsigned int console_mode = 0;
74unsigned int console_devno = -1; 74unsigned int console_devno = -1;
75unsigned int console_irq = -1; 75unsigned int console_irq = -1;
76unsigned long machine_flags = 0; 76unsigned long machine_flags;
77unsigned long elf_hwcap = 0; 77unsigned long elf_hwcap = 0;
78char elf_platform[ELF_PLATFORM_SIZE]; 78char elf_platform[ELF_PLATFORM_SIZE];
79 79
@@ -683,15 +683,6 @@ setup_memory(void)
683#endif 683#endif
684} 684}
685 685
686static __init unsigned int stfl(void)
687{
688 asm volatile(
689 " .insn s,0xb2b10000,0(0)\n" /* stfl */
690 "0:\n"
691 EX_TABLE(0b,0b));
692 return S390_lowcore.stfl_fac_list;
693}
694
695static int __init __stfle(unsigned long long *list, int doublewords) 686static int __init __stfle(unsigned long long *list, int doublewords)
696{ 687{
697 typedef struct { unsigned long long _[doublewords]; } addrtype; 688 typedef struct { unsigned long long _[doublewords]; } addrtype;
@@ -758,6 +749,9 @@ static void __init setup_hwcaps(void)
758 elf_hwcap |= 1UL << 6; 749 elf_hwcap |= 1UL << 6;
759 } 750 }
760 751
752 if (MACHINE_HAS_HPAGE)
753 elf_hwcap |= 1UL << 7;
754
761 switch (cpuinfo->cpu_id.machine) { 755 switch (cpuinfo->cpu_id.machine) {
762 case 0x9672: 756 case 0x9672:
763#if !defined(CONFIG_64BIT) 757#if !defined(CONFIG_64BIT)
@@ -881,8 +875,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
881 875
882static int show_cpuinfo(struct seq_file *m, void *v) 876static int show_cpuinfo(struct seq_file *m, void *v)
883{ 877{
884 static const char *hwcap_str[7] = { 878 static const char *hwcap_str[8] = {
885 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp" 879 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
880 "edat"
886 }; 881 };
887 struct cpuinfo_S390 *cpuinfo; 882 struct cpuinfo_S390 *cpuinfo;
888 unsigned long n = (unsigned long) v - 1; 883 unsigned long n = (unsigned long) v - 1;
@@ -897,7 +892,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
897 num_online_cpus(), loops_per_jiffy/(500000/HZ), 892 num_online_cpus(), loops_per_jiffy/(500000/HZ),
898 (loops_per_jiffy/(5000/HZ))%100); 893 (loops_per_jiffy/(5000/HZ))%100);
899 seq_puts(m, "features\t: "); 894 seq_puts(m, "features\t: ");
900 for (i = 0; i < 7; i++) 895 for (i = 0; i < 8; i++)
901 if (hwcap_str[i] && (elf_hwcap & (1UL << i))) 896 if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
902 seq_printf(m, "%s ", hwcap_str[i]); 897 seq_printf(m, "%s ", hwcap_str[i]);
903 seq_puts(m, "\n"); 898 seq_puts(m, "\n");
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 0dfa988c1b26..0aeb290060d9 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -505,7 +505,7 @@ out:
505 return rc; 505 return rc;
506} 506}
507 507
508static int smp_rescan_cpus(void) 508static int __smp_rescan_cpus(void)
509{ 509{
510 cpumask_t avail; 510 cpumask_t avail;
511 511
@@ -570,7 +570,7 @@ out:
570 kfree(info); 570 kfree(info);
571 printk(KERN_INFO "CPUs: %d configured, %d standby\n", c_cpus, s_cpus); 571 printk(KERN_INFO "CPUs: %d configured, %d standby\n", c_cpus, s_cpus);
572 get_online_cpus(); 572 get_online_cpus();
573 smp_rescan_cpus(); 573 __smp_rescan_cpus();
574 put_online_cpus(); 574 put_online_cpus();
575} 575}
576 576
@@ -890,8 +890,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
890 if (val != 0 && val != 1) 890 if (val != 0 && val != 1)
891 return -EINVAL; 891 return -EINVAL;
892 892
893 mutex_lock(&smp_cpu_state_mutex);
894 get_online_cpus(); 893 get_online_cpus();
894 mutex_lock(&smp_cpu_state_mutex);
895 rc = -EBUSY; 895 rc = -EBUSY;
896 if (cpu_online(cpu)) 896 if (cpu_online(cpu))
897 goto out; 897 goto out;
@@ -919,8 +919,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
919 break; 919 break;
920 } 920 }
921out: 921out:
922 put_online_cpus();
923 mutex_unlock(&smp_cpu_state_mutex); 922 mutex_unlock(&smp_cpu_state_mutex);
923 put_online_cpus();
924 return rc ? rc : count; 924 return rc ? rc : count;
925} 925}
926static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); 926static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
@@ -1088,17 +1088,17 @@ out:
1088} 1088}
1089 1089
1090#ifdef CONFIG_HOTPLUG_CPU 1090#ifdef CONFIG_HOTPLUG_CPU
1091static ssize_t __ref rescan_store(struct sys_device *dev, 1091
1092 const char *buf, size_t count) 1092int smp_rescan_cpus(void)
1093{ 1093{
1094 cpumask_t newcpus; 1094 cpumask_t newcpus;
1095 int cpu; 1095 int cpu;
1096 int rc; 1096 int rc;
1097 1097
1098 mutex_lock(&smp_cpu_state_mutex);
1099 get_online_cpus(); 1098 get_online_cpus();
1099 mutex_lock(&smp_cpu_state_mutex);
1100 newcpus = cpu_present_map; 1100 newcpus = cpu_present_map;
1101 rc = smp_rescan_cpus(); 1101 rc = __smp_rescan_cpus();
1102 if (rc) 1102 if (rc)
1103 goto out; 1103 goto out;
1104 cpus_andnot(newcpus, cpu_present_map, newcpus); 1104 cpus_andnot(newcpus, cpu_present_map, newcpus);
@@ -1109,10 +1109,19 @@ static ssize_t __ref rescan_store(struct sys_device *dev,
1109 } 1109 }
1110 rc = 0; 1110 rc = 0;
1111out: 1111out:
1112 put_online_cpus();
1113 mutex_unlock(&smp_cpu_state_mutex); 1112 mutex_unlock(&smp_cpu_state_mutex);
1113 put_online_cpus();
1114 if (!cpus_empty(newcpus)) 1114 if (!cpus_empty(newcpus))
1115 topology_schedule_update(); 1115 topology_schedule_update();
1116 return rc;
1117}
1118
1119static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf,
1120 size_t count)
1121{
1122 int rc;
1123
1124 rc = smp_rescan_cpus();
1116 return rc ? rc : count; 1125 return rc ? rc : count;
1117} 1126}
1118static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); 1127static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
@@ -1139,16 +1148,16 @@ static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
1139 if (val != 0 && val != 1) 1148 if (val != 0 && val != 1)
1140 return -EINVAL; 1149 return -EINVAL;
1141 rc = 0; 1150 rc = 0;
1142 mutex_lock(&smp_cpu_state_mutex);
1143 get_online_cpus(); 1151 get_online_cpus();
1152 mutex_lock(&smp_cpu_state_mutex);
1144 if (cpu_management == val) 1153 if (cpu_management == val)
1145 goto out; 1154 goto out;
1146 rc = topology_set_cpu_management(val); 1155 rc = topology_set_cpu_management(val);
1147 if (!rc) 1156 if (!rc)
1148 cpu_management = val; 1157 cpu_management = val;
1149out: 1158out:
1150 put_online_cpus();
1151 mutex_unlock(&smp_cpu_state_mutex); 1159 mutex_unlock(&smp_cpu_state_mutex);
1160 put_online_cpus();
1152 return rc ? rc : count; 1161 return rc ? rc : count;
1153} 1162}
1154static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store); 1163static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 12b39b3d9c38..661a07217057 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -9,6 +9,7 @@
9#include <linux/device.h> 9#include <linux/device.h>
10#include <linux/bootmem.h> 10#include <linux/bootmem.h>
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <linux/kthread.h>
12#include <linux/workqueue.h> 13#include <linux/workqueue.h>
13#include <linux/cpu.h> 14#include <linux/cpu.h>
14#include <linux/smp.h> 15#include <linux/smp.h>
@@ -66,6 +67,8 @@ static struct timer_list topology_timer;
66static void set_topology_timer(void); 67static void set_topology_timer(void);
67static DECLARE_WORK(topology_work, topology_work_fn); 68static DECLARE_WORK(topology_work, topology_work_fn);
68 69
70cpumask_t cpu_core_map[NR_CPUS];
71
69cpumask_t cpu_coregroup_map(unsigned int cpu) 72cpumask_t cpu_coregroup_map(unsigned int cpu)
70{ 73{
71 struct core_info *core = &core_info; 74 struct core_info *core = &core_info;
@@ -199,6 +202,14 @@ int topology_set_cpu_management(int fc)
199 return rc; 202 return rc;
200} 203}
201 204
205static void update_cpu_core_map(void)
206{
207 int cpu;
208
209 for_each_present_cpu(cpu)
210 cpu_core_map[cpu] = cpu_coregroup_map(cpu);
211}
212
202void arch_update_cpu_topology(void) 213void arch_update_cpu_topology(void)
203{ 214{
204 struct tl_info *info = tl_info; 215 struct tl_info *info = tl_info;
@@ -206,20 +217,33 @@ void arch_update_cpu_topology(void)
206 int cpu; 217 int cpu;
207 218
208 if (!machine_has_topology) { 219 if (!machine_has_topology) {
220 update_cpu_core_map();
209 topology_update_polarization_simple(); 221 topology_update_polarization_simple();
210 return; 222 return;
211 } 223 }
212 stsi(info, 15, 1, 2); 224 stsi(info, 15, 1, 2);
213 tl_to_cores(info); 225 tl_to_cores(info);
226 update_cpu_core_map();
214 for_each_online_cpu(cpu) { 227 for_each_online_cpu(cpu) {
215 sysdev = get_cpu_sysdev(cpu); 228 sysdev = get_cpu_sysdev(cpu);
216 kobject_uevent(&sysdev->kobj, KOBJ_CHANGE); 229 kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
217 } 230 }
218} 231}
219 232
220static void topology_work_fn(struct work_struct *work) 233static int topology_kthread(void *data)
221{ 234{
222 arch_reinit_sched_domains(); 235 arch_reinit_sched_domains();
236 return 0;
237}
238
239static void topology_work_fn(struct work_struct *work)
240{
241 /* We can't call arch_reinit_sched_domains() from a multi-threaded
242 * workqueue context since it may deadlock in case of cpu hotplug.
243 * So we have to create a kernel thread in order to call
244 * arch_reinit_sched_domains().
245 */
246 kthread_run(topology_kthread, NULL, "topology_update");
223} 247}
224 248
225void topology_schedule_update(void) 249void topology_schedule_update(void)
@@ -251,20 +275,23 @@ static int __init init_topology_update(void)
251{ 275{
252 int rc; 276 int rc;
253 277
278 rc = 0;
254 if (!machine_has_topology) { 279 if (!machine_has_topology) {
255 topology_update_polarization_simple(); 280 topology_update_polarization_simple();
256 return 0; 281 goto out;
257 } 282 }
258 init_timer_deferrable(&topology_timer); 283 init_timer_deferrable(&topology_timer);
259 if (machine_has_topology_irq) { 284 if (machine_has_topology_irq) {
260 rc = register_external_interrupt(0x2005, topology_interrupt); 285 rc = register_external_interrupt(0x2005, topology_interrupt);
261 if (rc) 286 if (rc)
262 return rc; 287 goto out;
263 ctl_set_bit(0, 8); 288 ctl_set_bit(0, 8);
264 } 289 }
265 else 290 else
266 set_topology_timer(); 291 set_topology_timer();
267 return 0; 292out:
293 update_cpu_core_map();
294 return rc;
268} 295}
269__initcall(init_topology_update); 296__initcall(init_topology_update);
270 297
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 57b607b61100..4584d81984c0 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)
113 } 113 }
114} 114}
115 115
116void show_trace(struct task_struct *task, unsigned long *stack) 116static void show_trace(struct task_struct *task, unsigned long *stack)
117{ 117{
118 register unsigned long __r15 asm ("15"); 118 register unsigned long __r15 asm ("15");
119 unsigned long sp; 119 unsigned long sp;
@@ -161,14 +161,14 @@ void show_stack(struct task_struct *task, unsigned long *sp)
161 show_trace(task, sp); 161 show_trace(task, sp);
162} 162}
163 163
164#ifdef CONFIG_64BIT 164static void show_last_breaking_event(struct pt_regs *regs)
165void show_last_breaking_event(struct pt_regs *regs)
166{ 165{
166#ifdef CONFIG_64BIT
167 printk("Last Breaking-Event-Address:\n"); 167 printk("Last Breaking-Event-Address:\n");
168 printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN); 168 printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
169 print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN); 169 print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
170}
171#endif 170#endif
171}
172 172
173/* 173/*
174 * The architecture-independent dump_stack generator 174 * The architecture-independent dump_stack generator
@@ -223,6 +223,24 @@ void show_registers(struct pt_regs *regs)
223 show_code(regs); 223 show_code(regs);
224} 224}
225 225
226void show_regs(struct pt_regs *regs)
227{
228 print_modules();
229 printk("CPU: %d %s %s %.*s\n",
230 task_thread_info(current)->cpu, print_tainted(),
231 init_utsname()->release,
232 (int)strcspn(init_utsname()->version, " "),
233 init_utsname()->version);
234 printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
235 current->comm, current->pid, current,
236 (void *) current->thread.ksp);
237 show_registers(regs);
238 /* Show stack backtrace if pt_regs is from kernel mode */
239 if (!(regs->psw.mask & PSW_MASK_PSTATE))
240 show_trace(NULL, (unsigned long *) regs->gprs[15]);
241 show_last_breaking_event(regs);
242}
243
226/* This is called from fs/proc/array.c */ 244/* This is called from fs/proc/array.c */
227void task_show_regs(struct seq_file *m, struct task_struct *task) 245void task_show_regs(struct seq_file *m, struct task_struct *task)
228{ 246{