⚠️ The code is based on: https://gitlab.com/riseproject/riscv-optee/optee_os/-/tree/dev-optee-mpxy

Commit ID: 75df9ba41a404aec897399ead0ff0aebcbff48ca

  • thread_rpc_cmd()
    • Call thread_rpc() with rpc_args (rv[THREAD_RPC_NUM_ARGS]). rpc_args’s first element is set to OPTEE_ABI_RETURN_RPC_CMD function.
  • thread_rpc()
  • __thread_rpc()
  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