[PATCH 1/1] Add RISC-V TEE support

liushiwei liushiwei at eswincomputing.com
Tue Jan 10 18:01:59 PST 2023


RISC-V Trusted Executable Environment security software includes
linux, opensbi, and OP-TEE OS. linux is the non-secure domain,
and OP-TEE OS is the secure domain. At boot time, opensbi boots
OP-TEE OS and then starts linux. At runtime, opensbi acts as a
secure monitor, responsible for context saving and restoring
when switching between linux and OP-TEE OS.
TEE function is off by default, when using configuration is
added in the config and objects file, such as
platform/generic/configs/defconfig add CONFIG_SBI_ECALL_TEE = y,
In the platform/generic/objects.mk add CONFIG_TEE_LOAD_ADDR =
0x27c000000, CONFIG_TEE_LOAD_ADDR is the starting address
of the OP-TEE OS.

Signed-off-by: liushiwei <liushiwei at eswincomputing.com>
---
 include/sbi/sbi_ecall_interface.h         |   3 +
 include/sbi_utils/tee/tee_context.h       | 104 ++++++++++
 include/sbi_utils/tee/tee_sm_dispatcher.h |  44 +++++
 include/sbi_utils/tee/teeecall_opteed.h   | 145 ++++++++++++++
 lib/sbi/Kconfig                           |   4 +
 lib/sbi/objects.mk                        |   3 +
 lib/sbi/sbi_ecall_tee.c                   |  19 ++
 lib/sbi/sbi_init.c                        |   5 +
 lib/utils/tee/objects.mk                  |  16 ++
 lib/utils/tee/tee_context.S               | 189 ++++++++++++++++++
 lib/utils/tee/tee_sm_dispatcher.c         | 228 ++++++++++++++++++++++
 11 files changed, 760 insertions(+)
 create mode 100644 include/sbi_utils/tee/tee_context.h
 create mode 100644 include/sbi_utils/tee/tee_sm_dispatcher.h
 create mode 100644 include/sbi_utils/tee/teeecall_opteed.h
 create mode 100644 lib/sbi/sbi_ecall_tee.c
 create mode 100644 lib/utils/tee/objects.mk
 create mode 100644 lib/utils/tee/tee_context.S
 create mode 100644 lib/utils/tee/tee_sm_dispatcher.c

diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index a3f2bf4..5ed5bd5 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -238,6 +238,9 @@ enum sbi_pmu_ctr_type {
 #define SBI_EXT_VENDOR_END			0x09FFFFFF
 #define SBI_EXT_FIRMWARE_START			0x0A000000
 #define SBI_EXT_FIRMWARE_END			0x0AFFFFFF
+#define SBI_EXT_TEE_START			0x0A000000
+#define SBI_EXT_TEE_END				0x0AFFFFFF
+#define SBI_EXT_TEE				0xFFFFEEEE
 
 /* SBI return error codes */
 #define SBI_SUCCESS				0
diff --git a/include/sbi_utils/tee/tee_context.h b/include/sbi_utils/tee/tee_context.h
new file mode 100644
index 0000000..467ff00
--- /dev/null
+++ b/include/sbi_utils/tee/tee_context.h
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright  2023  Beijing ESWIN Computing Technology Co., Ltd.
+ *
+ * Authors:
+ *   Chen Chaokai <chenchaokai at eswincomputing.com>
+ *   Liu Shiwei <liushiwei at eswincomputing.com>
+ */
+
+#ifndef __TEE_CONTEXT_H__
+#define __TEE_CONTEXT_H__
+
+#define TEE_SECURE_FLAG					(0xFFFF0000)
+#define TEE_NON_SECURE_FLAG				(0xFFFFFFFF)
+
+#define TEE_HART_COUNT					(0x8)
+#define OPTEED_CORE_COUNT				TEE_HART_COUNT
+
+#define ECALL_TEE_SHIFT					(0x10)
+#define MCAUSE_INTR					(1)
+
+/* The secure and non-secure contexts size are used to
+ * store the regisers respectively.
+ * The macros defined below are used to setup the spaces
+ * for secure and non-secure contexts.
+ * */
+
+#define SBI_SAVE_CONTEXT_sepc				35
+#define SBI_SAVE_CONTEXT_satp				36
+#define SBI_SAVE_CONTEXT_sstatus			37
+#define SBI_SAVE_CONTEXT_sie				38
+#define SBI_SAVE_CONTEXT_stvec				39
+#define SBI_SAVE_CONTEXT_sscratch			40
+#define SBI_SAVE_CONTEXT_scounteren			41
+#define SBI_SAVE_CONTEXT_scause				42
+#define SBI_SAVE_CONTEXT_stval				43
+#define SBI_SAVE_CONTEXT_sip				44
+#define SBI_SAVE_CONTEXT_last				45
+
+/** Get offset of member with name 'x' in sbi_save_context */
+#define SBI_SAVE_CONTEXT_OFFSET(x) ((SBI_SAVE_CONTEXT_##x) * __SIZEOF_POINTER__)
+/** Size (in bytes) of sbi_trap_regs */
+#define SBI_SAVE_CONTEXT_SIZE SBI_SAVE_CONTEXT_OFFSET(last)
+
+#ifndef __ASSEMBLER__
+#include <sbi/sbi_types.h>
+
+typedef uint32_t optee_vector_isn_t;
+
+typedef struct optee_vectors {
+	optee_vector_isn_t yield_smc_entry;
+	optee_vector_isn_t fast_smc_entry;
+	optee_vector_isn_t cpu_on_entry;
+	optee_vector_isn_t cpu_off_entry;
+	optee_vector_isn_t cpu_resume_entry;
+	optee_vector_isn_t cpu_suspend_entry;
+	optee_vector_isn_t fiq_entry;
+	optee_vector_isn_t system_off_entry;
+	optee_vector_isn_t system_reset_entry;
+} optee_vectors_t;
+
+struct sbi_save_context {
+	struct sbi_trap_regs regs;
+	unsigned long sepc;
+	unsigned long satp;
+	unsigned long sstatus;
+	unsigned long sie;
+	unsigned long stvec;
+	unsigned long sscratch;
+	unsigned long scounteren;
+	unsigned long scause;
+	unsigned long stval;
+	unsigned long sip;
+};
+
+/**
+ * Save opensbi context and enter into TEE OS
+ *
+ * @param cpu_ctx_addr Address of struct sbi_save_context to save context.
+ *
+ * @return Return 0 on success and negative value on failure
+ */
+int entry_teeos(unsigned long cpu_ctx_addr);
+
+/**
+ * Restore openSBI context and continue running openSBI
+ *
+ * @param cpu_ctx_addr Address of struct sbi_trap_regs to restore context.
+ * @param ret Return value coming from TEE OS.
+ *
+ */
+void teeos_entry_done(unsigned long cpu_ctx_addr);
+
+/**
+ * Load supervisor context and return to supervisor mode
+ *
+ * @param ctx_addr Address of struct sbi_trap_regs to restore context.
+ *
+ */
+void restore_to_supervisor(unsigned long ctx_addr);
+
+#endif /* __ASSEMBLER__ */
+#endif /* __TEE_CONTEXT_H__ */
diff --git a/include/sbi_utils/tee/tee_sm_dispatcher.h b/include/sbi_utils/tee/tee_sm_dispatcher.h
new file mode 100644
index 0000000..1c971a4
--- /dev/null
+++ b/include/sbi_utils/tee/tee_sm_dispatcher.h
@@ -0,0 +1,44 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright  2023  Beijing ESWIN Computing Technology Co., Ltd.
+ *
+ * Authors:
+ *   Chen Chaokai <chenchaokai at eswincomputing.com>
+ *   Liu Shiwei <liushiwei at eswincomputing.com>
+ */
+
+#ifndef __TEE_SM_DISPATCHER_H__
+#define __TEE_SM_DISPATCHER_H__
+
+#define TEE_ENTRY_ADDR      TEE_LOAD_ADDR
+
+#ifndef __ASSEMBLER__
+#include <sbi/sbi_types.h>
+
+/**
+ * Initialize tee os
+ *
+ * @return Return 0 on success and negative value on failure
+ */
+void tee_os_init(void);
+
+/**
+ * TEE dispatcher handler which interact bewteen REE and TEE
+ *
+ * @param extid is SBI_EXT_TEE
+ * @param funcid Function id for this ecall trap.
+ * @param args Parameter passed from supervisor mode
+ * @param out_value Output value
+ * @param out_trap Trap detail
+ *
+ * @return Return 0 on success and negative value on failure
+ */
+
+int sbi_ecall_tee_handler(ulong extid, ulong funcid,
+			  const struct sbi_trap_regs *regs,
+			  ulong *out_val,
+			  struct sbi_trap_info *out_trap);
+
+#endif /* __ASSEMBLER__ */
+#endif /* __TEE_SM_DISPATCHER_H__ */
diff --git a/include/sbi_utils/tee/teeecall_opteed.h b/include/sbi_utils/tee/teeecall_opteed.h
new file mode 100644
index 0000000..e953a36
--- /dev/null
+++ b/include/sbi_utils/tee/teeecall_opteed.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Copyright (c) 2014, Linaro Limited. All rights reserved. */
+
+#ifndef __TEEECALL_OPTEED_H__
+#define __TEEECALL_OPTEED_H__
+
+#define ECALL_TYPE_FAST     (1)
+#define ECALL_TYPE_YEILD    (0)
+
+#define FUNCID_TYPE_SHIFT   (31)
+#define FUNCID_TYPE_MASK    (0x1)
+#define ECALL_32            (0)
+#define FUNCID_CC_SHIFT     (30)
+#define FUNCID_OEN_SHIFT    (24)
+
+#define FUNCID_NUM_MASK      (0xffff)
+
+#define GET_ECALL_TYPE(id)        (((id) >> FUNCID_TYPE_SHIFT) & \
+                     FUNCID_TYPE_MASK)
+
+
+#define TEEECALL_OPTEED_RV(func_num) \
+        ((ECALL_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+         ((ECALL_32) << FUNCID_CC_SHIFT) | \
+         (62 << FUNCID_OEN_SHIFT) | \
+         ((func_num) & FUNCID_NUM_MASK))
+
+
+/*
+ * This file specify SMC function IDs used when returning from TEE to the
+ * secure monitor.
+ *
+ * All SMC Function IDs indicates SMC32 Calling Convention but will carry
+ * full 64 bit values in the argument registers if invoked from Aarch64
+ * mode. This violates the SMC Calling Convention, but since this
+ * convention only coveres API towards Normwal World it's something that
+ * only concerns the OP-TEE Dispatcher in ARM Trusted Firmware and OP-TEE
+ * OS at Secure EL1.
+ */
+
+/*
+ * Issued when returning from initial entry.
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_ENTRY_DONE
+ * r1/x1	Pointer to entry vector
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_ENTRY_DONE		0
+#define TEEECALL_OPTEED_RETURN_ENTRY_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_ENTRY_DONE)
+
+
+
+/*
+ * Issued when returning from "cpu_on" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_ON_DONE
+ * r1/x1	0 on success and anything else to indicate error condition
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_ON_DONE		1
+#define TEEECALL_OPTEED_RETURN_ON_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_ON_DONE)
+
+/*
+ * Issued when returning from "cpu_off" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_OFF_DONE
+ * r1/x1	0 on success and anything else to indicate error condition
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_OFF_DONE		2
+#define TEEECALL_OPTEED_RETURN_OFF_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_OFF_DONE)
+
+/*
+ * Issued when returning from "cpu_suspend" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_SUSPEND_DONE
+ * r1/x1	0 on success and anything else to indicate error condition
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_SUSPEND_DONE	3
+#define TEEECALL_OPTEED_RETURN_SUSPEND_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_SUSPEND_DONE)
+
+/*
+ * Issued when returning from "cpu_resume" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_RESUME_DONE
+ * r1/x1	0 on success and anything else to indicate error condition
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_RESUME_DONE		4
+#define TEEECALL_OPTEED_RETURN_RESUME_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_RESUME_DONE)
+
+/*
+ * Issued when returning from "std_smc" or "fast_smc" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_CALL_DONE
+ * r1-4/x1-4	Return value 0-3 which will passed to normal world in
+ *		r0-3/x0-3
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_CALL_DONE		5
+#define TEEECALL_OPTEED_RETURN_CALL_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_CALL_DONE)
+
+/*
+ * Issued when returning from "fiq" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_FIQ_DONE
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_FIQ_DONE		6
+#define TEEECALL_OPTEED_RETURN_FIQ_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_FIQ_DONE)
+
+/*
+ * Issued when returning from "system_off" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_SYSTEM_OFF_DONE
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE	7
+#define TEEECALL_OPTEED_RETURN_SYSTEM_OFF_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE)
+
+/*
+ * Issued when returning from "system_reset" vector
+ *
+ * Register usage:
+ * r0/x0	SMC Function ID, TEEECALL_OPTEED_RETURN_SYSTEM_RESET_DONE
+ */
+#define TEEECALL_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE	8
+#define TEEECALL_OPTEED_RETURN_SYSTEM_RESET_DONE \
+	TEEECALL_OPTEED_RV(TEEECALL_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE)
+
+#endif /* __TEEECALL_OPTEED_H__ */
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index df74bba..7cfc8c3 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -34,4 +34,8 @@ config SBI_ECALL_VENDOR
 	bool "Platform-defined vendor extensions"
 	default y
 
+config SBI_ECALL_TEE
+	bool "trusted execution environment"
+	default n
+
 endmenu
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index c774ebb..ea79924 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -43,6 +43,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_LEGACY) += sbi_ecall_legacy.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_VENDOR) += ecall_vendor
 libsbi-objs-$(CONFIG_SBI_ECALL_VENDOR) += sbi_ecall_vendor.o
 
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_TEE) += ecall_tee
+libsbi-objs-$(CONFIG_SBI_ECALL_TEE) += sbi_ecall_tee.o
+
 libsbi-objs-y += sbi_bitmap.o
 libsbi-objs-y += sbi_bitops.o
 libsbi-objs-y += sbi_console.o
