From 2fc72ef5f81f3fa4eb0cb908a7138b43b1478ff4 Mon Sep 17 00:00:00 2001 From: isiora Date: Fri, 7 Jul 2017 16:01:52 +0000 Subject: Added monitor code to route IRQ to non-secure world. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10303 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- .../ports/ARMCMAx-TZ/compilers/GCC/chcoreasm.S | 71 +++++++++++++++++----- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/os/common/ports/ARMCMAx-TZ/compilers/GCC/chcoreasm.S b/os/common/ports/ARMCMAx-TZ/compilers/GCC/chcoreasm.S index e3c15866a..41e0238ad 100644 --- a/os/common/ports/ARMCMAx-TZ/compilers/GCC/chcoreasm.S +++ b/os/common/ports/ARMCMAx-TZ/compilers/GCC/chcoreasm.S @@ -111,23 +111,64 @@ _port_switch_arm: */ /* - * We are on an architecures with security extension exploited. - * The following execution path is taken by the execution units running in - * non-secure state when a fiq interrupt is fired. - * It originates by the monitor fiq vector and runs in monitor mode, + * We are facing an architecure with security extension exploited. + * 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 FIQs are taken to monitor mode, IRQ locally - * SCR.FIQ == 0 and SCR.IRQ == 1 and CPSR.I == 1 in secure state, - * ie the secure code takes fiq locally and runs always with IRQ disabled(?) + * SCR.FW == 0 and SCR.FIQ == 0 and SCR.IRQ == 1 in secure state, + * ie the secure code takes fiq locally and the non-secure code takes irq locally + * ie the secure code takes irq to monitor and the non-secure code takes fiq to monitor * MVBAR holds the address of the monitor vectors base. - * The code and the stacks memory reside in secure memory. + * The code and the stacks memory reside both in secure memory. */ .balign 16 .code 32 .global Mon_Fiq_Handler + .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) + // + // This procedure is challenging, because the irq must be + // executed in the context of the NT thread. + // 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. + msr CPSR_c, #MODE_SYS | I_BIT | F_BIT + stmfd sp!, {r0-r3, r12, lr} + msr CPSR_c, #MODE_MON | I_BIT | F_BIT + 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. + + /* bl chSchDoNTReschedule */ + + // Re-establish the original conditions + ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ. + msr CPSR_c, #MODE_MON | I_BIT | F_BIT + msr SPSR_fsxc, r0 + mov lr, r1 + 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 + mrc p15, 0, lr, c1, c1, 0 + ldmfd sp!, {lr} + subs pc, lr, #4 // return into non-secure world + // and serve the IRQ +/* + * + */ Mon_Fiq_Handler: // here the fiq is taken from non-secure state // current mode is monitor (so current state is secure) @@ -135,7 +176,7 @@ Mon_Fiq_Handler: 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 + stmfd sp!, {r0-r3, r12} // IRQ frame, save scratch registers ldr r0, =ARM_IRQ_VECTOR_REG ldr r0, [r0] ldr lr, =_mon_fiq_ret_arm // ISR return point. @@ -187,7 +228,7 @@ _mon_fiq_ret_arm: Fiq_Handler: // the fiq is taken locally from secure state // current mode is fiq - stmfd sp!, {r0-r3, r12, lr} + stmfd sp!, {r0-r3, r12, lr} // save scratch registers and lr ldr r0, =ARM_IRQ_VECTOR_REG ldr r0, [r0] ldr lr, =_fiq_ret_arm // ISR return point. @@ -199,12 +240,12 @@ _fiq_ret_arm: // Now the frame is created in the system stack, the IRQ // stack is empty. - msr CPSR_c, #MODE_SYS | I_BIT + msr CPSR_c, #MODE_SYS | I_BIT | F_BIT stmfd sp!, {r0-r3, r12, lr} - msr CPSR_c, #MODE_FIQ | I_BIT + msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT mrs r0, SPSR mov r1, lr - msr CPSR_c, #MODE_SYS | I_BIT + msr CPSR_c, #MODE_SYS | I_BIT | F_BIT stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ. // Context switch. @@ -218,12 +259,12 @@ _fiq_ret_arm: // Re-establish the IRQ conditions again. ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ. - msr CPSR_c, #MODE_FIQ | I_BIT + msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT msr SPSR_fsxc, r0 mov lr, r1 - msr CPSR_c, #MODE_SYS | I_BIT + msr CPSR_c, #MODE_SYS | I_BIT | F_BIT ldmfd sp!, {r0-r3, r12, lr} - msr CPSR_c, #MODE_FIQ | I_BIT + msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT subs pc, lr, #4 /* -- cgit v1.2.3