Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sh/mm/extable_64.c
10817 views
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)&copy_user_memcpy) &&
37
(addr <= (unsigned long)&copy_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
}
83
84