linux-old/arch/x86_64/mm/extable.c
<<
>>
Prefs
   1/*
   2 * linux/arch/x86_64/mm/extable.c
   3 */
   4
   5#include <linux/config.h>
   6#include <linux/module.h>
   7#include <linux/spinlock.h>
   8#include <linux/init.h>
   9#include <asm/uaccess.h>
  10
  11extern const struct exception_table_entry __start___ex_table[];
  12extern const struct exception_table_entry __stop___ex_table[];
  13
  14static inline unsigned long
  15search_one_table(const struct exception_table_entry *first,
  16                 const struct exception_table_entry *last,
  17                 unsigned long value)
  18{
  19        while (first <= last) {
  20                const struct exception_table_entry *mid;
  21                long diff;
  22
  23                mid = (last - first) / 2 + first;
  24                diff = mid->insn - value;
  25                if (diff == 0)
  26                        return mid->fixup;
  27                else if (diff < 0)
  28                        first = mid+1;
  29                else
  30                        last = mid-1;
  31        }
  32        return 0;
  33}
  34
  35extern spinlock_t modlist_lock;
  36
  37unsigned long
  38search_exception_table(unsigned long addr)
  39{
  40        unsigned long ret = 0;
  41        unsigned long flags;
  42
  43        /* Workaround for an Opteron issue */
  44        if ((addr >> 32) == 0) 
  45                addr |= 0xffffffffUL << 32; 
  46
  47#ifndef CONFIG_MODULES
  48        /* There is only the kernel to search.  */
  49        ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
  50        return ret;
  51#else
  52        /* The kernel is the last "module" -- no need to treat it special.  */
  53        struct module *mp;
  54
  55        spin_lock_irqsave(&modlist_lock, flags);
  56        for (mp = module_list; mp != NULL; mp = mp->next) {
  57                if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
  58                        continue;
  59                ret = search_one_table(mp->ex_table_start,
  60                                       mp->ex_table_end - 1, addr);
  61                if (ret)
  62                        break;
  63        }
  64        spin_unlock_irqrestore(&modlist_lock, flags);
  65        return ret;
  66#endif
  67}
  68
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.