linux/arch/sparc/mm/extable.c
<<
>>
Prefs
   1/*
   2 * linux/arch/sparc/mm/extable.c
   3 */
   4
   5#include <linux/module.h>
   6#include <asm/uaccess.h>
   7
   8void sort_extable(struct exception_table_entry *start,
   9                  struct exception_table_entry *finish)
  10{
  11}
  12
  13/* Caller knows they are in a range if ret->fixup == 0 */
  14const struct exception_table_entry *
  15search_extable(const struct exception_table_entry *start,
  16               const struct exception_table_entry *last,
  17               unsigned long value)
  18{
  19        const struct exception_table_entry *walk;
  20
  21        /* Single insn entries are encoded as:
  22         *      word 1: insn address
  23         *      word 2: fixup code address
  24         *
  25         * Range entries are encoded as:
  26         *      word 1: first insn address
  27         *      word 2: 0
  28         *      word 3: last insn address + 4 bytes
  29         *      word 4: fixup code address
  30         *
  31         * Deleted entries are encoded as:
  32         *      word 1: unused
  33         *      word 2: -1
  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                /* A deleted entry; see trim_init_extable */
  47                if (walk->fixup == -1)
  48                        continue;
  49
  50                if (walk->insn == value)
  51                        return walk;
  52        }
  53
  54        /* 2. Try to find a range match. */
  55        for (walk = start; walk <= (last - 1); walk++) {
  56                if (walk->fixup)
  57                        continue;
  58
  59                if (walk[0].insn <= value && walk[1].insn > value)
  60                        return walk;
  61
  62                walk++;
  63        }
  64
  65        return NULL;
  66}
  67
  68#ifdef CONFIG_MODULES
  69/* We could memmove them around; easier to mark the trimmed ones. */
  70void trim_init_extable(struct module *m)
  71{
  72        unsigned int i;
  73        bool range;
  74
  75        for (i = 0; i < m->num_exentries; i += range ? 2 : 1) {
  76                range = m->extable[i].fixup == 0;
  77
  78                if (within_module_init(m->extable[i].insn, m)) {
  79                        m->extable[i].fixup = -1;
  80                        if (range)
  81                                m->extable[i+1].fixup = -1;
  82                }
  83                if (range)
  84                        i++;
  85        }
  86}
  87#endif /* CONFIG_MODULES */
  88
  89/* Special extable search, which handles ranges.  Returns fixup */
  90unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
  91{
  92        const struct exception_table_entry *entry;
  93
  94        entry = search_exception_tables(addr);
  95        if (!entry)
  96                return 0;
  97
  98        /* Inside range?  Fix g2 and return correct fixup */
  99        if (!entry->fixup) {
 100                *g2 = (addr - entry->insn) / 4;
 101                return (entry + 1)->fixup;
 102        }
 103
 104        return entry->fixup;
 105}
 106