Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sparc32: switch to generic extables

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro b4edf06c c4da8e0d

+22 -170
-1
arch/sparc/include/asm/elf_64.h
··· 8 8 9 9 #include <asm/ptrace.h> 10 10 #include <asm/processor.h> 11 - #include <asm/extable_64.h> 12 11 #include <asm/spitfire.h> 13 12 #include <asm/adi.h> 14 13
+2 -2
arch/sparc/include/asm/extable_64.h arch/sparc/include/asm/extable.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef __ASM_EXTABLE64_H 3 - #define __ASM_EXTABLE64_H 2 + #ifndef __ASM_EXTABLE_H 3 + #define __ASM_EXTABLE_H 4 4 /* 5 5 * The exception table consists of pairs of addresses: the first is the 6 6 * address of an instruction that is allowed to fault, and the second is
+3
arch/sparc/include/asm/uaccess.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 #ifndef ___ASM_SPARC_UACCESS_H 3 3 #define ___ASM_SPARC_UACCESS_H 4 + 5 + #include <asm/extable.h> 6 + 4 7 #if defined(__sparc__) && defined(__arch64__) 5 8 #include <asm/uaccess_64.h> 6 9 #else
-33
arch/sparc/include/asm/uaccess_32.h
··· 13 13 14 14 #include <asm/processor.h> 15 15 16 - #define ARCH_HAS_SORT_EXTABLE 17 - #define ARCH_HAS_SEARCH_EXTABLE 18 - 19 16 /* Sparc is not segmented, however we need to be able to fool access_ok() 20 17 * when doing system calls from kernel mode legitimately. 21 18 * ··· 36 39 #define __kernel_ok (uaccess_kernel()) 37 40 #define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size))) 38 41 #define access_ok(addr, size) __access_ok((unsigned long)(addr), size) 39 - 40 - /* 41 - * The exception table consists of pairs of addresses: the first is the 42 - * address of an instruction that is allowed to fault, and the second is 43 - * the address at which the program should continue. No registers are 44 - * modified, so it is entirely up to the continuation code to figure out 45 - * what to do. 46 - * 47 - * All the routines below use bits of fixup code that are out of line 48 - * with the main instruction path. This means when everything is well, 49 - * we don't even have to jump over them. Further, they do not intrude 50 - * on our cache or tlb entries. 51 - * 52 - * There is a special way how to put a range of potentially faulting 53 - * insns (like twenty ldd/std's with now intervening other instructions) 54 - * You specify address of first in insn and 0 in fixup and in the next 55 - * exception_table_entry you specify last potentially faulting insn + 1 56 - * and in fixup the routine which should handle the fault. 57 - * That fixup code will get 58 - * (faulting_insn_address - first_insn_in_the_range_address)/4 59 - * in %g2 (ie. index of the faulting instruction in the range). 60 - */ 61 - 62 - struct exception_table_entry 63 - { 64 - unsigned long insn, fixup; 65 - }; 66 - 67 - /* Returns 0 if exception not found and fixup otherwise. */ 68 - unsigned long search_extables_range(unsigned long addr, unsigned long *g2); 69 42 70 43 /* Uh, these should become the main single-value transfer routines.. 71 44 * They automatically use the right size if we just have the right
-1
arch/sparc/include/asm/uaccess_64.h
··· 10 10 #include <linux/string.h> 11 11 #include <asm/asi.h> 12 12 #include <asm/spitfire.h> 13 - #include <asm/extable_64.h> 14 13 15 14 #include <asm/processor.h> 16 15
+5 -5
arch/sparc/kernel/unaligned_32.c
··· 16 16 #include <linux/uaccess.h> 17 17 #include <linux/smp.h> 18 18 #include <linux/perf_event.h> 19 + #include <linux/extable.h> 19 20 20 21 #include <asm/setup.h> 21 22 ··· 214 213 215 214 static void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) 216 215 { 217 - unsigned long g2 = regs->u_regs [UREG_G2]; 218 - unsigned long fixup = search_extables_range(regs->pc, &g2); 216 + const struct exception_table_entry *entry; 219 217 220 - if (!fixup) { 218 + entry = search_exception_tables(regs->pc); 219 + if (!entry) { 221 220 unsigned long address = compute_effective_address(regs, insn); 222 221 if(address < PAGE_SIZE) { 223 222 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference in mna handler"); ··· 233 232 die_if_kernel("Oops", regs); 234 233 /* Not reached */ 235 234 } 236 - regs->pc = fixup; 235 + regs->pc = entry->fixup; 237 236 regs->npc = regs->pc + 4; 238 - regs->u_regs [UREG_G2] = g2; 239 237 } 240 238 241 239 asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+1 -1
arch/sparc/mm/Makefile
··· 8 8 obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o 9 9 obj-y += fault_$(BITS).o 10 10 obj-y += init_$(BITS).o 11 - obj-$(CONFIG_SPARC32) += extable.o srmmu.o iommu.o io-unit.o 11 + obj-$(CONFIG_SPARC32) += srmmu.o iommu.o io-unit.o 12 12 obj-$(CONFIG_SPARC32) += srmmu_access.o 13 13 obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o 14 14 obj-$(CONFIG_SPARC32) += leon_mm.o
-107
arch/sparc/mm/extable.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * linux/arch/sparc/mm/extable.c 4 - */ 5 - 6 - #include <linux/module.h> 7 - #include <linux/extable.h> 8 - #include <linux/uaccess.h> 9 - 10 - void sort_extable(struct exception_table_entry *start, 11 - struct exception_table_entry *finish) 12 - { 13 - } 14 - 15 - /* Caller knows they are in a range if ret->fixup == 0 */ 16 - const struct exception_table_entry * 17 - search_extable(const struct exception_table_entry *base, 18 - const size_t num, 19 - unsigned long value) 20 - { 21 - int i; 22 - 23 - /* Single insn entries are encoded as: 24 - * word 1: insn address 25 - * word 2: fixup code address 26 - * 27 - * Range entries are encoded as: 28 - * word 1: first insn address 29 - * word 2: 0 30 - * word 3: last insn address + 4 bytes 31 - * word 4: fixup code address 32 - * 33 - * Deleted entries are encoded as: 34 - * word 1: unused 35 - * word 2: -1 36 - * 37 - * See asm/uaccess.h for more details. 38 - */ 39 - 40 - /* 1. Try to find an exact match. */ 41 - for (i = 0; i < num; i++) { 42 - if (base[i].fixup == 0) { 43 - /* A range entry, skip both parts. */ 44 - i++; 45 - continue; 46 - } 47 - 48 - /* A deleted entry; see trim_init_extable */ 49 - if (base[i].fixup == -1) 50 - continue; 51 - 52 - if (base[i].insn == value) 53 - return &base[i]; 54 - } 55 - 56 - /* 2. Try to find a range match. */ 57 - for (i = 0; i < (num - 1); i++) { 58 - if (base[i].fixup) 59 - continue; 60 - 61 - if (base[i].insn <= value && base[i + 1].insn > value) 62 - return &base[i]; 63 - 64 - i++; 65 - } 66 - 67 - return NULL; 68 - } 69 - 70 - #ifdef CONFIG_MODULES 71 - /* We could memmove them around; easier to mark the trimmed ones. */ 72 - void trim_init_extable(struct module *m) 73 - { 74 - unsigned int i; 75 - bool range; 76 - 77 - for (i = 0; i < m->num_exentries; i += range ? 2 : 1) { 78 - range = m->extable[i].fixup == 0; 79 - 80 - if (within_module_init(m->extable[i].insn, m)) { 81 - m->extable[i].fixup = -1; 82 - if (range) 83 - m->extable[i+1].fixup = -1; 84 - } 85 - if (range) 86 - i++; 87 - } 88 - } 89 - #endif /* CONFIG_MODULES */ 90 - 91 - /* Special extable search, which handles ranges. Returns fixup */ 92 - unsigned long search_extables_range(unsigned long addr, unsigned long *g2) 93 - { 94 - const struct exception_table_entry *entry; 95 - 96 - entry = search_exception_tables(addr); 97 - if (!entry) 98 - return 0; 99 - 100 - /* Inside range? Fix g2 and return correct fixup */ 101 - if (!entry->fixup) { 102 - *g2 = (addr - entry->insn) / 4; 103 - return (entry + 1)->fixup; 104 - } 105 - 106 - return entry->fixup; 107 - }
+11 -15
arch/sparc/mm/fault_32.c
··· 23 23 #include <linux/interrupt.h> 24 24 #include <linux/kdebug.h> 25 25 #include <linux/uaccess.h> 26 + #include <linux/extable.h> 26 27 27 28 #include <asm/page.h> 28 29 #include <asm/openprom.h> ··· 115 114 struct vm_area_struct *vma; 116 115 struct task_struct *tsk = current; 117 116 struct mm_struct *mm = tsk->mm; 118 - unsigned int fixup; 119 - unsigned long g2; 120 117 int from_user = !(regs->psr & PSR_PS); 121 118 int code; 122 119 vm_fault_t fault; ··· 232 233 233 234 /* Is this in ex_table? */ 234 235 no_context: 235 - g2 = regs->u_regs[UREG_G2]; 236 236 if (!from_user) { 237 - fixup = search_extables_range(regs->pc, &g2); 238 - /* Values below 10 are reserved for other things */ 239 - if (fixup > 10) { 237 + const struct exception_table_entry *entry; 238 + 239 + entry = search_exception_tables(regs->pc); 240 240 #ifdef DEBUG_EXCEPTIONS 241 - printk("Exception: PC<%08lx> faddr<%08lx>\n", 242 - regs->pc, address); 243 - printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n", 244 - regs->pc, fixup, g2); 241 + printk("Exception: PC<%08lx> faddr<%08lx>\n", 242 + regs->pc, address); 243 + printk("EX_TABLE: insn<%08lx> fixup<%08x>\n", 244 + regs->pc, entry->fixup); 245 245 #endif 246 - regs->u_regs[UREG_G2] = g2; 247 - regs->pc = fixup; 248 - regs->npc = regs->pc + 4; 249 - return; 250 - } 246 + regs->pc = entry->fixup; 247 + regs->npc = regs->pc + 4; 248 + return; 251 249 } 252 250 253 251 unhandled_fault(address, tsk, regs);
-5
lib/extable.c
··· 21 21 } 22 22 #endif 23 23 24 - #ifndef ARCH_HAS_SORT_EXTABLE 25 24 #ifndef ARCH_HAS_RELATIVE_EXTABLE 26 25 #define swap_ex NULL 27 26 #else ··· 87 88 m->num_exentries--; 88 89 } 89 90 #endif /* CONFIG_MODULES */ 90 - #endif /* !ARCH_HAS_SORT_EXTABLE */ 91 - 92 - #ifndef ARCH_HAS_SEARCH_EXTABLE 93 91 94 92 static int cmp_ex_search(const void *key, const void *elt) 95 93 { ··· 116 120 return bsearch(&value, base, num, 117 121 sizeof(struct exception_table_entry), cmp_ex_search); 118 122 } 119 - #endif