diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config index 98021bb9fb20..62dbf7892303 100644 --- a/arch/arm64/configs/vendor/lahaina_GKI.config +++ b/arch/arm64/configs/vendor/lahaina_GKI.config @@ -19,6 +19,9 @@ CONFIG_MSM_CORE_HANG_DETECT=m CONFIG_QCOM_LLCC=m CONFIG_QCOM_LAHAINA_LLCC=m CONFIG_QCOM_IPCC=m +CONFIG_QCOM_SCM=m +CONFIG_QTEE_SHM_BRIDGE=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y CONFIG_HWSPINLOCK_QCOM=m CONFIG_QCOM_SMEM=m diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 59511471a539..f0320692beb0 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -27,6 +27,3 @@ CONFIG_MSM_GLOBAL_SYNX=y CONFIG_MSM_CVP=y CONFIG_ION_POOL_AUTO_REFILL=y CONFIG_MSM_BT_POWER=m -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set -CONFIG_QTEE_SHM_BRIDGE=y diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index a37ed1a677de..b3da58e1c44e 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -235,7 +235,7 @@ config INTEL_STRATIX10_RSU Say Y here if you want Intel RSU support. config QCOM_SCM - bool "Qualcomm Technologies, Inc. SCM Interface" + tristate "Qualcomm Technologies, Inc. SCM Interface" depends on ARM || ARM64 select RESET_CONTROLLER help diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 16a080bdec9b..f678b8055598 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o obj-$(CONFIG_QCOM_SCM) += _qcom_scm.o -_qcom_scm-y += qcom_scm.o qcom_scm-smc.o +_qcom_scm-y += qcom_scm.o qcom_scm-smc.o qcom_smc.o _qcom_scm-$(CONFIG_QTEE_SHM_BRIDGE) += qtee_shmbridge.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index b4b64b925409..77f4cb28a97f 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -15,12 +15,16 @@ #include #include +#include #include "qcom_scm.h" #define MAX_QCOM_SCM_ARGS 10 #define MAX_QCOM_SCM_RETS 3 +#define QCOM_SCM_ATOMIC BIT(0) +#define QCOM_SCM_NORETRY BIT(1) + enum qcom_scm_arg_types { QCOM_SCM_VAL, QCOM_SCM_RO, @@ -181,11 +185,12 @@ static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, } static int qcom_scm_call_smccc(struct device *dev, - struct qcom_scm_desc *desc, bool atomic) + struct qcom_scm_desc *desc, const u32 options) { int arglen = desc->arginfo & 0xf; int i, ret; size_t alloc_len; + const bool atomic = options & QCOM_SCM_ATOMIC; gfp_t flag = atomic ? GFP_ATOMIC : GFP_NOIO; u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL; u32 qcom_smccc_convention = @@ -262,7 +267,8 @@ static int qcom_scm_call_smccc(struct device *dev, mutex_unlock(&qcom_scm_lock); if (res.a0 == QCOM_SCM_V2_EBUSY) { - if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) + if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY || + (options & QCOM_SCM_NORETRY)) break; msleep(QCOM_SCM_EBUSY_WAIT_MS); } @@ -543,6 +549,31 @@ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) } } +/** + * qcom_scm_call_noretry() - Invoke a syscall in the secure world + * @dev: device + * @svc_id: service identifier + * @cmd_id: command identifier + * @desc: Descriptor structure containing arguments and return values + * + * Sends a command to the SCM and waits for the command to finish processing. + * This should *only* be called in pre-emptible context. + */ +static int qcom_scm_call_noretry(struct device *dev, struct qcom_scm_desc *desc) +{ + might_sleep(); + switch (__get_convention()) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, QCOM_SCM_NORETRY); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } +} + /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus @@ -665,6 +696,20 @@ int __qcom_scm_sec_wdog_deactivate(struct device *dev) return qcom_scm_call(dev, &desc); } +int __qcom_scm_sec_wdog_trigger(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SEC_WDOG_TRIGGER, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) { struct qcom_scm_desc desc = { @@ -683,6 +728,20 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) return ret ? : desc.res[0]; } +int __qcom_scm_spin_cpu(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SPIN_CPU, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = 0; + desc.arginfo = QCOM_SCM_ARGS(1); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { struct qcom_scm_desc desc = { @@ -698,6 +757,19 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_config_cpu_errata(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_CONFIG_CPU_ERRATA, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.arginfo = 0xffffffff; + + return qcom_scm_call(dev, &desc); +} + bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) { int ret; @@ -823,6 +895,28 @@ int __qcom_scm_get_sec_dump_state(struct device *dev, u32 *dump_state) return ret; } +int __qcom_scm_tz_blsp_modify_owner(struct device *dev, int food, u64 subsystem, + int *out) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_TZ, + .cmd = QOCM_SCM_TZ_BLSP_MODIFY_OWNER, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = subsystem; + desc.args[1] = food; + desc.arginfo = QCOM_SCM_ARGS(2); + + ret = qcom_scm_call(dev, &desc); + + if (out) + *out = desc.res[0]; + + return ret; +} + int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val) { @@ -858,6 +952,19 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_io_reset(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_RESET, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); +} + int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) { int ret; @@ -989,6 +1096,25 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, return ret; } +int __qcom_scm_mem_protect_video(struct device *dev, + u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_MEM_PROTECT_VIDEO, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = cp_start; + desc.args[1] = cp_size; + desc.args[2] = cp_nonpixel_start; + desc.args[3] = cp_nonpixel_size; + desc.arginfo = QCOM_SCM_ARGS(4); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, size_t size) { @@ -1008,6 +1134,33 @@ int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, return ret; } +int __qcom_scm_mem_protect_lock_id2_flat(struct device *dev, + phys_addr_t list_addr, size_t list_size, + size_t chunk_size, size_t memory_usage, + int lock) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_MEM_PROTECT_LOCK_ID2_FLAT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = list_addr; + desc.args[1] = list_size; + desc.args[2] = chunk_size; + desc.args[3] = memory_usage; + desc.args[4] = lock; + desc.args[5] = 0; + + desc.arginfo = QCOM_SCM_ARGS(6, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + int __qcom_scm_iommu_secure_map(struct device *dev, phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len) @@ -1088,6 +1241,317 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, return ret ? : desc.res[0]; } +int __qcom_scm_mem_protect_sd_ctrl(struct device *dev, u32 devid, + phys_addr_t mem_addr, u64 mem_size, u32 vmid) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_CMD_SD_CTRL, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = devid; + desc.args[1] = mem_addr; + desc.args[2] = mem_size; + desc.args[3] = vmid; + desc.arginfo = QCOM_SCM_ARGS(4); + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, + unsigned int num_context_bank) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_CP_SMMU_APERTURE_ID, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = 0xffff0000 | ((QCOM_SCM_CP_APERTURE_REG & 0xff) << 8) | + (num_context_bank & 0xff); + desc.args[1] = 0xffffffff; + desc.args[2] = 0xffffffff; + desc.args[3] = 0xffffffff; + desc.arginfo = QCOM_SCM_ARGS(4); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + +/** + * The following shmbridge functions should be called before the SCM driver + * has been initialized. If not, there could be errors that might cause the + * system to crash. + */ +int __qcom_scm_enable_shm_bridge(struct device *dev) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MEMP_SHM_BRIDGE_ENABLE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_delete_shm_bridge(struct device *dev, u64 handle) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MEMP_SHM_BRIDGE_DELETE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = handle; + desc.arginfo = QCOM_SCM_ARGS(1, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + +int __qcom_scm_create_shm_bridge(struct device *dev, u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, + u64 ns_vmids, u64 *handle) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MEMP_SHM_BRDIGE_CREATE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = pfn_and_ns_perm_flags; + desc.args[1] = ipfn_and_s_perm_flags; + desc.args[2] = size_and_flags; + desc.args[3] = ns_vmids; + + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (handle) + *handle = desc.res[1]; + + return ret ? : desc.res[0]; +} + +int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, int cb_num, + int operation) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_SMMU_PREPARE_ATOS_ID, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = dev_id; + desc.args[1] = cb_num; + desc.args[2] = operation; + + desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + +int __qcom_mdf_assign_memory_to_subsys(struct device *dev, u64 start_addr, + u64 end_addr, phys_addr_t paddr, u64 size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_MPU_LOCK_NS_REGION, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = start_addr; + desc.args[1] = end_addr; + desc.args[2] = paddr; + desc.args[3] = size; + desc.arginfo = QCOM_SCM_ARGS(4); + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +bool __qcom_scm_dcvs_core_available(struct device *dev) +{ + return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_INIT) && + __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_UPDATE) && + __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_RESET); +} + +bool __qcom_scm_dcvs_ca_available(struct device *dev) +{ + return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_INIT_CA_V2) && + __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_UPDATE_CA_V2); +} + +int __qcom_scm_dcvs_reset(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_RESET, + .owner = ARM_SMCCC_OWNER_SIP + }; + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_dcvs_init_v2(struct device *dev, phys_addr_t addr, size_t size, + int *version) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_INIT_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = addr; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (ret >= 0) + *version = desc.res[0]; + return ret; +} + +int __qcom_scm_dcvs_init_ca_v2(struct device *dev, phys_addr_t addr, + size_t size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_INIT_CA_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = addr; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_dcvs_update(struct device *dev, int level, s64 total_time, + s64 busy_time) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_UPDATE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = level; + desc.args[1] = total_time; + desc.args[2] = busy_time; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call_atomic(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_dcvs_update_v2(struct device *dev, int level, s64 total_time, + s64 busy_time) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_UPDATE_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = level; + desc.args[1] = total_time; + desc.args[2] = busy_time; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call(dev, &desc); + return ret ? : desc.res[0]; +} + +int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, s64 total_time, + s64 busy_time, int context_count) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_UPDATE_CA_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = level; + desc.args[1] = total_time; + desc.args[2] = busy_time; + desc.args[3] = context_count; + desc.arginfo = QCOM_SCM_ARGS(4); + + ret = qcom_scm_call(dev, &desc); + return ret ? : desc.res[0]; +} + +int __qcom_scm_config_set_ice_key(struct device *dev, uint32_t index, + phys_addr_t paddr, size_t size, + uint32_t cipher, unsigned int data_unit, + unsigned int food) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_CONFIG_SET_ICE_KEY, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = index; + desc.args[1] = paddr; + desc.args[2] = size; + desc.args[3] = cipher; + desc.args[4] = data_unit; + desc.args[5] = food; + desc.arginfo = QCOM_SCM_ARGS(6, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call_noretry(dev, &desc); +} + +int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index, + unsigned int food) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_CLEAR_ICE_KEY, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = index; + desc.args[1] = food; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_noretry(dev, &desc); +} + int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { @@ -1119,11 +1583,142 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, return ret; } +int __qcom_scm_lmh_read_buf_size(struct device *dev, int *size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.arginfo = QCOM_SCM_ARGS(0); + + ret = qcom_scm_call(dev, &desc); + + if (size) + *size = desc.res[0]; + + return ret; +} + +int __qcom_scm_lmh_limit_dcvsh(struct device *dev, phys_addr_t payload, + uint32_t payload_size, u64 limit_node, uint32_t node_id, + u64 version) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_LIMIT_DCVSH, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = payload; + desc.args[1] = payload_size; + desc.args[2] = limit_node; + desc.args[3] = node_id; + desc.args[4] = version; + desc.arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_lmh_debug_read(struct device *dev, phys_addr_t payload, + uint32_t size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_DEBUG_READ, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = payload; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_lmh_debug_config_write(struct device *dev, u64 cmd_id, + phys_addr_t payload, int payload_size, uint32_t *buf, + int buf_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = cmd_id, + .owner = ARM_SMCCC_OWNER_SIP + }; + + if (buf_size < 3) + return -EINVAL; + + desc.args[0] = payload; + desc.args[1] = payload_size; + desc.args[2] = buf[0]; + desc.args[3] = buf[1]; + desc.args[4] = buf[2]; + desc.arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_lmh_get_type(struct device *dev, phys_addr_t payload, + u64 payload_size, u64 debug_type, uint32_t get_from, + uint32_t *size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_DEBUG_GET_TYPE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = payload; + desc.args[1] = payload_size; + desc.args[2] = debug_type; + desc.args[3] = get_from; + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (size) + *size = desc.res[0]; + + return ret; +} + +int __qcom_scm_smmu_change_pgtbl_format(struct device *dev, u64 dev_id, + int cbndx) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, + .cmd = QCOM_SCM_SMMU_CHANGE_PGTBL_FORMAT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = dev_id; + desc.args[1] = cbndx; + desc.args[2] = 1; /* Enable */ + + desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) { struct qcom_scm_desc desc = { .svc = QCOM_SCM_SVC_SMMU_PROGRAM, - .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1, + .cmd = QCOM_SCM_SMMU_SECURE_LUT, .owner = ARM_SMCCC_OWNER_SIP, }; @@ -1134,6 +1729,76 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_smmu_notify_secure_lut(struct device *dev, u64 dev_id, + bool secure) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, + .cmd = QCOM_SCM_SMMU_SECURE_LUT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = dev_id; + desc.args[1] = secure; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, + u64 *out) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_QDSS, + .cmd = QCOM_SCM_QDSS_INVOKE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = addr; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RO, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (out) + *out = desc.res[1]; + + return ret ? : desc.res[0]; +} + +int __qcom_scm_camera_protect_all(struct device *dev, uint32_t protect, + uint32_t param) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_PROTECT_ALL, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = protect; + desc.args[1] = param; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_camera_protect_phy_lanes(struct device *dev, bool protect, + u64 regmask) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_PROTECT_PHY_LANES, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = protect; + desc.args[1] = regmask; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_ice_restore_cfg(struct device *dev) { struct qcom_scm_desc desc = { @@ -1147,6 +1812,105 @@ int __qcom_scm_ice_restore_cfg(struct device *dev) return qcom_scm_call(dev, &desc); } +int __qcom_scm_register_qsee_log_buf(struct device *dev, phys_addr_t buf, + size_t len) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_QSEELOG, + .cmd = QCOM_SCM_QSEELOG_REGISTER, + .owner = ARM_SMCCC_OWNER_TRUSTED_OS + }; + + + desc.args[0] = buf; + desc.args[1] = len; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, + size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size, + int32_t *result, u64 *response_type, unsigned int *data) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMCINVOKE, + .cmd = QCOM_SCM_SMCINVOKE_INVOKE, + .owner = ARM_SMCCC_OWNER_TRUSTED_OS + }; + + desc.args[0] = in_buf; + desc.args[1] = in_buf_size; + desc.args[2] = out_buf; + desc.args[3] = out_buf_size; + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (result) + *result = desc.res[1]; + + if (response_type) + *response_type = desc.res[0]; + + return ret; +} + +int __qcom_scm_invoke_callback_response(struct device *dev, phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *response_type, + unsigned int *data) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMCINVOKE, + .cmd = QCOM_SCM_SMCINVOKE_CB_RSP, + .owner = ARM_SMCCC_OWNER_TRUSTED_OS + }; + + desc.args[0] = out_buf; + desc.args[1] = out_buf_size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (result) + *result = desc.res[1]; + + if (response_type) + *response_type = desc.res[0]; + + if (data) + *data = desc.res[2]; + + return ret; +} + +int __qcom_scm_qseecom_do(u32 cmd_id, struct scm_desc *desc, bool retry) +{ + int _ret; + struct qcom_scm_desc _desc; + + memcpy(&_desc.args, desc->args, sizeof(_desc.args)); + _desc.owner = (cmd_id & 0x3f000000) >> 24; + _desc.svc = (cmd_id & 0xff00) >> 8; + _desc.cmd = (cmd_id & 0xff); + _desc.arginfo = desc->arginfo; + + if (retry) + _ret = qcom_scm_call(NULL, &_desc); + else + _ret = qcom_scm_call_noretry(NULL, &_desc); + + memcpy(desc->ret, &_desc.res, sizeof(_desc.res)); + + return _ret; +} + void __qcom_scm_init(void) { __query_convention(); diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 1eab6f19fc6d..3691cbba9f3c 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -37,19 +37,6 @@ struct qcom_scm { u64 dload_mode_addr; }; -struct qcom_scm_current_perm_info { - __le32 vmid; - __le32 perm; - __le64 ctx; - __le32 ctx_size; - __le32 unused; -}; - -struct qcom_scm_mem_map_info { - __le64 mem_addr; - __le64 mem_size; -}; - static struct qcom_scm *__scm; static int qcom_scm_clk_enable(void) @@ -137,12 +124,24 @@ int qcom_scm_sec_wdog_deactivate(void) } EXPORT_SYMBOL(qcom_scm_sec_wdog_deactivate); +int qcom_scm_sec_wdog_trigger(void) +{ + return __qcom_scm_sec_wdog_trigger(__scm->dev); +} +EXPORT_SYMBOL(qcom_scm_sec_wdog_trigger); + int qcom_scm_set_remote_state(u32 state, u32 id) { return __qcom_scm_set_remote_state(__scm->dev, state, id); } EXPORT_SYMBOL(qcom_scm_set_remote_state); +int qcom_scm_spin_cpu(void) +{ + return __qcom_scm_spin_cpu(__scm->dev); +} +EXPORT_SYMBOL(qcom_scm_spin_cpu); + static void qcom_scm_set_download_mode(bool enable) { bool avail; @@ -166,6 +165,12 @@ static void qcom_scm_set_download_mode(bool enable) dev_err(__scm->dev, "failed to set download mode: %d\n", ret); } +int qcom_scm_config_cpu_errata(void) +{ + return __qcom_scm_config_cpu_errata(__scm->dev); +} +EXPORT_SYMBOL(qcom_scm_config_cpu_errata); + /** * qcom_scm_pas_supported() - Check if the peripheral authentication service is * available for the given peripherial @@ -329,18 +334,47 @@ int qcom_scm_get_sec_dump_state(u32 *dump_state) } EXPORT_SYMBOL(qcom_scm_get_sec_dump_state); +int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, int *out) +{ + return __qcom_scm_tz_blsp_modify_owner(__scm->dev, subsystem, food, + out); +} +EXPORT_SYMBOL(qcom_scm_tz_blsp_modify_owner); + int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { - return __qcom_scm_io_readl(__scm->dev, addr, val); + return __qcom_scm_io_readl(__scm ? __scm->dev : NULL, addr, val); } EXPORT_SYMBOL(qcom_scm_io_readl); int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { - return __qcom_scm_io_writel(__scm->dev, addr, val); + return __qcom_scm_io_writel(__scm ? __scm->dev : NULL, addr, val); } EXPORT_SYMBOL(qcom_scm_io_writel); +/** + * qcom_scm_io_reset() + */ +int qcom_scm_io_reset(void) +{ + return __qcom_scm_io_reset(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_io_reset); + +bool qcom_scm_is_secure_wdog_trigger_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SEC_WDOG_TRIGGER); +} + +bool qcom_scm_is_mode_switch_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SWITCH_MODE); +} +EXPORT_SYMBOL(qcom_scm_is_mode_switch_available); + int qcom_scm_get_jtag_etm_feat_id(u64 *version) { return __qcom_scm_get_feat_version(__scm ? __scm->dev : NULL, @@ -372,12 +406,29 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) } EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); +int qcom_scm_mem_protect_video(u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size) +{ + return __qcom_scm_mem_protect_video(__scm->dev, cp_start, cp_size, + cp_nonpixel_start, cp_nonpixel_size); +} +EXPORT_SYMBOL(qcom_scm_mem_protect_video); + int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size) { return __qcom_scm_mem_protect_region_id(__scm->dev, paddr, size); } EXPORT_SYMBOL(qcom_scm_mem_protect_region_id); +int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, + size_t list_size, size_t chunk_size, + size_t memory_usage, int lock) +{ + return __qcom_scm_mem_protect_lock_id2_flat(__scm->dev, list_addr, + list_size, chunk_size, memory_usage, lock); +} +EXPORT_SYMBOL(qcom_scm_mem_protect_lock_id2_flat); + int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len) @@ -395,6 +446,39 @@ int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, } EXPORT_SYMBOL(qcom_scm_iommu_secure_unmap); +/** + * qcom_scm_assign_mem_regions() - Make a secure call to reassign memory + * ownership of several memory regions + * @mem_regions: A buffer describing the set of memory regions that need to + * be reassigned + * @mem_regions_sz: The size of the buffer describing the set of memory + * regions that need to be reassigned (in bytes) + * @srcvms: A buffer populated with he vmid(s) for the current set of + * owners + * @src_sz: The size of the src_vms buffer (in bytes) + * @newvms: A buffer populated with the new owners and corresponding + * permission flags. + * @newvms_sz: The size of the new_vms buffer (in bytes) + * + * NOTE: It is up to the caller to ensure that the buffers that will be accessed + * by the secure world are cache aligned, and have been flushed prior to + * invoking this call. + * + * Return negative errno on failure, 0 on success. + */ +int qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions, + size_t mem_regions_sz, u32 *srcvms, + size_t src_sz, + struct qcom_scm_current_perm_info *newvms, + size_t newvms_sz) +{ + return __qcom_scm_assign_mem(__scm ? __scm->dev : NULL, + virt_to_phys(mem_regions), mem_regions_sz, + virt_to_phys(srcvms), src_sz, + virt_to_phys(newvms), newvms_sz); +} +EXPORT_SYMBOL(qcom_scm_assign_mem_regions); + /** * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership * @mem_addr: mem region whose ownership need to be reassigned @@ -477,6 +561,160 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, } EXPORT_SYMBOL(qcom_scm_assign_mem); +/** + * qcom_scm_mem_protect_sd_ctrl() - SDE memory protect. + * + */ +int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, u64 mem_size, + u32 vmid) +{ + return __qcom_scm_mem_protect_sd_ctrl(__scm->dev, devid, mem_addr, + mem_size, vmid); +} +EXPORT_SYMBOL(qcom_scm_mem_protect_sd_ctrl); + +bool qcom_scm_kgsl_set_smmu_aperture_available(void) +{ + int ret; + + ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP, + QCOM_SCM_MP_CP_SMMU_APERTURE_ID); + + return ret > 0; +} +EXPORT_SYMBOL(qcom_scm_kgsl_set_smmu_aperture_available); + +int qcom_scm_kgsl_set_smmu_aperture(unsigned int num_context_bank) +{ + return __qcom_scm_kgsl_set_smmu_aperture(__scm->dev, + num_context_bank); +} +EXPORT_SYMBOL(qcom_scm_kgsl_set_smmu_aperture); + +int qcom_scm_enable_shm_bridge(void) +{ + return __qcom_scm_enable_shm_bridge(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_enable_shm_bridge); + +int qcom_scm_delete_shm_bridge(u64 handle) +{ + return __qcom_scm_delete_shm_bridge(__scm ? __scm->dev : NULL, handle); +} +EXPORT_SYMBOL(qcom_scm_delete_shm_bridge); + +int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, u64 ns_vmids, + u64 *handle) +{ + return __qcom_scm_create_shm_bridge(__scm ? __scm->dev : NULL, + pfn_and_ns_perm_flags, ipfn_and_s_perm_flags, + size_and_flags, ns_vmids, handle); +} +EXPORT_SYMBOL(qcom_scm_create_shm_bridge); + +int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation) +{ + return __qcom_scm_smmu_prepare_atos_id(__scm->dev, dev_id, cb_num, + operation); +} +EXPORT_SYMBOL(qcom_scm_smmu_prepare_atos_id); + +/** + * qcom_mdf_assign_memory_to_subsys - SDE memory protect. + * + */ +int qcom_mdf_assign_memory_to_subsys(u64 start_addr, u64 end_addr, + phys_addr_t paddr, u64 size) +{ + return __qcom_mdf_assign_memory_to_subsys(__scm->dev, + start_addr, end_addr, paddr, size); +} +EXPORT_SYMBOL(qcom_mdf_assign_memory_to_subsys); + +int qcom_scm_get_feat_version_cp(u64 *version) +{ + return __qcom_scm_get_feat_version(__scm->dev, QCOM_SCM_MP_CP_FEAT_ID, + version); +} +EXPORT_SYMBOL(qcom_scm_get_feat_version_cp); + +/** + * qcom_scm_dcvs_core_available() - check if core DCVS operations are available + */ +bool qcom_scm_dcvs_core_available(void) +{ + return __qcom_scm_dcvs_core_available(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_dcvs_core_available); + +/** + * qcom_scm_dcvs_ca_available() - check if context aware DCVS operations are + * available + */ +bool qcom_scm_dcvs_ca_available(void) +{ + return __qcom_scm_dcvs_ca_available(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_dcvs_ca_available); + +/** + * qcom_scm_dcvs_reset() + */ +int qcom_scm_dcvs_reset(void) +{ + return __qcom_scm_dcvs_reset(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_dcvs_reset); + +int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, int *version) +{ + return __qcom_scm_dcvs_init_v2(__scm->dev, addr, size, version); +} +EXPORT_SYMBOL(qcom_scm_dcvs_init_v2); + +int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size) +{ + return __qcom_scm_dcvs_init_ca_v2(__scm->dev, addr, size); +} +EXPORT_SYMBOL(qcom_scm_dcvs_init_ca_v2); + +int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time) +{ + return __qcom_scm_dcvs_update(__scm->dev, level, total_time, busy_time); +} +EXPORT_SYMBOL(qcom_scm_dcvs_update); + +int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time) +{ + return __qcom_scm_dcvs_update_v2(__scm->dev, level, total_time, + busy_time); +} +EXPORT_SYMBOL(qcom_scm_dcvs_update_v2); + +int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, + int context_count) +{ + return __qcom_scm_dcvs_update_ca_v2(__scm->dev, level, total_time, + busy_time, context_count); +} +EXPORT_SYMBOL(qcom_scm_dcvs_update_ca_v2); + +int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, size_t size, + uint32_t cipher, unsigned int data_unit, + unsigned int food) +{ + return __qcom_scm_config_set_ice_key(__scm->dev, index, paddr, size, + cipher, data_unit, food); +} +EXPORT_SYMBOL(qcom_scm_config_set_ice_key); + +int qcom_scm_clear_ice_key(uint32_t index, unsigned int food) +{ + return __qcom_scm_clear_ice_key(__scm->dev, index, food); +} +EXPORT_SYMBOL(qcom_scm_clear_ice_key); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * @@ -519,18 +757,144 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) } EXPORT_SYMBOL(qcom_scm_hdcp_req); +bool qcom_scm_is_lmh_debug_set_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_SET); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_set_available); + +bool qcom_scm_is_lmh_debug_read_buf_size_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_read_buf_size_available); + +bool qcom_scm_is_lmh_debug_read_buf_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_READ); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_read_buf_available); + +bool qcom_scm_is_lmh_debug_get_type_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_GET_TYPE); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_get_type_available); + +int qcom_scm_lmh_read_buf_size(int *size) +{ + return __qcom_scm_lmh_read_buf_size(__scm->dev, size); +} +EXPORT_SYMBOL(qcom_scm_lmh_read_buf_size); + +int qcom_scm_lmh_limit_dcvsh(phys_addr_t payload, uint32_t payload_size, + u64 limit_node, uint32_t node_id, u64 version) +{ + return __qcom_scm_lmh_limit_dcvsh(__scm->dev, payload, payload_size, + limit_node, node_id, version); +} +EXPORT_SYMBOL(qcom_scm_lmh_limit_dcvsh); + +int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size) +{ + return __qcom_scm_lmh_debug_read(__scm->dev, payload, size); +} +EXPORT_SYMBOL(qcom_scm_lmh_debug_read); + +int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, int payload_size, + uint32_t *buf, int buf_size) +{ + return __qcom_scm_lmh_debug_config_write(__scm->dev, + QCOM_SCM_LMH_DEBUG_SET, payload, payload_size, buf, + buf_size); +} +EXPORT_SYMBOL(qcom_scm_lmh_debug_set_config_write); + +int qcom_scm_lmh_get_type(phys_addr_t payload, u64 payload_size, + u64 debug_type, uint32_t get_from, uint32_t *size) +{ + return __qcom_scm_lmh_get_type(__scm->dev, payload, payload_size, + debug_type, get_from, size); +} +EXPORT_SYMBOL(qcom_scm_lmh_get_type); + +int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx) +{ + return __qcom_scm_smmu_change_pgtbl_format(__scm->dev, dev_id, cbndx); +} +EXPORT_SYMBOL(qcom_scm_smmu_change_pgtbl_format); + int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en); } EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); +int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure) +{ + return __qcom_scm_smmu_notify_secure_lut(__scm->dev, dev_id, secure); +} +EXPORT_SYMBOL(qcom_scm_smmu_notify_secure_lut); + +int qcom_scm_qdss_invoke(phys_addr_t paddr, size_t size, u64 *out) +{ + return __qcom_scm_qdss_invoke(__scm->dev, paddr, size, out); +} +EXPORT_SYMBOL(qcom_scm_qdss_invoke); + +int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param) +{ + return __qcom_scm_camera_protect_all(__scm->dev, protect, param); +} +EXPORT_SYMBOL(qcom_scm_camera_protect_all); + +int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask) +{ + return __qcom_scm_camera_protect_phy_lanes(__scm->dev, protect, + regmask); +} +EXPORT_SYMBOL(qcom_scm_camera_protect_phy_lanes); + int qcom_scm_ice_restore_cfg(void) { return __qcom_scm_ice_restore_cfg(__scm->dev); } EXPORT_SYMBOL(qcom_scm_ice_restore_cfg); +int qcom_scm_get_tz_log_feat_id(u64 *version) +{ + return __qcom_scm_get_feat_version(__scm->dev, QCOM_SCM_FEAT_LOG_ID, + version); +} +EXPORT_SYMBOL(qcom_scm_get_tz_log_feat_id); + +int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) +{ + return __qcom_scm_register_qsee_log_buf(__scm->dev, buf, len); +} +EXPORT_SYMBOL(qcom_scm_register_qsee_log_buf); + +int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *response_type, unsigned int *data) +{ + return __qcom_scm_invoke_smc(__scm->dev, in_buf, in_buf_size, out_buf, + out_buf_size, result, response_type, data); +} +EXPORT_SYMBOL(qcom_scm_invoke_smc); + +int qcom_scm_invoke_callback_response(phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *response_type, + unsigned int *data) +{ + return __qcom_scm_invoke_callback_response(__scm->dev, out_buf, + out_buf_size, result, response_type, data); +} + /** * qcom_scm_is_available() - Checks if SCM is available */ diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 47c8b8f8174b..87c5520f6f06 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -9,16 +9,23 @@ #define QCOM_SCM_BOOT_SET_ADDR 0x01 #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 #define QCOM_SCM_BOOT_SEC_WDOG_DIS 0x07 +#define QCOM_SCM_BOOT_SEC_WDOG_TRIGGER 0x08 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a +#define QCOM_SCM_BOOT_SPIN_CPU 0x0d +#define QCOM_SCM_BOOT_SWITCH_MODE 0x0f #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 +#define QCOM_SCM_BOOT_CONFIG_CPU_ERRATA 0x12 extern int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); extern void __qcom_scm_cpu_power_down(struct device *dev, u32 flags); extern int __qcom_scm_sec_wdog_deactivate(struct device *dev); +extern int __qcom_scm_sec_wdog_trigger(struct device *dev); extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); +extern int __qcom_scm_spin_cpu(struct device *dev); extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); +extern int __qcom_scm_config_cpu_errata(struct device *dev); #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 #define QCOM_SCM_SVC_PIL 0x02 @@ -41,11 +48,18 @@ extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset); #define QCOM_SCM_UTIL_GET_SEC_DUMP_STATE 0x10 extern int __qcom_scm_get_sec_dump_state(struct device *dev, u32 *dump_state); +#define QCOM_SCM_SVC_TZ 0x04 +#define QOCM_SCM_TZ_BLSP_MODIFY_OWNER 0x03 +extern int __qcom_scm_tz_blsp_modify_owner(struct device *dev, int food, + u64 subsystem, int *out); + #define QCOM_SCM_SVC_IO 0x05 #define QCOM_SCM_IO_READ 0x01 #define QCOM_SCM_IO_WRITE 0x02 +#define QCOM_SCM_IO_RESET 0x03 extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val); extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val); +extern int __qcom_scm_io_reset(struct device *dev); #define QCOM_SCM_SVC_INFO 0x06 #define QCOM_SCM_INFO_IS_CALL_AVAIL 0x01 @@ -55,6 +69,7 @@ extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, extern int __qcom_scm_get_feat_version(struct device *dev, u64 feat_id, u64 *version); #define QCOM_SCM_TZ_DBG_ETM_FEAT_ID 0x08 +#define QCOM_SCM_MP_CP_FEAT_ID 0x0c #define QCOM_SCM_SVC_PWR 0x09 #define QCOM_SCM_PWR_MMU_SYNC 0x08 @@ -64,18 +79,34 @@ extern void __qcom_scm_mmu_sync(struct device *dev, bool sync); #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 +#define QCOM_SCM_MP_MEM_PROTECT_VIDEO 0x08 #define QCOM_SCM_MP_MEM_PROTECT_REGION_ID 0x10 +#define QCOM_SCM_MP_MEM_PROTECT_LOCK_ID2_FLAT 0x11 #define QCOM_SCM_MP_IOMMU_SECURE_MAP2_FLAT 0x12 #define QCOM_SCM_MP_IOMMU_SECURE_UNMAP2_FLAT 0x13 #define QCOM_SCM_MP_ASSIGN 0x16 +#define QCOM_SCM_MP_CMD_SD_CTRL 0x18 +#define QCOM_SCM_MP_CP_SMMU_APERTURE_ID 0x1b +#define QCOM_SCM_MEMP_SHM_BRIDGE_ENABLE 0x1c +#define QCOM_SCM_MEMP_SHM_BRIDGE_DELETE 0x1d +#define QCOM_SCM_MEMP_SHM_BRDIGE_CREATE 0x1e +#define QCOM_SCM_MP_SMMU_PREPARE_ATOS_ID 0x21 +#define QCOM_SCM_MP_MPU_LOCK_NS_REGION 0x25 extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, size_t *size); extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare); +extern int __qcom_scm_mem_protect_video(struct device *dev, + u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size); extern int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, size_t size); +extern int __qcom_scm_mem_protect_lock_id2_flat(struct device *dev, + phys_addr_t list_addr, size_t list_size, + size_t chunk_size, size_t memory_usage, + int lock); extern int __qcom_scm_iommu_secure_map(struct device *dev, phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, @@ -87,24 +118,127 @@ extern int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, size_t mem_sz, phys_addr_t src, size_t src_sz, phys_addr_t dest, size_t dest_sz); +extern int __qcom_scm_mem_protect_sd_ctrl(struct device *dev, u32 devid, + phys_addr_t mem_addr, u64 mem_size, u32 vmid); +extern int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, + unsigned int num_context_bank); +extern int __qcom_scm_enable_shm_bridge(struct device *dev); +extern int __qcom_scm_delete_shm_bridge(struct device *dev, u64 handle); +extern int __qcom_scm_create_shm_bridge(struct device *dev, + u64 pfn_and_ns_perm_flags, u64 ipfn_and_s_perm_flags, + u64 size_and_flags, u64 ns_vmids, u64 *handle); +extern int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, + int cb_num, int operation); +extern int __qcom_mdf_assign_memory_to_subsys(struct device *dev, + u64 start_addr, u64 end_addr, phys_addr_t paddr, u64 size); #define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 +#define QCOM_SCM_CP_APERTURE_REG 0x0 + +#define QCOM_SCM_SVC_DCVS 0x0D +#define QCOM_SCM_DCVS_RESET 0x07 +#define QCOM_SCM_DCVS_UPDATE 0x08 +#define QCOM_SCM_DCVS_INIT 0x09 +#define QCOM_SCM_DCVS_UPDATE_V2 0x0a +#define QCOM_SCM_DCVS_INIT_V2 0x0b +#define QCOM_SCM_DCVS_INIT_CA_V2 0x0c +#define QCOM_SCM_DCVS_UPDATE_CA_V2 0x0d +extern bool __qcom_scm_dcvs_core_available(struct device *dev); +extern bool __qcom_scm_dcvs_ca_available(struct device *dev); +extern int __qcom_scm_dcvs_reset(struct device *dev); +extern int __qcom_scm_dcvs_init_v2(struct device *dev, phys_addr_t addr, + size_t size, int *version); +extern int __qcom_scm_dcvs_init_ca_v2(struct device *dev, phys_addr_t addr, + size_t size); +extern int __qcom_scm_dcvs_update(struct device *dev, int level, + s64 total_time, s64 busy_time); + +extern int __qcom_scm_dcvs_update_v2(struct device *dev, int level, + s64 total_time, s64 busy_time); + +extern int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, + s64 total_time, s64 busy_time, + int context_count); + +#define QCOM_SCM_SVC_ES 0x10 +#define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x05 +#define QCOM_SCM_ES_CLEAR_ICE_KEY 0x06 +extern int __qcom_scm_config_set_ice_key(struct device *dev, uint32_t index, + phys_addr_t paddr, size_t size, + uint32_t cipher, + unsigned int data_unit, + unsigned int food); +extern int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index, + unsigned int food); #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 extern int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); +#define QCOM_SCM_SVC_LMH 0x13 +#define QCOM_SCM_LMH_DEBUG_SET 0x08 +#define QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE 0x09 +#define QCOM_SCM_LMH_LIMIT_DCVSH 0x10 +#define QCOM_SCM_LMH_DEBUG_READ 0x0A +#define QCOM_SCM_LMH_DEBUG_GET_TYPE 0x0B +extern int __qcom_scm_lmh_read_buf_size(struct device *dev, int *size); +extern int __qcom_scm_lmh_limit_dcvsh(struct device *dev, phys_addr_t payload, + uint32_t payload_size, u64 limit_node, uint32_t node_id, + u64 version); +extern int __qcom_scm_lmh_debug_read(struct device *dev, phys_addr_t payload, + uint32_t size); +extern int __qcom_scm_lmh_debug_config_write(struct device *dev, u64 cmd_id, + phys_addr_t payload, int payload_size, uint32_t *buf, + int buf_size); +extern int __qcom_scm_lmh_get_type(struct device *dev, phys_addr_t payload, + u64 payload_size, u64 debug_type, uint32_t get_from, + uint32_t *size); + #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 -#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 +#define QCOM_SCM_SMMU_CHANGE_PGTBL_FORMAT 0x01 +#define QCOM_SCM_SMMU_SECURE_LUT 0x03 +extern int __qcom_scm_smmu_change_pgtbl_format(struct device *dev, u64 dev_id, + int cbndx); extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable); +extern int __qcom_scm_smmu_notify_secure_lut(struct device *dev, u64 dev_id, + bool secure); #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 +#define QCOM_SCM_SVC_QDSS 0x16 +#define QCOM_SCM_QDSS_INVOKE 0x01 +extern int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, + size_t size, u64 *out); + +#define QCOM_SCM_SVC_CAMERA 0x18 +#define QCOM_SCM_CAMERA_PROTECT_ALL 0x06 +#define QCOM_SCM_CAMERA_PROTECT_PHY_LANES 0x07 +extern int __qcom_scm_camera_protect_all(struct device *dev, uint32_t protect, + uint32_t param); +extern int __qcom_scm_camera_protect_phy_lanes(struct device *dev, + bool protect, u64 regmask); + // TOS Services and Function IDs +#define QCOM_SCM_SVC_QSEELOG 0x01 +#define QCOM_SCM_QSEELOG_REGISTER 0x06 +extern int __qcom_scm_register_qsee_log_buf(struct device *dev, phys_addr_t buf, + size_t len); +#define QCOM_SCM_FEAT_LOG_ID 0x0a + #define QCOM_SCM_SVC_KEYSTORE 0x05 #define QCOM_SCM_ICE_RESTORE_KEY_ID 0x06 extern int __qcom_scm_ice_restore_cfg(struct device *dev); +#define QCOM_SCM_SVC_SMCINVOKE 0x06 +#define QCOM_SCM_SMCINVOKE_INVOKE 0x00 +#define QCOM_SCM_SMCINVOKE_CB_RSP 0x01 +extern int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, + size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size, + int32_t *result, u64 *response_type, unsigned int *data); +extern int __qcom_scm_invoke_callback_response(struct device *dev, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *response_type, unsigned int *data); + extern void __qcom_scm_init(void); /* common error codes */ diff --git a/drivers/firmware/qcom_smc.c b/drivers/firmware/qcom_smc.c new file mode 100644 index 000000000000..cf39ee557a2f --- /dev/null +++ b/drivers/firmware/qcom_smc.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + */ +#include +#include +#include + +int qcom_scm_qseecom_call(u32 cmd_id, struct scm_desc *desc) +{ + return __qcom_scm_qseecom_do(cmd_id, desc, true); +} +EXPORT_SYMBOL(qcom_scm_qseecom_call); + +int qcom_scm_qseecom_call_noretry(u32 cmd_id, struct scm_desc *desc) +{ + return __qcom_scm_qseecom_do(cmd_id, desc, false); +} +EXPORT_SYMBOL(qcom_scm_qseecom_call_noretry); diff --git a/drivers/firmware/qtee_shmbridge.c b/drivers/firmware/qtee_shmbridge.c index e24df44e694c..a8c4fbf506f9 100644 --- a/drivers/firmware/qtee_shmbridge.c +++ b/drivers/firmware/qtee_shmbridge.c @@ -11,48 +11,13 @@ #include #include #include -#include +#include #include #include #include "qtee_shmbridge_internal.h" #define DEFAULT_BRIDGE_SIZE SZ_4M /*4M*/ -/* - * tz_enable_shm_bridge - * smc_id: 0x02000C1C - */ -#define TZ_SVC_MEMORY_PROTECTION 12 - -#define TZ_SHM_BRIDGE_ENABLE \ - TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_MEMORY_PROTECTION, 0x1C) - -#define TZ_SHM_BRIDGE_ENABLE_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_0 - -/* - * tz_create_shm_bridge - * smc_id: 0x02000C1E - */ - -#define TZ_SHM_BRIDGE_CREATE \ - TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_MEMORY_PROTECTION, 0x1E) - -#define TZ_SHM_BRIDGE_CREATE_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_4( \ - TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \ - TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL) - -/** - * tz_delete_shm_bridge - * smc_id: 0x02000C1D - */ -#define TZ_SHM_BRIDGE_DELETE \ - TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_MEMORY_PROTECTION, 0x1D) - -#define TZ_SHM_BRIDGE_DELETE_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_1( \ - TZ_SYSCALL_PARAM_TYPE_VAL) #define MAXSHMVMS 4 #define PERM_BITS 3 @@ -118,7 +83,6 @@ static bool qtee_shmbridge_enabled; static int32_t qtee_shmbridge_enable(bool enable) { int32_t ret = 0; - struct scm_desc desc = {0}; qtee_shmbridge_enabled = false; if (!enable) { @@ -126,14 +90,14 @@ static int32_t qtee_shmbridge_enable(bool enable) return ret; } - desc.arginfo = TZ_SHM_BRIDGE_ENABLE_PARAM_ID; - ret = scm_call2(TZ_SHM_BRIDGE_ENABLE, &desc); - if (ret || desc.ret[0]) { - pr_err("Failed to enable shmbridge, rsp = %lld, ret = %d\n", - desc.ret[0], ret); - if (ret == -EIO || desc.ret[0] == SHMBRIDGE_E_NOT_SUPPORTED) + ret = qcom_scm_enable_shm_bridge(); + + if (ret) { + pr_err("Failed to enable shmbridge, ret = %d\n", ret); + + if (ret == -EIO || ret == SHMBRIDGE_E_NOT_SUPPORTED) pr_warn("shmbridge is not supported by this target\n"); - return ret | desc.ret[0]; + return ret; } qtee_shmbridge_enabled = true; pr_warn("shmbridge is enabled\n"); @@ -210,9 +174,11 @@ int32_t qtee_shmbridge_register( { int32_t ret = 0; + uint64_t pfn_and_ns_perm_flags = 0; + uint64_t ipfn_and_s_perm_flags = 0; + uint64_t size_and_flags = 0; uint64_t ns_perms = 0; uint64_t ns_vmids = 0; - struct scm_desc desc = {0}; int i = 0; if (!qtee_shmbridge_enabled) @@ -234,23 +200,23 @@ int32_t qtee_shmbridge_register( ns_vmids = UPDATE_NS_VMIDS(ns_vmids, ns_vmid_list[i]); } - desc.arginfo = TZ_SHM_BRIDGE_CREATE_PARAM_ID; - desc.args[0] = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms); - desc.args[1] = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm); - desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num); - desc.args[3] = ns_vmids; + pfn_and_ns_perm_flags = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms); + ipfn_and_s_perm_flags = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm); + size_and_flags = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num); - pr_debug("%s: arginfo %x, desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n", - __func__, desc.arginfo, desc.args[0], - desc.args[1], desc.args[2], desc.args[3]); - ret = scm_call2(TZ_SHM_BRIDGE_CREATE, &desc); - if (ret || desc.ret[0]) { - pr_err("create shmbridge failed, ret = %d, status = %llx\n", - ret, desc.ret[0]); + pr_debug("%s: desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n", + __func__, pfn_and_ns_perm_flags, ipfn_and_s_perm_flags, + size_and_flags, ns_vmids); + + ret = qcom_scm_create_shm_bridge(pfn_and_ns_perm_flags, + ipfn_and_s_perm_flags, size_and_flags, ns_vmids, + handle); + + if (ret) { + pr_err("create shmbridge failed, ret = %d\n", ret); ret = -EINVAL; goto exit; } - *handle = desc.ret[1]; ret = qtee_shmbridge_list_add_nolock(paddr, *handle); exit: @@ -263,15 +229,14 @@ EXPORT_SYMBOL(qtee_shmbridge_register); int32_t qtee_shmbridge_deregister(uint64_t handle) { int32_t ret = 0; - struct scm_desc desc = {0}; if (!qtee_shmbridge_enabled) return 0; mutex_lock(&bridge_list_head.lock); - desc.arginfo = TZ_SHM_BRIDGE_DELETE_PARAM_ID; - desc.args[0] = handle; - ret = scm_call2(TZ_SHM_BRIDGE_DELETE, &desc); + + ret = qcom_scm_delete_shm_bridge(handle); + if (ret) { pr_err("Failed to del bridge %lld, ret = %d\n", handle, ret); goto exit; diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index e844c3895dd3..356da12ddf43 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "coresight-priv.h" @@ -4103,8 +4103,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_desc desc = { 0 }; static int traceid = TPDM_TRACE_ID_START; uint32_t version; - struct scm_desc des = {0}; - u32 scm_ret = 0; + u32 dump_state = 0; desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name) @@ -4115,10 +4114,8 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) adev->dev.platform_data = pdata; if (of_property_read_bool(adev->dev.of_node, "qcom,hw-enable-check")) { - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_UTIL, - HW_ENABLE_CHECK_VALUE), &des); - scm_ret = des.ret[0]; - if (scm_ret == 0) + ret = qcom_scm_get_sec_dump_state(&dump_state); + if (ret || !dump_state) return -ENXIO; } diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index 2dd7bd920541..cd563b0f6822 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -1184,28 +1184,20 @@ err_create_pkt: static int __tzbsp_set_cvp_state(enum tzbsp_subsys_state state) { - int tzbsp_rsp = 0; int rc = 0; - struct scm_desc desc = {0}; - desc.args[0] = state; - desc.args[1] = TZBSP_CVP_PAS_ID; - desc.arginfo = SCM_ARGS(2); + rc = qcom_scm_set_remote_state(state, TZBSP_CVP_PAS_ID); - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_BOOT, - TZBSP_PIL_SET_STATE), &desc); - tzbsp_rsp = desc.ret[0]; - - if (rc) { - dprintk(CVP_ERR, "Failed scm_call %d\n", rc); + if (rc < 0) { + dprintk(CVP_ERR, "Failed qcom_scm_set_remote_state %d\n", rc); return rc; } - dprintk(CVP_DBG, "Set state %d, resp %d\n", state, tzbsp_rsp); - if (tzbsp_rsp) { + dprintk(CVP_DBG, "Set state %d, resp %d\n", state, rc); + if (rc) { dprintk(CVP_ERR, "Failed to set cvp core state to suspend: %d\n", - tzbsp_rsp); + rc); return -EINVAL; } @@ -3744,50 +3736,7 @@ static void __deinit_resources(struct iris_hfi_device *device) static int __protect_cp_mem(struct iris_hfi_device *device) { - struct cvp_tzbsp_memprot memprot; - unsigned int resp = 0; - int rc = 0; - struct context_bank_info *cb; - struct scm_desc desc = {0}; - - if (!device) - return -EINVAL; - - memprot.cp_start = 0x0; - memprot.cp_size = 0x0; - memprot.cp_nonpixel_start = 0x0; - memprot.cp_nonpixel_size = 0x0; - - list_for_each_entry(cb, &device->res->context_banks, list) { - if (!strcmp(cb->name, "cvp_hlos")) { - desc.args[1] = memprot.cp_size = - cb->addr_range.start; - dprintk(CVP_DBG, "%s memprot.cp_size: %#x\n", - __func__, memprot.cp_size); - } - - if (!strcmp(cb->name, "cvp_sec_nonpixel")) { - desc.args[2] = memprot.cp_nonpixel_start = - cb->addr_range.start; - desc.args[3] = memprot.cp_nonpixel_size = - cb->addr_range.size; - dprintk(CVP_DBG, - "%s memprot.cp_nonpixel_start: %#x size: %#x\n", - __func__, memprot.cp_nonpixel_start, - memprot.cp_nonpixel_size); - } - } - - desc.arginfo = SCM_ARGS(4); - rc = 0; - resp = desc.ret[0]; - - if (rc) { - dprintk(CVP_ERR, "Failed to protect memory(%d) response: %d\n", - rc, resp); - } - - return rc; + return device ? 0 : -EINVAL; } static int __disable_regulator(struct regulator_info *rinfo, diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 288f8d33d01d..73a33eafceb6 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -380,7 +380,7 @@ config QCOM_SECURE_CHAN_MANAGER config QCOM_SECURE_BUFFER tristate "Helper functions for secure buffers through TZ" - depends on QCOM_SECURE_CHAN_MANAGER + depends on QCOM_SCM help Enable for targets that need to call into TZ to secure memory buffers. This ensures that only the correct clients can diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c index 795e1cfc2e5d..ccaaea742a48 100644 --- a/drivers/soc/qcom/dcc_v2.c +++ b/drivers/soc/qcom/dcc_v2.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #define TIMEOUT_US (100) diff --git a/drivers/soc/qcom/memory_dump_v2.c b/drivers/soc/qcom/memory_dump_v2.c index 49f93c9b604c..2eff0ac56faa 100644 --- a/drivers/soc/qcom/memory_dump_v2.c +++ b/drivers/soc/qcom/memory_dump_v2.c @@ -12,15 +12,13 @@ #include #include #include -#include +#include #include #include #include #define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) -#define SCM_CMD_DEBUG_LAR_UNLOCK 0x4 - struct msm_dump_table { uint32_t version; uint32_t num_entries; @@ -227,29 +225,6 @@ err0: } early_initcall(init_memory_dump); -#ifdef CONFIG_MSM_DEBUG_LAR_UNLOCK -static int __init init_debug_lar_unlock(void) -{ - int ret; - uint32_t argument = 0; - struct scm_desc desc = {0}; - - if (!is_scm_armv8()) - ret = scm_call(SCM_SVC_TZ, SCM_CMD_DEBUG_LAR_UNLOCK, &argument, - sizeof(argument), NULL, 0); - else - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TZ, - SCM_CMD_DEBUG_LAR_UNLOCK), &desc); - if (ret) - pr_err("Core Debug Lock unlock failed, ret: %d\n", ret); - else - pr_info("Core Debug Lock unlocked\n"); - - return ret; -} -early_initcall(init_debug_lar_unlock); -#endif - static int mem_dump_probe(struct platform_device *pdev) { struct device_node *child_node; diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c index c5145410b959..ff6932efa770 100644 --- a/drivers/soc/qcom/secure_buffer.c +++ b/drivers/soc/qcom/secure_buffer.c @@ -13,23 +13,22 @@ #include #include #include -#include +#include #include #define CREATE_TRACE_POINTS #include "trace_secure_buffer.h" -#define MEM_PROT_ASSIGN_ID 0x16 #define BATCH_MAX_SIZE SZ_2M #define BATCH_MAX_SECTIONS 32 static struct device *qcom_secure_buffer_dev; -static struct dest_vm_and_perm_info * +static struct qcom_scm_current_perm_info * populate_dest_info(int *dest_vmids, int nelements, int *dest_perms, size_t *size_in_bytes) { - struct dest_vm_and_perm_info *dest_info; + struct qcom_scm_current_perm_info *dest_info; int i; size_t size; @@ -42,18 +41,15 @@ populate_dest_info(int *dest_vmids, int nelements, int *dest_perms, if (!dest_info) return NULL; - for (i = 0; i < nelements; i++) { - dest_info[i].vm = dest_vmids[i]; - dest_info[i].perm = dest_perms[i]; - dest_info[i].ctx = 0x0; - dest_info[i].ctx_size = 0; - } + for (i = 0; i < nelements; i++) + qcom_scm_populate_vmperm_info(&dest_info[i], dest_vmids[i], + dest_perms[i]); *size_in_bytes = size; return dest_info; } -static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy, +static unsigned int get_batches_from_sgl(struct qcom_scm_mem_map_info *sgt_copy, struct scatterlist *sgl, struct scatterlist **next_sgl) { @@ -63,9 +59,10 @@ static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy, /* Ensure no zero size batches */ do { - sg_table_copy[i].addr = page_to_phys(sg_page(curr_sgl)); - sg_table_copy[i].size = curr_sgl->length; - batch_size += sg_table_copy[i].size; + qcom_scm_populate_mem_map_info(&sgt_copy[i], + page_to_phys(sg_page(curr_sgl)), + curr_sgl->length); + batch_size += curr_sgl->length; curr_sgl = sg_next(curr_sgl); i++; } while (curr_sgl && i < BATCH_MAX_SECTIONS && @@ -75,9 +72,11 @@ static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy, return i; } -static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) +static int batched_hyp_assign(struct sg_table *table, u32 *source_vmids, + size_t source_size, + struct qcom_scm_current_perm_info *destvms, + size_t destvms_size) { - unsigned int entries_size; unsigned int batch_start = 0; unsigned int batches_processed; unsigned int i = 0; @@ -87,40 +86,44 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) int ret = 0; ktime_t batch_assign_start_ts; ktime_t first_assign_ts; - struct mem_prot_info *sg_table_copy = kcalloc(BATCH_MAX_SECTIONS, - sizeof(*sg_table_copy), - GFP_KERNEL); + struct qcom_scm_mem_map_info *mem_regions_buf = + kcalloc(BATCH_MAX_SECTIONS, sizeof(*mem_regions_buf), + GFP_KERNEL); dma_addr_t entries_dma_addr; + size_t mem_regions_buf_size; - if (!sg_table_copy) + if (!mem_regions_buf) return -ENOMEM; first_assign_ts = ktime_get(); while (batch_start < table->nents) { - batches_processed = get_batches_from_sgl(sg_table_copy, + batches_processed = get_batches_from_sgl(mem_regions_buf, curr_sgl, &next_sgl); curr_sgl = next_sgl; - entries_size = batches_processed * sizeof(*sg_table_copy); + mem_regions_buf_size = batches_processed * + sizeof(*mem_regions_buf); entries_dma_addr = dma_map_single(qcom_secure_buffer_dev, - sg_table_copy, entries_size, + mem_regions_buf, + mem_regions_buf_size, DMA_TO_DEVICE); if (dma_mapping_error(qcom_secure_buffer_dev, entries_dma_addr)) { ret = -EADDRNOTAVAIL; break; } - desc->args[0] = entries_dma_addr; - desc->args[1] = entries_size; - trace_hyp_assign_batch_start(sg_table_copy, batches_processed); + trace_hyp_assign_batch_start(mem_regions_buf, + batches_processed); batch_assign_start_ts = ktime_get(); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, - MEM_PROT_ASSIGN_ID), desc); + ret = qcom_scm_assign_mem_regions(mem_regions_buf, + mem_regions_buf_size, + source_vmids, source_size, + destvms, destvms_size); trace_hyp_assign_batch_end(ret, ktime_us_delta(ktime_get(), batch_assign_start_ts)); dma_unmap_single(qcom_secure_buffer_dev, entries_dma_addr, - entries_size, DMA_TO_DEVICE); + mem_regions_buf_size, DMA_TO_DEVICE); i++; if (ret) { @@ -138,7 +141,7 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) } total_delta = ktime_us_delta(ktime_get(), first_assign_ts); trace_hyp_assign_end(total_delta, div64_u64(total_delta, i)); - kfree(sg_table_copy); + kfree(mem_regions_buf); return ret; } @@ -152,10 +155,9 @@ int hyp_assign_table(struct sg_table *table, int dest_nelems) { int ret = 0; - struct scm_desc desc = {0}; u32 *source_vm_copy; size_t source_vm_copy_size; - struct dest_vm_and_perm_info *dest_vm_copy; + struct qcom_scm_current_perm_info *dest_vm_copy; size_t dest_vm_copy_size; dma_addr_t source_dma_addr, dest_dma_addr; @@ -197,20 +199,12 @@ int hyp_assign_table(struct sg_table *table, goto out_free_dest; } - - desc.args[2] = source_dma_addr; - desc.args[3] = source_vm_copy_size; - desc.args[4] = dest_dma_addr; - desc.args[5] = dest_vm_copy_size; - desc.args[6] = 0; - - desc.arginfo = SCM_ARGS(7, SCM_RO, SCM_VAL, SCM_RO, SCM_VAL, SCM_RO, - SCM_VAL, SCM_VAL); - trace_hyp_assign_info(source_vm_list, source_nelems, dest_vmids, dest_perms, dest_nelems); - ret = batched_hyp_assign(table, &desc); + + ret = batched_hyp_assign(table, source_vm_copy, source_vm_copy_size, + dest_vm_copy, dest_vm_copy_size); dma_unmap_single(qcom_secure_buffer_dev, dest_dma_addr, dest_vm_copy_size, DMA_TO_DEVICE); diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index cbd3d3d57b16..fda0cba15c5a 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include -#include #include #include @@ -111,13 +111,6 @@ struct pil_tz_data { u32 bits_arr[2]; }; -enum scm_cmd { - PAS_INIT_IMAGE_CMD = 1, - PAS_MEM_SETUP_CMD, - PAS_AUTH_AND_RESET_CMD = 5, - PAS_SHUTDOWN_CMD, -}; - enum pas_id { PAS_MODEM, PAS_Q6, @@ -557,10 +550,7 @@ static int pil_init_image_trusted(struct pil_desc *pil, { struct pil_tz_data *d = desc_to_data(pil); u32 scm_ret = 0; - void *mdata_buf; - dma_addr_t mdata_phys; int ret; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; @@ -569,28 +559,9 @@ static int pil_init_image_trusted(struct pil_desc *pil, if (ret) return ret; - dma_set_mask(pil->dev, DMA_BIT_MASK(sizeof(dma_addr_t) * 8)); - mdata_buf = dma_alloc_coherent(pil->dev, size, &mdata_phys, GFP_KERNEL); - if (!mdata_buf) { - pr_err("scm-pas: Allocation for metadata failed.\n"); - scm_pas_disable_bw(); - return -ENOMEM; - } - - memcpy(mdata_buf, metadata, size); - - desc.args[0] = d->pas_id; - desc.args[1] = mdata_phys; - desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_RW); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD), - &desc); - scm_ret = desc.ret[0]; - - dma_free_coherent(pil->dev, size, mdata_buf, mdata_phys); + scm_ret = qcom_scm_pas_init_image(d->pas_id, metadata, size); scm_pas_disable_bw(); - if (ret) - return ret; return scm_ret; } @@ -599,22 +570,12 @@ static int pil_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr, { struct pil_tz_data *d = desc_to_data(pil); u32 scm_ret = 0; - int ret; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = d->pas_id; - desc.args[1] = addr; - desc.args[2] = size; - desc.arginfo = SCM_ARGS(3); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_MEM_SETUP_CMD), - &desc); - scm_ret = desc.ret[0]; + scm_ret = qcom_scm_pas_mem_setup(d->pas_id, addr, size); - if (ret) - return ret; return scm_ret; } @@ -622,15 +583,11 @@ static int pil_auth_and_reset(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); int rc; - u32 proc, scm_ret = 0; - struct scm_desc desc = {0}; + u32 scm_ret = 0; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = proc = d->pas_id; - desc.arginfo = SCM_ARGS(1); - rc = scm_pas_enable_bw(); if (rc) return rc; @@ -643,9 +600,7 @@ static int pil_auth_and_reset(struct pil_desc *pil) if (rc) goto err_clks; - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, - PAS_AUTH_AND_RESET_CMD), &desc); - scm_ret = desc.ret[0]; + scm_ret = qcom_scm_pas_auth_and_reset(d->pas_id); scm_pas_disable_bw(); if (rc) @@ -663,16 +618,12 @@ err_clks: static int pil_shutdown_trusted(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); - u32 proc, scm_ret = 0; + u32 scm_ret = 0; int rc; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = proc = d->pas_id; - desc.arginfo = SCM_ARGS(1); - rc = do_bus_scaling_request(pil, 1); if (rc) return rc; @@ -687,9 +638,7 @@ static int pil_shutdown_trusted(struct pil_desc *pil) if (rc) goto err_clks; - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD), - &desc); - scm_ret = desc.ret[0]; + scm_ret = qcom_scm_pas_shutdown(d->pas_id); disable_unprepare_clocks(d->proxy_clks, d->proxy_clk_count); disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false); @@ -715,23 +664,11 @@ err_regulators: static int pil_deinit_image_trusted(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); - u32 proc, scm_ret = 0; - int rc; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = proc = d->pas_id; - desc.arginfo = SCM_ARGS(1); - - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD), - &desc); - scm_ret = desc.ret[0]; - - if (rc) - return rc; - return scm_ret; + return qcom_scm_pas_shutdown(d->pas_id); } static struct pil_reset_ops pil_ops_trusted = { diff --git a/drivers/soc/qcom/trace_secure_buffer.h b/drivers/soc/qcom/trace_secure_buffer.h index f0655c8fa270..2fef8079fd56 100644 --- a/drivers/soc/qcom/trace_secure_buffer.h +++ b/drivers/soc/qcom/trace_secure_buffer.h @@ -52,7 +52,7 @@ TRACE_EVENT(hyp_assign_info, TRACE_EVENT(hyp_assign_batch_start, - TP_PROTO(struct mem_prot_info *info, int info_nelems), + TP_PROTO(struct qcom_scm_mem_map_info *info, int info_nelems), TP_ARGS(info, info_nelems), @@ -72,9 +72,9 @@ TRACE_EVENT(hyp_assign_batch_start, __entry->batch_size = 0; for (i = 0; i < info_nelems; i++) { - addr_arr_ptr[i] = info[i].addr; - sizes_arr_ptr[i] = info[i].size; - __entry->batch_size += info[i].size; + addr_arr_ptr[i] = info[i].mem_addr; + sizes_arr_ptr[i] = info[i].mem_size; + __entry->batch_size += info[i].mem_size; } ), diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index ea3ca01baad6..f12ef1372167 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -24,6 +24,19 @@ struct qcom_scm_vmperm { int perm; }; +struct qcom_scm_current_perm_info { + __le32 vmid; + __le32 perm; + __le64 ctx; + __le32 ctx_size; + __le32 unused; +}; + +struct qcom_scm_mem_map_info { + __le64 mem_addr; + __le64 mem_size; +}; + #define QCOM_SCM_VMID_HLOS 0x3 #define QCOM_SCM_VMID_MSS_MSA 0xF #define QCOM_SCM_VMID_WLAN 0x18 @@ -34,12 +47,39 @@ struct qcom_scm_vmperm { #define QCOM_SCM_PERM_RW (QCOM_SCM_PERM_READ | QCOM_SCM_PERM_WRITE) #define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC) +static inline void qcom_scm_populate_vmperm_info( + struct qcom_scm_current_perm_info *destvm, int vmid, int perm) +{ + if (!destvm) + return; + + destvm->vmid = cpu_to_le32(vmid); + destvm->perm = cpu_to_le32(perm); + destvm->ctx = 0; + destvm->ctx_size = 0; +} + +static inline void qcom_scm_populate_mem_map_info( + struct qcom_scm_mem_map_info *mem_to_map, + phys_addr_t mem_addr, size_t mem_size) +{ + if (!mem_to_map) + return; + + mem_to_map->mem_addr = cpu_to_le64(mem_addr); + mem_to_map->mem_size = cpu_to_le64(mem_size); +} + + #if IS_ENABLED(CONFIG_QCOM_SCM) extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); extern void qcom_scm_cpu_power_down(u32 flags); extern int qcom_scm_sec_wdog_deactivate(void); +extern int qcom_scm_sec_wdog_trigger(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); +extern int qcom_scm_spin_cpu(void); +extern int qcom_scm_config_cpu_errata(void); extern bool qcom_scm_pas_supported(u32 peripheral); extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size); @@ -48,28 +88,95 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); extern int qcom_scm_get_sec_dump_state(u32 *dump_state); +extern int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, int *out); extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); +extern int qcom_scm_io_reset(void); +extern bool qcom_scm_is_secure_wdog_trigger_available(void); +extern bool qcom_scm_is_mode_switch_available(void); extern int qcom_scm_get_jtag_etm_feat_id(u64 *version); extern void qcom_scm_mmu_sync(bool sync); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); +extern int qcom_scm_mem_protect_video(u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size); extern int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size); +extern int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, + size_t list_size, size_t chunk_size, + size_t memory_usage, int lock); extern int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len); extern int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, size_t total_len); +extern int +qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions, + size_t mem_regions_sz, u32 *srcvms, size_t src_sz, + struct qcom_scm_current_perm_info *newvms, + size_t newvms_sz); extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt); +extern int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, + u64 mem_size, u32 vmid); +extern int qcom_scm_get_feat_version_cp(u64 *version); +extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); +extern int qcom_scm_kgsl_set_smmu_aperture( + unsigned int num_context_bank); +extern int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation); +extern int qcom_mdf_assign_memory_to_subsys(u64 start_addr, + u64 end_addr, phys_addr_t paddr, u64 size); +extern bool qcom_scm_dcvs_core_available(void); +extern bool qcom_scm_dcvs_ca_available(void); +extern int qcom_scm_dcvs_reset(void); +extern int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, int *version); +extern int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size); +extern int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time); +extern int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time); +extern int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, + int context_count); +extern int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, + size_t size, uint32_t cipher, + unsigned int data_unit, + unsigned int food); +extern int qcom_scm_clear_ice_key(uint32_t index, unsigned int food); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); +extern int qcom_scm_enable_shm_bridge(void); +extern int qcom_scm_delete_shm_bridge(u64 handle); +extern int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, + u64 ns_vmids, u64 *handle); +extern bool qcom_scm_is_lmh_debug_set_available(void); +extern bool qcom_scm_is_lmh_debug_read_buf_size_available(void); +extern bool qcom_scm_is_lmh_debug_read_buf_available(void); +extern bool qcom_scm_is_lmh_debug_get_type_available(void); +extern int qcom_scm_lmh_read_buf_size(int *size); +extern int qcom_scm_lmh_limit_dcvsh(phys_addr_t payload, uint32_t payload_size, + u64 limit_node, uint32_t node_id, u64 version); +extern int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size); +extern int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, + int payload_size, uint32_t *buf, int buf_size); +extern int qcom_scm_lmh_get_type(phys_addr_t payload, u64 payload_size, + u64 debug_type, uint32_t get_from, uint32_t *size); +extern int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx); extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); +extern int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure); +extern int qcom_scm_qdss_invoke(phys_addr_t addr, size_t size, u64 *out); +extern int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param); +extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask); extern int qcom_scm_ice_restore_cfg(void); +extern int qcom_scm_get_tz_log_feat_id(u64 *version); +extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); +extern int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *response_type, unsigned int *data); +extern int qcom_scm_invoke_callback_response(phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *response_type, + unsigned int *data); extern bool qcom_scm_is_available(void); #else @@ -83,8 +190,12 @@ int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) { return -ENODEV; } static inline void qcom_scm_cpu_power_down(u32 flags) {} static inline int qcom_scm_sec_wdog_deactivate(void) { return -ENODEV; } +static inline int qcom_scm_sec_wdog_trigger(void) { return -ENODEV; } static inline u32 qcom_scm_set_remote_state(u32 state, u32 id) { return -ENODEV; } +static inline int qcom_scm_spin_cpu(void) { return -ENODEV; } +static inline int qcom_scm_config_cpu_errata(void) + { return -ENODEV; } static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) { return -ENODEV; } @@ -95,10 +206,18 @@ static inline int qcom_scm_pas_auth_and_reset(u32 peripheral) static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } static inline int qcom_scm_get_sec_dump_state(u32 *dump_state) {return -ENODEV; } +static inline int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, + int *out) { return -ENODEV; } static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; } static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; } +static inline int qcom_scm_io_reset(void) + { return -ENODEV; } +static inline bool qcom_scm_is_secure_wdog_trigger_available(void) + { return -ENODEV; } +static inline bool qcom_scm_is_mode_switch_available(void) + { return -ENODEV; } static inline int qcom_scm_get_jtag_etm_feat_id(u64 *version) { return -ENODEV; } static inline void qcom_scm_mmu_sync(bool sync) {} @@ -108,23 +227,110 @@ static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } +static inline int qcom_scm_mem_protect_video(u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size) + { return -ENODEV; } static inline int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size) { return -ENODEV; } +static inline int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, + size_t list_size, size_t chunk_size, size_t memory_usage, + int lock) { return -ENODEV; } static inline int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len) { return -ENODEV; } static inline int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, size_t total_len) { return -ENODEV; } +static inline int +qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions, + size_t mem_regions_sz, u32 *srcvms, size_t src_sz, + struct qcom_scm_current_perm_info *newvms, + size_t newvms_sz) { return -ENODEV; } static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt) { return -ENODEV; } +static inline int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, + u64 mem_size, u32 vmid) + { return -ENODEV; } +static inline bool qcom_scm_kgsl_set_smmu_aperture_available(void) + { return false; } +static inline int qcom_scm_kgsl_set_smmu_aperture( + unsigned int num_context_bank) { return -ENODEV; } +static inline int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, + int operation) { return -ENODEV; } +static inline int qcom_mdf_assign_memory_to_subsys(struct device *dev, + u64 start_addr, u64 end_addr, phys_addr_t paddr, u64 size) + { return -ENODEV; } +static inline int qcom_scm_get_feat_version_cp(u64 *version) + { return -ENODEV; } +static inline bool qcom_scm_dcvs_core_available(void) { return false; } +static inline bool qcom_scm_dcvs_ca_available(void) { return false; } +static inline int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, + int *version) { return -ENODEV; } +static inline int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size) + { return -ENODEV; } +static inline int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time) + { return -ENODEV; } +static inline int qcom_scm_dcvs_update_v2(int level, s64 total_time, + s64 busy_time) { return -ENODEV; } +static inline int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, + s64 busy_time, int context_count) { return -ENODEV; } +static inline int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, + size_t size, uint32_t cipher, unsigned int data_unit, + unsigned int food) { return -ENODEV; } +static inline int qcom_scm_clear_ice_key(uint32_t index, unsigned int food) + { return -ENODEV; } static inline bool qcom_scm_hdcp_available(void) { return false; } static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { return -ENODEV; } +static inline int qcom_scm_enable_shm_bridge(void) { return -ENODEV; } +static inline int qcom_scm_delete_shm_bridge(u64 handle) { return -ENODEV; } +static inline int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, + u64 ns_vmids, u64 *handle) { return -ENODEV; } +static inline bool qcom_scm_is_lmh_debug_set_available(void) + { return -EINVAL; } +static inline bool qcom_scm_is_lmh_debug_read_buf_size_available(void) + { return -EINVAL; } +static inline bool qcom_scm_is_lmh_debug_read_buf_available(void) + { return -EINVAL; } +static inline bool qcom_scm_is_lmh_debug_get_type_available(void) + { return -EINVAL; } +static inline int qcom_scm_lmh_read_buf_size(int *size) { return -ENODEV; } +static inline int qcom_scm_lmh_limit_dcvsh(phys_addr_t payload, + uint32_t payload_size, u64 limit_node, uint32_t node_id, + u64 version) { return -ENODEV; } +static inline int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size) + { return -ENODEV; } +static inline int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, + int payload_size, uint32_t *buf, int buf_size) + { return -ENODEV; } +static inline int qcom_scm_lmh_get_type(phys_addr_t payload, u64 payload_size, + u64 debug_type, uint32_t get_from, uint32_t *size) + { return -ENODEV; } +static inline int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx) + { return -ENODEV; } static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; } +static inline int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure) + { return -EINVAL; } +static inline int qcom_scm_qdss_invoke(phys_addr_t data, size_t size, u64 *out) + { return -EINVAL; } +static inline int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param) + { return -ENODEV; } +static inline int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask) + { return -EINVAL; } static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } +static inline int qcom_scm_get_tz_log_feat_id(u64 *version) + { return -ENODEV; } +static inline int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) + { return -ENODEV; } +static inline int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *request_type, unsigned int *data) { return -ENODEV; } +static inline int qcom_scm_invoke_callback_response(phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *request_type, + unsigned int *data) { return -ENODEV; } static inline bool qcom_scm_is_available(void) { return false; } #endif #endif diff --git a/include/soc/qcom/qseecom_scm.h b/include/soc/qcom/qseecom_scm.h new file mode 100644 index 000000000000..557e7f4bc625 --- /dev/null +++ b/include/soc/qcom/qseecom_scm.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __MACH_SCM_H +#define __MACH_SCM_H + +#define SCM_SVC_BOOT 0x1 +#define SCM_SVC_PIL 0x2 +#define SCM_SVC_UTIL 0x3 +#define SCM_SVC_TZ 0x4 +#define SCM_SVC_IO 0x5 +#define SCM_SVC_INFO 0x6 +#define SCM_SVC_SSD 0x7 +#define SCM_SVC_FUSE 0x8 +#define SCM_SVC_PWR 0x9 +#define SCM_SVC_MP 0xC +#define SCM_SVC_DCVS 0xD +#define SCM_SVC_ES 0x10 +#define SCM_SVC_HDCP 0x11 +#define SCM_SVC_MDTP 0x12 +#define SCM_SVC_LMH 0x13 +#define SCM_SVC_SMMU_PROGRAM 0x15 +#define SCM_SVC_QDSS 0x16 +#define SCM_SVC_RTIC 0x19 +#define SCM_SVC_TZSCHEDULER 0xFC + +#define SCM_FUSE_READ 0x7 +#define SCM_CMD_HDCP 0x01 + +/* SCM Features */ +#define SCM_SVC_SEC_CAMERA 0xD + +#define DEFINE_SCM_BUFFER(__n) \ +static char __n[PAGE_SIZE] __aligned(PAGE_SIZE) + +#define SCM_BUFFER_SIZE(__buf) sizeof(__buf) + +#define SCM_BUFFER_PHYS(__buf) virt_to_phys(__buf) + +#define SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) | 0x02000000) +#define SCM_QSEEOS_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) | \ + 0x32000000) +#define SCM_SVC_ID(s) (((s) & 0xFF00) >> 8) + +#define MAX_SCM_ARGS 10 +#define MAX_SCM_RETS 3 + +enum scm_arg_types { + SCM_VAL, + SCM_RO, + SCM_RW, + SCM_BUFVAL, +}; + +#define SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ + (((a) & 0xff) << 4) | \ + (((b) & 0xff) << 6) | \ + (((c) & 0xff) << 8) | \ + (((d) & 0xff) << 10) | \ + (((e) & 0xff) << 12) | \ + (((f) & 0xff) << 14) | \ + (((g) & 0xff) << 16) | \ + (((h) & 0xff) << 18) | \ + (((i) & 0xff) << 20) | \ + (((j) & 0xff) << 22) | \ + (num & 0xffff)) + +#define SCM_ARGS(...) SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +struct scm_desc { + u32 arginfo; + u64 args[MAX_SCM_ARGS]; + u64 ret[MAX_SCM_RETS]; +}; + +extern int __qcom_scm_qseecom_do(u32 cmd_id, struct scm_desc *desc, bool retry); + +#if IS_ENABLED(CONFIG_QCOM_SCM) + +int qcom_scm_qseecom_call(u32 cmd_id, struct scm_desc *desc); +int qcom_scm_qseecom_call_noretry(u32 cmd_id, struct scm_desc *desc); + +#else + +static inline int qcom_scm_qseecom_call(u32 cmd_id, struct scm_desc *desc) +{ + return -ENODEV; +} + +static inline int qcom_scm_qseecom_call_noretry(u32 cmd_id, + struct scm_desc *desc) +{ + return -ENODEV; +} + +#endif +#endif diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h index 0e43db3c96ac..584a0b8814d8 100644 --- a/include/soc/qcom/secure_buffer.h +++ b/include/soc/qcom/secure_buffer.h @@ -41,18 +41,6 @@ enum vmid { #define PERM_WRITE 0x2 #define PERM_EXEC 0x1 -struct dest_vm_and_perm_info { - u32 vm; - u32 perm; - u64 ctx; - u32 ctx_size; -}; - -struct mem_prot_info { - phys_addr_t addr; - u64 size; -}; - #if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) int hyp_assign_table(struct sg_table *table, u32 *source_vm_list, int source_nelems,