xref: /optee_os/core/arch/riscv/tee/entry_fast.c (revision d237e616e155e6127ff2399ac5cf90655624b0e9)
157b21489SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
257b21489SMarouene Boubakri /*
357b21489SMarouene Boubakri  * Copyright 2023 NXP
457b21489SMarouene Boubakri  * Copyright (c) 2015-2021, Linaro Limited
557b21489SMarouene Boubakri  * Copyright (c) 2014, STMicroelectronics International N.V.
657b21489SMarouene Boubakri  */
757b21489SMarouene Boubakri 
857b21489SMarouene Boubakri #include <config.h>
957b21489SMarouene Boubakri #include <kernel/boot.h>
1057b21489SMarouene Boubakri #include <kernel/misc.h>
1157b21489SMarouene Boubakri #include <kernel/notif.h>
1257b21489SMarouene Boubakri #include <kernel/tee_l2cc_mutex.h>
1357b21489SMarouene Boubakri #include <kernel/virtualization.h>
1457b21489SMarouene Boubakri #include <mm/core_mmu.h>
1557b21489SMarouene Boubakri #include <optee_msg.h>
1657b21489SMarouene Boubakri #include <tee/entry_fast.h>
1757b21489SMarouene Boubakri #include <tee/optee_abi.h>
1857b21489SMarouene Boubakri 
1957b21489SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
tee_entry_get_shm_config(struct thread_abi_args * args)2057b21489SMarouene Boubakri static void tee_entry_get_shm_config(struct thread_abi_args *args)
2157b21489SMarouene Boubakri {
2257b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_OK;
2357b21489SMarouene Boubakri 	args->a1 = default_nsec_shm_paddr;
2457b21489SMarouene Boubakri 	args->a2 = default_nsec_shm_size;
2557b21489SMarouene Boubakri 	/* Should this be TEEABI cache attributes instead? */
2657b21489SMarouene Boubakri 	args->a3 = core_mmu_is_shm_cached();
2757b21489SMarouene Boubakri }
2857b21489SMarouene Boubakri #endif
2957b21489SMarouene Boubakri 
tee_entry_fastcall_l2cc_mutex(struct thread_abi_args * args)3057b21489SMarouene Boubakri static void tee_entry_fastcall_l2cc_mutex(struct thread_abi_args *args)
3157b21489SMarouene Boubakri {
3257b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION;
3357b21489SMarouene Boubakri }
3457b21489SMarouene Boubakri 
tee_entry_exchange_capabilities(struct thread_abi_args * args)3557b21489SMarouene Boubakri static void tee_entry_exchange_capabilities(struct thread_abi_args *args)
3657b21489SMarouene Boubakri {
3757b21489SMarouene Boubakri 	bool res_shm_en = IS_ENABLED(CFG_CORE_RESERVED_SHM);
3857b21489SMarouene Boubakri 	bool dyn_shm_en __maybe_unused = false;
3957b21489SMarouene Boubakri 
4057b21489SMarouene Boubakri 	/*
4157b21489SMarouene Boubakri 	 * Currently we ignore OPTEE_ABI_NSEC_CAP_UNIPROCESSOR.
4257b21489SMarouene Boubakri 	 *
4357b21489SMarouene Boubakri 	 * The memory mapping of shared memory is defined as normal
4457b21489SMarouene Boubakri 	 * shared memory for SMP systems and normal memory for UP
4557b21489SMarouene Boubakri 	 * systems. Currently we map all memory as shared in secure
4657b21489SMarouene Boubakri 	 * world.
4757b21489SMarouene Boubakri 	 *
4857b21489SMarouene Boubakri 	 * When translation tables are created with shared bit cleared for
4957b21489SMarouene Boubakri 	 * uniprocessor systems we'll need to check
5057b21489SMarouene Boubakri 	 * OPTEE_ABI_NSEC_CAP_UNIPROCESSOR.
5157b21489SMarouene Boubakri 	 */
5257b21489SMarouene Boubakri 
5357b21489SMarouene Boubakri 	if (args->a1 & ~OPTEE_ABI_NSEC_CAP_UNIPROCESSOR) {
5457b21489SMarouene Boubakri 		/* Unknown capability. */
5557b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
5657b21489SMarouene Boubakri 		return;
5757b21489SMarouene Boubakri 	}
5857b21489SMarouene Boubakri 
5957b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_OK;
6057b21489SMarouene Boubakri 	args->a1 = 0;
6157b21489SMarouene Boubakri 
6257b21489SMarouene Boubakri 	if (res_shm_en)
6357b21489SMarouene Boubakri 		args->a1 |= OPTEE_ABI_SEC_CAP_HAVE_RESERVED_SHM;
6457b21489SMarouene Boubakri 	IMSG("Reserved shared memory is %sabled", res_shm_en ? "en" : "dis");
6557b21489SMarouene Boubakri 
6657b21489SMarouene Boubakri #if defined(CFG_CORE_DYN_SHM)
6757b21489SMarouene Boubakri 	dyn_shm_en = core_mmu_nsec_ddr_is_defined();
6857b21489SMarouene Boubakri 	if (dyn_shm_en)
6957b21489SMarouene Boubakri 		args->a1 |= OPTEE_ABI_SEC_CAP_DYNAMIC_SHM;
7057b21489SMarouene Boubakri #endif
7157b21489SMarouene Boubakri 	IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis");
7257b21489SMarouene Boubakri 
7357b21489SMarouene Boubakri 	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
7457b21489SMarouene Boubakri 		args->a1 |= OPTEE_ABI_SEC_CAP_VIRTUALIZATION;
7557b21489SMarouene Boubakri 	IMSG("Normal World virtualization support is %sabled",
7657b21489SMarouene Boubakri 	     IS_ENABLED(CFG_NS_VIRTUALIZATION) ? "en" : "dis");
7757b21489SMarouene Boubakri 
7857b21489SMarouene Boubakri 	args->a1 |= OPTEE_ABI_SEC_CAP_MEMREF_NULL;
7957b21489SMarouene Boubakri 
8057b21489SMarouene Boubakri 	if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) {
8157b21489SMarouene Boubakri 		args->a1 |= OPTEE_ABI_SEC_CAP_ASYNC_NOTIF;
8257b21489SMarouene Boubakri 		args->a2 = NOTIF_VALUE_MAX;
8357b21489SMarouene Boubakri 	}
8457b21489SMarouene Boubakri 	IMSG("Asynchronous notifications are %sabled",
8557b21489SMarouene Boubakri 	     IS_ENABLED(CFG_CORE_ASYNC_NOTIF) ? "en" : "dis");
8657b21489SMarouene Boubakri 
8757b21489SMarouene Boubakri 	args->a1 |= OPTEE_ABI_SEC_CAP_RPC_ARG;
8857b21489SMarouene Boubakri 	args->a3 = THREAD_RPC_MAX_NUM_PARAMS;
8957b21489SMarouene Boubakri }
9057b21489SMarouene Boubakri 
tee_entry_disable_shm_cache(struct thread_abi_args * args)9157b21489SMarouene Boubakri static void tee_entry_disable_shm_cache(struct thread_abi_args *args)
9257b21489SMarouene Boubakri {
9357b21489SMarouene Boubakri 	uint64_t cookie;
9457b21489SMarouene Boubakri 
9557b21489SMarouene Boubakri 	if (!thread_disable_prealloc_rpc_cache(&cookie)) {
9657b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_EBUSY;
9757b21489SMarouene Boubakri 		return;
9857b21489SMarouene Boubakri 	}
9957b21489SMarouene Boubakri 
10057b21489SMarouene Boubakri 	if (!cookie) {
10157b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
10257b21489SMarouene Boubakri 		return;
10357b21489SMarouene Boubakri 	}
10457b21489SMarouene Boubakri 
10557b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_OK;
10657b21489SMarouene Boubakri 	args->a1 = cookie >> 32;
10757b21489SMarouene Boubakri 	args->a2 = cookie;
10857b21489SMarouene Boubakri }
10957b21489SMarouene Boubakri 
tee_entry_enable_shm_cache(struct thread_abi_args * args)11057b21489SMarouene Boubakri static void tee_entry_enable_shm_cache(struct thread_abi_args *args)
11157b21489SMarouene Boubakri {
11257b21489SMarouene Boubakri 	if (thread_enable_prealloc_rpc_cache())
11357b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_OK;
11457b21489SMarouene Boubakri 	else
11557b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_EBUSY;
11657b21489SMarouene Boubakri }
11757b21489SMarouene Boubakri 
tee_entry_boot_secondary(struct thread_abi_args * args)11857b21489SMarouene Boubakri static void tee_entry_boot_secondary(struct thread_abi_args *args)
11957b21489SMarouene Boubakri {
12057b21489SMarouene Boubakri #if defined(CFG_BOOT_SECONDARY_REQUEST)
12157b21489SMarouene Boubakri 	if (!boot_core_release(args->a1, (paddr_t)(args->a3)))
12257b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_OK;
12357b21489SMarouene Boubakri 	else
12457b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_EBADCMD;
12557b21489SMarouene Boubakri #else
12657b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
12757b21489SMarouene Boubakri #endif
12857b21489SMarouene Boubakri }
12957b21489SMarouene Boubakri 
tee_entry_get_thread_count(struct thread_abi_args * args)13057b21489SMarouene Boubakri static void tee_entry_get_thread_count(struct thread_abi_args *args)
13157b21489SMarouene Boubakri {
13257b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_OK;
13357b21489SMarouene Boubakri 	args->a1 = CFG_NUM_THREADS;
13457b21489SMarouene Boubakri }
13557b21489SMarouene Boubakri 
13657b21489SMarouene Boubakri #if defined(CFG_NS_VIRTUALIZATION)
tee_entry_vm_created(struct thread_abi_args * args)13757b21489SMarouene Boubakri static void tee_entry_vm_created(struct thread_abi_args *args)
13857b21489SMarouene Boubakri {
13957b21489SMarouene Boubakri 	uint16_t guest_id = args->a1;
14057b21489SMarouene Boubakri 
14157b21489SMarouene Boubakri 	/* Only hypervisor can issue this request */
14257b21489SMarouene Boubakri 	if (args->a7 != HYP_CLNT_ID) {
14357b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
14457b21489SMarouene Boubakri 		return;
14557b21489SMarouene Boubakri 	}
14657b21489SMarouene Boubakri 
14757b21489SMarouene Boubakri 	if (virt_guest_created(guest_id))
14857b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
14957b21489SMarouene Boubakri 	else
15057b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_OK;
15157b21489SMarouene Boubakri }
15257b21489SMarouene Boubakri 
tee_entry_vm_destroyed(struct thread_abi_args * args)15357b21489SMarouene Boubakri static void tee_entry_vm_destroyed(struct thread_abi_args *args)
15457b21489SMarouene Boubakri {
15557b21489SMarouene Boubakri 	uint16_t guest_id = args->a1;
15657b21489SMarouene Boubakri 
15757b21489SMarouene Boubakri 	/* Only hypervisor can issue this request */
15857b21489SMarouene Boubakri 	if (args->a7 != HYP_CLNT_ID) {
15957b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
16057b21489SMarouene Boubakri 		return;
16157b21489SMarouene Boubakri 	}
16257b21489SMarouene Boubakri 
16357b21489SMarouene Boubakri 	if (virt_guest_destroyed(guest_id))
16457b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL;
16557b21489SMarouene Boubakri 	else
16657b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_OK;
16757b21489SMarouene Boubakri }
16857b21489SMarouene Boubakri #endif
16957b21489SMarouene Boubakri 
17057b21489SMarouene Boubakri /* Note: this function is weak to let platforms add special handling */
tee_entry_fast(struct thread_abi_args * args)17157b21489SMarouene Boubakri void __weak tee_entry_fast(struct thread_abi_args *args)
17257b21489SMarouene Boubakri {
17357b21489SMarouene Boubakri 	__tee_entry_fast(args);
17457b21489SMarouene Boubakri }
17557b21489SMarouene Boubakri 
get_async_notif_value(struct thread_abi_args * args)17657b21489SMarouene Boubakri static void get_async_notif_value(struct thread_abi_args *args)
17757b21489SMarouene Boubakri {
17857b21489SMarouene Boubakri 	bool value_valid = false;
17957b21489SMarouene Boubakri 	bool value_pending = false;
18057b21489SMarouene Boubakri 
18157b21489SMarouene Boubakri 	args->a0 = OPTEE_ABI_RETURN_OK;
18257b21489SMarouene Boubakri 	args->a1 = notif_get_value(&value_valid, &value_pending);
18357b21489SMarouene Boubakri 	args->a2 = 0;
18457b21489SMarouene Boubakri 	if (value_valid)
18557b21489SMarouene Boubakri 		args->a2 |= OPTEE_ABI_ASYNC_NOTIF_VALID;
18657b21489SMarouene Boubakri 	if (value_pending)
18757b21489SMarouene Boubakri 		args->a2 |= OPTEE_ABI_ASYNC_NOTIF_PENDING;
18857b21489SMarouene Boubakri }
18957b21489SMarouene Boubakri 
19057b21489SMarouene Boubakri /*
19157b21489SMarouene Boubakri  * If tee_entry_fast() is overridden, it's still supposed to call this
19257b21489SMarouene Boubakri  * function.
19357b21489SMarouene Boubakri  */
__tee_entry_fast(struct thread_abi_args * args)19457b21489SMarouene Boubakri void __tee_entry_fast(struct thread_abi_args *args)
19557b21489SMarouene Boubakri {
19657b21489SMarouene Boubakri 	switch (args->a0) {
19757b21489SMarouene Boubakri 	/* Generic functions */
19857b21489SMarouene Boubakri 	case OPTEE_ABI_CALLS_COUNT:
19957b21489SMarouene Boubakri 		tee_entry_get_api_call_count(args);
20057b21489SMarouene Boubakri 		break;
20157b21489SMarouene Boubakri 	case OPTEE_ABI_CALLS_UID:
20257b21489SMarouene Boubakri 		tee_entry_get_api_uuid(args);
20357b21489SMarouene Boubakri 		break;
20457b21489SMarouene Boubakri 	case OPTEE_ABI_CALLS_REVISION:
20557b21489SMarouene Boubakri 		tee_entry_get_api_revision(args);
20657b21489SMarouene Boubakri 		break;
20757b21489SMarouene Boubakri 	case OPTEE_ABI_CALL_GET_OS_UUID:
20857b21489SMarouene Boubakri 		tee_entry_get_os_uuid(args);
20957b21489SMarouene Boubakri 		break;
21057b21489SMarouene Boubakri 	case OPTEE_ABI_CALL_GET_OS_REVISION:
21157b21489SMarouene Boubakri 		tee_entry_get_os_revision(args);
21257b21489SMarouene Boubakri 		break;
21357b21489SMarouene Boubakri 
21457b21489SMarouene Boubakri 	/* OP-TEE specific ABI functions */
21557b21489SMarouene Boubakri #ifdef CFG_CORE_RESERVED_SHM
21657b21489SMarouene Boubakri 	case OPTEE_ABI_GET_SHM_CONFIG:
21757b21489SMarouene Boubakri 		tee_entry_get_shm_config(args);
21857b21489SMarouene Boubakri 		break;
21957b21489SMarouene Boubakri #endif
22057b21489SMarouene Boubakri 	case OPTEE_ABI_L2CC_MUTEX:
22157b21489SMarouene Boubakri 		tee_entry_fastcall_l2cc_mutex(args);
22257b21489SMarouene Boubakri 		break;
22357b21489SMarouene Boubakri 	case OPTEE_ABI_EXCHANGE_CAPABILITIES:
22457b21489SMarouene Boubakri 		tee_entry_exchange_capabilities(args);
22557b21489SMarouene Boubakri 		break;
22657b21489SMarouene Boubakri 	case OPTEE_ABI_DISABLE_SHM_CACHE:
22757b21489SMarouene Boubakri 		tee_entry_disable_shm_cache(args);
22857b21489SMarouene Boubakri 		break;
22957b21489SMarouene Boubakri 	case OPTEE_ABI_ENABLE_SHM_CACHE:
23057b21489SMarouene Boubakri 		tee_entry_enable_shm_cache(args);
23157b21489SMarouene Boubakri 		break;
23257b21489SMarouene Boubakri 	case OPTEE_ABI_BOOT_SECONDARY:
23357b21489SMarouene Boubakri 		tee_entry_boot_secondary(args);
23457b21489SMarouene Boubakri 		break;
23557b21489SMarouene Boubakri 	case OPTEE_ABI_GET_THREAD_COUNT:
23657b21489SMarouene Boubakri 		tee_entry_get_thread_count(args);
23757b21489SMarouene Boubakri 		break;
23857b21489SMarouene Boubakri 
23957b21489SMarouene Boubakri #if defined(CFG_NS_VIRTUALIZATION)
24057b21489SMarouene Boubakri 	case OPTEE_ABI_VM_CREATED:
24157b21489SMarouene Boubakri 		tee_entry_vm_created(args);
24257b21489SMarouene Boubakri 		break;
24357b21489SMarouene Boubakri 	case OPTEE_ABI_VM_DESTROYED:
24457b21489SMarouene Boubakri 		tee_entry_vm_destroyed(args);
24557b21489SMarouene Boubakri 		break;
24657b21489SMarouene Boubakri #endif
24757b21489SMarouene Boubakri 
24857b21489SMarouene Boubakri 	case OPTEE_ABI_ENABLE_ASYNC_NOTIF:
24957b21489SMarouene Boubakri 		if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) {
250*d237e616SJens Wiklander 			notif_deliver_atomic_event(NOTIF_EVENT_STARTED, 0);
25157b21489SMarouene Boubakri 			args->a0 = OPTEE_ABI_RETURN_OK;
25257b21489SMarouene Boubakri 		} else {
25357b21489SMarouene Boubakri 			args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION;
25457b21489SMarouene Boubakri 		}
25557b21489SMarouene Boubakri 		break;
25657b21489SMarouene Boubakri 	case OPTEE_ABI_GET_ASYNC_NOTIF_VALUE:
25757b21489SMarouene Boubakri 		if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
25857b21489SMarouene Boubakri 			get_async_notif_value(args);
25957b21489SMarouene Boubakri 		else
26057b21489SMarouene Boubakri 			args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION;
26157b21489SMarouene Boubakri 		break;
26257b21489SMarouene Boubakri 
26357b21489SMarouene Boubakri 	default:
26457b21489SMarouene Boubakri 		args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION;
26557b21489SMarouene Boubakri 		break;
26657b21489SMarouene Boubakri 	}
26757b21489SMarouene Boubakri }
26857b21489SMarouene Boubakri 
tee_entry_generic_get_api_call_count(void)26957b21489SMarouene Boubakri size_t tee_entry_generic_get_api_call_count(void)
27057b21489SMarouene Boubakri {
27157b21489SMarouene Boubakri 	/*
27257b21489SMarouene Boubakri 	 * All the different calls handled in this file. If the specific
27357b21489SMarouene Boubakri 	 * target has additional calls it will call this function and
27457b21489SMarouene Boubakri 	 * add the number of calls the target has added.
27557b21489SMarouene Boubakri 	 */
27657b21489SMarouene Boubakri 	size_t ret = 12;
27757b21489SMarouene Boubakri 
27857b21489SMarouene Boubakri 	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
27957b21489SMarouene Boubakri 		ret += 2;
28057b21489SMarouene Boubakri 
28157b21489SMarouene Boubakri 	return ret;
28257b21489SMarouene Boubakri }
28357b21489SMarouene Boubakri 
tee_entry_get_api_call_count(struct thread_abi_args * args)28457b21489SMarouene Boubakri void __weak tee_entry_get_api_call_count(struct thread_abi_args *args)
28557b21489SMarouene Boubakri {
28657b21489SMarouene Boubakri 	args->a0 = tee_entry_generic_get_api_call_count();
28757b21489SMarouene Boubakri }
28857b21489SMarouene Boubakri 
tee_entry_get_api_uuid(struct thread_abi_args * args)28957b21489SMarouene Boubakri void __weak tee_entry_get_api_uuid(struct thread_abi_args *args)
29057b21489SMarouene Boubakri {
29157b21489SMarouene Boubakri 	args->a0 = OPTEE_MSG_UID_0;
29257b21489SMarouene Boubakri 	args->a1 = OPTEE_MSG_UID_1;
29357b21489SMarouene Boubakri 	args->a2 = OPTEE_MSG_UID_2;
29457b21489SMarouene Boubakri 	args->a3 = OPTEE_MSG_UID_3;
29557b21489SMarouene Boubakri }
29657b21489SMarouene Boubakri 
tee_entry_get_api_revision(struct thread_abi_args * args)29757b21489SMarouene Boubakri void __weak tee_entry_get_api_revision(struct thread_abi_args *args)
29857b21489SMarouene Boubakri {
29957b21489SMarouene Boubakri 	args->a0 = OPTEE_MSG_REVISION_MAJOR;
30057b21489SMarouene Boubakri 	args->a1 = OPTEE_MSG_REVISION_MINOR;
30157b21489SMarouene Boubakri }
30257b21489SMarouene Boubakri 
tee_entry_get_os_uuid(struct thread_abi_args * args)30357b21489SMarouene Boubakri void __weak tee_entry_get_os_uuid(struct thread_abi_args *args)
30457b21489SMarouene Boubakri {
30557b21489SMarouene Boubakri 	args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0;
30657b21489SMarouene Boubakri 	args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1;
30757b21489SMarouene Boubakri 	args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2;
30857b21489SMarouene Boubakri 	args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3;
30957b21489SMarouene Boubakri }
31057b21489SMarouene Boubakri 
tee_entry_get_os_revision(struct thread_abi_args * args)31157b21489SMarouene Boubakri void __weak tee_entry_get_os_revision(struct thread_abi_args *args)
31257b21489SMarouene Boubakri {
31357b21489SMarouene Boubakri 	args->a0 = CFG_OPTEE_REVISION_MAJOR;
31457b21489SMarouene Boubakri 	args->a1 = CFG_OPTEE_REVISION_MINOR;
31557b21489SMarouene Boubakri 	args->a2 = TEE_IMPL_GIT_SHA1;
31657b21489SMarouene Boubakri }
317