1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
| // core/arch/riscv/kernel/thread_optee_abi_rv.S
/*
* void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS],
* unsigned long status);
*/
FUNC thread_rpc_xstatus , :
// Allocate stack space for 8 registers.
/* Use stack for temporary storage */
addi sp, sp, -REGOFF(8)
/* Read xSTATUS */
csrr a2, CSR_XSTATUS
/* Mask all maskable exceptions before switching to temporary stack */
csrw CSR_XIE, x0
/* Save return address xSTATUS and pointer to rv */
// $a0: rv[THREAD_RPC_NUM_ARGS]
// $a1: xstatus to restore
// $a2: current xstatus
STR a0, REGOFF(0)(sp)
STR a1, REGOFF(1)(sp)
STR s0, REGOFF(2)(sp)
STR ra, REGOFF(3)(sp)
STR a2, REGOFF(4)(sp)
#ifdef CFG_UNWIND
addi s0, sp, REGOFF(8)
#endif
/* Save thread state */
jal thread_get_ctx_regs
// $a0 = current thread's struct thread_ctx.
// Restore $ra.
LDR ra, REGOFF(3)(sp)
/* Save ra, sp, gp, tp, and s0~s11 */
store_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP
store_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1
store_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11
/* Get to tmp stack */
jal thread_get_tmp_sp
// $a0 = tmp stack.
/* Get pointer to rv */
LDR s1, REGOFF(0)(sp)
// $s1 = rv[THREAD_RPC_NUM_ARGS]
/* xSTATUS to restore */
LDR a1, REGOFF(1)(sp)
// $a1 = xstatus to restore
/* Switch to tmp stack */
mv sp, a0
/* Early load rv[] into s2-s4 */
lw s2, 0(s1)
lw s3, 4(s1)
lw s4, 8(s1)
li a0, THREAD_FLAGS_COPY_ARGS_ON_RETURN
la a2, .thread_rpc_return
// We are about to return to untrusted domain for RPC,
// suspend the current thread.
jal [thread_state_suspend](/posts/optee-threads/)
// $a0 = thread index before suspend.
mv a4, a0 /* thread index */
mv a1, s2 /* rv[0] */
mv a2, s3 /* rv[1] */
mv a3, s4 /* rv[2] */
li a0, TEEABI_OPTEED_RETURN_CALL_DONE
mv a5, zero
/* Return to untrusted domain */
// $a0: TEEABI_OPTEED_RETURN_CALL_DONE
// $a1: rv[0], e.g. OPTEE_ABI_RETURN_RPC_CMD
// $a2: rv[1]
// $a3: rv[2]
// $a4: thread index before suspend.
jal [thread_return_to_udomain](/posts/optee-threads/)
.thread_rpc_return:
/*
* Jumps here from thread_resume() above when RPC has returned.
* At this point has the stack pointer been restored to the value
* stored in THREAD_CTX above.
*/
/* Get pointer to rv[] */
LDR a4, REGOFF(0)(sp)
/* Store a0-a3 into rv[] */
sw a0, 0(a4)
sw a1, 4(a4)
sw a2, 8(a4)
sw a3, 12(a4)
/* Pop saved XSTATUS from stack */
LDR s0, REGOFF(4)(sp)
csrw CSR_XSTATUS, s0
/* Pop s0 from stack */
LDR s0, REGOFF(2)(sp)
addi sp, sp, REGOFF(8)
ret
END_FUNC thread_rpc_xstatus
DECLARE_KEEP_PAGER thread_rpc_xstatus
|