Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Jul 2015 04:47:12 +0000 (21:47 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Jul 2015 04:47:12 +0000 (21:47 -0700)
Pull arch/tile updates from Chris Metcalf:
 "These are a grab bag of changes to improve debugging and respond to a
  variety of issues raised on LKML over the last couple of months"

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  tile: avoid a "label not used" warning in do_page_fault()
  tile: vdso: use raw_read_seqcount_begin() in vdso
  tile: force CONFIG_TILEGX if ARCH != tilepro
  tile: improve stack backtrace
  tile: fix "odd fault" warning for stack backtraces
  tile: set up initial stack top to honor STACK_TOP_DELTA
  tile: support delivering NMIs for multicore backtrace
  drivers/tty/hvc/hvc_tile.c: properly return -EAGAIN
  tile: add <asm/word-at-a-time.h> and enable support functions
  tile: use READ_ONCE() in arch_spin_is_locked()
  tile: modify arch_spin_unlock_wait() semantics

1  2 
arch/tile/Kconfig
arch/tile/include/asm/uaccess.h
arch/tile/kernel/setup.c
arch/tile/mm/fault.c

diff --combined arch/tile/Kconfig
@@@ -24,11 -24,13 +24,14 @@@ config TIL
        select MODULES_USE_ELF_RELA
        select HAVE_ARCH_TRACEHOOK
        select HAVE_SYSCALL_TRACEPOINTS
+       select USER_STACKTRACE_SUPPORT
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select HAVE_DEBUG_STACKOVERFLOW
        select ARCH_WANT_FRAME_POINTERS
        select HAVE_CONTEXT_TRACKING
 +      select EDAC_SUPPORT
+       select GENERIC_STRNCPY_FROM_USER
+       select GENERIC_STRNLEN_USER
  
  # FIXME: investigate whether we need/want these options.
  #     select HAVE_IOREMAP_PROT
@@@ -125,8 -127,10 +128,10 @@@ config HVC_TIL
        select HVC_IRQ if TILEGX
        def_bool y
  
+ # Building with ARCH=tilegx (or ARCH=tile) implies using the
+ # 64-bit TILE-Gx toolchain, so force CONFIG_TILEGX on.
  config TILEGX
-       bool "Building for TILE-Gx (64-bit) processor"
+       def_bool ARCH != "tilepro"
        select SPARSE_IRQ
        select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
        select HAVE_FUNCTION_TRACER
@@@ -64,6 -64,13 +64,13 @@@ static inline int is_arch_mappable_rang
  #define is_arch_mappable_range(addr, size) 0
  #endif
  
+ /*
+  * Note that using this definition ignores is_arch_mappable_range(),
+  * so on tilepro code that uses user_addr_max() is constrained not
+  * to reference the tilepro user-interrupt region.
+  */
+ #define user_addr_max() (current_thread_info()->addr_limit.seg)
  /*
   * Test whether a block of memory is a valid user space address.
   * Returns 0 if the range is valid, nonzero otherwise.
@@@ -78,8 -85,7 +85,8 @@@ int __range_ok(unsigned long addr, unsi
   * @addr: User space pointer to start of block to check
   * @size: Size of block to check
   *
 - * Context: User context only.  This function may sleep.
 + * Context: User context only. This function may sleep if pagefaults are
 + *          enabled.
   *
   * Checks if a pointer to a block of memory in user space is valid.
   *
@@@ -193,8 -199,7 +200,8 @@@ extern int __get_user_bad(void
   * @x:   Variable to store result.
   * @ptr: Source address, in user space.
   *
 - * Context: User context only.  This function may sleep.
 + * Context: User context only. This function may sleep if pagefaults are
 + *          enabled.
   *
   * This macro copies a single simple variable from user space to kernel
   * space.  It supports simple types like char and int, but not larger
@@@ -276,8 -281,7 +283,8 @@@ extern int __put_user_bad(void
   * @x:   Value to copy to user space.
   * @ptr: Destination address, in user space.
   *
 - * Context: User context only.  This function may sleep.
 + * Context: User context only. This function may sleep if pagefaults are
 + *          enabled.
   *
   * This macro copies a single simple value from kernel space to user
   * space.  It supports simple types like char and int, but not larger
   * @from: Source address, in kernel space.
   * @n:    Number of bytes to copy.
   *
 - * Context: User context only.  This function may sleep.
 + * Context: User context only. This function may sleep if pagefaults are
 + *          enabled.
   *
   * Copy data from kernel space to user space.  Caller must check
   * the specified block with access_ok() before calling this function.
@@@ -370,8 -373,7 +377,8 @@@ copy_to_user(void __user *to, const voi
   * @from: Source address, in user space.
   * @n:    Number of bytes to copy.
   *
 - * Context: User context only.  This function may sleep.
 + * Context: User context only. This function may sleep if pagefaults are
 + *          enabled.
   *
   * Copy data from user space to kernel space.  Caller must check
   * the specified block with access_ok() before calling this function.
@@@ -442,8 -444,7 +449,8 @@@ static inline unsigned long __must_chec
   * @from: Source address, in user space.
   * @n:    Number of bytes to copy.
   *
 - * Context: User context only.  This function may sleep.
 + * Context: User context only. This function may sleep if pagefaults are
 + *          enabled.
   *
   * Copy data from user space to user space.  Caller must check
   * the specified blocks with access_ok() before calling this function.
@@@ -471,62 -472,9 +478,9 @@@ copy_in_user(void __user *to, const voi
  #endif
  
  
- /**
-  * strlen_user: - Get the size of a string in user space.
-  * @str: The string to measure.
-  *
-  * Context: User context only.  This function may sleep.
-  *
-  * Get the size of a NUL-terminated string in user space.
-  *
-  * Returns the size of the string INCLUDING the terminating NUL.
-  * On exception, returns 0.
-  *
-  * If there is a limit on the length of a valid string, you may wish to
-  * consider using strnlen_user() instead.
-  */
- extern long strnlen_user_asm(const char __user *str, long n);
- static inline long __must_check strnlen_user(const char __user *str, long n)
- {
-       might_fault();
-       return strnlen_user_asm(str, n);
- }
- #define strlen_user(str) strnlen_user(str, LONG_MAX)
- /**
-  * strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
-  * @dst:   Destination address, in kernel space.  This buffer must be at
-  *         least @count bytes long.
-  * @src:   Source address, in user space.
-  * @count: Maximum number of bytes to copy, including the trailing NUL.
-  *
-  * Copies a NUL-terminated string from userspace to kernel space.
-  * Caller must check the specified block with access_ok() before calling
-  * this function.
-  *
-  * On success, returns the length of the string (not including the trailing
-  * NUL).
-  *
-  * If access to userspace fails, returns -EFAULT (some data may have been
-  * copied).
-  *
-  * If @count is smaller than the length of the string, copies @count bytes
-  * and returns @count.
-  */
- extern long strncpy_from_user_asm(char *dst, const char __user *src, long);
- static inline long __must_check __strncpy_from_user(
-       char *dst, const char __user *src, long count)
- {
-       might_fault();
-       return strncpy_from_user_asm(dst, src, count);
- }
- static inline long __must_check strncpy_from_user(
-       char *dst, const char __user *src, long count)
- {
-       if (access_ok(VERIFY_READ, src, 1))
-               return __strncpy_from_user(dst, src, count);
-       return -EFAULT;
- }
+ extern long strnlen_user(const char __user *str, long n);
+ extern long strlen_user(const char __user *str);
+ extern long strncpy_from_user(char *dst, const char __user *src, long);
  
  /**
   * clear_user: - Zero a block of memory in user space.
diff --combined arch/tile/kernel/setup.c
@@@ -71,7 -71,7 +71,7 @@@ static unsigned long __initdata node_pe
   * per-CPU stack and boot info.
   */
  DEFINE_PER_CPU(unsigned long, boot_sp) =
-       (unsigned long)init_stack + THREAD_SIZE;
+       (unsigned long)init_stack + THREAD_SIZE - STACK_TOP_DELTA;
  
  #ifdef CONFIG_SMP
  DEFINE_PER_CPU(unsigned long, boot_pc) = (unsigned long)start_kernel;
@@@ -774,7 -774,7 +774,7 @@@ static void __init zone_sizes_init(void
                 * though, there'll be no lowmem, so we just alloc_bootmem
                 * the memmap.  There will be no percpu memory either.
                 */
 -              if (i != 0 && cpumask_test_cpu(i, &isolnodes)) {
 +              if (i != 0 && node_isset(i, isolnodes)) {
                        node_memmap_pfn[i] =
                                alloc_bootmem_pfn(0, memmap_size, 0);
                        BUG_ON(node_percpu[i] != 0);
diff --combined arch/tile/mm/fault.c
@@@ -354,9 -354,9 +354,9 @@@ static int handle_page_fault(struct pt_
  
        /*
         * If we're in an interrupt, have no user context or are running in an
 -       * atomic region then we must not take the fault.
 +       * region with pagefaults disabled then we must not take the fault.
         */
 -      if (in_atomic() || !mm) {
 +      if (pagefault_disabled() || !mm) {
                vma = NULL;  /* happy compiler */
                goto bad_area_nosemaphore;
        }
@@@ -699,11 -699,10 +699,10 @@@ struct intvec_state do_page_fault_ics(s
   * interrupt away appropriately and return immediately.  We can't do
   * page faults for user code while in kernel mode.
   */
void do_page_fault(struct pt_regs *regs, int fault_num,
-                  unsigned long address, unsigned long write)
static inline void __do_page_fault(struct pt_regs *regs, int fault_num,
+                                  unsigned long address, unsigned long write)
  {
        int is_page_fault;
-       enum ctx_state prev_state = exception_enter();
  
  #ifdef CONFIG_KPROBES
        /*
         */
        if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1,
                       regs->faultnum, SIGSEGV) == NOTIFY_STOP)
-               goto done;
+               return;
  #endif
  
  #ifdef __tilegx__
                        async->is_fault = is_page_fault;
                        async->is_write = write;
                        async->address = address;
-                       goto done;
+                       return;
                }
        }
  #endif
  
        handle_page_fault(regs, fault_num, is_page_fault, address, write);
+ }
  
- done:
+ void do_page_fault(struct pt_regs *regs, int fault_num,
+                  unsigned long address, unsigned long write)
+ {
+       enum ctx_state prev_state = exception_enter();
+       __do_page_fault(regs, fault_num, address, write);
        exception_exit(prev_state);
  }
  
  #if CHIP_HAS_TILE_DMA()
  /*
   * This routine effectively re-issues asynchronous page faults