diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 51c5758fdcea..4bd839164480 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -38,12 +38,16 @@ /* * Interrupt handling. */ - .macro irq_handler #ifdef CONFIG_AMLOGIC_VMAP + .macro irq_handler, vmap=0 + .if \vmap mov r8, sp /* back up sp */ mov r0, sp bl irq_stack_entry /* switch IRQ stack */ mov sp, r0 + .endif +#else + .macro irq_handler #endif #ifdef CONFIG_MULTI_IRQ_HANDLER ldr r1, =handle_arch_irq @@ -59,7 +63,9 @@ #endif 9997: #ifdef CONFIG_AMLOGIC_VMAP + .if \vmap mov sp, r8 /* switch stack back to task stack */ + .endif #endif .endm @@ -226,8 +232,14 @@ ENDPROC(__und_invalid) * get fault task thread info */ ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] +#ifdef CONFIG_AMLOGIC_KASAN32 + /* FAR may be kasan shadow then nobody will handle it */ mrc p15, 0, r1, c6, c0, 0 @ get FAR bl pmd_check +#endif + /* sp may not access able when swith task */ + mov r1, r0 + bl pmd_check mov tsk, r0 mov tsk, tsk, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT mov tsk, tsk, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT @@ -294,7 +306,11 @@ __dabt_svc: 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 #else svc_entry uaccess=0 @@ -309,7 +325,11 @@ ENDPROC(__dabt_svc) .align 5 __irq_svc: svc_entry +#ifdef CONFIG_AMLOGIC_VMAP + irq_handler vmap=1 +#else irq_handler +#endif #ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index dae386a4d855..ccca528caeea 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -179,12 +179,12 @@ unsigned long notrace pmd_check(unsigned long addr, unsigned long far) pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; - if (addr < TASK_SIZE) + if (far < TASK_SIZE) return addr; - index = pgd_index(addr); + index = pgd_index(far); - pgd = cpu_get_pgd() + index; + pgd = cpu_get_pgd() + index; pgd_k = init_mm.pgd + index; if (pgd_none(*pgd_k)) @@ -192,16 +192,16 @@ unsigned long notrace pmd_check(unsigned long addr, unsigned long far) if (!pgd_present(*pgd)) set_pgd(pgd, *pgd_k); - pud = pud_offset(pgd, addr); - pud_k = pud_offset(pgd_k, addr); + pud = pud_offset(pgd, far); + pud_k = pud_offset(pgd_k, far); if (pud_none(*pud_k)) goto bad_area; if (!pud_present(*pud)) set_pud(pud, *pud_k); - pmd = pmd_offset(pud, addr); - pmd_k = pmd_offset(pud_k, addr); + pmd = pmd_offset(pud, far); + pmd_k = pmd_offset(pud_k, far); #ifdef CONFIG_ARM_LPAE /* @@ -217,7 +217,7 @@ unsigned long notrace pmd_check(unsigned long addr, unsigned long far) * pmd_none() check for the entry really corresponded to address, not * for the first of pair. */ - index = (addr >> SECTION_SHIFT) & 1; + index = (far >> SECTION_SHIFT) & 1; #endif if (pmd_none(pmd_k[index])) goto bad_area;