mm: fix crash in vmap stack [1/1]
authorTao Zeng <tao.zeng@amlogic.com>
Mon, 28 Oct 2019 09:22:50 +0000 (17:22 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Mon, 4 Nov 2019 06:05:07 +0000 (23:05 -0700)
PD#SWPL-12145

Problem:
When switch IRQ stack, there is a 16 bytes miss match of irq
stack. This may cause context not match some times;

Solution:
Save sp to right place

Verify:
X301

Change-Id: I75dfa5208cb3cec050c1568ac78ae2e783ca106b
Signed-off-by: Tao Zeng <tao.zeng@amlogic.com>
arch/arm/kernel/entry-armv.S
arch/arm/kernel/unwind.c
drivers/amlogic/memory_ext/vmap_stack.c

index 4bd8391..2d0a147 100644 (file)
 #endif
 #ifdef CONFIG_MULTI_IRQ_HANDLER
        ldr     r1, =handle_arch_irq
-#ifdef CONFIG_AMLOGIC_VMAP
-       mov     r0, r8
-#else
        mov     r0, sp
-#endif
        badr    lr, 9997f
        ldr     pc, [r1]
 #else
@@ -416,10 +412,28 @@ ENDPROC(__und_svc)
 
        .align  5
 __pabt_svc:
+#ifdef CONFIG_AMLOGIC_VMAP
+       svc_entry vmap=1        /* keep using abt stack */
+       /* re-build context for normal abort handler */
+       ldr     r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)]
+       sub     r0, #SVC_REGS_SIZE
+       mov     r1, sp
+       mov     r2, #SVC_REGS_SIZE
+#ifdef CONFIG_AMLOGIC_KASAN32
+       bl      __memcpy                /* copy back sp */
+#else
+       bl      memcpy                  /* copy back sp */
+#endif
+       mov     sp, r0
+       mov     r2, sp                          @ regs
+       pabt_helper
+       svc_exit r5                             @ return from exception
+#else
        svc_entry
        mov     r2, sp                          @ regs
        pabt_helper
        svc_exit r5                             @ return from exception
+#endif
  UNWIND(.fnend         )
 ENDPROC(__pabt_svc)
 
index 7ad8026..91a9321 100644 (file)
@@ -541,11 +541,10 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
                                unsigned long sp_irq;
 
                                keep = 1;
-                               sp_irq = (unsigned long)irq_stack[cpu];
-                               addr = *((unsigned long *)(sp_irq +
-                                       THREAD_INFO_OFFSET - 8 -
-                                       sizeof(addr) - 12));
-                               pt_regs = (struct pt_regs *)addr;
+                               sp_irq   = (unsigned long)irq_stack[cpu];
+                               addr     = *((unsigned long *)(sp_irq +
+                                             THREAD_INFO_OFFSET - 8));
+                               pt_regs  = (struct pt_regs *)addr;
                                frame.fp = pt_regs->ARM_fp;
                                frame.sp = pt_regs->ARM_sp;
                                frame.lr = pt_regs->ARM_lr;
index cbceeeb..387fb80 100644 (file)
@@ -165,9 +165,9 @@ unsigned long notrace irq_stack_entry(unsigned long sp)
                sp_irq = (unsigned long)dst - 8;
                /*
                 * save start addr of the interrupted task's context
-                * minus an extra 12 to force base sp 16Bytes aligned
+                * used to back trace stack call from irq
+                * Note: sp_irq must be aligned to 16 bytes
                 */
-               sp_irq = sp_irq - sizeof(sp) - 12;
                *((unsigned long *)sp_irq) = sp;
                return sp_irq;
        }