From: Arnd Bergmann <a...@arndb.de>

sh uses set_fs/get_fs only in one file, to handle address
errors in both user and kernel memory.

It already has an abstraction to differentiate between I/O
and memory, so adding a third class for kernel memory fits
into the same scheme and lets us kill off CONFIG_SET_FS.

Signed-off-by: Arnd Bergmann <a...@arndb.de>
---
 arch/sh/Kconfig                   |  1 -
 arch/sh/include/asm/processor.h   |  1 -
 arch/sh/include/asm/segment.h     | 33 -------------------------------
 arch/sh/include/asm/thread_info.h |  2 --
 arch/sh/include/asm/uaccess.h     |  4 ----
 arch/sh/kernel/io_trapped.c       |  9 ++-------
 arch/sh/kernel/process_32.c       |  2 --
 arch/sh/kernel/traps_32.c         | 30 +++++++++++++++++-----------
 8 files changed, 21 insertions(+), 61 deletions(-)
 delete mode 100644 arch/sh/include/asm/segment.h

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 2474a04ceac4..f676e92b7d5b 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -65,7 +65,6 @@ config SUPERH
        select PERF_EVENTS
        select PERF_USE_VMALLOC
        select RTC_LIB
-       select SET_FS
        select SPARSE_IRQ
        select TRACE_IRQFLAGS_SUPPORT
        help
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 3820d698846e..85a6c1c3c16e 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -3,7 +3,6 @@
 #define __ASM_SH_PROCESSOR_H
 
 #include <asm/cpu-features.h>
-#include <asm/segment.h>
 #include <asm/cache.h>
 
 #ifndef __ASSEMBLY__
diff --git a/arch/sh/include/asm/segment.h b/arch/sh/include/asm/segment.h
deleted file mode 100644
index 02e54a3335d6..000000000000
--- a/arch/sh/include/asm/segment.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_SH_SEGMENT_H
-#define __ASM_SH_SEGMENT_H
-
-#ifndef __ASSEMBLY__
-
-typedef struct {
-       unsigned long seg;
-} mm_segment_t;
-
-#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons, these macros are grossly misnamed.
- */
-#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFFUL)
-#ifdef CONFIG_MMU
-#define USER_DS                MAKE_MM_SEG(PAGE_OFFSET)
-#else
-#define USER_DS                KERNEL_DS
-#endif
-
-#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
-
-#define get_fs()       (current_thread_info()->addr_limit)
-#define set_fs(x)      (current_thread_info()->addr_limit = (x))
-
-#endif /* __ASSEMBLY__ */
-#endif /* __ASM_SH_SEGMENT_H */
diff --git a/arch/sh/include/asm/thread_info.h 
b/arch/sh/include/asm/thread_info.h
index 598d0184ffea..b119b859a0a3 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -30,7 +30,6 @@ struct thread_info {
        __u32                   status;         /* thread synchronous flags */
        __u32                   cpu;
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
-       mm_segment_t            addr_limit;     /* thread address space */
        unsigned long           previous_sp;    /* sp of previous stack in case
                                                   of nested IRQ stacks */
        __u8                    supervisor_stack[0];
@@ -58,7 +57,6 @@ struct thread_info {
        .status         = 0,                    \
        .cpu            = 0,                    \
        .preempt_count  = INIT_PREEMPT_COUNT,   \
-       .addr_limit     = KERNEL_DS,            \
 }
 
 /* how to get the current stack pointer from C */
diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h
index ccd219d74851..a79609eb14be 100644
--- a/arch/sh/include/asm/uaccess.h
+++ b/arch/sh/include/asm/uaccess.h
@@ -2,11 +2,7 @@
 #ifndef __ASM_SH_UACCESS_H
 #define __ASM_SH_UACCESS_H
 
-#include <asm/segment.h>
 #include <asm/extable.h>
-
-#define user_addr_max()        (current_thread_info()->addr_limit.seg)
-
 #include <asm-generic/access_ok.h>
 
 /*
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
index 004ad0130b10..e803b14ef12e 100644
--- a/arch/sh/kernel/io_trapped.c
+++ b/arch/sh/kernel/io_trapped.c
@@ -270,7 +270,6 @@ static struct mem_access trapped_io_access = {
 
 int handle_trapped_io(struct pt_regs *regs, unsigned long address)
 {
-       mm_segment_t oldfs;
        insn_size_t instruction;
        int tmp;
 
@@ -281,16 +280,12 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long 
address)
 
        WARN_ON(user_mode(regs));
 
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       if (copy_from_user(&instruction, (void *)(regs->pc),
-                          sizeof(instruction))) {
-               set_fs(oldfs);
+       if (copy_from_kernel_nofault(&instruction, (void *)(regs->pc),
+                                    sizeof(instruction))) {
                return 0;
        }
 
        tmp = handle_unaligned_access(instruction, regs,
                                      &trapped_io_access, 1, address);
-       set_fs(oldfs);
        return tmp == 0;
 }
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 1c28e3cddb60..ca01286a0610 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -123,7 +123,6 @@ int copy_thread(unsigned long clone_flags, unsigned long 
usp, unsigned long arg,
 #if defined(CONFIG_SH_FPU)
                childregs->sr |= SR_FD;
 #endif
-               ti->addr_limit = KERNEL_DS;
                ti->status &= ~TS_USEDFPU;
                p->thread.fpu_counter = 0;
                return 0;
@@ -132,7 +131,6 @@ int copy_thread(unsigned long clone_flags, unsigned long 
usp, unsigned long arg,
 
        if (usp)
                childregs->regs[15] = usp;
-       ti->addr_limit = USER_DS;
 
        if (clone_flags & CLONE_SETTLS)
                childregs->gbr = tls;
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index b3c715bc254b..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;
 
@@ -489,13 +505,10 @@ asmlinkage void do_address_error(struct pt_regs *regs,
                local_irq_enable();
                inc_unaligned_user_access();
 
-               oldfs = force_uaccess_begin();
                if (copy_from_user(&instruction, (insn_size_t __user 
*)(regs->pc & ~1),
                                   sizeof(instruction))) {
-                       force_uaccess_end(oldfs);
                        goto uspace_segv;
                }
-               force_uaccess_end(oldfs);
 
                /* shout about userspace fixups */
                unaligned_fixups_notify(current, instruction, regs);
@@ -518,11 +531,9 @@ asmlinkage void do_address_error(struct pt_regs *regs,
                        goto uspace_segv;
                }
 
-               oldfs = force_uaccess_begin();
                tmp = handle_unaligned_access(instruction, regs,
                                              &user_mem_access, 0,
                                              address);
-               force_uaccess_end(oldfs);
 
                if (tmp == 0)
                        return; /* sorted */
@@ -538,21 +549,18 @@ asmlinkage void do_address_error(struct pt_regs *regs,
                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);
        }
 }
 
-- 
2.29.2

Reply via email to