blob: 5555675dadb6d4a2fd02b42c0cd5ffb97206da71 [file] [log] [blame]
Harvey Harrison6d485832008-01-30 13:31:41 +01001#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) {
Hiroshi Shimamotofe40c0a2009-01-23 15:49:41 -080026 /* If fixup is less than 16, it means uaccess error */
27 if (fixup->fixup < 16) {
Andy Lutomirski4fc34902011-11-07 16:33:40 -080028 current_thread_info()->uaccess_err = 1;
Hiroshi Shimamotofe40c0a2009-01-23 15:49:41 -080029 regs->ip += fixup->fixup;
30 return 1;
31 }
Harvey Harrison6d485832008-01-30 13:31:41 +010032 regs->ip = fixup->fixup;
33 return 1;
34 }
35
36 return 0;
37}
H. Peter Anvin6a1ea272012-04-19 15:24:20 -070038
39/* Restricted version used during very early boot */
40int __init early_fixup_exception(unsigned long *ip)
41{
42 const struct exception_table_entry *fixup;
43
44 fixup = search_exception_tables(*ip);
45 if (fixup) {
46 if (fixup->fixup < 16)
47 return 0; /* Not supported during early boot */
48
49 *ip = fixup->fixup;
50 return 1;
51 }
52
53 return 0;
54}