Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
ia64
mm
extable.c
Go to the documentation of this file.
1
/*
2
* Kernel exception handling table support. Derived from arch/alpha/mm/extable.c.
3
*
4
* Copyright (C) 1998, 1999, 2001-2002, 2004 Hewlett-Packard Co
5
* David Mosberger-Tang <
[email protected]
>
6
*/
7
8
#include <
linux/sort.h
>
9
10
#include <asm/uaccess.h>
11
#include <linux/module.h>
12
13
static
int
cmp_ex(
const
void
*
a
,
const
void
*
b
)
14
{
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;
18
19
/* avoid overflow */
20
if
(lip >
rip
)
21
return
1;
22
if
(lip <
rip
)
23
return
-1;
24
return
0;
25
}
26
27
static
void
swap_ex(
void
*a,
void
*b,
int
size
)
28
{
29
struct
exception_table_entry
*l =
a
, *r =
b
,
tmp
;
30
u64
delta
= (
u64
) r - (
u64
)
l
;
31
32
tmp = *
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
;
37
}
38
39
/*
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
47
* exception-table).
48
*/
49
void
sort_extable
(
struct
exception_table_entry
*
start
,
50
struct
exception_table_entry
*finish)
51
{
52
sort
(start, finish - start,
sizeof
(
struct
exception_table_entry
),
53
cmp_ex, swap_ex);
54
}
55
56
static
inline
unsigned
long
ex_to_addr(
const
struct
exception_table_entry
*
x
)
57
{
58
return
(
unsigned
long
)&x->
addr
+ x->
addr
;
59
}
60
61
#ifdef CONFIG_MODULES
62
/*
63
* Any entry referring to the module init will be at the beginning or
64
* the end.
65
*/
66
void
trim_init_extable
(
struct
module
*
m
)
67
{
68
/*trim the beginning*/
69
while
(m->num_exentries &&
70
within_module_init(ex_to_addr(&m->extable[0]), m)) {
71
m->extable++;
72
m->num_exentries--;
73
}
74
/*trim the end*/
75
while
(m->num_exentries &&
76
within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]),
77
m))
78
m->num_exentries--;
79
}
80
#endif
/* CONFIG_MODULES */
81
82
const
struct
exception_table_entry
*
83
search_extable
(
const
struct
exception_table_entry
*
first
,
84
const
struct
exception_table_entry
*last,
85
unsigned
long
ip
)
86
{
87
const
struct
exception_table_entry
*
mid
;
88
unsigned
long
mid_ip;
89
long
diff;
90
91
while
(first <= last) {
92
mid = &first[(last -
first
)/2];
93
mid_ip = (
u64
) &mid->
addr
+ mid->
addr
;
94
diff = mid_ip - ip;
95
if
(diff == 0)
96
return
mid
;
97
else
if
(diff < 0)
98
first = mid + 1;
99
else
100
last = mid - 1;
101
}
102
return
NULL
;
103
}
104
105
void
106
ia64_handle_exception
(
struct
pt_regs
*
regs
,
const
struct
exception_table_entry
*
e
)
107
{
108
long
fix = (
u64
) &e->
cont
+ e->
cont
;
109
110
regs->
r8
= -
EFAULT
;
111
if
(fix & 4)
112
regs->
r9
= 0;
113
regs->
cr_iip
= fix & ~0xf;
114
ia64_psr
(regs)->ri = fix & 0x3;
/* set continuation slot number */
115
}
Generated on Thu Jan 10 2013 12:53:52 for Linux Kernel by
1.8.2