From 0e4213f267a2cdffd3488fc12f6f2e7305cd4c8a Mon Sep 17 00:00:00 2001 From: isiora Date: Sat, 29 Jul 2017 12:44:40 +0000 Subject: Added monitor code to switch between secure and non-secure state. Added monitor code to route IRQ to non-secure world. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10345 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- .../ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S | 55 +++++++++++++--------- 1 file changed, 32 insertions(+), 23 deletions(-) (limited to 'os/common') diff --git a/os/common/ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S b/os/common/ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S index 90438ea6d..fe5a58b2e 100644 --- a/os/common/ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S +++ b/os/common/ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S @@ -112,16 +112,16 @@ _port_switch_arm: /* * We are facing an architecure with security extension exploited. - * The following two monitor execution paths are followed by the execution units + * The following two monitor execution paths are taken by the execution units * running in secure state when an irq is fired (Mon_Irq_Handler), and in non-secure * state when a fiq interrupt is fired (Mon_Fiq_Handler). * They originate by the monitor irq/fiq vector and run in monitor mode, * ie in secure state. * It assumes the following, set at boot time, or wherever it needs: * SCR.FW == 0 and SCR.FIQ == 1 and SCR.IRQ == 0 in non-secure state, - * ie, in non-secure state, FIQs are taken to monitor mode and IRQs locally + * ie FIQs are taken to monitor mode, IRQs are taken locally * SCR.FW == 0 and SCR.FIQ == 0 and SCR.IRQ == 1 in secure state, - * ie, in the secure-state, FIQs are taken locally and IRQs to monitor + * ie FIQs are taken locally, IRQs are taken to monitor mode * MVBAR holds the address of the monitor vectors base. * The code and the stacks memory reside both in secure memory. */ @@ -131,17 +131,18 @@ _port_switch_arm: .global Mon_Irq_Handler .global Fiq_Handler Mon_Irq_Handler: - // here the irq is taken from secure state - // current mode is monitor (so current state is secure) + // Here the IRQ is taken from secure state, + // current mode is monitor (so current state is secure), + // the previous mode and status is in mon.spsr and + // the return address+4 is in mon.lr. // // This procedure is challenging, because the irq must be - // executed in the context of the NT thread, it must run - // in non-secure state. - // So we shall switch to a NT thread(?) and return into non-secure - // world where the IRQ will be served. - - // The frame is created in the system stack, - // current state is secure. + // executed in the non secure context and must return in this + // secure context. The non secure IRQ handler has + // the responsibility to return into secure state via a smc. + // + // The thread is interrupted in the same way that local FIQ. + // The frame is created in the system stack of the current thread msr CPSR_c, #MODE_SYS | I_BIT | F_BIT stmfd sp!, {r0-r3, r12, lr} msr CPSR_c, #MODE_MON | I_BIT | F_BIT @@ -161,7 +162,7 @@ Mon_Irq_Handler: ldmfd sp!, {r0-r3, r12, lr} msr CPSR_c, #MODE_MON | I_BIT | F_BIT stmfd sp!, {lr} // save lr into monitor stack - ldr lr, =MON_NS_SCR // set non-secure SCR before return + ldr lr, =MON_NS_SCR // set non-secure SCR before return mrc p15, 0, lr, c1, c1, 0 ldmfd sp!, {lr} subs pc, lr, #4 // return into non-secure world @@ -170,10 +171,12 @@ Mon_Irq_Handler: * */ Mon_Fiq_Handler: - // here the fiq is taken from non-secure state - // current mode is monitor (so current state is secure) + // Here the fiq is taken from non-secure state + // current mode is monitor (so current state is secure). + // Note also that we never leave secure state while sec FIQ was disabled, + // then it's always safe to process the FIQ here. stmfd sp!, {lr} // save lr into monitor stack - ldr lr, =MON_S_SCR // set secure SCR before to switch to FIQ mode + ldr lr, =MON_S_SCR // set secure SCR before to switch to FIQ mode mrc p15, 0, lr, c1, c1, 0 cpsid if, #MODE_FIQ // secure FIQ mode stmfd sp!, {r0-r3, r12} // IRQ frame, save scratch registers @@ -185,20 +188,25 @@ _mon_fiq_ret_arm: cmp r0, #0 ldmfd sp!, {r0-r3, r12} cpsid if, #MODE_MON - ldr lr, =MON_NS_SCR // set non-secure SCR before return + ldr lr, =MON_NS_SCR // set non-secure SCR before return mrceq p15, 0, lr, c1, c1, 0 // only if it will return ldmfd sp!, {lr} subeqs pc, lr, #4 // No reschedule, returns. - // Now the frame is created in the system stack, the IRQ - // and monitor stacks are empty, the state is secure. + // Now the frame is created in the system stack + // relative to non secure context, + // the IRQ and monitor stacks are empty, + // the state is secure. msr CPSR_c, #MODE_SYS | I_BIT | F_BIT stmfd sp!, {r0-r3, r12, lr} + mov r0, sp msr CPSR_c, #MODE_MON | I_BIT | F_BIT + stmfd sp!, {r0} // address of ns_ctx in mon stack mrs r0, SPSR mov r1, lr msr CPSR_c, #MODE_SYS | I_BIT | F_BIT stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ. + mov r0, sp // Context switch. #if CH_DBG_SYSTEM_STATE_CHECK @@ -214,11 +222,12 @@ _mon_fiq_ret_arm: msr CPSR_c, #MODE_MON | I_BIT | F_BIT msr SPSR_fsxc, r0 mov lr, r1 + ldmfd sp!, {r0} // ns_ctx no longer exists, cleanup mon stack msr CPSR_c, #MODE_SYS | I_BIT | F_BIT ldmfd sp!, {r0-r3, r12, lr} msr CPSR_c, #MODE_MON | I_BIT | F_BIT - stmfd sp!, {lr} // save lr into monitor stack - ldr lr, =MON_NS_SCR // set non-secure SCR before return + stmfd sp!, {lr} // save lr into mon stack + ldr lr, =MON_NS_SCR // set non-secure SCR before return mrc p15, 0, lr, c1, c1, 0 ldmfd sp!, {lr} subs pc, lr, #4 // return into non-secure world @@ -238,8 +247,8 @@ _fiq_ret_arm: ldmfd sp!, {r0-r3, r12, lr} subeqs pc, lr, #4 // No reschedule, returns. - // Now the frame is created in the system stack, the IRQ - // stack is empty. + // Now the frame is created in the system stack of the current + // thread, the IRQ stack is empty. msr CPSR_c, #MODE_SYS | I_BIT | F_BIT stmfd sp!, {r0-r3, r12, lr} msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT -- cgit v1.2.3