diff options
Diffstat (limited to 'arch/sh/kernel/traps_32.c')
-rw-r--r-- | arch/sh/kernel/traps_32.c | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 058c6181bb30..6cdda3a621a1 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -75,6 +75,23 @@ static struct mem_access user_mem_access = { copy_to_user, }; +static unsigned long copy_from_kernel_wrapper(void *dst, const void __user *src, + unsigned long cnt) +{ + return copy_from_kernel_nofault(dst, (const void __force *)src, cnt); +} + +static unsigned long copy_to_kernel_wrapper(void __user *dst, const void *src, + unsigned long cnt) +{ + return copy_to_kernel_nofault((void __force *)dst, src, cnt); +} + +static struct mem_access kernel_mem_access = { + copy_from_kernel_wrapper, + copy_to_kernel_wrapper, +}; + /* * handle an instruction that does an unaligned memory access by emulating the * desired behaviour @@ -473,7 +490,6 @@ asmlinkage void do_address_error(struct pt_regs *regs, unsigned long address) { unsigned long error_code = 0; - mm_segment_t oldfs; insn_size_t instruction; int tmp; @@ -482,8 +498,6 @@ asmlinkage void do_address_error(struct pt_regs *regs, error_code = lookup_exception_vector(); #endif - oldfs = get_fs(); - if (user_mode(regs)) { int si_code = BUS_ADRERR; unsigned int user_action; @@ -491,13 +505,10 @@ asmlinkage void do_address_error(struct pt_regs *regs, local_irq_enable(); inc_unaligned_user_access(); - set_fs(USER_DS); - if (copy_from_user(&instruction, (insn_size_t *)(regs->pc & ~1), + if (copy_from_user(&instruction, (insn_size_t __user *)(regs->pc & ~1), sizeof(instruction))) { - set_fs(oldfs); goto uspace_segv; } - set_fs(oldfs); /* shout about userspace fixups */ unaligned_fixups_notify(current, instruction, regs); @@ -520,11 +531,9 @@ fixup: goto uspace_segv; } - set_fs(USER_DS); tmp = handle_unaligned_access(instruction, regs, &user_mem_access, 0, address); - set_fs(oldfs); if (tmp == 0) return; /* sorted */ @@ -540,21 +549,18 @@ uspace_segv: if (regs->pc & 1) die("unaligned program counter", regs, error_code); - set_fs(KERNEL_DS); - if (copy_from_user(&instruction, (void __user *)(regs->pc), + if (copy_from_kernel_nofault(&instruction, (void *)(regs->pc), sizeof(instruction))) { /* Argh. Fault on the instruction itself. This should never happen non-SMP */ - set_fs(oldfs); die("insn faulting in do_address_error", regs, 0); } unaligned_fixups_notify(current, instruction, regs); - handle_unaligned_access(instruction, regs, &user_mem_access, + handle_unaligned_access(instruction, regs, &kernel_mem_access, 0, address); - set_fs(oldfs); } } @@ -616,7 +622,7 @@ asmlinkage void do_reserved_inst(void) unsigned short inst = 0; int err; - get_user(inst, (unsigned short*)regs->pc); + get_user(inst, (unsigned short __user *)regs->pc); err = do_fpu_inst(inst, regs); if (!err) { @@ -701,9 +707,9 @@ asmlinkage void do_illegal_slot_inst(void) return; #ifdef CONFIG_SH_FPU_EMU - get_user(inst, (unsigned short *)regs->pc + 1); + get_user(inst, (unsigned short __user *)regs->pc + 1); if (!do_fpu_inst(inst, regs)) { - get_user(inst, (unsigned short *)regs->pc); + get_user(inst, (unsigned short __user *)regs->pc); if (!emulate_branch(inst, regs)) return; /* fault in branch.*/ |