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