Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/frv/mm/extable.c
10817 views
1
/*
2
* linux/arch/frv/mm/extable.c
3
*/
4
5
#include <linux/module.h>
6
#include <linux/spinlock.h>
7
#include <asm/uaccess.h>
8
9
extern const struct exception_table_entry __attribute__((aligned(8))) __start___ex_table[];
10
extern const struct exception_table_entry __attribute__((aligned(8))) __stop___ex_table[];
11
extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
12
extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
13
extern spinlock_t modlist_lock;
14
15
/*****************************************************************************/
16
/*
17
*
18
*/
19
static inline unsigned long search_one_table(const struct exception_table_entry *first,
20
const struct exception_table_entry *last,
21
unsigned long value)
22
{
23
while (first <= last) {
24
const struct exception_table_entry __attribute__((aligned(8))) *mid;
25
long diff;
26
27
mid = (last - first) / 2 + first;
28
diff = mid->insn - value;
29
if (diff == 0)
30
return mid->fixup;
31
else if (diff < 0)
32
first = mid + 1;
33
else
34
last = mid - 1;
35
}
36
return 0;
37
} /* end search_one_table() */
38
39
/*****************************************************************************/
40
/*
41
* see if there's a fixup handler available to deal with a kernel fault
42
*/
43
unsigned long search_exception_table(unsigned long pc)
44
{
45
const struct exception_table_entry *extab;
46
47
/* determine if the fault lay during a memcpy_user or a memset_user */
48
if (__frame->lr == (unsigned long) &__memset_user_error_lr &&
49
(unsigned long) &memset <= pc && pc < (unsigned long) &__memset_end
50
) {
51
/* the fault occurred in a protected memset
52
* - we search for the return address (in LR) instead of the program counter
53
* - it was probably during a clear_user()
54
*/
55
return (unsigned long) &__memset_user_error_handler;
56
}
57
58
if (__frame->lr == (unsigned long) &__memcpy_user_error_lr &&
59
(unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end
60
) {
61
/* the fault occurred in a protected memset
62
* - we search for the return address (in LR) instead of the program counter
63
* - it was probably during a copy_to/from_user()
64
*/
65
return (unsigned long) &__memcpy_user_error_handler;
66
}
67
68
extab = search_exception_tables(pc);
69
if (extab)
70
return extab->fixup;
71
72
return 0;
73
74
} /* end search_exception_table() */
75
76