diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 125 | ||||
-rw-r--r-- | arch/s390/kernel/head31.S | 61 | ||||
-rw-r--r-- | arch/s390/kernel/head64.S | 64 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 18 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 57 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 21 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 31 | ||||
-rw-r--r-- | arch/s390/kernel/topology.c | 35 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 26 |
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 | ||
5 | EXTRA_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 | ||
271 | static 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 | |||
284 | static __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 | |||
301 | static __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 | |||
317 | static __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 | |||
336 | static __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 | |||
352 | static __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 | |||
368 | static __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 | ||
141 | 0: | ||
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 | ||
150 | 0: | ||
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 | ||
164 | 0: | ||
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 | ||
175 | 0: | ||
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 | ||
185 | 0: tm 0x8f,0x13 # special-operation exception? | ||
186 | bno 1f-.LPG1(%r13) # if yes, MVCOS is present | ||
187 | oi 6(%r12),2 # set MVCOS flag | ||
188 | 1: | ||
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 | ||
183 | void 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 | |||
201 | extern void kernel_thread_starter(void); | 183 | extern void kernel_thread_starter(void); |
202 | 184 | ||
203 | asm( | 185 | asm( |
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 | 610 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
611 | |||
612 | static int | ||
613 | do_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 | ||
696 | asmlinkage long | ||
697 | sys_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); | ||
716 | out: | ||
717 | unlock_kernel(); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | asmlinkage void | 666 | asmlinkage void |
722 | syscall_trace(struct pt_regs *regs, int entryexit) | 667 | syscall_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); | |||
73 | unsigned int console_mode = 0; | 73 | unsigned int console_mode = 0; |
74 | unsigned int console_devno = -1; | 74 | unsigned int console_devno = -1; |
75 | unsigned int console_irq = -1; | 75 | unsigned int console_irq = -1; |
76 | unsigned long machine_flags = 0; | 76 | unsigned long machine_flags; |
77 | unsigned long elf_hwcap = 0; | 77 | unsigned long elf_hwcap = 0; |
78 | char elf_platform[ELF_PLATFORM_SIZE]; | 78 | char elf_platform[ELF_PLATFORM_SIZE]; |
79 | 79 | ||
@@ -683,15 +683,6 @@ setup_memory(void) | |||
683 | #endif | 683 | #endif |
684 | } | 684 | } |
685 | 685 | ||
686 | static __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 | |||
695 | static int __init __stfle(unsigned long long *list, int doublewords) | 686 | static 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 | ||
882 | static int show_cpuinfo(struct seq_file *m, void *v) | 876 | static 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 | ||
508 | static int smp_rescan_cpus(void) | 508 | static 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 | } |
921 | out: | 921 | out: |
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 | } |
926 | static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store); | 926 | static 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 |
1091 | static ssize_t __ref rescan_store(struct sys_device *dev, | 1091 | |
1092 | const char *buf, size_t count) | 1092 | int 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; |
1111 | out: | 1111 | out: |
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 | |||
1119 | static 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 | } |
1118 | static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); | 1127 | static 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; |
1149 | out: | 1158 | out: |
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 | } |
1154 | static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store); | 1163 | static 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; | |||
66 | static void set_topology_timer(void); | 67 | static void set_topology_timer(void); |
67 | static DECLARE_WORK(topology_work, topology_work_fn); | 68 | static DECLARE_WORK(topology_work, topology_work_fn); |
68 | 69 | ||
70 | cpumask_t cpu_core_map[NR_CPUS]; | ||
71 | |||
69 | cpumask_t cpu_coregroup_map(unsigned int cpu) | 72 | cpumask_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 | ||
205 | static 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 | |||
202 | void arch_update_cpu_topology(void) | 213 | void 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 | ||
220 | static void topology_work_fn(struct work_struct *work) | 233 | static int topology_kthread(void *data) |
221 | { | 234 | { |
222 | arch_reinit_sched_domains(); | 235 | arch_reinit_sched_domains(); |
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static 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 | ||
225 | void topology_schedule_update(void) | 249 | void 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; | 292 | out: |
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 | ||
116 | void show_trace(struct task_struct *task, unsigned long *stack) | 116 | static 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 | 164 | static void show_last_breaking_event(struct pt_regs *regs) |
165 | void 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 | ||
226 | void 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 */ |
227 | void task_show_regs(struct seq_file *m, struct task_struct *task) | 245 | void task_show_regs(struct seq_file *m, struct task_struct *task) |
228 | { | 246 | { |