blob: 72098964e50835e8c952d9ef016b5149b8e57948 [file] [log] [blame]
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2013, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
SECTION MSTACK:DATA:NOROOT(3)
SECTION CSTACK:DATA:NOROOT(3)
#include "mon_macros.h"
#define __ASSEMBLY__
AIC DEFINE 0xFC06E000
AIC_IVR DEFINE 0x10
AIC_EOICR DEFINE 0x38
SAIC DEFINE 0xFC068400
AIC_FVR DEFINE 0x14
SECTION monitor_vector:CODE:NOROOT(2)
PUBLIC monitor_vectors
PUBLIC SM_Handler
EXTERN NWVector
EXTERN SwitchToNormalWorld
EXTERN SwitchToSecureWorld
EXTERN TZ_FIQ_Handler
EXTERN TZ_IRQ_Handler
EXTERN TzResetVector
ARM
/*
*-----------------------------------------------------------------------------
* Monitor exception vector table
* Most of these exceptions does not do anything other than branching to
* itself except smc vector. The SMC vector jumps to smc handler which
* takes care of proper switching from NWd to SWd and from SWd to NWd.
* -----------------------------------------------------------------------------
*/
monitor_vectors:
B . ; Reset: not used by Monitor
B . ; Undef: not used by Monitor
LDR pc, =SM_Handler
B . ; Prefetch: can be used by Monitor
B . ; Data abort: can be used by Monitor
B . ; RESERVED */
B . ; IRQ: can be used by Monitor
B . ; FIQ - can be used by Monitor
SECTION monitor:CODE:NOROOT(2)
SECTION MSTACK:DATA:NOROOT(3)
SM_Handler:
CPSID IF
PUSH {r0-r3} ; r0-r3 contain args to be passed between worlds
; Temporarily stack, so can be used as scratch regs
; Which world have we come from
; ------------------------------
MRC p15, 0, r0, c1, c1, 0 ; Read Secure Configuration Register data
TST r0, #NS_BIT ; Is the NS bit set?
BIC r0, r0, #NS_BIT ; Make sure the SCR.NS bit is now clear
// LDRNE r0, =SCR_SW_BIT
MCR p15, 0, r0, c1, c1, 0 ; Write Secure Configuration Register data
ISB
LDREQ r2, =MON_DATA_BASE
LDRNE r3, =MON_DATA_BASE
ADDEQ r3, r2, #Struct_size
ADDNE r2, r3, #Struct_size
STM r2!, {r4-r12} ; Save r4 to r12 registers of current world
LDM r3!, {r4-r12} ; Restore r4 to r12 registers of world we need to switch
; Save current world MON_LR MON_SP and MON_SPSR and restore for other world
MRS r1, SPSR
STM r2!, {r1, sp, lr}
LDM r3!, {r1, sp, lr}
MSR spsr_cxsf, r1
; Save current world SVC_LR, SVC_SP and SVC_SPSR and restore for other world
CPS #ARM_MODE_SVC
MRS r1, SPSR
STM r2!, {r1, sp, lr}
LDM r3!, {r1, sp, lr}
MSR spsr_cxsf, r1
; Save current world FIQ_LR FIQ_SP and FIQ_SPSR and restore for other world
CPS #ARM_MODE_FIQ
MRS r1, SPSR
STM r2!, {r1, sp, lr}
LDM r3!, {r1, sp, lr}
MSR spsr_cxsf, r1
; Save current world IRQ_LR IRQ_SP and IRQ_SPSR and restore for other world
CPS #ARM_MODE_IRQ
MRS r1, SPSR
STM r2!, {r1, sp, lr}
LDM r3!, {r1, sp, lr}
MSR spsr_cxsf, r1
; Change to SVC mode before going to MON mode
CPS #ARM_MODE_SVC
CPS #ARM_MODE_MON
CLREX ; Clear local monitor
LDREQ r0, =SCR_NW_BIT ; set FIQ to moitor exception(optional) and NS bit to 1 if comming from secure
MCREQ p15, 0, r0, c1, c1, 0 ; Write Secure Configuration Register data
ISB
/* set the monitor vector base */
LDREQ r2, =NWVector
MCREQ p15, 0, r2, c12, c0, 0 ; non secure copy of VBAR
BNE secureworld
nonsecureworld:
CPSIE IF
secureworld:
CPSIE F
; Now restore args (r0-r3)
; -------------------------
POP {r0-r3}
; exception return
; -------------------------
MOVS pc, lr
//***************************************************//
; Monitor initialization code
//***************************************************//
SECTION monitor:CODE:NOROOT(2)
SECTION MSTACK:DATA:NOROOT(3)
PUBLIC SecureMonitor_init
EXTERN nw_start
EXTERN TzResetVector
ARM
SecureMonitor_init:
/* Switch to MON mode */
MRS r4, cpsr
CPS #ARM_MODE_MON ; change back to SVC mode
/* set the monitor stack */
LDR sp, =SFE(MSTACK)
BIC sp,sp,#0x7 ; Make sure SP is 8 aligned
/* set the monitor vector base */
LDR r2, =monitor_vectors ; Update monitor exception vector table addr
MCR p15, 0, r2, c12, c0, 1
MSR cpsr_c, r4 ; change back to SVC mode
/* set the monitor vector base */
LDR r2, =TzResetVector ; Update secure exception vector table addr
MCR p15, 0, r2, c12, c0, 0
// Load zero to context memory block
MOV r3, #0
LDR r0, =MON_DATA_SIZE
LDR r1, =MON_DATA_BASE
MOV r2, #0
loop_init:
CMP r2, r0
STRNE r3,[r1]
ADD r1, r1, #4
ADD r2, r2, #1
BNE loop_init
BX lr
END