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)