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
sh
mm
extable_64.c
Go to the documentation of this file.
1
/*
2
* arch/sh/mm/extable_64.c
3
*
4
* Copyright (C) 2003 Richard Curnow
5
* Copyright (C) 2003, 2004 Paul Mundt
6
*
7
* Cloned from the 2.5 SH version..
8
*
9
* This file is subject to the terms and conditions of the GNU General Public
10
* License. See the file "COPYING" in the main directory of this archive
11
* for more details.
12
*/
13
#include <
linux/rwsem.h
>
14
#include <linux/module.h>
15
#include <asm/uaccess.h>
16
17
extern
unsigned
long
copy_user_memcpy
,
copy_user_memcpy_end
;
18
extern
void
__copy_user_fixup
(
void
);
19
20
static
const
struct
exception_table_entry
__copy_user_fixup_ex = {
21
.fixup = (
unsigned
long
)&
__copy_user_fixup
,
22
};
23
24
/*
25
* Some functions that may trap due to a bad user-mode address have too
26
* many loads and stores in them to make it at all practical to label
27
* each one and put them all in the main exception table.
28
*
29
* In particular, the fast memcpy routine is like this. It's fix-up is
30
* just to fall back to a slow byte-at-a-time copy, which is handled the
31
* conventional way. So it's functionally OK to just handle any trap
32
* occurring in the fast memcpy with that fixup.
33
*/
34
static
const
struct
exception_table_entry
*check_exception_ranges(
unsigned
long
addr
)
35
{
36
if
((addr >= (
unsigned
long
)©_user_memcpy) &&
37
(addr <= (
unsigned
long
)©_user_memcpy_end))
38
return
&__copy_user_fixup_ex;
39
40
return
NULL
;
41
}
42
43
/* Simple binary search */
44
const
struct
exception_table_entry
*
45
search_extable
(
const
struct
exception_table_entry
*
first
,
46
const
struct
exception_table_entry
*last,
47
unsigned
long
value
)
48
{
49
const
struct
exception_table_entry
*
mid
;
50
51
mid = check_exception_ranges(value);
52
if
(mid)
53
return
mid
;
54
55
while
(first <= last) {
56
long
diff;
57
58
mid = (last -
first
) / 2 + first;
59
diff = mid->
insn
-
value
;
60
if
(diff == 0)
61
return
mid
;
62
else
if
(diff < 0)
63
first = mid+1;
64
else
65
last = mid-1;
66
}
67
68
return
NULL
;
69
}
70
71
int
fixup_exception
(
struct
pt_regs
*
regs
)
72
{
73
const
struct
exception_table_entry
*
fixup
;
74
75
fixup =
search_exception_tables
(regs->
pc
);
76
if
(fixup) {
77
regs->
pc
= fixup->
fixup
;
78
return
1;
79
}
80
81
return
0;
82
}
Generated on Thu Jan 10 2013 13:18:01 for Linux Kernel by
1.8.2