From b183f51456f22526101fdac36bf3ac8a2e6a130a Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Mon, 28 Oct 2019 17:22:50 +0800 Subject: [PATCH] mm: fix crash in vmap stack [1/1] 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 --- arch/arm/kernel/entry-armv.S | 22 ++++++++++++++++++---- arch/arm/kernel/unwind.c | 9 ++++----- drivers/amlogic/memory_ext/vmap_stack.c | 4 ++-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 4bd8391..2d0a147 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -51,11 +51,7 @@ #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) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 7ad8026..91a9321 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -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; diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index cbceeeb..387fb80 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -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; } -- 2.7.4