1 #include <linux/module.h>
2 #include <asm/uaccess.h>
4 typedef bool (*ex_handler_t
)(const struct exception_table_entry
*,
5 struct pt_regs
*, int);
7 static inline unsigned long
8 ex_fixup_addr(const struct exception_table_entry
*x
)
10 return (unsigned long)&x
->fixup
+ x
->fixup
;
12 static inline ex_handler_t
13 ex_fixup_handler(const struct exception_table_entry
*x
)
15 return (ex_handler_t
)((unsigned long)&x
->handler
+ x
->handler
);
18 bool ex_handler_default(const struct exception_table_entry
*fixup
,
19 struct pt_regs
*regs
, int trapnr
)
21 regs
->ip
= ex_fixup_addr(fixup
);
24 EXPORT_SYMBOL(ex_handler_default
);
26 bool ex_handler_fault(const struct exception_table_entry
*fixup
,
27 struct pt_regs
*regs
, int trapnr
)
29 regs
->ip
= ex_fixup_addr(fixup
);
33 EXPORT_SYMBOL_GPL(ex_handler_fault
);
35 bool ex_handler_ext(const struct exception_table_entry
*fixup
,
36 struct pt_regs
*regs
, int trapnr
)
38 /* Special hack for uaccess_err */
39 current_thread_info()->uaccess_err
= 1;
40 regs
->ip
= ex_fixup_addr(fixup
);
43 EXPORT_SYMBOL(ex_handler_ext
);
45 bool ex_has_fault_handler(unsigned long ip
)
47 const struct exception_table_entry
*e
;
50 e
= search_exception_tables(ip
);
53 handler
= ex_fixup_handler(e
);
55 return handler
== ex_handler_fault
;
58 int fixup_exception(struct pt_regs
*regs
, int trapnr
)
60 const struct exception_table_entry
*e
;
64 if (unlikely(SEGMENT_IS_PNP_CODE(regs
->cs
))) {
65 extern u32 pnp_bios_fault_eip
, pnp_bios_fault_esp
;
66 extern u32 pnp_bios_is_utter_crap
;
67 pnp_bios_is_utter_crap
= 1;
68 printk(KERN_CRIT
"PNPBIOS fault.. attempting recovery.\n");
72 : : "g" (pnp_bios_fault_esp
), "g" (pnp_bios_fault_eip
));
73 panic("do_trap: can't hit this");
77 e
= search_exception_tables(regs
->ip
);
81 handler
= ex_fixup_handler(e
);
82 return handler(e
, regs
, trapnr
);
85 /* Restricted version used during very early boot */
86 int __init
early_fixup_exception(unsigned long *ip
)
88 const struct exception_table_entry
*e
;
92 e
= search_exception_tables(*ip
);
96 new_ip
= ex_fixup_addr(e
);
97 handler
= ex_fixup_handler(e
);
99 /* special handling not supported during early boot */
100 if (handler
!= ex_handler_default
)