diff --git a/lib/sbi/sbi_ecall_tee.c b/lib/sbi/sbi_ecall_tee.c
new file mode 100644
index 0000000..86deea3
--- /dev/null
+++ b/lib/sbi/sbi_ecall_tee.c
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright  2023  Beijing ESWIN Computing Technology Co., Ltd.
+ *
+ * Authors:
+ *   Chen Chaokai <chenchaokai at eswincomputing.com>
+ *   Liu Shiwei <liushiwei at eswincomputing.com>
+ */
+
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi_utils/tee/tee_sm_dispatcher.h>
+
+struct sbi_ecall_extension ecall_tee = {
+	.extid_start = SBI_EXT_TEE,
+	.extid_end = SBI_EXT_TEE,
+	.handle = sbi_ecall_tee_handler,
+};
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 259a191..1158949 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -26,6 +26,7 @@
 #include <sbi/sbi_timer.h>
 #include <sbi/sbi_tlb.h>
 #include <sbi/sbi_version.h>
+#include <sbi_utils/tee/tee_sm_dispatcher.h>
 
 #define BANNER                                              \
 	"   ____                    _____ ____ _____\n"     \
@@ -350,6 +351,10 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 	init_count = sbi_scratch_offset_ptr(scratch, init_count_offset);
 	(*init_count)++;
 
