git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11378 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
282bc3a8f0
commit
837c6f9717
|
@ -1,195 +1,193 @@
|
||||||
/*
|
/*
|
||||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file ARMCAx-TZ/compilers/GCC/monitor.S
|
* @file ARMCAx-TZ/compilers/GCC/monitor.S
|
||||||
* @brief ARMCAx-TZ monitor code
|
* @brief ARMCAx-TZ monitor code
|
||||||
*
|
*
|
||||||
* @addtogroup ARM_CORE
|
* @addtogroup ARM_CORE
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
|
||||||
#define _FROM_ASM_
|
#define _FROM_ASM_
|
||||||
#include "chlicense.h"
|
#include "chlicense.h"
|
||||||
#include "chconf.h"
|
#include "chconf.h"
|
||||||
#include "armparams.h"
|
#include "armparams.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are facing an architecure with security extension exploited.
|
* We are facing an architecure with security extension exploited.
|
||||||
* The following execution paths are taken by the execution units
|
* The following execution paths are taken by the execution units
|
||||||
* running in secure state when an irq is fired (sm_irq), and in non-secure
|
* running in secure state when an irq is fired (sm_irq), and in non-secure
|
||||||
* state when a fiq interrupt is fired (sm_fiq).
|
* state when a fiq interrupt is fired (sm_fiq).
|
||||||
* They originate by the monitor irq/fiq vector and run in monitor mode,
|
* They originate by the monitor irq/fiq vector and run in monitor mode,
|
||||||
* ie in secure state.
|
* ie in secure state.
|
||||||
* It assumes the following, intially set at boot time, or wherever it needs:
|
* It assumes the following, intially set at boot time, or wherever it needs:
|
||||||
* SCR.FW == 0 and SCR.FIQ == 1 and SCR.IRQ == 0 in non-secure state,
|
* SCR.FW == 0 and SCR.FIQ == 1 and SCR.IRQ == 0 in non-secure state,
|
||||||
* ie FIQs are taken to monitor mode, IRQs are taken 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,
|
* SCR.FW == 0 and SCR.FIQ == 0 and SCR.IRQ == 1 in secure state,
|
||||||
* ie FIQs are taken locally, IRQs are taken to monitor mode
|
* ie FIQs are taken locally, IRQs are taken to monitor mode
|
||||||
* MVBAR holds the address of the monitor vectors base.
|
* MVBAR holds the address of the monitor vectors base.
|
||||||
* The code and the stacks memory reside both in secure memory.
|
* The code and the stacks memory reside both in secure memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(__DOXYGEN__)
|
#if !defined(__DOXYGEN__)
|
||||||
|
|
||||||
.set MODE_USR, 0x10
|
.set MODE_USR, 0x10
|
||||||
.set MODE_FIQ, 0x11
|
.set MODE_FIQ, 0x11
|
||||||
.set MODE_IRQ, 0x12
|
.set MODE_IRQ, 0x12
|
||||||
.set MODE_SVC, 0x13
|
.set MODE_SVC, 0x13
|
||||||
.set MODE_MON, 0x16
|
.set MODE_MON, 0x16
|
||||||
.set MODE_ABT, 0x17
|
.set MODE_ABT, 0x17
|
||||||
.set MODE_UND, 0x1B
|
.set MODE_UND, 0x1B
|
||||||
.set MODE_SYS, 0x1F
|
.set MODE_SYS, 0x1F
|
||||||
|
|
||||||
.set I_BIT, 0x80
|
.set I_BIT, 0x80
|
||||||
.set F_BIT, 0x40
|
.set F_BIT, 0x40
|
||||||
|
|
||||||
.set SCR_NS, 0x01
|
.set SCR_NS, 0x01
|
||||||
.set SCR_IRQ, 0x02
|
.set SCR_IRQ, 0x02
|
||||||
.set SCR_FIQ, 0x04
|
.set SCR_FIQ, 0x04
|
||||||
.set SCR_EA, 0x08
|
.set SCR_EA, 0x08
|
||||||
.set SCR_FW, 0x10
|
.set SCR_FW, 0x10
|
||||||
.set SCR_AW, 0x20
|
.set SCR_AW, 0x20
|
||||||
|
|
||||||
.set MON_S_SCR, (SCR_IRQ) // (SCR_EA|SCR_IRQ)
|
.set MON_S_SCR, (SCR_IRQ) // (SCR_EA|SCR_IRQ)
|
||||||
.set MON_NS_SCR, (SCR_FIQ|SCR_NS)
|
.set MON_NS_SCR, (SCR_FIQ|SCR_NS)
|
||||||
|
|
||||||
.set MSG_OK, 0
|
.set MSG_OK, 0
|
||||||
.set MSG_TIMEOUT, -1
|
.set MSG_TIMEOUT, -1
|
||||||
.set MSG_RESET, -2
|
.set MSG_RESET, -2
|
||||||
.section .data
|
|
||||||
.balign 4
|
.global _ns_thread
|
||||||
_ns_thread: .zero 4
|
.section .text
|
||||||
|
.code 32
|
||||||
.section .text
|
.balign 4
|
||||||
.code 32
|
/*
|
||||||
.balign 4
|
* Monitor vectors
|
||||||
/*
|
*/
|
||||||
* Monitor vectors
|
.global _monitor_vectors
|
||||||
*/
|
_monitor_vectors:
|
||||||
.global _monitor_vectors
|
b . // Reset vector, not used
|
||||||
_monitor_vectors:
|
b . // Undefined instruction, not used
|
||||||
b . // Reset vector, not used
|
b sm_call // Secure monitor call
|
||||||
b . // Undefined instruction, not used
|
b . // Prefetch abort, not taken to Monitor mode
|
||||||
b sm_call // Secure monitor call
|
b . // Data abort, not taken to Monitor mode
|
||||||
b . // Prefetch abort, not taken to Monitor mode
|
b . // Reserved
|
||||||
b . // Data abort, not taken to Monitor mode
|
b sm_irq // IRQ
|
||||||
b . // Reserved
|
b sm_fiq // FIQ
|
||||||
b sm_irq // IRQ
|
/*
|
||||||
b sm_fiq // FIQ
|
* SMC entry
|
||||||
/*
|
*/
|
||||||
* SMC entry
|
sm_call:
|
||||||
*/
|
ldr r12, =MON_S_SCR // enter in the secure world
|
||||||
sm_call:
|
mcr p15, 0, r12, c1, c1, 0
|
||||||
ldr r12, =MON_S_SCR // enter in the secure world
|
ands r0, r0 // OS special service,
|
||||||
mcr p15, 0, r12, c1, c1, 0
|
// 0 == jump trampoline to non secure world
|
||||||
ands r0, r0 // OS special service,
|
// r1 contains the address where it jumps
|
||||||
// 0 == jump trampoline to non secure world
|
beq 1f
|
||||||
// r1 contains the address where it jumps
|
msr CPSR_c, #MODE_SYS | I_BIT // switch to sys mode, foreign int disabled
|
||||||
beq 1f
|
stmfd sp!, {lr} // save lr
|
||||||
msr CPSR_c, #MODE_SYS | I_BIT // switch to sys mode, foreign int disabled
|
bl smcEntry // call the C smc handler
|
||||||
stmfd sp!, {lr} // save lr
|
ldmfd sp!, {lr} // restore lr
|
||||||
bl smcEntry // call the C smc handler
|
msr CPSR_c, #MODE_MON | I_BIT | F_BIT // switch to monitor mode
|
||||||
ldmfd sp!, {lr} // restore lr
|
ldr r12, =MON_NS_SCR // enter in the non-secure world
|
||||||
msr CPSR_c, #MODE_MON | I_BIT | F_BIT // switch to monitor mode
|
mcr p15, 0, r12, c1, c1, 0
|
||||||
ldr r12, =MON_NS_SCR // enter in the non-secure world
|
subs pc, lr, #0 // return from smc
|
||||||
mcr p15, 0, r12, c1, c1, 0
|
1:
|
||||||
subs pc, lr, #0 // return from smc
|
mov lr, r1 // use the address in r1 as return address
|
||||||
1:
|
// in the non secure world
|
||||||
mov lr, r1 // use the address in r1 as return address
|
ldr r12, =MON_NS_SCR // enter in the non-secure world
|
||||||
// in the non secure world
|
mcr p15, 0, r12, c1, c1, 0
|
||||||
ldr r12, =MON_NS_SCR // enter in the non-secure world
|
subs pc, lr, #0 // return from smc
|
||||||
mcr p15, 0, r12, c1, c1, 0
|
|
||||||
subs pc, lr, #0 // return from smc
|
/*
|
||||||
|
* FIQ entry
|
||||||
/*
|
*
|
||||||
* FIQ entry
|
* Here the fiq is taken from non-secure state, via the FIQ vector
|
||||||
*
|
* that is in the monitor vector table.
|
||||||
* Here the fiq is taken from non-secure state, via the FIQ vector
|
* Current mode is monitor (so current state is secure).
|
||||||
* that is in the monitor vector table.
|
* We switch immediately to system mode, enabling FIQ.
|
||||||
* Current mode is monitor (so current state is secure).
|
* The FIQ is then served while the ns_thread is running.
|
||||||
* We switch immediately to system mode, enabling FIQ.
|
* Because the ns_thread has the highest priority, the handler returns here
|
||||||
* The FIQ is then served while the ns_thread is running.
|
* without scheduling.
|
||||||
* Because the ns_thread has the highest priority, the handler returns here
|
*/
|
||||||
* without scheduling.
|
sm_fiq:
|
||||||
*/
|
// check point: SCR.NS == 1
|
||||||
sm_fiq:
|
stmfd sp!, {r0}
|
||||||
// check point: SCR.NS == 1
|
ldr r0, =MON_S_SCR // enter in the secure world
|
||||||
stmfd sp!, {r0}
|
mcr p15, 0, r0, c1, c1, 0
|
||||||
ldr r0, =MON_S_SCR // enter in the secure world
|
msr CPSR_c, #MODE_SYS | I_BIT // FIQ enabled, served via base table
|
||||||
mcr p15, 0, r0, c1, c1, 0
|
msr CPSR_c, #MODE_MON | I_BIT | F_BIT // the handler returns here. Switch to monitor mode
|
||||||
msr CPSR_c, #MODE_SYS | I_BIT // FIQ enabled, served via base table
|
ldr r0, =MON_NS_SCR // set non-secure SCR before return
|
||||||
msr CPSR_c, #MODE_MON | I_BIT | F_BIT // the handler returns here. Switch to monitor mode
|
mcr p15, 0, r0, c1, c1, 0
|
||||||
ldr r0, =MON_NS_SCR // set non-secure SCR before return
|
ldmfd sp!, {r0}
|
||||||
mcr p15, 0, r0, c1, c1, 0
|
subs pc, lr, #4 // return into non-secure world
|
||||||
ldmfd sp!, {r0}
|
/*
|
||||||
subs pc, lr, #4 // return into non-secure world
|
* IRQ entry
|
||||||
/*
|
*
|
||||||
* IRQ entry
|
* 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.
|
* the previous mode and status is in mon.spsr and
|
||||||
* Current mode is monitor (so current state is secure),
|
* the return address+4 is in mon.lr.
|
||||||
* the previous mode and status is in mon.spsr and
|
* Because we are running in secure state, we are sure that
|
||||||
* the return address+4 is in mon.lr.
|
* the main thread is suspended in the smc handler.
|
||||||
* Because we are running in secure state, we are sure that
|
* The main thread is then resumed with MSG_TIMEOUT
|
||||||
* the main thread is suspended in the smc handler.
|
* The non secure IRQ handler has then the responsibility to return into
|
||||||
* The main thread is then resumed with MSG_TIMEOUT
|
* secure state via a smc.
|
||||||
* The non secure IRQ handler has then the responsibility to return into
|
*
|
||||||
* secure state via a smc.
|
*/
|
||||||
*
|
sm_irq:
|
||||||
*/
|
// check point: SCR.NS == 0
|
||||||
sm_irq:
|
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
||||||
// check point: SCR.NS == 0
|
stmfd sp!, {r0-r3, r12, lr} // save scratch registers and lr
|
||||||
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
msr CPSR_c, #MODE_MON | I_BIT | F_BIT
|
||||||
stmfd sp!, {r0-r3, r12, lr} // save scratch registers and lr
|
mrs r0, SPSR
|
||||||
msr CPSR_c, #MODE_MON | I_BIT | F_BIT
|
mov r1, lr
|
||||||
mrs r0, SPSR
|
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
||||||
mov r1, lr
|
stmfd sp!, {r0, r1} // push R0=SPSR, R1=LR_MON.
|
||||||
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
// check point: ns_tread != 0
|
||||||
stmfd sp!, {r0, r1} // push R0=SPSR, R1=LR_MON.
|
ldr r0, =_ns_thread
|
||||||
// check point: ns_tread != 0
|
mov r1, #MSG_TIMEOUT
|
||||||
ldr r0, =_ns_thread
|
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
||||||
mov r1, #MSG_TIMEOUT
|
bl _dbg_check_lock
|
||||||
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
#endif
|
||||||
bl _dbg_check_lock
|
bl chThdResumeS // resume the ns_thread and serve the IRQ
|
||||||
#endif
|
// into non-secure world
|
||||||
bl chThdResumeS // resume the ns_thread and serve the IRQ
|
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
||||||
// into non-secure world
|
bl _dbg_check_unlock
|
||||||
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
#endif
|
||||||
bl _dbg_check_unlock
|
// The ns_thread reentered smc, that set SRC.NS to 0
|
||||||
#endif
|
// re-establish the original conditions
|
||||||
// The ns_thread reentered smc, that set SRC.NS to 0
|
ldmfd sp!, {r0, r1} // pop R0=SPSR, R1=LR_MON.
|
||||||
// re-establish the original conditions
|
msr CPSR_c, #MODE_MON | I_BIT | F_BIT
|
||||||
ldmfd sp!, {r0, r1} // pop R0=SPSR, R1=LR_MON.
|
msr SPSR_fsxc, r0
|
||||||
msr CPSR_c, #MODE_MON | I_BIT | F_BIT
|
mov lr, r1
|
||||||
msr SPSR_fsxc, r0
|
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
||||||
mov lr, r1
|
ldmfd sp!, {r0-r3, r12, lr}
|
||||||
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
msr CPSR_c, #MODE_MON | I_BIT | F_BIT
|
||||||
ldmfd sp!, {r0-r3, r12, lr}
|
subs pc, lr, #4 // return into secure world
|
||||||
msr CPSR_c, #MODE_MON | I_BIT | F_BIT
|
|
||||||
subs pc, lr, #4 // return into secure world
|
.global _ns_trampoline
|
||||||
|
_ns_trampoline:
|
||||||
.global _ns_trampoline
|
mov r1, r0
|
||||||
_ns_trampoline:
|
ldr r0, =#0
|
||||||
mov r1, r0
|
smc #0
|
||||||
ldr r0, =#0
|
|
||||||
smc #0
|
#endif /* !defined(__DOXYGEN__) */
|
||||||
|
|
||||||
#endif /* !defined(__DOXYGEN__) */
|
/** @} */
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
Loading…
Reference in New Issue