linux/arch/s390/mm/extable.c
<<
>>
Prefs
   1#include <linux/module.h>
   2#include <linux/sort.h>
   3#include <asm/uaccess.h>
   4
   5/*
   6 * Search one exception table for an entry corresponding to the
   7 * given instruction address, and return the address of the entry,
   8 * or NULL if none is found.
   9 * We use a binary search, and thus we assume that the table is
  10 * already sorted.
  11 */
  12const struct exception_table_entry *
  13search_extable(const struct exception_table_entry *first,
  14               const struct exception_table_entry *last,
  15               unsigned long value)
  16{
  17        const struct exception_table_entry *mid;
  18        unsigned long addr;
  19
  20        while (first <= last) {
  21                mid = ((last - first) >> 1) + first;
  22                addr = extable_insn(mid);
  23                if (addr < value)
  24                        first = mid + 1;
  25                else if (addr > value)
  26                        last = mid - 1;
  27                else
  28                        return mid;
  29        }
  30        return NULL;
  31}
  32
  33/*
  34 * The exception table needs to be sorted so that the binary
  35 * search that we use to find entries in it works properly.
  36 * This is used both for the kernel exception table and for
  37 * the exception tables of modules that get loaded.
  38 *
  39 */
  40static int cmp_ex(const void *a, const void *b)
  41{
  42        const struct exception_table_entry *x = a, *y = b;
  43
  44        /* This compare is only valid after normalization. */
  45        return x->insn - y->insn;
  46}
  47
  48void sort_extable(struct exception_table_entry *start,
  49                  struct exception_table_entry *finish)
  50{
  51        struct exception_table_entry *p;
  52        int i;
  53
  54        /* Normalize entries to being relative to the start of the section */
  55        for (p = start, i = 0; p < finish; p++, i += 8)
  56                p->insn += i;
  57        sort(start, finish - start, sizeof(*start), cmp_ex, NULL);
  58        /* Denormalize all entries */
  59        for (p = start, i = 0; p < finish; p++, i += 8)
  60                p->insn -= i;
  61}
  62
  63#ifdef CONFIG_MODULES
  64/*
  65 * If the exception table is sorted, any referring to the module init
  66 * will be at the beginning or the end.
  67 */
  68void trim_init_extable(struct module *m)
  69{
  70        /* Trim the beginning */
  71        while (m->num_exentries &&
  72               within_module_init(extable_insn(&m->extable[0]), m)) {
  73                m->extable++;
  74                m->num_exentries--;
  75        }
  76        /* Trim the end */
  77        while (m->num_exentries &&
  78               within_module_init(extable_insn(&m->extable[m->num_exentries-1]), m))
  79                m->num_exentries--;
  80}
  81#endif /* CONFIG_MODULES */
  82