diff options
author | David Howells <dhowells@redhat.com> | 2006-01-08 04:01:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-08 23:13:36 -0500 |
commit | 018b8d12bc85f8fb332239b11d919ea0724c49a4 (patch) | |
tree | 88e1cfa3540e09df74ba0fcc82fad6af8a892b0c /arch/frv/mm | |
parent | 402344012ebe696d9353bbf056889ddaaec83079 (diff) |
[PATCH] frv: support module exception tables
Fix the exception table handling so that modules exceptions are dealt with.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/frv/mm')
-rw-r--r-- | arch/frv/mm/extable.c | 34 |
1 files changed, 9 insertions, 25 deletions
diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c index 41be1128dc64..caacf030ac75 100644 --- a/arch/frv/mm/extable.c +++ b/arch/frv/mm/extable.c | |||
@@ -43,7 +43,7 @@ static inline unsigned long search_one_table(const struct exception_table_entry | |||
43 | */ | 43 | */ |
44 | unsigned long search_exception_table(unsigned long pc) | 44 | unsigned long search_exception_table(unsigned long pc) |
45 | { | 45 | { |
46 | unsigned long ret = 0; | 46 | const struct exception_table_entry *extab; |
47 | 47 | ||
48 | /* determine if the fault lay during a memcpy_user or a memset_user */ | 48 | /* determine if the fault lay during a memcpy_user or a memset_user */ |
49 | if (__frame->lr == (unsigned long) &__memset_user_error_lr && | 49 | if (__frame->lr == (unsigned long) &__memset_user_error_lr && |
@@ -55,9 +55,10 @@ unsigned long search_exception_table(unsigned long pc) | |||
55 | */ | 55 | */ |
56 | return (unsigned long) &__memset_user_error_handler; | 56 | return (unsigned long) &__memset_user_error_handler; |
57 | } | 57 | } |
58 | else if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && | 58 | |
59 | (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end | 59 | if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && |
60 | ) { | 60 | (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end |
61 | ) { | ||
61 | /* the fault occurred in a protected memset | 62 | /* the fault occurred in a protected memset |
62 | * - we search for the return address (in LR) instead of the program counter | 63 | * - we search for the return address (in LR) instead of the program counter |
63 | * - it was probably during a copy_to/from_user() | 64 | * - it was probably during a copy_to/from_user() |
@@ -65,27 +66,10 @@ unsigned long search_exception_table(unsigned long pc) | |||
65 | return (unsigned long) &__memcpy_user_error_handler; | 66 | return (unsigned long) &__memcpy_user_error_handler; |
66 | } | 67 | } |
67 | 68 | ||
68 | #ifndef CONFIG_MODULES | 69 | extab = search_exception_tables(pc); |
69 | /* there is only the kernel to search. */ | 70 | if (extab) |
70 | ret = search_one_table(__start___ex_table, __stop___ex_table - 1, pc); | 71 | return extab->fixup; |
71 | return ret; | ||
72 | |||
73 | #else | ||
74 | /* the kernel is the last "module" -- no need to treat it special */ | ||
75 | unsigned long flags; | ||
76 | struct module *mp; | ||
77 | 72 | ||
78 | spin_lock_irqsave(&modlist_lock, flags); | 73 | return 0; |
79 | |||
80 | for (mp = module_list; mp != NULL; mp = mp->next) { | ||
81 | if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) | ||
82 | continue; | ||
83 | ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, pc); | ||
84 | if (ret) | ||
85 | break; | ||
86 | } | ||
87 | 74 | ||
88 | spin_unlock_irqrestore(&modlist_lock, flags); | ||
89 | return ret; | ||
90 | #endif | ||
91 | } /* end search_exception_table() */ | 75 | } /* end search_exception_table() */ |