2 * Kernel exception handling table support. Derived from arch/alpha/mm/extable.c.
4 * Copyright (C) 1998, 1999, 2001-2002, 2004 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com>
8 #include <linux/sort.h>
10 #include <asm/uaccess.h>
11 #include <linux/module.h>
13 static int cmp_ex(const void *a
, const void *b
)
15 const struct exception_table_entry
*l
= a
, *r
= b
;
16 u64 lip
= (u64
) &l
->addr
+ l
->addr
;
17 u64 rip
= (u64
) &r
->addr
+ r
->addr
;
27 static void swap_ex(void *a
, void *b
, int size
)
29 struct exception_table_entry
*l
= a
, *r
= b
, tmp
;
30 u64 delta
= (u64
) r
- (u64
) l
;
33 l
->addr
= r
->addr
+ delta
;
34 l
->cont
= r
->cont
+ delta
;
35 r
->addr
= tmp
.addr
- delta
;
36 r
->cont
= tmp
.cont
- delta
;
40 * Sort the exception table. It's usually already sorted, but there
41 * may be unordered entries due to multiple text sections (such as the
42 * .init text section). Note that the exception-table-entries contain
43 * location-relative addresses, which requires a bit of care during
44 * sorting to avoid overflows in the offset members (e.g., it would
45 * not be safe to make a temporary copy of an exception-table entry on
46 * the stack, because the stack may be more than 2GB away from the
49 void sort_extable (struct exception_table_entry
*start
,
50 struct exception_table_entry
*finish
)
52 sort(start
, finish
- start
, sizeof(struct exception_table_entry
),
56 static inline unsigned long ex_to_addr(const struct exception_table_entry
*x
)
58 return (unsigned long)&x
->addr
+ x
->addr
;
63 * Any entry referring to the module init will be at the beginning or
66 void trim_init_extable(struct module
*m
)
68 /*trim the beginning*/
69 while (m
->num_exentries
&&
70 within_module_init(ex_to_addr(&m
->extable
[0]), m
)) {
75 while (m
->num_exentries
&&
76 within_module_init(ex_to_addr(&m
->extable
[m
->num_exentries
-1]),
80 #endif /* CONFIG_MODULES */
82 const struct exception_table_entry
*
83 search_extable (const struct exception_table_entry
*first
,
84 const struct exception_table_entry
*last
,
87 const struct exception_table_entry
*mid
;
91 while (first
<= last
) {
92 mid
= &first
[(last
- first
)/2];
93 mid_ip
= (u64
) &mid
->addr
+ mid
->addr
;
106 ia64_handle_exception (struct pt_regs
*regs
, const struct exception_table_entry
*e
)
108 long fix
= (u64
) &e
->cont
+ e
->cont
;
113 regs
->cr_iip
= fix
& ~0xf;
114 ia64_psr(regs
)->ri
= fix
& 0x3; /* set continuation slot number */