diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-09-24 04:38:18 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-09-24 04:38:18 -0400 |
commit | 23c4c82171008c8b18d8627c9741cdd577631cea (patch) | |
tree | 8c9d2950fe69cbd6c1aa96ad6c698bbeb5c92325 /arch | |
parent | acf3cc283f1ea4ed7e579663eefed62f0aa572da (diff) |
sh: Handle unaligned 16-bit instructions on SH-2A.
This adds some sanity checking in the unaligned instruction handler to
verify the instruction size, which enables basic support for 16-bit
fixups on SH-2A parts.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/kernel/traps_32.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 6aba9af79eaf..f9760c5c234a 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -452,6 +452,12 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | |||
452 | u_int rm; | 452 | u_int rm; |
453 | int ret, index; | 453 | int ret, index; |
454 | 454 | ||
455 | /* | ||
456 | * XXX: We can't handle mixed 16/32-bit instructions yet | ||
457 | */ | ||
458 | if (instruction_size(instruction) != 2) | ||
459 | return -EINVAL; | ||
460 | |||
455 | index = (instruction>>8)&15; /* 0x0F00 */ | 461 | index = (instruction>>8)&15; /* 0x0F00 */ |
456 | rm = regs->regs[index]; | 462 | rm = regs->regs[index]; |
457 | 463 | ||
@@ -619,9 +625,9 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
619 | 625 | ||
620 | se_user += 1; | 626 | se_user += 1; |
621 | 627 | ||
622 | #ifndef CONFIG_CPU_SH2A | ||
623 | set_fs(USER_DS); | 628 | set_fs(USER_DS); |
624 | if (copy_from_user(&instruction, (u16 *)(regs->pc & ~1), 2)) { | 629 | if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1), |
630 | sizeof(instruction))) { | ||
625 | set_fs(oldfs); | 631 | set_fs(oldfs); |
626 | goto uspace_segv; | 632 | goto uspace_segv; |
627 | } | 633 | } |
@@ -633,7 +639,6 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
633 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", | 639 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", |
634 | current->comm, current->pid, (void *)regs->pc, | 640 | current->comm, current->pid, (void *)regs->pc, |
635 | instruction); | 641 | instruction); |
636 | #endif | ||
637 | 642 | ||
638 | if (se_usermode & 2) | 643 | if (se_usermode & 2) |
639 | goto fixup; | 644 | goto fixup; |