diff options
Diffstat (limited to 'arch/s390/kernel/traps.c')
-rw-r--r-- | arch/s390/kernel/traps.c | 222 |
1 files changed, 79 insertions, 143 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 5d8f0f3d0250..a65d2e82f61d 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/atomic.h> | 39 | #include <asm/atomic.h> |
40 | #include <asm/mathemu.h> | 40 | #include <asm/mathemu.h> |
41 | #include <asm/cpcmd.h> | 41 | #include <asm/cpcmd.h> |
42 | #include <asm/s390_ext.h> | ||
43 | #include <asm/lowcore.h> | 42 | #include <asm/lowcore.h> |
44 | #include <asm/debug.h> | 43 | #include <asm/debug.h> |
45 | #include "entry.h" | 44 | #include "entry.h" |
@@ -237,43 +236,6 @@ void show_regs(struct pt_regs *regs) | |||
237 | show_last_breaking_event(regs); | 236 | show_last_breaking_event(regs); |
238 | } | 237 | } |
239 | 238 | ||
240 | /* This is called from fs/proc/array.c */ | ||
241 | void task_show_regs(struct seq_file *m, struct task_struct *task) | ||
242 | { | ||
243 | struct pt_regs *regs; | ||
244 | |||
245 | regs = task_pt_regs(task); | ||
246 | seq_printf(m, "task: %p, ksp: %p\n", | ||
247 | task, (void *)task->thread.ksp); | ||
248 | seq_printf(m, "User PSW : %p %p\n", | ||
249 | (void *) regs->psw.mask, (void *)regs->psw.addr); | ||
250 | |||
251 | seq_printf(m, "User GPRS: " FOURLONG, | ||
252 | regs->gprs[0], regs->gprs[1], | ||
253 | regs->gprs[2], regs->gprs[3]); | ||
254 | seq_printf(m, " " FOURLONG, | ||
255 | regs->gprs[4], regs->gprs[5], | ||
256 | regs->gprs[6], regs->gprs[7]); | ||
257 | seq_printf(m, " " FOURLONG, | ||
258 | regs->gprs[8], regs->gprs[9], | ||
259 | regs->gprs[10], regs->gprs[11]); | ||
260 | seq_printf(m, " " FOURLONG, | ||
261 | regs->gprs[12], regs->gprs[13], | ||
262 | regs->gprs[14], regs->gprs[15]); | ||
263 | seq_printf(m, "User ACRS: %08x %08x %08x %08x\n", | ||
264 | task->thread.acrs[0], task->thread.acrs[1], | ||
265 | task->thread.acrs[2], task->thread.acrs[3]); | ||
266 | seq_printf(m, " %08x %08x %08x %08x\n", | ||
267 | task->thread.acrs[4], task->thread.acrs[5], | ||
268 | task->thread.acrs[6], task->thread.acrs[7]); | ||
269 | seq_printf(m, " %08x %08x %08x %08x\n", | ||
270 | task->thread.acrs[8], task->thread.acrs[9], | ||
271 | task->thread.acrs[10], task->thread.acrs[11]); | ||
272 | seq_printf(m, " %08x %08x %08x %08x\n", | ||
273 | task->thread.acrs[12], task->thread.acrs[13], | ||
274 | task->thread.acrs[14], task->thread.acrs[15]); | ||
275 | } | ||
276 | |||
277 | static DEFINE_SPINLOCK(die_lock); | 239 | static DEFINE_SPINLOCK(die_lock); |
278 | 240 | ||
279 | void die(const char * str, struct pt_regs * regs, long err) | 241 | void die(const char * str, struct pt_regs * regs, long err) |
@@ -329,27 +291,19 @@ int is_valid_bugaddr(unsigned long addr) | |||
329 | return 1; | 291 | return 1; |
330 | } | 292 | } |
331 | 293 | ||
332 | static void __kprobes inline do_trap(long interruption_code, int signr, | 294 | static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str, |
333 | char *str, struct pt_regs *regs, | 295 | struct pt_regs *regs, siginfo_t *info) |
334 | siginfo_t *info) | ||
335 | { | 296 | { |
336 | /* | 297 | if (notify_die(DIE_TRAP, str, regs, pgm_int_code, |
337 | * We got all needed information from the lowcore and can | 298 | pgm_int_code, signr) == NOTIFY_STOP) |
338 | * now safely switch on interrupts. | ||
339 | */ | ||
340 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
341 | local_irq_enable(); | ||
342 | |||
343 | if (notify_die(DIE_TRAP, str, regs, interruption_code, | ||
344 | interruption_code, signr) == NOTIFY_STOP) | ||
345 | return; | 299 | return; |
346 | 300 | ||
347 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 301 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
348 | struct task_struct *tsk = current; | 302 | struct task_struct *tsk = current; |
349 | 303 | ||
350 | tsk->thread.trap_no = interruption_code & 0xffff; | 304 | tsk->thread.trap_no = pgm_int_code & 0xffff; |
351 | force_sig_info(signr, info, tsk); | 305 | force_sig_info(signr, info, tsk); |
352 | report_user_fault(regs, interruption_code, signr); | 306 | report_user_fault(regs, pgm_int_code, signr); |
353 | } else { | 307 | } else { |
354 | const struct exception_table_entry *fixup; | 308 | const struct exception_table_entry *fixup; |
355 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 309 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
@@ -361,77 +315,77 @@ static void __kprobes inline do_trap(long interruption_code, int signr, | |||
361 | btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs); | 315 | btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs); |
362 | if (btt == BUG_TRAP_TYPE_WARN) | 316 | if (btt == BUG_TRAP_TYPE_WARN) |
363 | return; | 317 | return; |
364 | die(str, regs, interruption_code); | 318 | die(str, regs, pgm_int_code); |
365 | } | 319 | } |
366 | } | 320 | } |
367 | } | 321 | } |
368 | 322 | ||
369 | static inline void __user *get_check_address(struct pt_regs *regs) | 323 | static inline void __user *get_psw_address(struct pt_regs *regs, |
324 | long pgm_int_code) | ||
370 | { | 325 | { |
371 | return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); | 326 | return (void __user *) |
327 | ((regs->psw.addr - (pgm_int_code >> 16)) & PSW_ADDR_INSN); | ||
372 | } | 328 | } |
373 | 329 | ||
374 | void __kprobes do_single_step(struct pt_regs *regs) | 330 | void __kprobes do_per_trap(struct pt_regs *regs) |
375 | { | 331 | { |
376 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, | 332 | if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) |
377 | SIGTRAP) == NOTIFY_STOP){ | ||
378 | return; | 333 | return; |
379 | } | ||
380 | if (tracehook_consider_fatal_signal(current, SIGTRAP)) | 334 | if (tracehook_consider_fatal_signal(current, SIGTRAP)) |
381 | force_sig(SIGTRAP, current); | 335 | force_sig(SIGTRAP, current); |
382 | } | 336 | } |
383 | 337 | ||
384 | static void default_trap_handler(struct pt_regs * regs, long interruption_code) | 338 | static void default_trap_handler(struct pt_regs *regs, long pgm_int_code, |
339 | unsigned long trans_exc_code) | ||
385 | { | 340 | { |
386 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 341 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
387 | local_irq_enable(); | 342 | report_user_fault(regs, pgm_int_code, SIGSEGV); |
388 | report_user_fault(regs, interruption_code, SIGSEGV); | ||
389 | do_exit(SIGSEGV); | 343 | do_exit(SIGSEGV); |
390 | } else | 344 | } else |
391 | die("Unknown program exception", regs, interruption_code); | 345 | die("Unknown program exception", regs, pgm_int_code); |
392 | } | 346 | } |
393 | 347 | ||
394 | #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \ | 348 | #define DO_ERROR_INFO(name, signr, sicode, str) \ |
395 | static void name(struct pt_regs * regs, long interruption_code) \ | 349 | static void name(struct pt_regs *regs, long pgm_int_code, \ |
350 | unsigned long trans_exc_code) \ | ||
396 | { \ | 351 | { \ |
397 | siginfo_t info; \ | 352 | siginfo_t info; \ |
398 | info.si_signo = signr; \ | 353 | info.si_signo = signr; \ |
399 | info.si_errno = 0; \ | 354 | info.si_errno = 0; \ |
400 | info.si_code = sicode; \ | 355 | info.si_code = sicode; \ |
401 | info.si_addr = siaddr; \ | 356 | info.si_addr = get_psw_address(regs, pgm_int_code); \ |
402 | do_trap(interruption_code, signr, str, regs, &info); \ | 357 | do_trap(pgm_int_code, signr, str, regs, &info); \ |
403 | } | 358 | } |
404 | 359 | ||
405 | DO_ERROR_INFO(SIGILL, "addressing exception", addressing_exception, | 360 | DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR, |
406 | ILL_ILLADR, get_check_address(regs)) | 361 | "addressing exception") |
407 | DO_ERROR_INFO(SIGILL, "execute exception", execute_exception, | 362 | DO_ERROR_INFO(execute_exception, SIGILL, ILL_ILLOPN, |
408 | ILL_ILLOPN, get_check_address(regs)) | 363 | "execute exception") |
409 | DO_ERROR_INFO(SIGFPE, "fixpoint divide exception", divide_exception, | 364 | DO_ERROR_INFO(divide_exception, SIGFPE, FPE_INTDIV, |
410 | FPE_INTDIV, get_check_address(regs)) | 365 | "fixpoint divide exception") |
411 | DO_ERROR_INFO(SIGFPE, "fixpoint overflow exception", overflow_exception, | 366 | DO_ERROR_INFO(overflow_exception, SIGFPE, FPE_INTOVF, |
412 | FPE_INTOVF, get_check_address(regs)) | 367 | "fixpoint overflow exception") |
413 | DO_ERROR_INFO(SIGFPE, "HFP overflow exception", hfp_overflow_exception, | 368 | DO_ERROR_INFO(hfp_overflow_exception, SIGFPE, FPE_FLTOVF, |
414 | FPE_FLTOVF, get_check_address(regs)) | 369 | "HFP overflow exception") |
415 | DO_ERROR_INFO(SIGFPE, "HFP underflow exception", hfp_underflow_exception, | 370 | DO_ERROR_INFO(hfp_underflow_exception, SIGFPE, FPE_FLTUND, |
416 | FPE_FLTUND, get_check_address(regs)) | 371 | "HFP underflow exception") |
417 | DO_ERROR_INFO(SIGFPE, "HFP significance exception", hfp_significance_exception, | 372 | DO_ERROR_INFO(hfp_significance_exception, SIGFPE, FPE_FLTRES, |
418 | FPE_FLTRES, get_check_address(regs)) | 373 | "HFP significance exception") |
419 | DO_ERROR_INFO(SIGFPE, "HFP divide exception", hfp_divide_exception, | 374 | DO_ERROR_INFO(hfp_divide_exception, SIGFPE, FPE_FLTDIV, |
420 | FPE_FLTDIV, get_check_address(regs)) | 375 | "HFP divide exception") |
421 | DO_ERROR_INFO(SIGFPE, "HFP square root exception", hfp_sqrt_exception, | 376 | DO_ERROR_INFO(hfp_sqrt_exception, SIGFPE, FPE_FLTINV, |
422 | FPE_FLTINV, get_check_address(regs)) | 377 | "HFP square root exception") |
423 | DO_ERROR_INFO(SIGILL, "operand exception", operand_exception, | 378 | DO_ERROR_INFO(operand_exception, SIGILL, ILL_ILLOPN, |
424 | ILL_ILLOPN, get_check_address(regs)) | 379 | "operand exception") |
425 | DO_ERROR_INFO(SIGILL, "privileged operation", privileged_op, | 380 | DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC, |
426 | ILL_PRVOPC, get_check_address(regs)) | 381 | "privileged operation") |
427 | DO_ERROR_INFO(SIGILL, "special operation exception", special_op_exception, | 382 | DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, |
428 | ILL_ILLOPN, get_check_address(regs)) | 383 | "special operation exception") |
429 | DO_ERROR_INFO(SIGILL, "translation exception", translation_exception, | 384 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, |
430 | ILL_ILLOPN, get_check_address(regs)) | 385 | "translation exception") |
431 | 386 | ||
432 | static inline void | 387 | static inline void do_fp_trap(struct pt_regs *regs, void __user *location, |
433 | do_fp_trap(struct pt_regs *regs, void __user *location, | 388 | int fpc, long pgm_int_code) |
434 | int fpc, long interruption_code) | ||
435 | { | 389 | { |
436 | siginfo_t si; | 390 | siginfo_t si; |
437 | 391 | ||
@@ -453,26 +407,19 @@ do_fp_trap(struct pt_regs *regs, void __user *location, | |||
453 | else if (fpc & 0x0800) /* inexact */ | 407 | else if (fpc & 0x0800) /* inexact */ |
454 | si.si_code = FPE_FLTRES; | 408 | si.si_code = FPE_FLTRES; |
455 | } | 409 | } |
456 | current->thread.ieee_instruction_pointer = (addr_t) location; | 410 | do_trap(pgm_int_code, SIGFPE, |
457 | do_trap(interruption_code, SIGFPE, | ||
458 | "floating point exception", regs, &si); | 411 | "floating point exception", regs, &si); |
459 | } | 412 | } |
460 | 413 | ||
461 | static void illegal_op(struct pt_regs * regs, long interruption_code) | 414 | static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, |
415 | unsigned long trans_exc_code) | ||
462 | { | 416 | { |
463 | siginfo_t info; | 417 | siginfo_t info; |
464 | __u8 opcode[6]; | 418 | __u8 opcode[6]; |
465 | __u16 __user *location; | 419 | __u16 __user *location; |
466 | int signal = 0; | 420 | int signal = 0; |
467 | 421 | ||
468 | location = get_check_address(regs); | 422 | location = get_psw_address(regs, pgm_int_code); |
469 | |||
470 | /* | ||
471 | * We got all needed information from the lowcore and can | ||
472 | * now safely switch on interrupts. | ||
473 | */ | ||
474 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
475 | local_irq_enable(); | ||
476 | 423 | ||
477 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 424 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
478 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) | 425 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) |
@@ -512,7 +459,7 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) | |||
512 | * If we get an illegal op in kernel mode, send it through the | 459 | * If we get an illegal op in kernel mode, send it through the |
513 | * kprobes notifier. If kprobes doesn't pick it up, SIGILL | 460 | * kprobes notifier. If kprobes doesn't pick it up, SIGILL |
514 | */ | 461 | */ |
515 | if (notify_die(DIE_BPT, "bpt", regs, interruption_code, | 462 | if (notify_die(DIE_BPT, "bpt", regs, pgm_int_code, |
516 | 3, SIGTRAP) != NOTIFY_STOP) | 463 | 3, SIGTRAP) != NOTIFY_STOP) |
517 | signal = SIGILL; | 464 | signal = SIGILL; |
518 | } | 465 | } |
@@ -520,13 +467,13 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) | |||
520 | #ifdef CONFIG_MATHEMU | 467 | #ifdef CONFIG_MATHEMU |
521 | if (signal == SIGFPE) | 468 | if (signal == SIGFPE) |
522 | do_fp_trap(regs, location, | 469 | do_fp_trap(regs, location, |
523 | current->thread.fp_regs.fpc, interruption_code); | 470 | current->thread.fp_regs.fpc, pgm_int_code); |
524 | else if (signal == SIGSEGV) { | 471 | else if (signal == SIGSEGV) { |
525 | info.si_signo = signal; | 472 | info.si_signo = signal; |
526 | info.si_errno = 0; | 473 | info.si_errno = 0; |
527 | info.si_code = SEGV_MAPERR; | 474 | info.si_code = SEGV_MAPERR; |
528 | info.si_addr = (void __user *) location; | 475 | info.si_addr = (void __user *) location; |
529 | do_trap(interruption_code, signal, | 476 | do_trap(pgm_int_code, signal, |
530 | "user address fault", regs, &info); | 477 | "user address fault", regs, &info); |
531 | } else | 478 | } else |
532 | #endif | 479 | #endif |
@@ -535,28 +482,22 @@ static void illegal_op(struct pt_regs * regs, long interruption_code) | |||
535 | info.si_errno = 0; | 482 | info.si_errno = 0; |
536 | info.si_code = ILL_ILLOPC; | 483 | info.si_code = ILL_ILLOPC; |
537 | info.si_addr = (void __user *) location; | 484 | info.si_addr = (void __user *) location; |
538 | do_trap(interruption_code, signal, | 485 | do_trap(pgm_int_code, signal, |
539 | "illegal operation", regs, &info); | 486 | "illegal operation", regs, &info); |
540 | } | 487 | } |
541 | } | 488 | } |
542 | 489 | ||
543 | 490 | ||
544 | #ifdef CONFIG_MATHEMU | 491 | #ifdef CONFIG_MATHEMU |
545 | asmlinkage void | 492 | asmlinkage void specification_exception(struct pt_regs *regs, |
546 | specification_exception(struct pt_regs * regs, long interruption_code) | 493 | long pgm_int_code, |
494 | unsigned long trans_exc_code) | ||
547 | { | 495 | { |
548 | __u8 opcode[6]; | 496 | __u8 opcode[6]; |
549 | __u16 __user *location = NULL; | 497 | __u16 __user *location = NULL; |
550 | int signal = 0; | 498 | int signal = 0; |
551 | 499 | ||
552 | location = (__u16 __user *) get_check_address(regs); | 500 | location = (__u16 __user *) get_psw_address(regs, pgm_int_code); |
553 | |||
554 | /* | ||
555 | * We got all needed information from the lowcore and can | ||
556 | * now safely switch on interrupts. | ||
557 | */ | ||
558 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
559 | local_irq_enable(); | ||
560 | 501 | ||
561 | if (regs->psw.mask & PSW_MASK_PSTATE) { | 502 | if (regs->psw.mask & PSW_MASK_PSTATE) { |
562 | get_user(*((__u16 *) opcode), location); | 503 | get_user(*((__u16 *) opcode), location); |
@@ -592,35 +533,29 @@ specification_exception(struct pt_regs * regs, long interruption_code) | |||
592 | 533 | ||
593 | if (signal == SIGFPE) | 534 | if (signal == SIGFPE) |
594 | do_fp_trap(regs, location, | 535 | do_fp_trap(regs, location, |
595 | current->thread.fp_regs.fpc, interruption_code); | 536 | current->thread.fp_regs.fpc, pgm_int_code); |
596 | else if (signal) { | 537 | else if (signal) { |
597 | siginfo_t info; | 538 | siginfo_t info; |
598 | info.si_signo = signal; | 539 | info.si_signo = signal; |
599 | info.si_errno = 0; | 540 | info.si_errno = 0; |
600 | info.si_code = ILL_ILLOPN; | 541 | info.si_code = ILL_ILLOPN; |
601 | info.si_addr = location; | 542 | info.si_addr = location; |
602 | do_trap(interruption_code, signal, | 543 | do_trap(pgm_int_code, signal, |
603 | "specification exception", regs, &info); | 544 | "specification exception", regs, &info); |
604 | } | 545 | } |
605 | } | 546 | } |
606 | #else | 547 | #else |
607 | DO_ERROR_INFO(SIGILL, "specification exception", specification_exception, | 548 | DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, |
608 | ILL_ILLOPN, get_check_address(regs)); | 549 | "specification exception"); |
609 | #endif | 550 | #endif |
610 | 551 | ||
611 | static void data_exception(struct pt_regs * regs, long interruption_code) | 552 | static void data_exception(struct pt_regs *regs, long pgm_int_code, |
553 | unsigned long trans_exc_code) | ||
612 | { | 554 | { |
613 | __u16 __user *location; | 555 | __u16 __user *location; |
614 | int signal = 0; | 556 | int signal = 0; |
615 | 557 | ||
616 | location = get_check_address(regs); | 558 | location = get_psw_address(regs, pgm_int_code); |
617 | |||
618 | /* | ||
619 | * We got all needed information from the lowcore and can | ||
620 | * now safely switch on interrupts. | ||
621 | */ | ||
622 | if (regs->psw.mask & PSW_MASK_PSTATE) | ||
623 | local_irq_enable(); | ||
624 | 559 | ||
625 | if (MACHINE_HAS_IEEE) | 560 | if (MACHINE_HAS_IEEE) |
626 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); | 561 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); |
@@ -686,19 +621,19 @@ static void data_exception(struct pt_regs * regs, long interruption_code) | |||
686 | signal = SIGILL; | 621 | signal = SIGILL; |
687 | if (signal == SIGFPE) | 622 | if (signal == SIGFPE) |
688 | do_fp_trap(regs, location, | 623 | do_fp_trap(regs, location, |
689 | current->thread.fp_regs.fpc, interruption_code); | 624 | current->thread.fp_regs.fpc, pgm_int_code); |
690 | else if (signal) { | 625 | else if (signal) { |
691 | siginfo_t info; | 626 | siginfo_t info; |
692 | info.si_signo = signal; | 627 | info.si_signo = signal; |
693 | info.si_errno = 0; | 628 | info.si_errno = 0; |
694 | info.si_code = ILL_ILLOPN; | 629 | info.si_code = ILL_ILLOPN; |
695 | info.si_addr = location; | 630 | info.si_addr = location; |
696 | do_trap(interruption_code, signal, | 631 | do_trap(pgm_int_code, signal, "data exception", regs, &info); |
697 | "data exception", regs, &info); | ||
698 | } | 632 | } |
699 | } | 633 | } |
700 | 634 | ||
701 | static void space_switch_exception(struct pt_regs * regs, long int_code) | 635 | static void space_switch_exception(struct pt_regs *regs, long pgm_int_code, |
636 | unsigned long trans_exc_code) | ||
702 | { | 637 | { |
703 | siginfo_t info; | 638 | siginfo_t info; |
704 | 639 | ||
@@ -709,11 +644,11 @@ static void space_switch_exception(struct pt_regs * regs, long int_code) | |||
709 | info.si_signo = SIGILL; | 644 | info.si_signo = SIGILL; |
710 | info.si_errno = 0; | 645 | info.si_errno = 0; |
711 | info.si_code = ILL_PRVOPC; | 646 | info.si_code = ILL_PRVOPC; |
712 | info.si_addr = get_check_address(regs); | 647 | info.si_addr = get_psw_address(regs, pgm_int_code); |
713 | do_trap(int_code, SIGILL, "space switch event", regs, &info); | 648 | do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info); |
714 | } | 649 | } |
715 | 650 | ||
716 | asmlinkage void kernel_stack_overflow(struct pt_regs * regs) | 651 | asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs) |
717 | { | 652 | { |
718 | bust_spinlocks(1); | 653 | bust_spinlocks(1); |
719 | printk("Kernel stack overflow.\n"); | 654 | printk("Kernel stack overflow.\n"); |
@@ -758,5 +693,6 @@ void __init trap_init(void) | |||
758 | pgm_check_table[0x15] = &operand_exception; | 693 | pgm_check_table[0x15] = &operand_exception; |
759 | pgm_check_table[0x1C] = &space_switch_exception; | 694 | pgm_check_table[0x1C] = &space_switch_exception; |
760 | pgm_check_table[0x1D] = &hfp_sqrt_exception; | 695 | pgm_check_table[0x1D] = &hfp_sqrt_exception; |
761 | pfault_irq_init(); | 696 | /* Enable machine checks early. */ |
697 | local_mcck_enable(); | ||
762 | } | 698 | } |