diff --git a/Android.mk b/Android.mk index 9a2fd6ec26..b80fe8ef86 100644 --- a/Android.mk +++ b/Android.mk @@ -22,6 +22,9 @@ SYNX_VENDOR_BOARDS := pineapple # List of board platforms for which SMCINVOKE_DLKM driver API should be enabled SMCINVOKE_DLKM_BOARDS := pineapple +# List of board platforms for which SMMU_PROXY_DLKM driver API should be enabled +SMMU_PROXY_DLKM_BOARDS := pineapple + CAMERA_SRC_FILES := \ $(addprefix $(LOCAL_PATH)/, $(call all-named-files-under,*.h,drivers dt-bindings include))\ $(addprefix $(LOCAL_PATH)/, $(call all-named-files-under,*.mk,config))\ diff --git a/dependency.mk b/dependency.mk index 9154e41905..747bea077c 100644 --- a/dependency.mk +++ b/dependency.mk @@ -48,5 +48,19 @@ endif # End of check for board platform SMCINVOKE_DLKM_BOARDS endif # End of find smcinvoke_dlkm driver -KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(CAM_MMRM_EXTRA_SYMBOLS) KBUILD_EXTRA_SYMBOLS+=$(CAM_SYNX_EXTRA_SYMBOLS) KBUILD_EXTRA_SYMBOLS+=$(SMCINVOKE_EXTRA_SYMBOLS) -KBUILD_OPTIONS += KBUILD_EXTRA_CONFIGS=$(CAM_MMRM_EXTRA_CONFIGS) KBUILD_EXTRA_CONFIGS+=$(CAM_SYNX_EXTRA_CONFIGS) KBUILD_EXTRA_CONFIGS+=$(CAM_SMCINOKE_EXTRA_CONFIGS) +# Check if this board's product.mk finds smmu_proxy_dlkm.ko driver +ifeq ($(findstring smmu_proxy_dlkm.ko, $(BOARD_VENDOR_KERNEL_MODULES)), smmu_proxy_dlkm.ko) + +ifeq ($(call is-board-platform-in-list, $(SMMU_PROXY_DLKM_BOARDS)),true) +SMMU_PROXY_EXTRA_SYMBOLS ?= $(realpath $(TOP))/$(call intermediates-dir-for,DLKM,smmu_proxy_dlkm.ko)/Module.symvers +$(info camera-kernel: Found smmu proxy driver, adding symbol dependency! $(SMMU_PROXY_EXTRA_SYMBOLS)) +LOCAL_REQUIRED_MODULES += smmu_proxy_dlkm.ko +CAM_SMMU_PROXY_EXTRA_CONFIGS ?= $(realpath $(TOP))/vendor/qcom/opensource/securemsm-kernel/config/sec-kernel_defconfig_smmu_proxy.conf +LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,smmu_proxy_dlkm.ko)/Module.symvers + +endif # End of check for board platform SMMU_PROXY_DLKM_BOARDS + +endif # End of find smmu_proxy_dlkm driver + +KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(CAM_MMRM_EXTRA_SYMBOLS) KBUILD_EXTRA_SYMBOLS+=$(CAM_SYNX_EXTRA_SYMBOLS) KBUILD_EXTRA_SYMBOLS+=$(SMCINVOKE_EXTRA_SYMBOLS) KBUILD_EXTRA_SYMBOLS+=$(SMMU_PROXY_EXTRA_SYMBOLS) +KBUILD_OPTIONS += KBUILD_EXTRA_CONFIGS=$(CAM_MMRM_EXTRA_CONFIGS) KBUILD_EXTRA_CONFIGS+=$(CAM_SYNX_EXTRA_CONFIGS) KBUILD_EXTRA_CONFIGS+=$(CAM_SMCINOKE_EXTRA_CONFIGS) KBUILD_EXTRA_CONFIGS+=$(CAM_SMMU_PROXY_EXTRA_CONFIGS) diff --git a/drivers/cam_req_mgr/cam_mem_mgr.c b/drivers/cam_req_mgr/cam_mem_mgr.c index 5fae97cf2a..a087e96519 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/cam_req_mgr/cam_mem_mgr.c @@ -258,6 +258,8 @@ int cam_mem_mgr_init(void) cam_common_register_mini_dump_cb(cam_mem_mgr_mini_dump_cb, "cam_mem", NULL); + cam_smmu_get_csf_version(&tbl.csf_version); + return 0; put_heaps: #if IS_REACHABLE(CONFIG_DMABUF_HEAPS) @@ -714,11 +716,15 @@ static int cam_mem_util_get_dma_buf(size_t len, } if (cam_flags & CAM_MEM_FLAG_PROTECTED_MODE) { - heap = tbl.secure_display_heap; - - vmids[num_vmids] = VMID_CP_CAMERA; - perms[num_vmids] = PERM_READ | PERM_WRITE; - num_vmids++; + if (IS_CSF25(tbl.csf_version.arch_ver, tbl.csf_version.max_ver)) { + heap = tbl.system_heap; + len = cam_align_dma_buf_size(len); + } else { + heap = tbl.secure_display_heap; + vmids[num_vmids] = VMID_CP_CAMERA; + perms[num_vmids] = PERM_READ | PERM_WRITE; + num_vmids++; + } if (cam_flags & CAM_MEM_FLAG_CDSP_OUTPUT) { CAM_DBG(CAM_MEM, "Secure mode CDSP flags"); @@ -783,7 +789,8 @@ static int cam_mem_util_get_dma_buf(size_t len, *i_ino = file_inode((*buf)->file)->i_ino; - if ((cam_flags & CAM_MEM_FLAG_PROTECTED_MODE) || + if (((cam_flags & CAM_MEM_FLAG_PROTECTED_MODE) && + !IS_CSF25(tbl.csf_version.arch_ver, tbl.csf_version.max_ver)) || (cam_flags & CAM_MEM_FLAG_EVA_NOPIXEL)) { if (num_vmids >= CAM_MAX_VMIDS) { CAM_ERR(CAM_MEM, "Insufficient array size for vmids %d", num_vmids); diff --git a/drivers/cam_req_mgr/cam_mem_mgr.h b/drivers/cam_req_mgr/cam_mem_mgr.h index df6f61d064..3ffd28e0a3 100644 --- a/drivers/cam_req_mgr/cam_mem_mgr.h +++ b/drivers/cam_req_mgr/cam_mem_mgr.h @@ -89,6 +89,7 @@ struct cam_mem_buf_queue { * @force_cache_allocs: Force all internal buffer allocations with cache * @need_shared_buffer_padding: Whether padding is needed for shared buffer * allocations. + * @csf_version: Camera security framework version * @system_heap: Handle to system heap * @system_uncached_heap: Handle to system uncached heap * @camera_heap: Handle to camera heap @@ -104,6 +105,7 @@ struct cam_mem_table { size_t dbg_buf_idx; bool force_cache_allocs; bool need_shared_buffer_padding; + struct cam_csf_version csf_version; #if IS_REACHABLE(CONFIG_DMABUF_HEAPS) struct dma_heap *system_heap; struct dma_heap *system_uncached_heap; diff --git a/drivers/cam_smmu/cam_smmu_api.c b/drivers/cam_smmu/cam_smmu_api.c index 562e51d8ec..905147a9a1 100644 --- a/drivers/cam_smmu/cam_smmu_api.c +++ b/drivers/cam_smmu/cam_smmu_api.c @@ -237,6 +237,7 @@ struct cam_iommu_cb_set { bool force_cache_allocs; bool need_shared_buffer_padding; bool is_expanded_memory; + struct cam_csf_version csf_version; }; static const struct of_device_id msm_cam_smmu_dt_match[] = { @@ -327,6 +328,15 @@ struct cam_smmu_mini_dump_info { static struct cam_iommu_cb_set iommu_cb_set; +/* + * This is expected to succeed as the SMMU bind would have + * failed if it could not fetch the CSF version from SMMU proxy + */ +void cam_smmu_get_csf_version(struct cam_csf_version *csf_ver) +{ + memcpy(csf_ver, &iommu_cb_set.csf_version, sizeof(*csf_ver)); +} + static enum dma_data_direction cam_smmu_translate_dir( enum cam_smmu_map_dir dir); @@ -3465,6 +3475,11 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; + if (IS_CSF25(iommu_cb_set.csf_version.arch_ver, + iommu_cb_set.csf_version.max_ver)) + attach->dma_map_attrs = + cam_update_dma_map_attributes(attach->dma_map_attrs); + table = dma_buf_map_attachment(attach, dma_dir); if (IS_ERR_OR_NULL(table)) { CAM_ERR(CAM_SMMU, "Error: dma buf map attachment failed"); @@ -3473,7 +3488,12 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, } /* return addr and len to client */ - *paddr_ptr = sg_phys(table->sgl); + if (IS_CSF25(iommu_cb_set.csf_version.arch_ver, + iommu_cb_set.csf_version.max_ver)) + *paddr_ptr = sg_dma_address(table->sgl); + else + *paddr_ptr = sg_phys(table->sgl); + *len_ptr = (size_t)sg_dma_len(table->sgl); /* fill up mapping_info */ @@ -5405,6 +5425,8 @@ const static struct component_ops cam_smmu_cb_qsmmu_component_ops = { static int cam_smmu_component_bind(struct device *dev, struct device *master_dev, void *data) { + int rc; + INIT_WORK(&iommu_cb_set.smmu_work, cam_smmu_page_fault_work); mutex_init(&iommu_cb_set.payload_list_lock); INIT_LIST_HEAD(&iommu_cb_set.payload_list); @@ -5420,6 +5442,12 @@ static int cam_smmu_component_bind(struct device *dev, cam_common_register_mini_dump_cb(cam_smmu_mini_dump_cb, "cam_smmu", NULL); + rc = cam_smmu_fetch_csf_version(&iommu_cb_set.csf_version); + if (rc) { + CAM_ERR(CAM_SMMU, "Failed to fetch CSF version: %d", rc); + return rc; + } + CAM_DBG(CAM_SMMU, "Main component bound successfully"); return 0; } diff --git a/drivers/cam_smmu/cam_smmu_api.h b/drivers/cam_smmu/cam_smmu_api.h index c8548defdd..0733a8eadf 100644 --- a/drivers/cam_smmu/cam_smmu_api.h +++ b/drivers/cam_smmu/cam_smmu_api.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_SMMU_API_H_ @@ -57,6 +57,22 @@ enum cam_smmu_subregion_id { CAM_SMMU_SUBREGION_MAX, }; +/** + * @brief : Represents camera security framework version + * + * @param arch_ver : Captures the version of the high level secure + * camera architecture. + * @param max_ver : Captures the version of the solution with in the + * high level architecture. + * @param min_ver : Captures the version of the memory assignment + * mechanism with in the solution. + */ +struct cam_csf_version { + uint32_t arch_ver; + uint32_t max_ver; + uint32_t min_ver; +}; + /** * @brief : cam_smmu_pf_info * @@ -502,4 +518,9 @@ bool cam_smmu_is_expanded_memory(void); */ int cam_smmu_is_cb_non_fatal_fault_en(int smmu_hdl, bool *non_fatal_en); +/** + * @brief : API to get CSF version in use that's received from SMMU proxy driver + */ +void cam_smmu_get_csf_version(struct cam_csf_version *csf_ver); + #endif /* _CAM_SMMU_API_H_ */ diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index f7c6eaecd8..7c5a739c9f 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -111,6 +111,47 @@ int cam_cpas_drv_channel_switch_for_dev(const struct device *dev) } #endif +int cam_smmu_fetch_csf_version(struct cam_csf_version *csf_version) +{ +#if KERNEL_VERSION(6, 0, 0) <= LINUX_VERSION_CODE + struct csf_version csf_ver; + int rc; + + /* Fetch CSF version from SMMU proxy driver */ + rc = smmu_proxy_get_csf_version(&csf_ver); + if (rc) { + CAM_ERR(CAM_SMMU, + "Failed to get CSF version from SMMU proxy: %d", rc); + return rc; + } + + csf_version->arch_ver = csf_ver.arch_ver; + csf_version->max_ver = csf_ver.max_ver; + csf_version->min_ver = csf_ver.min_ver; +#else + /* This defaults to the legacy version */ + csf_version->arch_ver = 2; + csf_version->max_ver = 0; + csf_version->min_ver = 0; +#endif + return 0; +} + +unsigned long cam_update_dma_map_attributes(unsigned long attrs) +{ +#if KERNEL_VERSION(6, 0, 0) <= LINUX_VERSION_CODE + attrs |= DMA_ATTR_QTI_SMMU_PROXY_MAP; +#endif + return attrs; +} + +size_t cam_align_dma_buf_size(size_t len) +{ +#if KERNEL_VERSION(6, 0, 0) <= LINUX_VERSION_CODE + len = ALIGN(len, SMMU_PROXY_MEM_ALIGNMENT); +#endif + return len; +} #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length) diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h index 95c3169cd0..5621fac1b3 100644 --- a/drivers/cam_utils/cam_compat.h +++ b/drivers/cam_utils/cam_compat.h @@ -23,6 +23,11 @@ #include "cam_cpastop_hw.h" #include "cam_smmu_api.h" +#if KERNEL_VERSION(6, 0, 0) <= LINUX_VERSION_CODE +#include +#include +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) #include #include @@ -46,6 +51,8 @@ MODULE_IMPORT_NS(DMA_BUF); #include #endif +#define IS_CSF25(x, y) ((((x) == 2) && ((y) == 5)) ? 1 : 0) + struct cam_fw_alloc_info { struct device *fw_dev; void *fw_kva; @@ -100,4 +107,10 @@ int cam_compat_util_get_irq(struct cam_hw_soc_info *soc_info); bool cam_secure_get_vfe_fd_port_config(void); +int cam_smmu_fetch_csf_version(struct cam_csf_version *csf_version); + +unsigned long cam_update_dma_map_attributes(unsigned long attr); + +size_t cam_align_dma_buf_size(size_t len); + #endif /* _CAM_COMPAT_H_ */