Merge branch 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jul 2017 19:17:25 +0000 (12:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jul 2017 19:17:25 +0000 (12:17 -0700)
Pull ARM updates from Russell King:

 - add support for ftrace-with-registers, which is needed for kgraft and
   other ftrace tools

 - support for mremap() for the sigpage/vDSO so that checkpoint/restore
   can work

 - add timestamps to each line of the register dump output

 - remove the unused KTHREAD_SIZE from nommu

 - align the ARM bitops APIs with the generic API (using unsigned long
   pointers rather than void pointers)

 - make the configuration of userspace Thumb support an expert option so
   that we can default it on, and avoid some hard to debug userspace
   crashes

* 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm:
  ARM: 8684/1: NOMMU: Remove unused KTHREAD_SIZE definition
  ARM: 8683/1: ARM32: Support mremap() for sigpage/vDSO
  ARM: 8679/1: bitops: Align prototypes to generic API
  ARM: 8678/1: ftrace: Adds support for CONFIG_DYNAMIC_FTRACE_WITH_REGS
  ARM: make configuration of userspace Thumb support an expert option
  ARM: 8673/1: Fix __show_regs output timestamps

arch/arm/Kconfig
arch/arm/include/asm/bitops.h
arch/arm/include/asm/ftrace.h
arch/arm/include/asm/page-nommu.h
arch/arm/kernel/entry-ftrace.S
arch/arm/kernel/ftrace.c
arch/arm/kernel/process.c
arch/arm/kernel/vdso.c
arch/arm/mm/Kconfig
arch/x86/entry/vdso/vma.c
mm/mmap.c

index 0b731e8ab17eef4daa15c017df98ed4194cbe9bd..a208bfe367b55574e2ca4a901de8b3a2862aee2e 100644 (file)
@@ -58,6 +58,7 @@ config ARM
        select HAVE_DMA_API_DEBUG
        select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
+       select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
        select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
        select HAVE_EXIT_THREAD
        select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
index e943e6cee254503cb642bf95caa573eca03de758..f308c8c40cb930c86b889e52c91cdaeecbc55224 100644 (file)
@@ -159,16 +159,16 @@ extern int _test_and_change_bit(int nr, volatile unsigned long * p);
 /*
  * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
  */
-extern int _find_first_zero_bit_le(const void * p, unsigned size);
-extern int _find_next_zero_bit_le(const void * p, int size, int offset);
+extern int _find_first_zero_bit_le(const unsigned long *p, unsigned size);
+extern int _find_next_zero_bit_le(const unsigned long *p, int size, int offset);
 extern int _find_first_bit_le(const unsigned long *p, unsigned size);
 extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
 
 /*
  * Big endian assembly bitops.  nr = 0 -> byte 3 bit 0.
  */
-extern int _find_first_zero_bit_be(const void * p, unsigned size);
-extern int _find_next_zero_bit_be(const void * p, int size, int offset);
+extern int _find_first_zero_bit_be(const unsigned long *p, unsigned size);
+extern int _find_next_zero_bit_be(const unsigned long *p, int size, int offset);
 extern int _find_first_bit_be(const unsigned long *p, unsigned size);
 extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
 
index 22b73112b75f2070e440068184f9655cff781afe..f379881d5cc3feba90ebda6a873fb4fb950a1cdf 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _ASM_ARM_FTRACE
 #define _ASM_ARM_FTRACE
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
+
 #ifdef CONFIG_FUNCTION_TRACER
 #define MCOUNT_ADDR            ((unsigned long)(__gnu_mcount_nc))
 #define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */
index 503f488053de6b362fd39e8dff79109fce9b1d5b..8f2c47bec375c96e4182b5647f5295ee0af71726 100644 (file)
 #ifndef _ASMARM_PAGE_NOMMU_H
 #define _ASMARM_PAGE_NOMMU_H
 
-#if !defined(CONFIG_SMALL_TASKS) && PAGE_SHIFT < 13
-#define KTHREAD_SIZE (8192)
-#else
-#define KTHREAD_SIZE PAGE_SIZE
-#endif
 #define clear_page(page)       memset((page), 0, PAGE_SIZE)
 #define copy_page(to,from)     memcpy((to), (from), PAGE_SIZE)
 
index c73c4030ca5dd549e3b102d4a77f493e1549e02d..efcd9f25a14bfbc13eeea1108a7d47f73d168604 100644 (file)
 2:     mcount_exit
 .endm
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+
+.macro __ftrace_regs_caller
+
+       sub     sp, sp, #8      @ space for PC and CPSR OLD_R0,
+                               @ OLD_R0 will overwrite previous LR
+
+       add     ip, sp, #12     @ move in IP the value of SP as it was
+                               @ before the push {lr} of the mcount mechanism
+
+       str     lr, [sp, #0]    @ store LR instead of PC
+
+       ldr     lr, [sp, #8]    @ get previous LR
+
+       str     r0, [sp, #8]    @ write r0 as OLD_R0 over previous LR
+
+       stmdb   sp!, {ip, lr}
+       stmdb   sp!, {r0-r11, lr}
+
+       @ stack content at this point:
+       @ 0  4          48   52       56            60   64    68       72
+       @ R0 | R1 | ... | LR | SP + 4 | previous LR | LR | PSR | OLD_R0 |
+
+       mov r3, sp                              @ struct pt_regs*
+
+       ldr r2, =function_trace_op
+       ldr r2, [r2]                            @ pointer to the current
+                                               @ function tracing op
+
+       ldr     r1, [sp, #S_LR]                 @ lr of instrumented func
+
+       ldr     lr, [sp, #S_PC]                 @ get LR
+
+       mcount_adjust_addr      r0, lr          @ instrumented function
+
+       .globl ftrace_regs_call
+ftrace_regs_call:
+       bl      ftrace_stub
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       .globl ftrace_graph_regs_call
+ftrace_graph_regs_call:
+       mov     r0, r0
+#endif
+
+       @ pop saved regs
+       ldmia   sp!, {r0-r12}                   @ restore r0 through r12
+       ldr     ip, [sp, #8]                    @ restore PC
+       ldr     lr, [sp, #4]                    @ restore LR
+       ldr     sp, [sp, #0]                    @ restore SP
+       mov     pc, ip                          @ return
+.endm
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+.macro __ftrace_graph_regs_caller
+
+       sub     r0, fp, #4              @ lr of instrumented routine (parent)
+
+       @ called from __ftrace_regs_caller
+       ldr     r1, [sp, #S_PC]         @ instrumented routine (func)
+       mcount_adjust_addr      r1, r1
+
+       mov     r2, fp                  @ frame pointer
+       bl      prepare_ftrace_return
+
+       @ pop registers saved in ftrace_regs_caller
+       ldmia   sp!, {r0-r12}                   @ restore r0 through r12
+       ldr     ip, [sp, #8]                    @ restore PC
+       ldr     lr, [sp, #4]                    @ restore LR
+       ldr     sp, [sp, #0]                    @ restore SP
+       mov     pc, ip                          @ return
+
+.endm
+#endif
+#endif
+
 .macro __ftrace_caller suffix
        mcount_enter
 
        mcount_get_lr   r1                      @ lr of instrumented func
        mcount_adjust_addr      r0, lr          @ instrumented function
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+       ldr r2, =function_trace_op
+       ldr r2, [r2]                            @ pointer to the current
+                                               @ function tracing op
+       mov r3, #0                              @ regs is NULL
+#endif
+
        .globl ftrace_call\suffix
 ftrace_call\suffix:
        bl      ftrace_stub
@@ -212,6 +295,15 @@ UNWIND(.fnstart)
        __ftrace_caller
 UNWIND(.fnend)
 ENDPROC(ftrace_caller)
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+ENTRY(ftrace_regs_caller)
+UNWIND(.fnstart)
+       __ftrace_regs_caller
+UNWIND(.fnend)
+ENDPROC(ftrace_regs_caller)
+#endif
+
 #endif
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -220,6 +312,14 @@ UNWIND(.fnstart)
        __ftrace_graph_caller
 UNWIND(.fnend)
 ENDPROC(ftrace_graph_caller)
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+ENTRY(ftrace_graph_regs_caller)
+UNWIND(.fnstart)
+       __ftrace_graph_regs_caller
+UNWIND(.fnend)
+ENDPROC(ftrace_graph_regs_caller)
+#endif
 #endif
 
 .purgem mcount_enter
index 833c991075a18decd0fc64f06d1b188bb5c19f37..5617932a83dfaab416a05e429642b2d19b0a4438 100644 (file)
@@ -141,6 +141,15 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
 
        ret = ftrace_modify_code(pc, 0, new, false);
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+       if (!ret) {
+               pc = (unsigned long)&ftrace_regs_call;
+               new = ftrace_call_replace(pc, (unsigned long)func);
+
+               ret = ftrace_modify_code(pc, 0, new, false);
+       }
+#endif
+
 #ifdef CONFIG_OLD_MCOUNT
        if (!ret) {
                pc = (unsigned long)&ftrace_call_old;
@@ -159,11 +168,29 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
        unsigned long ip = rec->ip;
 
        old = ftrace_nop_replace(rec);
+
+       new = ftrace_call_replace(ip, adjust_address(rec, addr));
+
+       return ftrace_modify_code(rec->ip, old, new, true);
+}
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+                               unsigned long addr)
+{
+       unsigned long new, old;
+       unsigned long ip = rec->ip;
+
+       old = ftrace_call_replace(ip, adjust_address(rec, old_addr));
+
        new = ftrace_call_replace(ip, adjust_address(rec, addr));
 
        return ftrace_modify_code(rec->ip, old, new, true);
 }
 
+#endif
+
 int ftrace_make_nop(struct module *mod,
                    struct dyn_ftrace *rec, unsigned long addr)
 {
@@ -231,6 +258,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 extern unsigned long ftrace_graph_call;
 extern unsigned long ftrace_graph_call_old;
 extern void ftrace_graph_caller_old(void);
+extern unsigned long ftrace_graph_regs_call;
+extern void ftrace_graph_regs_caller(void);
 
 static int __ftrace_modify_caller(unsigned long *callsite,
                                  void (*func) (void), bool enable)
@@ -253,6 +282,14 @@ static int ftrace_modify_graph_caller(bool enable)
                                     ftrace_graph_caller,
                                     enable);
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+       if (!ret)
+               ret = __ftrace_modify_caller(&ftrace_graph_regs_call,
+                                    ftrace_graph_regs_caller,
+                                    enable);
+#endif
+
+
 #ifdef CONFIG_OLD_MCOUNT
        if (!ret)
                ret = __ftrace_modify_caller(&ftrace_graph_call_old,
index 939e8b58c59d1e16f7dbab4b803eb76455e71ee4..d96714e1858c466ff8e055d84df9828349469d80 100644 (file)
@@ -123,10 +123,10 @@ void __show_regs(struct pt_regs *regs)
 
        print_symbol("PC is at %s\n", instruction_pointer(regs));
        print_symbol("LR is at %s\n", regs->ARM_lr);
-       printk("pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
-              "sp : %08lx  ip : %08lx  fp : %08lx\n",
-               regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
-               regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+       printk("pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n",
+              regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr);
+       printk("sp : %08lx  ip : %08lx  fp : %08lx\n",
+              regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
        printk("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
                regs->ARM_r10, regs->ARM_r9,
                regs->ARM_r8);
@@ -404,9 +404,17 @@ static unsigned long sigpage_addr(const struct mm_struct *mm,
 static struct page *signal_page;
 extern struct page *get_signal_page(void);
 
+static int sigpage_mremap(const struct vm_special_mapping *sm,
+               struct vm_area_struct *new_vma)
+{
+       current->mm->context.sigpage = new_vma->vm_start;
+       return 0;
+}
+
 static const struct vm_special_mapping sigpage_mapping = {
        .name = "[sigpage]",
        .pages = &signal_page,
+       .mremap = sigpage_mremap,
 };
 
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
index 53cf86cf2d1af943831a7f7b1980c7a30c4889b8..a4d6dc0f24273e15d18b53b23dbf1481f6b7cfc7 100644 (file)
@@ -54,8 +54,26 @@ static const struct vm_special_mapping vdso_data_mapping = {
        .pages = &vdso_data_page,
 };
 
+static int vdso_mremap(const struct vm_special_mapping *sm,
+               struct vm_area_struct *new_vma)
+{
+       unsigned long new_size = new_vma->vm_end - new_vma->vm_start;
+       unsigned long vdso_size;
+
+       /* without VVAR page */
+       vdso_size = (vdso_total_pages - 1) << PAGE_SHIFT;
+
+       if (vdso_size != new_size)
+               return -EINVAL;
+
+       current->mm->context.vdso = new_vma->vm_start;
+
+       return 0;
+}
+
 static struct vm_special_mapping vdso_text_mapping __ro_after_init = {
        .name = "[vdso]",
+       .mremap = vdso_mremap,
 };
 
 struct elfinfo {
index 877a0e3fd17d30796b8ec353c434ea42983037c0..60cdfdc151aa3fb934e8b465fac261b92c46a3c9 100644 (file)
@@ -679,7 +679,7 @@ config ARCH_DMA_ADDR_T_64BIT
        bool
 
 config ARM_THUMB
-       bool "Support Thumb user binaries" if !CPU_THUMBONLY
+       bool "Support Thumb user binaries" if !CPU_THUMBONLY && EXPERT
        depends on CPU_THUMB_CAPABLE
        default y
        help
@@ -690,6 +690,10 @@ config ARM_THUMB
          instruction set resulting in smaller binaries at the expense of
          slightly less efficient code.
 
+         If this option is disabled, and you run userspace that switches to
+         Thumb mode, signal handling will not work correctly, resulting in
+         segmentation faults or illegal instruction aborts.
+
          If you don't know what this all is, saying Y is a safe choice.
 
 config ARM_THUMBEE
index 139ad7726e10d58d739f21c16717e9553da3b2a2..726355ce8497bf5c9c90828862a3afa1bc5c34b6 100644 (file)
@@ -78,9 +78,6 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
        if (image->size != new_size)
                return -EINVAL;
 
-       if (WARN_ON_ONCE(current->mm != new_vma->vm_mm))
-               return -EFAULT;
-
        vdso_fix_landing(image, new_vma);
        current->mm->context.vdso = (void __user *)new_vma->vm_start;
 
index 5a0ba9788cdda01fa759a85e1461f2f2aeeb642f..7f8cfe9d9b4d06000632f1779051daa0361cd4b4 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -3186,8 +3186,12 @@ static int special_mapping_mremap(struct vm_area_struct *new_vma)
 {
        struct vm_special_mapping *sm = new_vma->vm_private_data;
 
+       if (WARN_ON_ONCE(current->mm != new_vma->vm_mm))
+               return -EFAULT;
+
        if (sm->mremap)
                return sm->mremap(sm, new_vma);
+
        return 0;
 }