~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/s390/kernel/traps.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6
6
 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7
7
 *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
8
 
 *  Portions added by T. Halloran: (C) Copyright 2002 IBM Poughkeepsie, IBM Corporation
9
8
 *
10
9
 *  Derived from "arch/i386/kernel/traps.c"
11
10
 *    Copyright (C) 1991, 1992 Linus Torvalds
34
33
#include <linux/kprobes.h>
35
34
#include <linux/bug.h>
36
35
#include <linux/utsname.h>
37
 
#include <trace/trap.h>
38
36
#include <asm/system.h>
39
37
#include <asm/uaccess.h>
40
38
#include <asm/io.h>
41
39
#include <asm/atomic.h>
42
40
#include <asm/mathemu.h>
43
41
#include <asm/cpcmd.h>
44
 
#include <asm/s390_ext.h>
45
42
#include <asm/lowcore.h>
46
43
#include <asm/debug.h>
47
44
#include "entry.h"
67
64
#endif /* CONFIG_64BIT */
68
65
 
69
66
/*
70
 
 * Also used in fault.c.
71
 
 */
72
 
DEFINE_TRACE(trap_entry);
73
 
DEFINE_TRACE(trap_exit);
74
 
 
75
 
/*
76
67
 * For show_trace we have tree different stack to consider:
77
68
 *   - the panic stack which is used if the kernel stack has overflown
78
69
 *   - the asynchronous interrupt stack (cpu related)
307
298
                       pgm_int_code, signr) == NOTIFY_STOP)
308
299
                return;
309
300
 
310
 
        trace_trap_entry(regs, pgm_int_code & 0xffff);
311
 
 
312
301
        if (regs->psw.mask & PSW_MASK_PSTATE) {
313
302
                struct task_struct *tsk = current;
314
303
 
324
313
                        enum bug_trap_type btt;
325
314
 
326
315
                        btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
327
 
                        if (btt == BUG_TRAP_TYPE_WARN) {
328
 
                                trace_trap_exit();
 
316
                        if (btt == BUG_TRAP_TYPE_WARN)
329
317
                                return;
330
 
                        }
331
318
                        die(str, regs, pgm_int_code);
332
319
                }
333
320
        }
334
 
        trace_trap_exit();
335
321
}
336
322
 
337
323
static inline void __user *get_psw_address(struct pt_regs *regs,
435
421
 
436
422
        location = get_psw_address(regs, pgm_int_code);
437
423
 
438
 
        trace_trap_entry(regs, pgm_int_code & 0xffff);
439
 
 
440
424
        if (regs->psw.mask & PSW_MASK_PSTATE) {
441
425
                if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
442
 
                        goto end;
 
426
                        return;
443
427
                if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
444
428
                        if (tracehook_consider_fatal_signal(current, SIGTRAP))
445
429
                                force_sig(SIGTRAP, current);
448
432
#ifdef CONFIG_MATHEMU
449
433
                } else if (opcode[0] == 0xb3) {
450
434
                        if (get_user(*((__u16 *) (opcode+2)), location+1))
451
 
                                goto end;
 
435
                                return;
452
436
                        signal = math_emu_b3(opcode, regs);
453
437
                } else if (opcode[0] == 0xed) {
454
438
                        if (get_user(*((__u32 *) (opcode+2)),
455
439
                                     (__u32 __user *)(location+1)))
456
 
                                goto end;
 
440
                                return;
457
441
                        signal = math_emu_ed(opcode, regs);
458
442
                } else if (*((__u16 *) opcode) == 0xb299) {
459
443
                        if (get_user(*((__u16 *) (opcode+2)), location+1))
460
 
                                goto end;
 
444
                                return;
461
445
                        signal = math_emu_srnm(opcode, regs);
462
446
                } else if (*((__u16 *) opcode) == 0xb29c) {
463
447
                        if (get_user(*((__u16 *) (opcode+2)), location+1))
464
 
                                goto end;
 
448
                                return;
465
449
                        signal = math_emu_stfpc(opcode, regs);
466
450
                } else if (*((__u16 *) opcode) == 0xb29d) {
467
451
                        if (get_user(*((__u16 *) (opcode+2)), location+1))
468
 
                                goto end;
 
452
                                return;
469
453
                        signal = math_emu_lfpc(opcode, regs);
470
454
#endif
471
455
                } else
501
485
                do_trap(pgm_int_code, signal,
502
486
                        "illegal operation", regs, &info);
503
487
        }
504
 
end:
505
 
        trace_trap_exit();
506
488
}
507
489
 
508
490
 
517
499
 
518
500
        location = (__u16 __user *) get_psw_address(regs, pgm_int_code);
519
501
 
520
 
        trace_trap_entry(regs, pgm_int_code & 0xffff);
521
 
 
522
502
        if (regs->psw.mask & PSW_MASK_PSTATE) {
523
503
                get_user(*((__u16 *) opcode), location);
524
504
                switch (opcode[0]) {
563
543
                do_trap(pgm_int_code, signal,
564
544
                        "specification exception", regs, &info);
565
545
        }
566
 
        trace_trap_exit();
567
546
}
568
547
#else
569
548
DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
578
557
 
579
558
        location = get_psw_address(regs, pgm_int_code);
580
559
 
581
 
        trace_trap_entry(regs, pgm_int_code & 0xffff);
582
 
 
583
560
        if (MACHINE_HAS_IEEE)
584
561
                asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
585
562
 
653
630
                info.si_addr = location;
654
631
                do_trap(pgm_int_code, signal, "data exception", regs, &info);
655
632
        }
656
 
        trace_trap_exit();
657
633
}
658
634
 
659
635
static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
661
637
{
662
638
        siginfo_t info;
663
639
 
664
 
        trace_trap_entry(regs, pgm_int_code & 0xffff);
665
640
        /* Set user psw back to home space mode. */
666
641
        if (regs->psw.mask & PSW_MASK_PSTATE)
667
642
                regs->psw.mask |= PSW_ASC_HOME;
671
646
        info.si_code = ILL_PRVOPC;
672
647
        info.si_addr = get_psw_address(regs, pgm_int_code);
673
648
        do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
674
 
        trace_trap_exit();
675
649
}
676
650
 
677
651
asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs)