// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include "ssmr/memory_ssmr.h" #include "private/tmem_entry.h" #include "private/tmem_error.h" #include "private/tmem_utils.h" #include "public/trusted_mem_api.h" static inline void trusted_mem_type_enum_validate(void) { COMPILE_ASSERT((int)TRUSTED_MEM_REQ_SVP_REGION == (int)TRUSTED_MEM_SVP_REGION); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_SVP_PAGE == (int)TRUSTED_MEM_SVP_PAGE); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_PROT_REGION == (int)TRUSTED_MEM_PROT_REGION); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_PROT_PAGE == (int)TRUSTED_MEM_PROT_PAGE); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_WFD_REGION == (int)TRUSTED_MEM_WFD_REGION); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_WFD_PAGE == (int)TRUSTED_MEM_WFD_PAGE); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_TUI_REGION == (int)TRUSTED_MEM_TUI_REGION); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_HAPP == (int)TRUSTED_MEM_HAPP); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_HAPP_EXTRA == (int)TRUSTED_MEM_HAPP_EXTRA); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_SDSP == (int)TRUSTED_MEM_SDSP); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_SDSP_SHARED == (int)TRUSTED_MEM_SDSP_SHARED); COMPILE_ASSERT((int)TRUSTED_MEM_REQ_2D_FR == (int)TRUSTED_MEM_2D_FR); COMPILE_ASSERT((int)(TRUSTED_MEM_REQ_SAPU_ENGINE_SHM) == (int)TRUSTED_MEM_SAPU_ENGINE_SHM); COMPILE_ASSERT((int)(TRUSTED_MEM_REQ_AP_MD_SHM) == (int)TRUSTED_MEM_AP_MD_SHM); COMPILE_ASSERT((int)(TRUSTED_MEM_REQ_AP_SCP_SHM) == (int)TRUSTED_MEM_AP_SCP_SHM); COMPILE_ASSERT((int)(TRUSTED_MEM_MAX - 1) == (int)TRUSTED_MEM_AP_SCP_SHM); } static inline enum TRUSTED_MEM_TYPE get_mem_type(enum TRUSTED_MEM_REQ_TYPE req_type) { trusted_mem_type_enum_validate(); switch (req_type) { case TRUSTED_MEM_REQ_SVP_REGION: return TRUSTED_MEM_SVP_REGION; case TRUSTED_MEM_REQ_SVP_PAGE: return TRUSTED_MEM_SVP_PAGE; case TRUSTED_MEM_REQ_PROT_REGION: return TRUSTED_MEM_PROT_REGION; case TRUSTED_MEM_REQ_PROT_PAGE: return TRUSTED_MEM_PROT_PAGE; case TRUSTED_MEM_REQ_WFD_REGION: return TRUSTED_MEM_WFD_REGION; case TRUSTED_MEM_REQ_WFD_PAGE: return TRUSTED_MEM_WFD_PAGE; case TRUSTED_MEM_REQ_HAPP: return TRUSTED_MEM_HAPP; case TRUSTED_MEM_REQ_HAPP_EXTRA: return TRUSTED_MEM_HAPP_EXTRA; case TRUSTED_MEM_REQ_SDSP: return TRUSTED_MEM_SDSP; case TRUSTED_MEM_REQ_SDSP_SHARED: return TRUSTED_MEM_SDSP_SHARED; case TRUSTED_MEM_REQ_2D_FR: return TRUSTED_MEM_2D_FR; case TRUSTED_MEM_REQ_SAPU_DATA_SHM: return TRUSTED_MEM_SAPU_DATA_SHM; case TRUSTED_MEM_REQ_SAPU_ENGINE_SHM: return TRUSTED_MEM_SAPU_ENGINE_SHM; case TRUSTED_MEM_REQ_AP_MD_SHM: return TRUSTED_MEM_AP_MD_SHM; case TRUSTED_MEM_REQ_AP_SCP_SHM: return TRUSTED_MEM_AP_SCP_SHM; case TRUSTED_MEM_REQ_TUI_REGION: return TRUSTED_MEM_TUI_REGION; default: pr_info("[TMEM] %s: req_type=%d not found\n", __func__, req_type); return TRUSTED_MEM_SVP_REGION; } } static inline enum TRUSTED_MEM_TYPE get_region_mem_type(enum TRUSTED_MEM_TYPE req_type) { switch (req_type) { case TRUSTED_MEM_SVP_PAGE: return TRUSTED_MEM_SVP_REGION; case TRUSTED_MEM_PROT_PAGE: return TRUSTED_MEM_PROT_REGION; case TRUSTED_MEM_WFD_PAGE: return TRUSTED_MEM_WFD_REGION; default: return req_type; } } int trusted_mem_api_alloc(enum TRUSTED_MEM_REQ_TYPE req_mem_type, u32 alignment, u32 *size, u32 *refcount, u64 *sec_handle, uint8_t *owner, uint32_t id, struct ssheap_buf_info **buf_info) { enum TRUSTED_MEM_TYPE mem_type = get_mem_type(req_mem_type); if ((mem_type == TRUSTED_MEM_SVP_REGION || mem_type == TRUSTED_MEM_SVP_PAGE || mem_type == TRUSTED_MEM_WFD_REGION || mem_type == TRUSTED_MEM_WFD_PAGE) && !is_svp_enabled()) { pr_info("[TMEM][%d] %s: TMEM_OPERATION_NOT_REGISTERED\n", mem_type, __func__); return TMEM_OPERATION_NOT_REGISTERED; } /* Page-Based */ if (is_page_based_memory(mem_type)) { pr_info("[TMEM][%d] %s: page-based: size = 0x%x\n", mem_type, __func__, *size); return tmem_core_alloc_page(mem_type, *size, buf_info); } /* Region-Based */ /* IOMMU need to map 1MB alignment space */ if (alignment == SZ_1M) *size = (((*size - 1) / SZ_1M) + 1) * SZ_1M; /* return error when page-based memory is not enabled */ if (mem_type != get_region_mem_type(mem_type)) { pr_info("[TMEM][%d] %s: page-based disable\n", mem_type, __func__); return TMEM_PARAMETER_ERROR; } pr_info("[TMEM][%d] %s: region-based: size = 0x%x\n", mem_type, __func__, *size); return tmem_core_alloc_chunk(mem_type, alignment, *size, refcount, sec_handle, owner, id, 0); } EXPORT_SYMBOL(trusted_mem_api_alloc); int trusted_mem_api_alloc_zero(enum TRUSTED_MEM_REQ_TYPE mem_type, u32 alignment, u32 size, u32 *refcount, u64 *sec_handle, uint8_t *owner, uint32_t id) { return tmem_core_alloc_chunk(get_mem_type(mem_type), alignment, size, refcount, sec_handle, owner, id, 1); } EXPORT_SYMBOL(trusted_mem_api_alloc_zero); int trusted_mem_api_unref(enum TRUSTED_MEM_REQ_TYPE req_mem_type, u64 sec_handle, uint8_t *owner, uint32_t id, struct ssheap_buf_info *buf_info) { enum TRUSTED_MEM_TYPE mem_type = get_mem_type(req_mem_type); if (is_page_based_memory(mem_type)) return tmem_core_unref_page(mem_type, buf_info); mem_type = get_region_mem_type(mem_type); return tmem_core_unref_chunk(mem_type, sec_handle, owner, id); } EXPORT_SYMBOL(trusted_mem_api_unref); bool trusted_mem_api_get_region_info(enum TRUSTED_MEM_REQ_TYPE mem_type, u64 *pa, u32 *size) { return tmem_core_get_region_info(get_mem_type(mem_type), pa, size); } EXPORT_SYMBOL(trusted_mem_api_get_region_info); int trusted_mem_api_query_pa(enum TRUSTED_MEM_REQ_TYPE mem_type, u32 alignment, u32 size, u32 *refcount, u32 *handle, u8 *owner, u32 id, u32 clean, uint64_t *phy_addr) { #if IS_ENABLED(CONFIG_MTK_GZ_KREE) return tmem_query_gz_handle_to_pa(get_mem_type(mem_type), alignment, size, refcount, handle, owner, id, 0, phy_addr); #else return TMEM_OPERATION_NOT_REGISTERED; #endif } EXPORT_SYMBOL(trusted_mem_api_query_pa); int trusted_mem_ffa_query_pa(u64 *handle, uint64_t *phy_addr) { #if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) if (is_ffa_enabled()) return tmem_query_ffa_handle_to_pa(*handle, phy_addr); else return TMEM_OPERATION_NOT_REGISTERED; #else return TMEM_OPERATION_NOT_REGISTERED; #endif } EXPORT_SYMBOL(trusted_mem_ffa_query_pa); enum TRUSTED_MEM_REQ_TYPE trusted_mem_api_get_page_replace( enum TRUSTED_MEM_REQ_TYPE req_type) { switch (req_type) { case TRUSTED_MEM_REQ_SVP_PAGE: return TRUSTED_MEM_REQ_SVP_REGION; case TRUSTED_MEM_REQ_PROT_PAGE: return TRUSTED_MEM_REQ_PROT_REGION; default: return req_type; } } EXPORT_SYMBOL(trusted_mem_api_get_page_replace);