summaryrefslogtreecommitdiff
path: root/arch/sh/kernel/traps_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/traps_32.c')
-rw-r--r--arch/sh/kernel/traps_32.c40
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.*/