aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/fault.c')
-rw-r--r--arch/sh/mm/fault.c26
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 */
29asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, 29asmlinkage 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 */
67good_area: 71good_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))