diff options
Diffstat (limited to 'arch/sh/mm/fault.c')
-rw-r--r-- | arch/sh/mm/fault.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 68663b8f99ae..43bed2cb00e3 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c | |||
@@ -26,13 +26,16 @@ extern void die(const char *,struct pt_regs *,long); | |||
26 | * and the problem, and then passes it off to one of the appropriate | 26 | * and the problem, and then passes it off to one of the appropriate |
27 | * routines. | 27 | * routines. |
28 | */ | 28 | */ |
29 | asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, | 29 | asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, |
30 | unsigned long address) | 30 | unsigned long writeaccess, |
31 | unsigned long address) | ||
31 | { | 32 | { |
32 | struct task_struct *tsk; | 33 | struct task_struct *tsk; |
33 | struct mm_struct *mm; | 34 | struct mm_struct *mm; |
34 | struct vm_area_struct * vma; | 35 | struct vm_area_struct * vma; |
35 | unsigned long page; | 36 | unsigned long page; |
37 | int si_code; | ||
38 | siginfo_t info; | ||
36 | 39 | ||
37 | #ifdef CONFIG_SH_KGDB | 40 | #ifdef CONFIG_SH_KGDB |
38 | if (kgdb_nofault && kgdb_bus_err_hook) | 41 | if (kgdb_nofault && kgdb_bus_err_hook) |
@@ -41,6 +44,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, | |||
41 | 44 | ||
42 | tsk = current; | 45 | tsk = current; |
43 | mm = tsk->mm; | 46 | mm = tsk->mm; |
47 | si_code = SEGV_MAPERR; | ||
44 | 48 | ||
45 | /* | 49 | /* |
46 | * If we're in an interrupt or have no user | 50 | * If we're in an interrupt or have no user |
@@ -65,6 +69,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, | |||
65 | * we can handle it.. | 69 | * we can handle it.. |
66 | */ | 70 | */ |
67 | good_area: | 71 | good_area: |
72 | si_code = SEGV_ACCERR; | ||
68 | if (writeaccess) { | 73 | if (writeaccess) { |
69 | if (!(vma->vm_flags & VM_WRITE)) | 74 | if (!(vma->vm_flags & VM_WRITE)) |
70 | goto bad_area; | 75 | goto bad_area; |
@@ -105,9 +110,11 @@ bad_area: | |||
105 | up_read(&mm->mmap_sem); | 110 | up_read(&mm->mmap_sem); |
106 | 111 | ||
107 | if (user_mode(regs)) { | 112 | if (user_mode(regs)) { |
108 | tsk->thread.address = address; | 113 | info.si_signo = SIGSEGV; |
109 | tsk->thread.error_code = writeaccess; | 114 | info.si_errno = 0; |
110 | force_sig(SIGSEGV, tsk); | 115 | info.si_code = si_code; |
116 | info.si_addr = (void *) address; | ||
117 | force_sig_info(SIGSEGV, &info, tsk); | ||
111 | return; | 118 | return; |
112 | } | 119 | } |
113 | 120 | ||
@@ -166,10 +173,11 @@ do_sigbus: | |||
166 | * Send a sigbus, regardless of whether we were in kernel | 173 | * Send a sigbus, regardless of whether we were in kernel |
167 | * or user mode. | 174 | * or user mode. |
168 | */ | 175 | */ |
169 | tsk->thread.address = address; | 176 | info.si_signo = SIGBUS; |
170 | tsk->thread.error_code = writeaccess; | 177 | info.si_errno = 0; |
171 | tsk->thread.trap_no = 14; | 178 | info.si_code = BUS_ADRERR; |
172 | force_sig(SIGBUS, tsk); | 179 | info.si_addr = (void *)address; |
180 | force_sig_info(SIGBUS, &info, tsk); | ||
173 | 181 | ||
174 | /* Kernel mode? Handle exceptions or die */ | 182 | /* Kernel mode? Handle exceptions or die */ |
175 | if (!user_mode(regs)) | 183 | if (!user_mode(regs)) |