diff --git a/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S b/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S index 571f422a74..9c4b7ebe62 100644 --- a/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S +++ b/components/lwp/arch/aarch64/cortex-a/lwp_gcc.S @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,7 @@ arch_get_user_sp: .global arch_clone_exit arch_fork_exit: arch_clone_exit: + mov x0, xzr b arch_syscall_exit /* @@ -131,12 +133,31 @@ START_POINT(SVC_Handler) /* x0 is initial sp */ mov sp, x0 + bl _SVC_Handler + + /* jump explictly, make this code position independant */ + b arch_syscall_exit +START_POINT_END(SVC_Handler) + +TRACE_SYMBOL(_SVC_Handler) +#define FRAME_REG x19 + +/** + * x0 -> frame_addr + */ +_SVC_Handler: + .local _SVC_Handler + + stp fp, lr, [sp, -16]! + mov fp, sp + + mov FRAME_REG, x0 /* save the value of frame address */ msr daifclr, #3 /* enable interrupt */ GET_THREAD_SELF x0 bl lwp_user_setting_save - ldp x8, x9, [sp, #(CONTEXT_OFFSET_X8)] + ldp x8, x9, [FRAME_REG, #(CONTEXT_OFFSET_X8)] and x0, x8, #0xf000 cmp x0, #0xe000 beq arch_signal_quit @@ -149,78 +170,46 @@ START_POINT(SVC_Handler) cmp x0, xzr mov x30, x0 beq arch_syscall_exit - ldp x0, x1, [sp, #(CONTEXT_OFFSET_X0)] - ldp x2, x3, [sp, #(CONTEXT_OFFSET_X2)] - ldp x4, x5, [sp, #(CONTEXT_OFFSET_X4)] - ldp x6, x7, [sp, #(CONTEXT_OFFSET_X6)] + ldp x0, x1, [FRAME_REG, #(CONTEXT_OFFSET_X0)] + ldp x2, x3, [FRAME_REG, #(CONTEXT_OFFSET_X2)] + ldp x4, x5, [FRAME_REG, #(CONTEXT_OFFSET_X4)] + ldp x6, x7, [FRAME_REG, #(CONTEXT_OFFSET_X6)] blr x30 - /* jump explictly, make this code position independant */ - b arch_syscall_exit -START_POINT_END(SVC_Handler) -.global arch_syscall_exit + ldp fp, lr, [sp], 16 + ret + +/** + * void arch_syscall_exit(long rc) + */ arch_syscall_exit: + .global arch_syscall_exit /** - * @brief back up former x0 which is required to restart syscall, then setup + * backup former x0 which is required to restart syscall, then setup * syscall return value in stack frame */ mov x1, sp bl arch_syscall_prepare_signal + /** + * disable local irq so we don't messup with the spsr_el1 witch is not saved + * for kernel space IRQ/EXCEPTION + */ msr daifset, #3 - ldp x2, x3, [sp], #0x10 /* SPSR and ELR. */ - msr spsr_el1, x3 - msr elr_el1, x2 - - ldp x29, x30, [sp], #0x10 - msr sp_el0, x29 - ldp x28, x29, [sp], #0x10 - msr fpcr, x28 - msr fpsr, x29 - ldp x28, x29, [sp], #0x10 - ldp x26, x27, [sp], #0x10 - ldp x24, x25, [sp], #0x10 - ldp x22, x23, [sp], #0x10 - ldp x20, x21, [sp], #0x10 - ldp x18, x19, [sp], #0x10 - ldp x16, x17, [sp], #0x10 - ldp x14, x15, [sp], #0x10 - ldp x12, x13, [sp], #0x10 - ldp x10, x11, [sp], #0x10 - ldp x8, x9, [sp], #0x10 - ldp x6, x7, [sp], #0x10 - ldp x4, x5, [sp], #0x10 - ldp x2, x3, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - RESTORE_FPU sp + b arch_ret_to_user /* the sp is reset to the outer most level, irq and fiq are disabled */ START_POINT(arch_ret_to_user) msr daifset, #3 - /* save exception frame */ - SAVE_FPU sp - stp x0, x1, [sp, #-0x10]! - stp x2, x3, [sp, #-0x10]! - stp x4, x5, [sp, #-0x10]! - stp x6, x7, [sp, #-0x10]! - stp x8, x9, [sp, #-0x10]! - stp x10, x11, [sp, #-0x10]! - stp x12, x13, [sp, #-0x10]! - stp x14, x15, [sp, #-0x10]! - stp x16, x17, [sp, #-0x10]! - stp x18, x19, [sp, #-0x10]! - stp x20, x21, [sp, #-0x10]! - stp x22, x23, [sp, #-0x10]! - stp x24, x25, [sp, #-0x10]! - stp x26, x27, [sp, #-0x10]! - stp x28, x29, [sp, #-0x10]! - mrs x0, fpcr - mrs x1, fpsr - stp x0, x1, [sp, #-0x10]! - stp x29, x30, [sp, #-0x10]! + ldr x2, [sp, #CONTEXT_OFFSET_SP_EL0] + msr sp_el0, x2 + ldr x2, [sp, #CONTEXT_OFFSET_ELR_EL1] + msr elr_el1, x2 + ldr x3, [sp, #CONTEXT_OFFSET_SPSR_EL1] + msr spsr_el1, x3 /* pre-action */ bl lwp_check_debug @@ -231,7 +220,8 @@ START_POINT(arch_ret_to_user) msr daifclr, #3 mov x0, xzr b sys_exit -1: + +1: /* handling dbg */ /* check if dbg ops exist */ ldr x0, =rt_dbg_ops ldr x0, [x0] @@ -243,104 +233,42 @@ START_POINT(arch_ret_to_user) orr x2, x2, x1 msr spsr_el1, x2 b 3f -2: +2: /* clear software step */ bic x2, x2, x1 msr spsr_el1, x2 -3: +3: /* handling signal */ /** - * push 2 dummy words to simulate a exception frame of interrupt - * Note: in kernel state, the context switch dont saved the context + * push updated spsr & elr to exception frame. + * Note: these 2 maybe updated after handling dbg */ mrs x0, spsr_el1 + str x0, [sp, #CONTEXT_OFFSET_SPSR_EL1] mrs x1, elr_el1 - stp x1, x0, [sp, #-0x10]! + str x1, [sp, #CONTEXT_OFFSET_ELR_EL1] mov x0, sp + + /* restore the thread execution environment */ msr daifclr, #3 bl lwp_thread_signal_catch + + /* restore the exception-return exec-flow */ msr daifset, #3 - ldp x1, x0, [sp], #0x10 - msr spsr_el1, x0 - msr elr_el1, x1 /* check debug */ - /* restore exception frame */ - ldp x29, x30, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - msr fpcr, x0 - msr fpsr, x1 - ldp x28, x29, [sp], #0x10 - ldp x26, x27, [sp], #0x10 - ldp x24, x25, [sp], #0x10 - ldp x22, x23, [sp], #0x10 - ldp x20, x21, [sp], #0x10 - ldp x18, x19, [sp], #0x10 - ldp x16, x17, [sp], #0x10 - ldp x14, x15, [sp], #0x10 - ldp x12, x13, [sp], #0x10 - ldp x10, x11, [sp], #0x10 - ldp x8, x9, [sp], #0x10 - ldp x6, x7, [sp], #0x10 - ldp x4, x5, [sp], #0x10 - ldp x2, x3, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - RESTORE_FPU sp - - stp x0, x1, [sp, #-0x10]! ldr x0, =rt_dbg_ops ldr x0, [x0] cmp x0, xzr - ldp x0, x1, [sp], #0x10 + beq 1f - /* save */ - SAVE_FPU sp - stp x0, x1, [sp, #-0x10]! - stp x2, x3, [sp, #-0x10]! - stp x4, x5, [sp, #-0x10]! - stp x6, x7, [sp, #-0x10]! - stp x8, x9, [sp, #-0x10]! - stp x10, x11, [sp, #-0x10]! - stp x12, x13, [sp, #-0x10]! - stp x14, x15, [sp, #-0x10]! - stp x16, x17, [sp, #-0x10]! - stp x18, x19, [sp, #-0x10]! - stp x20, x21, [sp, #-0x10]! - stp x22, x23, [sp, #-0x10]! - stp x24, x25, [sp, #-0x10]! - stp x26, x27, [sp, #-0x10]! - stp x28, x29, [sp, #-0x10]! - mrs x0, fpcr - mrs x1, fpsr - stp x0, x1, [sp, #-0x10]! - stp x29, x30, [sp, #-0x10]! - - mrs x0, elr_el1 + ldr x0, [sp, #CONTEXT_OFFSET_ELR_EL1] bl dbg_attach_req - /* restore */ - ldp x29, x30, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - msr fpcr, x0 - msr fpsr, x1 - ldp x28, x29, [sp], #0x10 - ldp x26, x27, [sp], #0x10 - ldp x24, x25, [sp], #0x10 - ldp x22, x23, [sp], #0x10 - ldp x20, x21, [sp], #0x10 - ldp x18, x19, [sp], #0x10 - ldp x16, x17, [sp], #0x10 - ldp x14, x15, [sp], #0x10 - ldp x12, x13, [sp], #0x10 - ldp x10, x11, [sp], #0x10 - ldp x8, x9, [sp], #0x10 - ldp x6, x7, [sp], #0x10 - ldp x4, x5, [sp], #0x10 - ldp x2, x3, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - RESTORE_FPU sp 1: + RESTORE_IRQ_CONTEXT_NO_SPEL0 + eret START_POINT_END(arch_ret_to_user) @@ -410,32 +338,7 @@ arch_syscall_restart: /* restore previous exception frame */ msr spsel, #0 - ldp x2, x3, [sp], #0x10 - msr elr_el1, x2 - msr spsr_el1, x3 - - ldp x29, x30, [sp], #0x10 - - ldp x28, x29, [sp], #0x10 - msr fpcr, x28 - msr fpsr, x29 - - ldp x28, x29, [sp], #0x10 - ldp x26, x27, [sp], #0x10 - ldp x24, x25, [sp], #0x10 - ldp x22, x23, [sp], #0x10 - ldp x20, x21, [sp], #0x10 - ldp x18, x19, [sp], #0x10 - ldp x16, x17, [sp], #0x10 - ldp x14, x15, [sp], #0x10 - ldp x12, x13, [sp], #0x10 - ldp x10, x11, [sp], #0x10 - ldp x8, x9, [sp], #0x10 - ldp x6, x7, [sp], #0x10 - ldp x4, x5, [sp], #0x10 - ldp x2, x3, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - RESTORE_FPU sp + RESTORE_IRQ_CONTEXT_NO_SPEL0 msr spsel, #1 @@ -443,8 +346,8 @@ arch_syscall_restart: arch_signal_quit: - /* drop current exception frame */ - add sp, sp, #CONTEXT_SIZE + /* drop current exception frame & sigreturn */ + add sp, sp, #(CONTEXT_SIZE + 0x10) mov x1, sp mrs x0, sp_el0 bl arch_signal_ucontext_restore @@ -460,35 +363,12 @@ arch_signal_quit: /* restore previous exception frame */ msr spsel, #0 - ldp x2, x3, [sp], #0x10 - msr elr_el1, x2 - msr spsr_el1, x3 - - ldp x29, x30, [sp], #0x10 - - ldp x28, x29, [sp], #0x10 - msr fpcr, x28 - msr fpsr, x29 - - ldp x28, x29, [sp], #0x10 - ldp x26, x27, [sp], #0x10 - ldp x24, x25, [sp], #0x10 - ldp x22, x23, [sp], #0x10 - ldp x20, x21, [sp], #0x10 - ldp x18, x19, [sp], #0x10 - ldp x16, x17, [sp], #0x10 - ldp x14, x15, [sp], #0x10 - ldp x12, x13, [sp], #0x10 - ldp x10, x11, [sp], #0x10 - ldp x8, x9, [sp], #0x10 - ldp x6, x7, [sp], #0x10 - ldp x4, x5, [sp], #0x10 - ldp x2, x3, [sp], #0x10 - ldp x0, x1, [sp], #0x10 - RESTORE_FPU sp + RESTORE_IRQ_CONTEXT_NO_SPEL0 msr spsel, #1 + SAVE_IRQ_CONTEXT + b arch_ret_to_user /** diff --git a/libcpu/aarch64/common/include/vector_gcc.h b/libcpu/aarch64/common/include/vector_gcc.h index 31c532316e..63df0c59e3 100644 --- a/libcpu/aarch64/common/include/vector_gcc.h +++ b/libcpu/aarch64/common/include/vector_gcc.h @@ -54,6 +54,52 @@ #include "../up/context_gcc.h" #endif +.macro RESTORE_IRQ_CONTEXT_NO_SPEL0 + ldp x2, x3, [sp], #0x10 + msr elr_el1, x2 + msr spsr_el1, x3 + + ldp x29, x30, [sp], #0x10 + + ldp x28, x29, [sp], #0x10 + msr fpcr, x28 + msr fpsr, x29 + + ldp x28, x29, [sp], #0x10 + ldp x26, x27, [sp], #0x10 + ldp x24, x25, [sp], #0x10 + ldp x22, x23, [sp], #0x10 + ldp x20, x21, [sp], #0x10 + ldp x18, x19, [sp], #0x10 + ldp x16, x17, [sp], #0x10 + ldp x14, x15, [sp], #0x10 + ldp x12, x13, [sp], #0x10 + ldp x10, x11, [sp], #0x10 + ldp x8, x9, [sp], #0x10 + ldp x6, x7, [sp], #0x10 + ldp x4, x5, [sp], #0x10 + ldp x2, x3, [sp], #0x10 + ldp x0, x1, [sp], #0x10 + + RESTORE_FPU sp +.endm + +.macro EXCEPTION_SWITCH, eframex, tmpx +#ifdef RT_USING_SMART + /** + * test the spsr for execution level 0 + * That is { PSTATE.[NZCV] := SPSR_EL1 & M.EL0t } + */ + ldr \tmpx, [\eframex, #CONTEXT_OFFSET_SPSR_EL1] + and \tmpx, \tmpx, 0x1f + cbz \tmpx, 1f + b 2f +1: + b arch_ret_to_user +2: +#endif /* RT_USING_SMART */ +.endm + .macro SAVE_USER_CTX, eframex, tmpx #ifdef RT_USING_SMART mrs \tmpx, spsr_el1 diff --git a/libcpu/aarch64/common/up/context_gcc.h b/libcpu/aarch64/common/up/context_gcc.h index cb48e5f244..d2f6e9a755 100644 --- a/libcpu/aarch64/common/up/context_gcc.h +++ b/libcpu/aarch64/common/up/context_gcc.h @@ -19,17 +19,23 @@ #include #include -.macro RESTORE_CONTEXT_SWITCH using_sp - /* Set the SP to point to the stack of the task being restored. */ - mov sp, \using_sp - +/* restore address space */ +.macro RESTORE_ADDRESS_SPACE #ifdef RT_USING_SMART bl rt_thread_self mov x19, x0 bl lwp_aspace_switch mov x0, x19 bl lwp_user_setting_restore -#endif /* RT_USING_SMART */ +#endif +.endm + +.macro RESTORE_CONTEXT_SWITCH using_sp + /* Set the SP to point to the stack of the task being restored. */ + mov sp, \using_sp + + RESTORE_ADDRESS_SPACE + _RESTORE_CONTEXT_SWITCH .endm diff --git a/libcpu/aarch64/common/up/vector_gcc.S b/libcpu/aarch64/common/up/vector_gcc.S index 26428fa597..8b51a48282 100644 --- a/libcpu/aarch64/common/up/vector_gcc.S +++ b/libcpu/aarch64/common/up/vector_gcc.S @@ -28,7 +28,8 @@ vector_fiq: SAVE_IRQ_CONTEXT bl rt_hw_trap_fiq - RESTORE_IRQ_CONTEXT + + b rt_hw_irq_exit .globl rt_thread_switch_interrupt_flag .globl rt_hw_context_switch_interrupt_do diff --git a/libcpu/aarch64/common/vector_gcc.S b/libcpu/aarch64/common/vector_gcc.S index aaa172fcf9..d4c6223bcf 100644 --- a/libcpu/aarch64/common/vector_gcc.S +++ b/libcpu/aarch64/common/vector_gcc.S @@ -79,7 +79,11 @@ START_POINT(vector_exception) bl rt_hw_trap_exception RESTORE_USER_CTX EFRAMEX, x0 + /* do exception switch for IRQ/exception handlers */ + EXCEPTION_SWITCH sp, x0 + RESTORE_IRQ_CONTEXT + eret START_POINT_END(vector_exception) START_POINT(vector_serror) @@ -123,4 +127,8 @@ START_POINT_END(vector_irq) rt_hw_irq_exit: .globl rt_hw_irq_exit + /* do exception switch for IRQ/exception handlers */ + EXCEPTION_SWITCH sp, x0 + RESTORE_IRQ_CONTEXT + eret