summaryrefslogtreecommitdiffstats
path: root/arch/frv
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-12-25 14:12:18 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2017-03-28 18:23:32 -0400
commit9a7513cfa26f5fcce15de6130ce3c27d77c0ce55 (patch)
tree1f7769fc94432e965b7e6d19bb0f28ed40254ae5 /arch/frv
parentd597580d373774b1bdab84b3d26ff0b55162b916 (diff)
frv: switch to use of fixup_exception()
Massage frv search_exception_table() to a) taking pt_regs pointer as explicit argument b) updating ->pc on success Simplifies callers a bit and allows to convert to generic extable.h, while we are at it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/frv')
-rw-r--r--arch/frv/include/asm/Kbuild1
-rw-r--r--arch/frv/include/asm/uaccess.h23
-rw-r--r--arch/frv/kernel/traps.c7
-rw-r--r--arch/frv/mm/extable.c27
-rw-r--r--arch/frv/mm/fault.c6
5 files changed, 18 insertions, 46 deletions
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index c33b46715f65..cce3bc3603ea 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -1,6 +1,7 @@
1 1
2generic-y += clkdev.h 2generic-y += clkdev.h
3generic-y += exec.h 3generic-y += exec.h
4generic-y += extable.h
4generic-y += irq_work.h 5generic-y += irq_work.h
5generic-y += mcs_spinlock.h 6generic-y += mcs_spinlock.h
6generic-y += mm-arch-hooks.h 7generic-y += mm-arch-hooks.h
diff --git a/arch/frv/include/asm/uaccess.h b/arch/frv/include/asm/uaccess.h
index 55b3a69c6c53..5bcc57de3c95 100644
--- a/arch/frv/include/asm/uaccess.h
+++ b/arch/frv/include/asm/uaccess.h
@@ -18,6 +18,7 @@
18#include <linux/mm.h> 18#include <linux/mm.h>
19#include <asm/segment.h> 19#include <asm/segment.h>
20#include <asm/sections.h> 20#include <asm/sections.h>
21#include <asm/extable.h>
21 22
22#define __ptr(x) ((unsigned long __force *)(x)) 23#define __ptr(x) ((unsigned long __force *)(x))
23 24
@@ -59,26 +60,6 @@ static inline int ___range_ok(unsigned long addr, unsigned long size)
59#define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0) 60#define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0)
60#define __access_ok(addr,size) (__range_ok((addr), (size)) == 0) 61#define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
61 62
62/*
63 * The exception table consists of pairs of addresses: the first is the
64 * address of an instruction that is allowed to fault, and the second is
65 * the address at which the program should continue. No registers are
66 * modified, so it is entirely up to the continuation code to figure out
67 * what to do.
68 *
69 * All the routines below use bits of fixup code that are out of line
70 * with the main instruction path. This means when everything is well,
71 * we don't even have to jump over them. Further, they do not intrude
72 * on our cache or tlb entries.
73 */
74struct exception_table_entry
75{
76 unsigned long insn, fixup;
77};
78
79/* Returns 0 if exception not found and fixup otherwise. */
80extern unsigned long search_exception_table(unsigned long);
81
82 63
83/* 64/*
84 * These are the main single-value transfer routines. They automatically 65 * These are the main single-value transfer routines. They automatically
@@ -314,6 +295,4 @@ extern long strnlen_user(const char __user *src, long count);
314 295
315#define strlen_user(str) strnlen_user(str, 32767) 296#define strlen_user(str) strnlen_user(str, 32767)
316 297
317extern unsigned long search_exception_table(unsigned long addr);
318
319#endif /* _ASM_UACCESS_H */ 298#endif /* _ASM_UACCESS_H */
diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c
index ce29991e4219..fb08ebe0dab4 100644
--- a/arch/frv/kernel/traps.c
+++ b/arch/frv/kernel/traps.c
@@ -360,13 +360,8 @@ asmlinkage void memory_access_exception(unsigned long esr0,
360 siginfo_t info; 360 siginfo_t info;
361 361
362#ifdef CONFIG_MMU 362#ifdef CONFIG_MMU
363 unsigned long fixup; 363 if (fixup_exception(__frame))
364
365 fixup = search_exception_table(__frame->pc);
366 if (fixup) {
367 __frame->pc = fixup;
368 return; 364 return;
369 }
370#endif 365#endif
371 366
372 die_if_kernel("-- Memory Access Exception --\n" 367 die_if_kernel("-- Memory Access Exception --\n"
diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c
index a0e8b3e03e4c..9198ddd16092 100644
--- a/arch/frv/mm/extable.c
+++ b/arch/frv/mm/extable.c
@@ -10,40 +10,39 @@ extern const void __memset_end, __memset_user_error_lr, __memset_user_error_hand
10extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler; 10extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
11extern spinlock_t modlist_lock; 11extern spinlock_t modlist_lock;
12 12
13 13int fixup_exception(struct pt_regs *regs)
14/*****************************************************************************/
15/*
16 * see if there's a fixup handler available to deal with a kernel fault
17 */
18unsigned long search_exception_table(unsigned long pc)
19{ 14{
20 const struct exception_table_entry *extab; 15 const struct exception_table_entry *extab;
16 unsigned long pc = regs->pc;
21 17
22 /* determine if the fault lay during a memcpy_user or a memset_user */ 18 /* determine if the fault lay during a memcpy_user or a memset_user */
23 if (__frame->lr == (unsigned long) &__memset_user_error_lr && 19 if (regs->lr == (unsigned long) &__memset_user_error_lr &&
24 (unsigned long) &memset <= pc && pc < (unsigned long) &__memset_end 20 (unsigned long) &memset <= pc && pc < (unsigned long) &__memset_end
25 ) { 21 ) {
26 /* the fault occurred in a protected memset 22 /* the fault occurred in a protected memset
27 * - we search for the return address (in LR) instead of the program counter 23 * - we search for the return address (in LR) instead of the program counter
28 * - it was probably during a clear_user() 24 * - it was probably during a clear_user()
29 */ 25 */
30 return (unsigned long) &__memset_user_error_handler; 26 regs->pc = (unsigned long) &__memset_user_error_handler;
27 return 1;
31 } 28 }
32 29
33 if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && 30 if (regs->lr == (unsigned long) &__memcpy_user_error_lr &&
34 (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end 31 (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end
35 ) { 32 ) {
36 /* the fault occurred in a protected memset 33 /* the fault occurred in a protected memset
37 * - we search for the return address (in LR) instead of the program counter 34 * - we search for the return address (in LR) instead of the program counter
38 * - it was probably during a copy_to/from_user() 35 * - it was probably during a copy_to/from_user()
39 */ 36 */
40 return (unsigned long) &__memcpy_user_error_handler; 37 regs->pc = (unsigned long) &__memcpy_user_error_handler;
38 return 1;
41 } 39 }
42 40
43 extab = search_exception_tables(pc); 41 extab = search_exception_tables(pc);
44 if (extab) 42 if (extab) {
45 return extab->fixup; 43 regs->pc = extab->fixup;
44 return 1;
45 }
46 46
47 return 0; 47 return 0;
48 48}
49} /* end search_exception_table() */
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c
index 614a46c413d2..179e79e220e5 100644
--- a/arch/frv/mm/fault.c
+++ b/arch/frv/mm/fault.c
@@ -33,7 +33,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
33{ 33{
34 struct vm_area_struct *vma; 34 struct vm_area_struct *vma;
35 struct mm_struct *mm; 35 struct mm_struct *mm;
36 unsigned long _pme, lrai, lrad, fixup; 36 unsigned long _pme, lrai, lrad;
37 unsigned long flags = 0; 37 unsigned long flags = 0;
38 siginfo_t info; 38 siginfo_t info;
39 pgd_t *pge; 39 pgd_t *pge;
@@ -201,10 +201,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
201 201
202 no_context: 202 no_context:
203 /* are we prepared to handle this kernel fault? */ 203 /* are we prepared to handle this kernel fault? */
204 if ((fixup = search_exception_table(__frame->pc)) != 0) { 204 if (fixup_exception(__frame))
205 __frame->pc = fixup;
206 return; 205 return;
207 }
208 206
209/* 207/*
210 * Oops. The kernel tried to access some bad page. We'll have to 208 * Oops. The kernel tried to access some bad page. We'll have to