diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/kernel/traps.c | 33 | ||||
-rw-r--r-- | arch/ia64/mm/fault.c | 8 |
2 files changed, 40 insertions, 1 deletions
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 1861173bd4f6..e7e520d90f03 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -21,12 +21,26 @@ | |||
21 | #include <asm/intrinsics.h> | 21 | #include <asm/intrinsics.h> |
22 | #include <asm/processor.h> | 22 | #include <asm/processor.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <asm/kdebug.h> | ||
24 | 25 | ||
25 | extern spinlock_t timerlist_lock; | 26 | extern spinlock_t timerlist_lock; |
26 | 27 | ||
27 | fpswa_interface_t *fpswa_interface; | 28 | fpswa_interface_t *fpswa_interface; |
28 | EXPORT_SYMBOL(fpswa_interface); | 29 | EXPORT_SYMBOL(fpswa_interface); |
29 | 30 | ||
31 | struct notifier_block *ia64die_chain; | ||
32 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
33 | |||
34 | int register_die_notifier(struct notifier_block *nb) | ||
35 | { | ||
36 | int err = 0; | ||
37 | unsigned long flags; | ||
38 | spin_lock_irqsave(&die_notifier_lock, flags); | ||
39 | err = notifier_chain_register(&ia64die_chain, nb); | ||
40 | spin_unlock_irqrestore(&die_notifier_lock, flags); | ||
41 | return err; | ||
42 | } | ||
43 | |||
30 | void __init | 44 | void __init |
31 | trap_init (void) | 45 | trap_init (void) |
32 | { | 46 | { |
@@ -137,6 +151,10 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
137 | 151 | ||
138 | switch (break_num) { | 152 | switch (break_num) { |
139 | case 0: /* unknown error (used by GCC for __builtin_abort()) */ | 153 | case 0: /* unknown error (used by GCC for __builtin_abort()) */ |
154 | if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) | ||
155 | == NOTIFY_STOP) { | ||
156 | return; | ||
157 | } | ||
140 | die_if_kernel("bugcheck!", regs, break_num); | 158 | die_if_kernel("bugcheck!", regs, break_num); |
141 | sig = SIGILL; code = ILL_ILLOPC; | 159 | sig = SIGILL; code = ILL_ILLOPC; |
142 | break; | 160 | break; |
@@ -189,6 +207,15 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
189 | sig = SIGILL; code = __ILL_BNDMOD; | 207 | sig = SIGILL; code = __ILL_BNDMOD; |
190 | break; | 208 | break; |
191 | 209 | ||
210 | case 0x80200: | ||
211 | case 0x80300: | ||
212 | if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP) | ||
213 | == NOTIFY_STOP) { | ||
214 | return; | ||
215 | } | ||
216 | sig = SIGTRAP; code = TRAP_BRKPT; | ||
217 | break; | ||
218 | |||
192 | default: | 219 | default: |
193 | if (break_num < 0x40000 || break_num > 0x100000) | 220 | if (break_num < 0x40000 || break_num > 0x100000) |
194 | die_if_kernel("Bad break", regs, break_num); | 221 | die_if_kernel("Bad break", regs, break_num); |
@@ -548,7 +575,11 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, | |||
548 | #endif | 575 | #endif |
549 | break; | 576 | break; |
550 | case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; | 577 | case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; |
551 | case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; | 578 | case 36: |
579 | if (notify_die(DIE_SS, "ss", ®s, vector, | ||
580 | vector, SIGTRAP) == NOTIFY_STOP) | ||
581 | return; | ||
582 | siginfo.si_code = TRAP_TRACE; ifa = 0; break; | ||
552 | } | 583 | } |
553 | siginfo.si_signo = SIGTRAP; | 584 | siginfo.si_signo = SIGTRAP; |
554 | siginfo.si_errno = 0; | 585 | siginfo.si_errno = 0; |
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 4174ec999dde..ff62551eb3a1 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <asm/processor.h> | 14 | #include <asm/processor.h> |
15 | #include <asm/system.h> | 15 | #include <asm/system.h> |
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/kdebug.h> | ||
17 | 18 | ||
18 | extern void die (char *, struct pt_regs *, long); | 19 | extern void die (char *, struct pt_regs *, long); |
19 | 20 | ||
@@ -102,6 +103,13 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re | |||
102 | goto bad_area_no_up; | 103 | goto bad_area_no_up; |
103 | #endif | 104 | #endif |
104 | 105 | ||
106 | /* | ||
107 | * This is to handle the kprobes on user space access instructions | ||
108 | */ | ||
109 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT, | ||
110 | SIGSEGV) == NOTIFY_STOP) | ||
111 | return; | ||
112 | |||
105 | down_read(&mm->mmap_sem); | 113 | down_read(&mm->mmap_sem); |
106 | 114 | ||
107 | vma = find_vma_prev(mm, address, &prev_vma); | 115 | vma = find_vma_prev(mm, address, &prev_vma); |