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