ARM: start_thread(): don't always clear all regs
authorNicolas Pitre <nicolas.pitre@linaro.org>
Fri, 28 Jul 2017 22:48:48 +0000 (18:48 -0400)
committerNicolas Pitre <nicolas.pitre@linaro.org>
Sun, 10 Sep 2017 23:31:46 +0000 (19:31 -0400)
The elf_fdpic binary format driver has to initialize extra registers
beside the stack and program counter as required by the corresponding
ABI. So reinstate them after the regs structure has been cleared.

While at it let's get rid of start_thread_nommu().

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Mickael GUENE <mickael.guene@st.com>
Tested-by: Vincent Abriou <vincent.abriou@st.com>
Tested-by: Andras Szemzo <szemzo.andras@gmail.com>
arch/arm/include/asm/processor.h

index c3d5fc124a054c6309ffacdb2845ff22fd5bfa56..338cbe0a18efe742bfc9ab9c9210036636a2d53b 100644 (file)
@@ -47,15 +47,24 @@ struct thread_struct {
 
 #define INIT_THREAD  { }
 
-#ifdef CONFIG_MMU
-#define nommu_start_thread(regs) do { } while (0)
-#else
-#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
-#endif
-
 #define start_thread(regs,pc,sp)                                       \
 ({                                                                     \
+       unsigned long r7, r8, r9;                                       \
+                                                                       \
+       if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC)) {                      \
+               r7 = regs->ARM_r7;                                      \
+               r8 = regs->ARM_r8;                                      \
+               r9 = regs->ARM_r9;                                      \
+       }                                                               \
        memset(regs->uregs, 0, sizeof(regs->uregs));                    \
+       if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&                      \
+           current->personality & FDPIC_FUNCPTRS) {                    \
+               regs->ARM_r7 = r7;                                      \
+               regs->ARM_r8 = r8;                                      \
+               regs->ARM_r9 = r9;                                      \
+               regs->ARM_r10 = current->mm->start_data;                \
+       } else if (!IS_ENABLED(CONFIG_MMU))                             \
+               regs->ARM_r10 = current->mm->start_data;                \
        if (current->personality & ADDR_LIMIT_32BIT)                    \
                regs->ARM_cpsr = USR_MODE;                              \
        else                                                            \
@@ -65,7 +74,6 @@ struct thread_struct {
        regs->ARM_cpsr |= PSR_ENDSTATE;                                 \
        regs->ARM_pc = pc & ~1;         /* pc */                        \
        regs->ARM_sp = sp;              /* sp */                        \
-       nommu_start_thread(regs);                                       \
 })
 
 /* Forward declaration, a strange C thing */