linux/arch/x86/mm/extable.c
<<
>>
Prefs
   1#include <linux/module.h>
   2#include <linux/spinlock.h>
   3#include <asm/uaccess.h>
   4
   5
   6int fixup_exception(struct pt_regs *regs)
   7{
   8        const struct exception_table_entry *fixup;
   9
  10#ifdef CONFIG_PNPBIOS
  11        if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
  12                extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
  13                extern u32 pnp_bios_is_utter_crap;
  14                pnp_bios_is_utter_crap = 1;
  15                printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
  16                __asm__ volatile(
  17                        "movl %0, %%esp\n\t"
  18                        "jmp *%1\n\t"
  19                        : : "g" (pnp_bios_fault_esp), "g" (pnp_bios_fault_eip));
  20                panic("do_trap: can't hit this");
  21        }
  22#endif
  23
  24        fixup = search_exception_tables(regs->ip);
  25        if (fixup) {
  26                regs->ip = fixup->fixup;
  27                return 1;
  28        }
  29
  30        return 0;
  31}
  32
  33#ifdef CONFIG_X86_64
  34/*
  35 * Need to defined our own search_extable on X86_64 to work around
  36 * a B stepping K8 bug.
  37 */
  38const struct exception_table_entry *
  39search_extable(const struct exception_table_entry *first,
  40               const struct exception_table_entry *last,
  41               unsigned long value)
  42{
  43        /* B stepping K8 bug */
  44        if ((value >> 32) == 0)
  45                value |= 0xffffffffUL << 32;
  46
  47        while (first <= last) {
  48                const struct exception_table_entry *mid;
  49                long diff;
  50
  51                mid = (last - first) / 2 + first;
  52                diff = mid->insn - value;
  53                if (diff == 0)
  54                        return mid;
  55                else if (diff < 0)
  56                        first = mid+1;
  57                else
  58                        last = mid-1;
  59        }
  60        return NULL;
  61}
  62#endif
  63