+#ifdef CONFIG_SBI_ECALL_TEE
+	tee_os_init();
+#endif
+
 	sbi_hsm_prepare_next_jump(scratch, hartid);
 	sbi_hart_switch_mode(hartid, scratch->next_arg1, scratch->next_addr,
 			     scratch->next_mode, false);
diff --git a/lib/utils/tee/objects.mk b/lib/utils/tee/objects.mk
new file mode 100644
index 0000000..5bf81f7
--- /dev/null
+++ b/lib/utils/tee/objects.mk
@@ -0,0 +1,16 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright  2023  Beijing ESWIN Computing Technology Co., Ltd.
+#
+# Authors:
+#   Chen Chaokai <chenchaokai at eswincomputing.com>
+#   Liu Shiwei <liushiwei at eswincomputing.com>
+#
+
+ifdef CONFIG_TEE_LOAD_ADDR
+firmware-cflags-y += -DTEE_LOAD_ADDR=$(CONFIG_TEE_LOAD_ADDR)
+endif
+
+libsbiutils-objs-$(CONFIG_SBI_ECALL_TEE) += tee/tee_context.o
+libsbiutils-objs-$(CONFIG_SBI_ECALL_TEE) += tee/tee_sm_dispatcher.o
diff --git a/lib/utils/tee/tee_context.S b/lib/utils/tee/tee_context.S
new file mode 100644
index 0000000..90b1013
--- /dev/null
+++ b/lib/utils/tee/tee_context.S
@@ -0,0 +1,189 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright  2023  Beijing ESWIN Computing Technology Co., Ltd.
+ *
+ * Authors:
+ *   Chen Chaokai <chenchaokai at eswincomputing.com>
+ *   Liu Shiwei <liushiwei at eswincomputing.com>
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_platform.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_trap.h>
+#include <sbi_utils/tee/tee_context.h>
+
+	.global entry_teeos
+	.type entry_teeos, @function
+entry_teeos:
+	/* Save t0 into scratch temporarily */
+	csrrw	tp, CSR_MSCRATCH, tp
+	REG_S	t0, SBI_SCRATCH_TMP0_OFFSET(tp)
+
+	li	t0, 0
+	addi	t0, sp, 0
+
+	/* Set new SP */
+	li	sp, 0
+	addi	sp, a0, 0
+
+	/* Save original SP and t0 */
+	REG_S	t0, SBI_TRAP_REGS_OFFSET(sp)(sp)
+	REG_L	t0, SBI_SCRATCH_TMP0_OFFSET(tp)
+	REG_S	t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
+
+	csrrw	tp, CSR_MSCRATCH, tp
+
+	/* Save all general registers except SP and T0*/
+	REG_S	ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
+	REG_S	a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
+	REG_S	gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
+	REG_S	tp, SBI_TRAP_REGS_OFFSET(tp)(sp)
+	REG_S	t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
+	REG_S	t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
+	REG_S	s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
+	REG_S	s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
+	REG_S	a1, SBI_TRAP_REGS_OFFSET(a1)(sp)
+	REG_S	a2, SBI_TRAP_REGS_OFFSET(a2)(sp)
+	REG_S	a3, SBI_TRAP_REGS_OFFSET(a3)(sp)
+	REG_S	a4, SBI_TRAP_REGS_OFFSET(a4)(sp)
+	REG_S	a5, SBI_TRAP_REGS_OFFSET(a5)(sp)
+	REG_S	a6, SBI_TRAP_REGS_OFFSET(a6)(sp)
+	REG_S	a7, SBI_TRAP_REGS_OFFSET(a7)(sp)
+	REG_S	s2, SBI_TRAP_REGS_OFFSET(s2)(sp)
+	REG_S	s3, SBI_TRAP_REGS_OFFSET(s3)(sp)
+	REG_S	s4, SBI_TRAP_REGS_OFFSET(s4)(sp)
+	REG_S	s5, SBI_TRAP_REGS_OFFSET(s5)(sp)
+	REG_S	s6, SBI_TRAP_REGS_OFFSET(s6)(sp)
+	REG_S	s7, SBI_TRAP_REGS_OFFSET(s7)(sp)
+	REG_S	s8, SBI_TRAP_REGS_OFFSET(s8)(sp)
+	REG_S	s9, SBI_TRAP_REGS_OFFSET(s9)(sp)
+	REG_S	s10, SBI_TRAP_REGS_OFFSET(s10)(sp)
+	REG_S	s11, SBI_TRAP_REGS_OFFSET(s11)(sp)
+	REG_S	t3, SBI_TRAP_REGS_OFFSET(t3)(sp)
+	REG_S	t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
+	REG_S	t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
+	REG_S	t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
+	REG_L	sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
+
+	/* Enter supervisor mode */
+	call	enter_teeos_start_point
+
+	.global teeos_entry_done
+	.type teeos_entry_done, @function
+teeos_entry_done:
+	li	sp, 0
+	addi	sp, a0, 0
+
+	/* Restore all general purpose registers except SP and T0*/
+	REG_L	ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
+	REG_L	gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
+	REG_L	tp, SBI_TRAP_REGS_OFFSET(tp)(sp)
+	REG_L	t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
+	REG_L	t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
+	REG_L	s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
+	REG_L	s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
+	REG_L	a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
+	REG_L	a1, SBI_TRAP_REGS_OFFSET(a1)(sp)
+	REG_L	a2, SBI_TRAP_REGS_OFFSET(a2)(sp)
+	REG_L	a3, SBI_TRAP_REGS_OFFSET(a3)(sp)
+	REG_L	a4, SBI_TRAP_REGS_OFFSET(a4)(sp)
+	REG_L	a5, SBI_TRAP_REGS_OFFSET(a5)(sp)
+	REG_L	a6, SBI_TRAP_REGS_OFFSET(a6)(sp)
+	REG_L	a7, SBI_TRAP_REGS_OFFSET(a7)(sp)
+	REG_L	s2, SBI_TRAP_REGS_OFFSET(s2)(sp)
+	REG_L	s3, SBI_TRAP_REGS_OFFSET(s3)(sp)
+	REG_L	s4, SBI_TRAP_REGS_OFFSET(s4)(sp)
+	REG_L	s5, SBI_TRAP_REGS_OFFSET(s5)(sp)
+	REG_L	s6, SBI_TRAP_REGS_OFFSET(s6)(sp)
+	REG_L	s7, SBI_TRAP_REGS_OFFSET(s7)(sp)
+	REG_L	s8, SBI_TRAP_REGS_OFFSET(s8)(sp)
+	REG_L	s9, SBI_TRAP_REGS_OFFSET(s9)(sp)
+	REG_L	s10, SBI_TRAP_REGS_OFFSET(s10)(sp)
+	REG_L	s11, SBI_TRAP_REGS_OFFSET(s11)(sp)
+	REG_L	t3, SBI_TRAP_REGS_OFFSET(t3)(sp)
+	REG_L	t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
+	REG_L	t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
+	REG_L	t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
+
+	/* Restore T0 */
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
+
+	/* Restore SP */
+	REG_L	sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
+	ret
+
+	.global restore_to_supervisor
+	.type restore_to_supervisor, @function
+restore_to_supervisor:
+	li	sp, 0
+	add	sp, a0, zero
+
+	/* Restore all general purpose registers except SP and T0*/
+	REG_L	zero, SBI_TRAP_REGS_OFFSET(zero)(sp)
+	REG_L	ra, SBI_TRAP_REGS_OFFSET(ra)(sp)
+	REG_L	gp, SBI_TRAP_REGS_OFFSET(gp)(sp)
+	REG_L	tp, SBI_TRAP_REGS_OFFSET(tp)(sp)
+	REG_L	t1, SBI_TRAP_REGS_OFFSET(t1)(sp)
+	REG_L	t2, SBI_TRAP_REGS_OFFSET(t2)(sp)
+	REG_L	s0, SBI_TRAP_REGS_OFFSET(s0)(sp)
+	REG_L	s1, SBI_TRAP_REGS_OFFSET(s1)(sp)
+	REG_L	a0, SBI_TRAP_REGS_OFFSET(a0)(sp)
+	REG_L	a1, SBI_TRAP_REGS_OFFSET(a1)(sp)
+	REG_L	a2, SBI_TRAP_REGS_OFFSET(a2)(sp)
+	REG_L	a3, SBI_TRAP_REGS_OFFSET(a3)(sp)
+	REG_L	a4, SBI_TRAP_REGS_OFFSET(a4)(sp)
+	REG_L	a5, SBI_TRAP_REGS_OFFSET(a5)(sp)
+	REG_L	a6, SBI_TRAP_REGS_OFFSET(a6)(sp)
+	REG_L	a7, SBI_TRAP_REGS_OFFSET(a7)(sp)
+	REG_L	s2, SBI_TRAP_REGS_OFFSET(s2)(sp)
+	REG_L	s3, SBI_TRAP_REGS_OFFSET(s3)(sp)
+	REG_L	s4, SBI_TRAP_REGS_OFFSET(s4)(sp)
+	REG_L	s5, SBI_TRAP_REGS_OFFSET(s5)(sp)
+	REG_L	s6, SBI_TRAP_REGS_OFFSET(s6)(sp)
+	REG_L	s7, SBI_TRAP_REGS_OFFSET(s7)(sp)
+	REG_L	s8, SBI_TRAP_REGS_OFFSET(s8)(sp)
+	REG_L	s9, SBI_TRAP_REGS_OFFSET(s9)(sp)
+	REG_L	s10, SBI_TRAP_REGS_OFFSET(s10)(sp)
+	REG_L	s11, SBI_TRAP_REGS_OFFSET(s11)(sp)
+	REG_L	t3, SBI_TRAP_REGS_OFFSET(t3)(sp)
+	REG_L	t4, SBI_TRAP_REGS_OFFSET(t4)(sp)
+	REG_L	t5, SBI_TRAP_REGS_OFFSET(t5)(sp)
+	REG_L	t6, SBI_TRAP_REGS_OFFSET(t6)(sp)
+
+	/* Restore Supervisor mode CSRs */
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(sepc)(sp)
+	csrw	CSR_SEPC, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(satp)(sp)
+	csrw	CSR_SATP, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(sstatus)(sp)
+	csrw	CSR_SSTATUS, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(sie)(sp)
+	csrw	CSR_SIE, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(stvec)(sp)
+	csrw	CSR_STVEC, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(sscratch)(sp)
+	csrw	CSR_SSCRATCH, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(scounteren)(sp)
+	csrw	CSR_SCOUNTEREN, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(scause)(sp)
+	csrw	CSR_SCAUSE, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(stval)(sp)
+	csrw	CSR_STVAL, t0
+	REG_L	t0, SBI_SAVE_CONTEXT_OFFSET(sip)(sp)
+	csrw	CSR_SIP, t0
+
+	/* Restore Machine mode CSRs */
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(mepc)(sp)
+	csrw	CSR_MEPC, t0
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp)
+	csrw	CSR_MSTATUS, t0
+
+	/* Restore T0 */
+	REG_L	t0, SBI_TRAP_REGS_OFFSET(t0)(sp)
+
+	/* Restore SP */
+	REG_L	sp, SBI_TRAP_REGS_OFFSET(sp)(sp)
+	mret
diff --git a/lib/utils/tee/tee_sm_dispatcher.c b/lib/utils/tee/tee_sm_dispatcher.c
new file mode 100644
index 0000000..74e55c5
--- /dev/null
+++ b/lib/utils/tee/tee_sm_dispatcher.c
@@ -0,0 +1,228 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright  2023  Beijing ESWIN Computing Technology Co., Ltd.
+ *
+ * Authors:
+ *   Chen Chaokai <chenchaokai at eswincomputing.com>
+ *   Liu Shiwei <liushiwei at eswincomputing.com>
+ */
+
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_error.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_platform.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_string.h>
+#include <sbi/sbi_types.h>
+#include <sbi_utils/tee/tee_context.h>
+#include <sbi_utils/tee/teeecall_opteed.h>
+#include <sbi_utils/tee/tee_sm_dispatcher.h>
+
+optee_vectors_t *optee_vector_table;
+struct sbi_save_context nsec_cpu_context[OPTEED_CORE_COUNT];
+struct sbi_save_context sec_cpu_context[OPTEED_CORE_COUNT];
+struct sbi_trap_regs cpu_start_context[OPTEED_CORE_COUNT];
+ulong mscratch[OPTEED_CORE_COUNT];
+typedef ulong tee_tmp_trap_stack[1024];
+static tee_tmp_trap_stack tmp_stack[OPTEED_CORE_COUNT];
+
+static ulong get_save_context_addr(uint32_t direction)
+{
+	ulong addr = 0;
+	ulong hartid = current_hartid();
+	switch (direction) {
+	case TEE_SECURE_FLAG:
+		addr = (ulong)&sec_cpu_context[hartid];
+		break;
+	case TEE_NON_SECURE_FLAG:
+		addr = (ulong)&nsec_cpu_context[hartid];
+		break;
+	default:
+		sbi_printf("wrong state\n");
+		while(1)
+			wfi();
+	}
+
+	return addr;
+}
+
+static ulong save_context(const struct sbi_trap_regs *regs)
+{
+	ulong addr = 0;
+	struct sbi_save_context *context = NULL;
+
+	addr = get_save_context_addr(regs->a5);
+	context = (struct sbi_save_context *)addr;
+	if (context != NULL) {
+		sbi_memset(context, 0, sizeof(struct sbi_save_context));
+		sbi_memcpy(context, regs, sizeof(struct sbi_trap_regs));
+	} else {
+		return SBI_EINVAL;
+	}
+
+	context->sepc = csr_read(CSR_SEPC);
+	context->satp = csr_read(CSR_SATP);
+	context->sstatus = csr_read(CSR_SSTATUS);
+	context->sie = csr_read(CSR_SIE);
+	context->stvec = csr_read(CSR_STVEC);
+	context->sscratch = csr_read(CSR_SSCRATCH);
+	context->scounteren = csr_read(CSR_SCOUNTEREN);
+	context->scause = csr_read(CSR_SCAUSE);
+	context->stval = csr_read(CSR_STVAL);
+	context->sip = csr_read(CSR_SIP);
+
+	return SBI_OK;
+}
+
+static void restore_context(ulong ctx_addr)
+{
+	restore_to_supervisor(ctx_addr);
+}
+
+void enter_teeos_start_point(void)
+{
+	uint32_t hartid = current_hartid();
+	mscratch[hartid] = csr_read(CSR_MSCRATCH);
+	csr_write(CSR_MSCRATCH,&tmp_stack[hartid + 1]);
+	sbi_hart_switch_mode(hartid, 0, TEE_ENTRY_ADDR, PRV_S, false);
+}
+
+static void teeos_back(void)
+{
+	uint32_t hartid = current_hartid();
+	struct sbi_trap_regs *optee_ctx = &cpu_start_context[hartid];
+	csr_write(CSR_MSCRATCH,mscratch[hartid]);
+
+	teeos_entry_done((ulong)optee_ctx);
+
+	sbi_printf("Error, should never reach here\n");
+}
+
+static ulong prepare_tee_ctx(ulong funcid, ulong *args, ulong *ctx_addr)
+{
+	uint32_t hartid = current_hartid();
+	struct sbi_trap_regs *tee_regs = (struct sbi_trap_regs *)&sec_cpu_context[hartid];
+	tee_regs->mstatus |= MSTATUS_SUM;
+	struct sbi_save_context *context = (struct sbi_save_context *)tee_regs;
+	context->sstatus |= MSTATUS_SUM;
+	ulong func_type = GET_ECALL_TYPE(funcid);
+
+	if (func_type == ECALL_TYPE_FAST) {
+		tee_regs->mepc = (ulong)&optee_vector_table->fast_smc_entry;
+		tee_regs->a0 = funcid;
+		tee_regs->a1 = args[1];
+		tee_regs->a2 = args[2];
+		tee_regs->a3 = args[3];
+		tee_regs->a4 = args[4];
+		tee_regs->a5 = args[5];
+	} else if (func_type == ECALL_TYPE_YEILD) {
+		tee_regs->mepc = (ulong)&optee_vector_table->yield_smc_entry;
+		tee_regs->a0 = funcid;
+		tee_regs->a1 = args[1];
+		tee_regs->a2 = args[2];
+		tee_regs->a3 = args[3];
+		tee_regs->a4 = args[4];
+		tee_regs->a5 = args[0];
+	} else
+		return SBI_EFAIL;
+
+	*ctx_addr = (ulong)tee_regs;
+	return SBI_OK;
+}
+
+static ulong prepare_ree_ctx(ulong *args, ulong *ctx_addr)
+{
+	struct sbi_save_context *ns_regs = NULL;
+	uint32_t hartid = current_hartid();
+
+	ns_regs = &nsec_cpu_context[hartid];
+	ns_regs->regs.a0 = args[0];
+	ns_regs->regs.a1 = args[1];
+	ns_regs->regs.a2 = args[2];
+	ns_regs->regs.a3 = args[3];
+	ns_regs->regs.a4 = args[4];
+	ns_regs->regs.a5 = args[5];
+	ns_regs->regs.mepc += 4;
+	*ctx_addr = (ulong)ns_regs;
+
+	return SBI_OK;
+}
+
+void tee_os_init(void)
+{
+	uint32_t hartid = current_hartid();
+	struct sbi_trap_regs *optee_cpu_ctx = &cpu_start_context[hartid];
+
+	sbi_memset(optee_cpu_ctx, 0, sizeof(struct sbi_save_context));
+	entry_teeos((ulong )optee_cpu_ctx);
+}
+
+int sbi_ecall_tee_handler(ulong extid, ulong funcid,
+			  const struct sbi_trap_regs *regs,
+			  ulong *out_val,
+			  struct sbi_trap_info *out_trap)
+{
+	ulong ret;
+	int tee_func_id = funcid;
+	ulong ctx_addr = 0;
+	ulong args[8] = {0};
+	ulong secure_state = 0;
+	args[0] = regs->a0;
+	args[1] = regs->a1;
+	args[2] = regs->a2;
+	args[3] = regs->a3;
+	args[4] = regs->a4;
+	args[5] = regs->a5;
+	args[6] = regs->a6;
+	args[7] = regs->a7;
+	secure_state = args[5];
+
+	ret = save_context(regs);
+	if (ret != SBI_OK) {
+		sbi_printf("save exception context failed\n");
+		return ret;
+	}
+
+	if (secure_state == TEE_NON_SECURE_FLAG) {
+		ret = prepare_tee_ctx(funcid, args, &ctx_addr);
+		if ( ret != SBI_OK) {
+			sbi_printf("Set optee context failed\n");
+			return ret;
+		}
+		restore_context(ctx_addr);
+	} else if (secure_state == TEE_SECURE_FLAG) {
+		switch (tee_func_id) {
+		case TEEECALL_OPTEED_RETURN_ENTRY_DONE:
+		/* Stash the OPTEE entry point information. */
+			optee_vector_table = (optee_vectors_t *)args[1];
+			if (!args[1] || (args[1] & 3)) {
+				sbi_printf("Get TEE vector table failed.\n");
+				while(1);
+					wfi();
+			}
+			teeos_back();
+			break;
+		case TEEECALL_OPTEED_RETURN_CALL_DONE:
+			ret = prepare_ree_ctx(args, &ctx_addr);
+			if (ret != SBI_OK) {
+				sbi_printf("Set ree context failed\n");
+				return ret;
+			}
+			restore_context(ctx_addr);
+			break;
+		default:
+			sbi_printf("Wrong TEE funcid, funcid = %lx\n", funcid);
+			return SBI_EILL;
+		}
+
+	} else {
+		sbi_printf("Wrong secure state!\n");
+		return SBI_EILL;
+	}
+
+	return SBI_OK;
+}
-- 
2.17.1




More information about the opensbi mailing list