aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/mm
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-09-28 23:21:11 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-09-28 23:21:11 -0400
commit8cf14af0a740fb7e9f94a203b5a989beb875d58f (patch)
treea7bec4d60c352e780d6a2b75e9b95e637e3a14f7 /arch/sparc64/mm
parent705747ab87c96f1b4b8e73ba617c323d9087f6ac (diff)
[SPARC64]: Convert to use generic exception table support.
The funny "range" exception table entries we had were only used by the compat layer socketcall assembly, and it wasn't even needed there. For free we now get proper exception table sorting and fast binary searching. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/mm')
-rw-r--r--arch/sparc64/mm/Makefile2
-rw-r--r--arch/sparc64/mm/extable.c80
-rw-r--r--arch/sparc64/mm/fault.c10
3 files changed, 4 insertions, 88 deletions
diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile
index cda87333a77b..9d0960e69f48 100644
--- a/arch/sparc64/mm/Makefile
+++ b/arch/sparc64/mm/Makefile
@@ -5,6 +5,6 @@
5EXTRA_AFLAGS := -ansi 5EXTRA_AFLAGS := -ansi
6EXTRA_CFLAGS := -Werror 6EXTRA_CFLAGS := -Werror
7 7
8obj-y := ultra.o tlb.o fault.o init.o generic.o extable.o 8obj-y := ultra.o tlb.o fault.o init.o generic.o
9 9
10obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 10obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
deleted file mode 100644
index ec334297ff4f..000000000000
--- a/arch/sparc64/mm/extable.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * linux/arch/sparc64/mm/extable.c
3 */
4
5#include <linux/config.h>
6#include <linux/module.h>
7#include <asm/uaccess.h>
8
9extern const struct exception_table_entry __start___ex_table[];
10extern const struct exception_table_entry __stop___ex_table[];
11
12void sort_extable(struct exception_table_entry *start,
13 struct exception_table_entry *finish)
14{
15}
16
17/* Caller knows they are in a range if ret->fixup == 0 */
18const struct exception_table_entry *
19search_extable(const struct exception_table_entry *start,
20 const struct exception_table_entry *last,
21 unsigned long value)
22{
23 const struct exception_table_entry *walk;
24
25 /* Single insn entries are encoded as:
26 * word 1: insn address
27 * word 2: fixup code address
28 *
29 * Range entries are encoded as:
30 * word 1: first insn address
31 * word 2: 0
32 * word 3: last insn address + 4 bytes
33 * word 4: fixup code address
34 *
35 * See asm/uaccess.h for more details.
36 */
37
38 /* 1. Try to find an exact match. */
39 for (walk = start; walk <= last; walk++) {
40 if (walk->fixup == 0) {
41 /* A range entry, skip both parts. */
42 walk++;
43 continue;
44 }
45
46 if (walk->insn == value)
47 return walk;
48 }
49
50 /* 2. Try to find a range match. */
51 for (walk = start; walk <= (last - 1); walk++) {
52 if (walk->fixup)
53 continue;
54
55 if (walk[0].insn <= value && walk[1].insn > value)
56 return walk;
57
58 walk++;
59 }
60
61 return NULL;
62}
63
64/* Special extable search, which handles ranges. Returns fixup */
65unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
66{
67 const struct exception_table_entry *entry;
68
69 entry = search_exception_tables(addr);
70 if (!entry)
71 return 0;
72
73 /* Inside range? Fix g2 and return correct fixup */
74 if (!entry->fixup) {
75 *g2 = (addr - entry->insn) / 4;
76 return (entry + 1)->fixup;
77 }
78
79 return entry->fixup;
80}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index db1e3310e907..59dc9a2ece5a 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -242,7 +242,6 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
242static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, 242static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
243 unsigned int insn, unsigned long address) 243 unsigned int insn, unsigned long address)
244{ 244{
245 unsigned long g2;
246 unsigned char asi = ASI_P; 245 unsigned char asi = ASI_P;
247 246
248 if ((!insn) && (regs->tstate & TSTATE_PRIV)) 247 if ((!insn) && (regs->tstate & TSTATE_PRIV))
@@ -273,11 +272,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
273 } 272 }
274 } 273 }
275 274
276 g2 = regs->u_regs[UREG_G2];
277
278 /* Is this in ex_table? */ 275 /* Is this in ex_table? */
279 if (regs->tstate & TSTATE_PRIV) { 276 if (regs->tstate & TSTATE_PRIV) {
280 unsigned long fixup; 277 const struct exception_table_entry *entry;
281 278
282 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { 279 if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
283 if (insn & 0x2000) 280 if (insn & 0x2000)
@@ -288,10 +285,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
288 285
289 /* Look in asi.h: All _S asis have LS bit set */ 286 /* Look in asi.h: All _S asis have LS bit set */
290 if ((asi & 0x1) && 287 if ((asi & 0x1) &&
291 (fixup = search_extables_range(regs->tpc, &g2))) { 288 (entry = search_exception_tables(regs->tpc))) {
292 regs->tpc = fixup; 289 regs->tpc = entry->fixup;
293 regs->tnpc = regs->tpc + 4; 290 regs->tnpc = regs->tpc + 4;
294 regs->u_regs[UREG_G2] = g2;
295 return; 291 return;
296 } 292 }
297 } else { 293 } else {