github.com/usbarmory/GoTEE@v0.0.0-20240405084336-c52770d9fcdb/monitor/exec_arm.s (about)

     1  // Copyright (c) WithSecure Corporation
     2  // https://foundry.withsecure.com
     3  //
     4  // Use of this source code is governed by the license
     5  // that can be found in the LICENSE file.
     6  
     7  #include "go_asm.h"
     8  #include "textflag.h"
     9  
    10  // GoTEE exception handling relies on one exit point (Exec) and one return
    11  // point (monitor), both are used for:
    12  //
    13  //   Secure      User Mode execution and exception handling
    14  //   NonSecure System mode execution and supervisor call handling
    15  //
    16  // An execution context (ExecCtx) structure is used to hold initial register
    17  // state at execution as well as store the updated state on re-entry.
    18  //
    19  // The exception handling uses a Thread ID Register (TPIDRPRW) in a similar
    20  // manner to Go own use of TLS (https://golang.org/src/runtime/tls_arm.s).
    21  //
    22  // With respect to TrustZone the handler must save and restore the following
    23  // registers between Secure <> NonSecure World switches:
    24  //
    25  //  • r0-r15, CPSR of Supervisor, System/User modes:
    26  //
    27  //    TamaGo (and therefore GoTEE) does not use Supervisor mode, System/User
    28  //    mode share the same register banks.
    29  //
    30  //    The r0-r15 and CPSR registers of the invoking mode are saved/restored.
    31  //
    32  //  • r13-r14 of Abort/Undefined/IRQ modes, r8-r14 of FIQ mode:
    33  //
    34  //    TamaGo (and therefore GoTEE) panics on Abort/Undefined exceptions
    35  //    therefore their banked registers are not saved/restored, interrupt
    36  //    handling (IRQ/FIQ) must be exclusive to either World.
    37  //
    38  //  • Data register of shared coprocessors (e.g VFP/FPU):
    39  //
    40  //    The d0-d31, FPSCR and FPEXC registers are saved/restored.
    41  
    42  // func Exec(ctx *ExecCtx)
    43  TEXT ·Exec(SB),$0-4
    44  	// save general purpose registers
    45  	MOVM.DB.W	[R0-R12, R14], (R13)	// push {r0-r12, r14}
    46  
    47  	// get argument pointer
    48  	ADD	$(14*4), R13, R13
    49  	MOVW	ctx+0(FP), R0
    50  	SUB	$(14*4), R13, R13
    51  
    52  	// save g stack pointer
    53  	MOVW	R13, ExecCtx_g_sp(R0)
    54  
    55  	// restore SP, LR
    56  	MOVW	ExecCtx_R13(R0), R13
    57  	MOVW	ExecCtx_R14(R0), R14
    58  
    59  	// save context pointer as Thread ID (TPIDRPRW)
    60  	MCR	15, 0, R0, C13, C0, 4
    61  
    62  	// switch to monitor mode
    63  	WORD	$0xf1020016			// cps 0x16
    64  
    65  	// restore mode
    66  	MOVW	ExecCtx_SPSR(R0), R1
    67  	WORD	$0xe16ff001			// msr SPSR, r1
    68  
    69  	MOVW	ExecCtx_ns(R0), R1
    70  	CMP	$1, R1
    71  	BNE	restore
    72  
    73  	// enable EA, FIQ, and NS bit in SCR
    74  	MOVW	$13, R1
    75  	MCR	15, 0, R1, C1, C1, 0
    76  
    77  restore:
    78  	/* restore VFP registers */
    79  	MOVW	ExecCtx_VFP(R0), R1
    80  	WORD	$0xecb10b20			// vldm r1!, {d0-d15}
    81  	WORD	$0xecf10b20			// vldm r1!, {d15-d31}
    82  	MOVW	ExecCtx_FPSCR(R0), R1
    83  	WORD	$0xeee11a10			// vmsr fpscr, r1
    84  	MOVW	ExecCtx_FPEXC(R0), R1
    85  	WORD	$0xeee81a10			// vmsr fpexc, r1
    86  
    87  	MOVW	ExecCtx_Domain(R0), R1
    88  	CMP	$0, R1
    89  	BEQ	switch
    90  
    91  	// enable DACR bit for ExecCtx_Domain
    92  	MOVW	$2, R2
    93  	MUL	R1, R2
    94  	MOVW	$1, R1
    95  	MOVW	R1<<R2, R1
    96  
    97  	// Set Domain Access (ExecCtx_Domain + 0)
    98  	ORR	$1, R1, R1
    99  	MCR	15, 0, R1, C3, C0, 0
   100  
   101  switch:
   102  	// restore r0-r12, r15
   103  	WORD	$0xe8d0ffff			// ldmia r0, {r0-r15}^
   104  
   105  #define MONITOR_EXCEPTION(OFFSET)						\
   106  	/* disable FIQ interrupts */						\
   107  	WORD	$0xf10c0040			/* cpsid f */			\
   108  										\
   109  	/* save R0 */								\
   110  	MOVW	R0, R13								\
   111  										\
   112  	/* disable EA, FIQ and NS bit in SCR */					\
   113  	MOVW	$0, R0								\
   114  	MCR	15, 0, R0, C1, C1, 0						\
   115  										\
   116  	/* restore context pointer from Thread ID (TPIDRPRW) */			\
   117  	MRC	15, 0, R0, C13, C0, 4						\
   118  										\
   119  	/* save general purpose registers */					\
   120  	WORD	$0xe8c07fff			/* stmia r0, {r0-r14}^ */	\
   121  	MOVW	R0, R1								\
   122  	MOVW	R13, ExecCtx_R0(R1)						\
   123  										\
   124  	/* save PC from LR */							\
   125  	MOVW	R14, ExecCtx_R15(R1)						\
   126  										\
   127  	WORD	$0xe14f0000			/* mrs r0, SPSR */		\
   128  	MOVW	R0, ExecCtx_SPSR(R1)						\
   129  										\
   130  	WORD	$0xe10f0000			/* mrs r0, CPSR */		\
   131  	MOVW	R0, ExecCtx_CPSR(R1)						\
   132  										\
   133  	MOVW	$OFFSET, R0							\
   134  	MOVW	R0, ExecCtx_ExceptionVector(R1)					\
   135  										\
   136  	/* Save FPEXC */							\
   137  	WORD	$0xeef80a10			/* vmrs r0, fpexc */		\
   138  	MOVW	R0, ExecCtx_FPEXC(R1)						\
   139  										\
   140  	/* Ensure VFP is enabled */						\
   141  	MOVW	$(1 << 30), R0							\
   142  	WORD	$0xeee80a10			/* vmsr fpexc, r0 */		\
   143  										\
   144  	/* save VFP registers */						\
   145  	MOVW	ExecCtx_VFP(R1), R0						\
   146  	WORD	$0xeca00b20			/* vstm r0!, {d0-d15} */	\
   147  	WORD	$0xece00b20			/* vstm r0!, {d16-d31} */	\
   148  	WORD	$0xeef10a10			/* vmrs r0, fpscr */		\
   149  	MOVW	R0, ExecCtx_FPSCR(R1)						\
   150  										\
   151  	/* switch to System Mode */						\
   152  	MOVW	$0x1df, R0			/* AIF masked, SYS mode */	\
   153  	WORD	$0xe16ff000			/* msr SPSR, R0 */		\
   154  	WORD	$0xf102001f			/* cps 0x1f */			\
   155  										\
   156  	/* restore g registers */						\
   157  	MOVW		ExecCtx_g_sp(R1), R13					\
   158  	MOVM.IA.W	(R13), [R0-R12, R14]	/* pop {r0-r12, r14} */		\
   159  										\
   160  	/* restore PC from LR */						\
   161  	MOVW	R14, R15							\
   162  
   163  TEXT ·resetMonitor(SB),NOSPLIT|NOFRAME,$0
   164  	MONITOR_EXCEPTION(0x0)
   165  
   166  TEXT ·undefinedMonitor(SB),NOSPLIT|NOFRAME,$0
   167  	MONITOR_EXCEPTION(0x4)
   168  
   169  TEXT ·supervisorMonitor(SB),NOSPLIT|NOFRAME,$0
   170  	MONITOR_EXCEPTION(0x8)
   171  
   172  TEXT ·prefetchAbortMonitor(SB),NOSPLIT|NOFRAME,$0
   173  	MONITOR_EXCEPTION(0xc)
   174  
   175  TEXT ·dataAbortMonitor(SB),NOSPLIT|NOFRAME,$0
   176  	MONITOR_EXCEPTION(0x10)
   177  
   178  TEXT ·irqMonitor(SB),NOSPLIT|NOFRAME,$0
   179  	MONITOR_EXCEPTION(0x18)
   180  
   181  TEXT ·fiqMonitor(SB),NOSPLIT|NOFRAME,$0
   182  	MONITOR_EXCEPTION(0x1c)