diff options
Diffstat (limited to 'arch/arm/kernel/traps.c')
| -rw-r--r-- | arch/arm/kernel/traps.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 7277aef83098..872f1f8fbb57 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
| @@ -288,14 +288,28 @@ void unregister_undef_hook(struct undef_hook *hook) | |||
| 288 | spin_unlock_irqrestore(&undef_lock, flags); | 288 | spin_unlock_irqrestore(&undef_lock, flags); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | static int call_undef_hook(struct pt_regs *regs, unsigned int instr) | ||
| 292 | { | ||
| 293 | struct undef_hook *hook; | ||
| 294 | unsigned long flags; | ||
| 295 | int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; | ||
| 296 | |||
| 297 | spin_lock_irqsave(&undef_lock, flags); | ||
| 298 | list_for_each_entry(hook, &undef_hook, node) | ||
| 299 | if ((instr & hook->instr_mask) == hook->instr_val && | ||
| 300 | (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) | ||
| 301 | fn = hook->fn; | ||
| 302 | spin_unlock_irqrestore(&undef_lock, flags); | ||
| 303 | |||
| 304 | return fn ? fn(regs, instr) : 1; | ||
| 305 | } | ||
| 306 | |||
| 291 | asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | 307 | asmlinkage void __exception do_undefinstr(struct pt_regs *regs) |
| 292 | { | 308 | { |
| 293 | unsigned int correction = thumb_mode(regs) ? 2 : 4; | 309 | unsigned int correction = thumb_mode(regs) ? 2 : 4; |
| 294 | unsigned int instr; | 310 | unsigned int instr; |
| 295 | struct undef_hook *hook; | ||
| 296 | siginfo_t info; | 311 | siginfo_t info; |
| 297 | void __user *pc; | 312 | void __user *pc; |
| 298 | unsigned long flags; | ||
| 299 | 313 | ||
| 300 | /* | 314 | /* |
| 301 | * According to the ARM ARM, PC is 2 or 4 bytes ahead, | 315 | * According to the ARM ARM, PC is 2 or 4 bytes ahead, |
| @@ -325,17 +339,8 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
| 325 | } | 339 | } |
| 326 | #endif | 340 | #endif |
| 327 | 341 | ||
| 328 | spin_lock_irqsave(&undef_lock, flags); | 342 | if (call_undef_hook(regs, instr) == 0) |
| 329 | list_for_each_entry(hook, &undef_hook, node) { | 343 | return; |
| 330 | if ((instr & hook->instr_mask) == hook->instr_val && | ||
| 331 | (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { | ||
| 332 | if (hook->fn(regs, instr) == 0) { | ||
| 333 | spin_unlock_irqrestore(&undef_lock, flags); | ||
| 334 | return; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | } | ||
| 338 | spin_unlock_irqrestore(&undef_lock, flags); | ||
| 339 | 344 | ||
| 340 | #ifdef CONFIG_DEBUG_USER | 345 | #ifdef CONFIG_DEBUG_USER |
| 341 | if (user_debug & UDBG_UNDEFINED) { | 346 | if (user_debug & UDBG_UNDEFINED) { |
