···11/* SPDX-License-Identifier: GPL-2.0 */22-#ifndef __ASM_EXTABLE64_H33-#define __ASM_EXTABLE64_H22+#ifndef __ASM_EXTABLE_H33+#define __ASM_EXTABLE_H44/*55 * The exception table consists of pairs of addresses: the first is the66 * address of an instruction that is allowed to fault, and the second is
···13131414#include <asm/processor.h>15151616-#define ARCH_HAS_SORT_EXTABLE1717-#define ARCH_HAS_SEARCH_EXTABLE1818-1916/* Sparc is not segmented, however we need to be able to fool access_ok()2017 * when doing system calls from kernel mode legitimately.2118 *···3639#define __kernel_ok (uaccess_kernel())3740#define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size)))3841#define access_ok(addr, size) __access_ok((unsigned long)(addr), size)3939-4040-/*4141- * The exception table consists of pairs of addresses: the first is the4242- * address of an instruction that is allowed to fault, and the second is4343- * the address at which the program should continue. No registers are4444- * modified, so it is entirely up to the continuation code to figure out4545- * what to do.4646- *4747- * All the routines below use bits of fixup code that are out of line4848- * with the main instruction path. This means when everything is well,4949- * we don't even have to jump over them. Further, they do not intrude5050- * on our cache or tlb entries.5151- *5252- * There is a special way how to put a range of potentially faulting5353- * insns (like twenty ldd/std's with now intervening other instructions)5454- * You specify address of first in insn and 0 in fixup and in the next5555- * exception_table_entry you specify last potentially faulting insn + 15656- * and in fixup the routine which should handle the fault.5757- * That fixup code will get5858- * (faulting_insn_address - first_insn_in_the_range_address)/45959- * in %g2 (ie. index of the faulting instruction in the range).6060- */6161-6262-struct exception_table_entry6363-{6464- unsigned long insn, fixup;6565-};6666-6767-/* Returns 0 if exception not found and fixup otherwise. */6868-unsigned long search_extables_range(unsigned long addr, unsigned long *g2);69427043/* Uh, these should become the main single-value transfer routines..7144 * They automatically use the right size if we just have the right
···11-// SPDX-License-Identifier: GPL-2.022-/*33- * linux/arch/sparc/mm/extable.c44- */55-66-#include <linux/module.h>77-#include <linux/extable.h>88-#include <linux/uaccess.h>99-1010-void sort_extable(struct exception_table_entry *start,1111- struct exception_table_entry *finish)1212-{1313-}1414-1515-/* Caller knows they are in a range if ret->fixup == 0 */1616-const struct exception_table_entry *1717-search_extable(const struct exception_table_entry *base,1818- const size_t num,1919- unsigned long value)2020-{2121- int i;2222-2323- /* Single insn entries are encoded as:2424- * word 1: insn address2525- * word 2: fixup code address2626- *2727- * Range entries are encoded as:2828- * word 1: first insn address2929- * word 2: 03030- * word 3: last insn address + 4 bytes3131- * word 4: fixup code address3232- *3333- * Deleted entries are encoded as:3434- * word 1: unused3535- * word 2: -13636- *3737- * See asm/uaccess.h for more details.3838- */3939-4040- /* 1. Try to find an exact match. */4141- for (i = 0; i < num; i++) {4242- if (base[i].fixup == 0) {4343- /* A range entry, skip both parts. */4444- i++;4545- continue;4646- }4747-4848- /* A deleted entry; see trim_init_extable */4949- if (base[i].fixup == -1)5050- continue;5151-5252- if (base[i].insn == value)5353- return &base[i];5454- }5555-5656- /* 2. Try to find a range match. */5757- for (i = 0; i < (num - 1); i++) {5858- if (base[i].fixup)5959- continue;6060-6161- if (base[i].insn <= value && base[i + 1].insn > value)6262- return &base[i];6363-6464- i++;6565- }6666-6767- return NULL;6868-}6969-7070-#ifdef CONFIG_MODULES7171-/* We could memmove them around; easier to mark the trimmed ones. */7272-void trim_init_extable(struct module *m)7373-{7474- unsigned int i;7575- bool range;7676-7777- for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {7878- range = m->extable[i].fixup == 0;7979-8080- if (within_module_init(m->extable[i].insn, m)) {8181- m->extable[i].fixup = -1;8282- if (range)8383- m->extable[i+1].fixup = -1;8484- }8585- if (range)8686- i++;8787- }8888-}8989-#endif /* CONFIG_MODULES */9090-9191-/* Special extable search, which handles ranges. Returns fixup */9292-unsigned long search_extables_range(unsigned long addr, unsigned long *g2)9393-{9494- const struct exception_table_entry *entry;9595-9696- entry = search_exception_tables(addr);9797- if (!entry)9898- return 0;9999-100100- /* Inside range? Fix g2 and return correct fixup */101101- if (!entry->fixup) {102102- *g2 = (addr - entry->insn) / 4;103103- return (entry + 1)->fixup;104104- }105105-106106- return entry->fixup;107107-}
+11-15
arch/sparc/mm/fault_32.c
···2323#include <linux/interrupt.h>2424#include <linux/kdebug.h>2525#include <linux/uaccess.h>2626+#include <linux/extable.h>26272728#include <asm/page.h>2829#include <asm/openprom.h>···115114 struct vm_area_struct *vma;116115 struct task_struct *tsk = current;117116 struct mm_struct *mm = tsk->mm;118118- unsigned int fixup;119119- unsigned long g2;120117 int from_user = !(regs->psr & PSR_PS);121118 int code;122119 vm_fault_t fault;···232233233234 /* Is this in ex_table? */234235no_context:235235- g2 = regs->u_regs[UREG_G2];236236 if (!from_user) {237237- fixup = search_extables_range(regs->pc, &g2);238238- /* Values below 10 are reserved for other things */239239- if (fixup > 10) {237237+ const struct exception_table_entry *entry;238238+239239+ entry = search_exception_tables(regs->pc);240240#ifdef DEBUG_EXCEPTIONS241241- printk("Exception: PC<%08lx> faddr<%08lx>\n",242242- regs->pc, address);243243- printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",244244- regs->pc, fixup, g2);241241+ printk("Exception: PC<%08lx> faddr<%08lx>\n",242242+ regs->pc, address);243243+ printk("EX_TABLE: insn<%08lx> fixup<%08x>\n",244244+ regs->pc, entry->fixup);245245#endif246246- regs->u_regs[UREG_G2] = g2;247247- regs->pc = fixup;248248- regs->npc = regs->pc + 4;249249- return;250250- }246246+ regs->pc = entry->fixup;247247+ regs->npc = regs->pc + 4;248248+ return;251249 }252250253251 unhandled_fault(address, tsk, regs);