aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorisiora <none@example.com>2017-07-29 12:44:40 +0000
committerisiora <none@example.com>2017-07-29 12:44:40 +0000
commit0e4213f267a2cdffd3488fc12f6f2e7305cd4c8a (patch)
treeb4b0bdd788a889f2fc6af53e95d1b5cb0544fff3 /os
parent8f2d65dd1f495759cd77094864c7159233078ef5 (diff)
downloadChibiOS-0e4213f267a2cdffd3488fc12f6f2e7305cd4c8a.tar.gz
ChibiOS-0e4213f267a2cdffd3488fc12f6f2e7305cd4c8a.tar.bz2
ChibiOS-0e4213f267a2cdffd3488fc12f6f2e7305cd4c8a.zip
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
Diffstat (limited to 'os')
-rw-r--r--os/common/ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S55
1 files changed, 32 insertions, 23 deletions
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