diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index f0320692beb0..09bd336fa82b 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -1,4 +1,3 @@ -CONFIG_QCOM_SECURE_CHAN_MANAGER=y CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y CONFIG_IOMMU_DEBUGFS=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 77f4cb28a97f..aceeeb41aad0 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -19,6 +19,9 @@ #include "qcom_scm.h" +#define CREATE_TRACE_POINTS +#include + #define MAX_QCOM_SCM_ARGS 10 #define MAX_QCOM_SCM_RETS 3 @@ -169,10 +172,15 @@ static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, struct arm_smccc_res *res) { unsigned long a0 = smc->a[0]; + ktime_t time; + const bool trace = trace_scm_call_enabled(); struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 }; quirk.state.a6 = 0; + if (trace) + time = ktime_get(); + do { arm_smccc_smc_quirk(a0, smc->a[1], smc->a[2], smc->a[3], smc->a[4], smc->a[5], quirk.state.a6, @@ -182,6 +190,9 @@ static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, a0 = res->a0; } while (res->a0 == QCOM_SCM_INTERRUPTED); + + if (trace) + trace_scm_call(smc->a, res, ktime_us_delta(ktime_get(), time)); } static int qcom_scm_call_smccc(struct device *dev, @@ -261,9 +272,7 @@ static int qcom_scm_call_smccc(struct device *dev, do { mutex_lock(&qcom_scm_lock); - __qcom_scm_call_do_quirk(&smc, &res); - mutex_unlock(&qcom_scm_lock); if (res.a0 == QCOM_SCM_V2_EBUSY) { @@ -329,10 +338,19 @@ static inline void *legacy_get_response_buffer( static void __qcom_scm_call_do(const struct arm_smccc_args *smc, struct arm_smccc_res *res) { + ktime_t time; + const bool trace = trace_scm_call_enabled(); + + if (trace) + time = ktime_get(); + do { arm_smccc_smc(smc->a[0], smc->a[1], smc->a[2], smc->a[3], smc->a[4], smc->a[5], smc->a[6], smc->a[7], res); } while (res->a0 == QCOM_SCM_INTERRUPTED); + + if (trace) + trace_scm_call(smc->a, res, ktime_us_delta(ktime_get(), time)); } /** @@ -438,6 +456,8 @@ static int qcom_scm_call_atomic_legacy(struct device *dev, struct arm_smccc_args smc = {{0}}; struct arm_smccc_res res; size_t i, arglen = desc->arginfo & 0xf; + const bool trace = trace_scm_call_enabled(); + ktime_t time; BUG_ON(arglen > LEGACY_ATOMIC_N_REG_ARGS); @@ -447,9 +467,14 @@ static int qcom_scm_call_atomic_legacy(struct device *dev, for (i = 0; i < arglen; i++) smc.a[i + LEGACY_ATOMIC_FIRST_REG_IDX] = desc->args[i]; + if (trace) + time = ktime_get(); arm_smccc_smc(smc.a[0], smc.a[1], smc.a[2], smc.a[3], smc.a[4], smc.a[5], smc.a[6], smc.a[7], &res); + if (trace) + trace_scm_call(smc.a, &res, ktime_us_delta(ktime_get(), time)); + desc->res[0] = res.a1; desc->res[1] = res.a2; desc->res[2] = res.a3; diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index b52b850ec9be..f3d2924f07fc 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -370,14 +370,6 @@ config QCOM_APR used by audio driver to configure QDSP6 ASM, ADM and AFE modules. -config QCOM_SECURE_CHAN_MANAGER - tristate "Secure Channel Manager (SCM) support" - help - Say y or m here to enable Secure Channel Mananger (SCM) - support for Qualcomm SoC. SCM provides communication - channel to communicate with secure world (EL2 and EL3) - by using smc call. - config QCOM_SECURE_BUFFER tristate "Helper functions for secure buffers through TZ" depends on QCOM_SCM diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index c47029d20af4..43efcd69ff28 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -28,8 +28,6 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o obj-$(CONFIG_QSEE_IPC_IRQ_BRIDGE) += qsee_ipc_irq_bridge.o obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_MSM_CORE_HANG_DETECT) += core_hang_detect.o -CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1, -Wno-asm-operand-widths) -obj-$(CONFIG_QCOM_SECURE_CHAN_MANAGER) += scm.o obj-$(CONFIG_QCOM_SECURE_BUFFER) += secure_buffer.o obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c deleted file mode 100644 index c647e2002bb9..000000000000 --- a/drivers/soc/qcom/scm.c +++ /dev/null @@ -1,623 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define CREATE_TRACE_POINTS -#include - -#ifdef CONFIG_ARM64 -/* - * This is used to ensure the compiler did actually allocate the register we - * asked it for some inline assembly sequences. Apparently we can't trust the - * compiler from one version to another so a bit of paranoia won't hurt. This - * string is meant to be concatenated with the inline asm string and will - * cause compilation to stop on mismatch. (for details, see gcc PR 15089) - */ -#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" - -#else - -#include -#include - -#endif - -#define SCM_ENOMEM -9 -#define SCM_EINVAL_ADDR -3 -#define SCM_EINVAL_ARG -2 -#define SCM_ERROR -1 -#define SCM_INTERRUPTED 1 -#define SCM_V2_EBUSY -12 - -static DEFINE_MUTEX(scm_lock); - -#define SCM_EBUSY_WAIT_MS 30 -#define SCM_EBUSY_MAX_RETRY 67 - -#define N_EXT_SCM_ARGS 7 -#define FIRST_EXT_ARG_IDX 3 -#define SMC_ATOMIC_SYSCALL 31 -#define N_REGISTER_ARGS (MAX_SCM_ARGS - N_EXT_SCM_ARGS + 1) -#define SMC64_MASK 0x40000000 -#define SMC_ATOMIC_MASK 0x80000000 -#define IS_CALL_AVAIL_CMD 1 - -#ifdef CONFIG_ARM64 - -#define R0_STR "x0" -#define R1_STR "x1" -#define R2_STR "x2" -#define R3_STR "x3" -#define R4_STR "x4" -#define R5_STR "x5" -#define R6_STR "x6" - -/* Outer caches unsupported on ARM64 platforms */ -#define outer_flush_range(x, y) - -#else - -#define R0_STR "r0" -#define R1_STR "r1" -#define R2_STR "r2" -#define R3_STR "r3" -#define R4_STR "r4" -#define R5_STR "r5" -#define R6_STR "r6" - -#endif - -static struct device *qcom_scm_dev; - -struct scm_dma_buf { - size_t size; - dma_addr_t extra_arg_buf_phy; -}; - -static int scm_remap_error(int err) -{ - switch (err) { - case SCM_ERROR: - return -EOPNOTSUPP; - case SCM_EINVAL_ADDR: - case SCM_EINVAL_ARG: - return -EINVAL; - case SCM_ENOMEM: - return -ENOMEM; - case SCM_V2_EBUSY: - return -EBUSY; - } - return -EINVAL; -} - -#ifdef CONFIG_ARM64 - -static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, - u64 *ret1, u64 *ret2, u64 *ret3) -{ - register u64 r0 asm("x0") = x0; - register u64 r1 asm("x1") = x1; - register u64 r2 asm("x2") = x2; - register u64 r3 asm("x3") = x3; - register u64 r4 asm("x4") = x4; - register u64 r5 asm("x5") = x5; - register u64 r6 asm("x6") = 0; - - do { - asm volatile( - __asmeq("%0", R0_STR) - __asmeq("%1", R1_STR) - __asmeq("%2", R2_STR) - __asmeq("%3", R3_STR) - __asmeq("%4", R4_STR) - __asmeq("%5", R5_STR) - __asmeq("%6", R6_STR) - __asmeq("%7", R0_STR) - __asmeq("%8", R1_STR) - __asmeq("%9", R2_STR) - __asmeq("%10", R3_STR) - __asmeq("%11", R4_STR) - __asmeq("%12", R5_STR) - __asmeq("%13", R6_STR) -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0\n" - : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3), - "=r" (r4), "=r" (r5), "=r" (r6) - : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), - "r" (r5), "r" (r6) - : "x7", "x8", "x9", "x10", "x11", "x12", "x13", - "x14", "x15", "x16", "x17"); - } while (r0 == SCM_INTERRUPTED); - - if (ret1) - *ret1 = r1; - if (ret2) - *ret2 = r2; - if (ret3) - *ret3 = r3; - - return r0; -} - -static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, - u64 *ret1, u64 *ret2, u64 *ret3) -{ - register u32 r0 asm("w0") = w0; - register u32 r1 asm("w1") = w1; - register u32 r2 asm("w2") = w2; - register u32 r3 asm("w3") = w3; - register u32 r4 asm("w4") = w4; - register u32 r5 asm("w5") = w5; - register u32 r6 asm("w6") = 0; - - do { - asm volatile( - __asmeq("%0", R0_STR) - __asmeq("%1", R1_STR) - __asmeq("%2", R2_STR) - __asmeq("%3", R3_STR) - __asmeq("%4", R4_STR) - __asmeq("%5", R5_STR) - __asmeq("%6", R6_STR) - __asmeq("%7", R0_STR) - __asmeq("%8", R1_STR) - __asmeq("%9", R2_STR) - __asmeq("%10", R3_STR) - __asmeq("%11", R4_STR) - __asmeq("%12", R5_STR) - __asmeq("%13", R6_STR) -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0\n" - : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3), - "=r" (r4), "=r" (r5), "=r" (r6) - : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), - "r" (r5), "r" (r6) - : "x7", "x8", "x9", "x10", "x11", "x12", "x13", - "x14", "x15", "x16", "x17"); - - } while (r0 == SCM_INTERRUPTED); - - if (ret1) - *ret1 = r1; - if (ret2) - *ret2 = r2; - if (ret3) - *ret3 = r3; - - return r0; -} - -#else - -static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, - u64 *ret1, u64 *ret2, u64 *ret3) -{ - register u32 r0 asm("r0") = w0; - register u32 r1 asm("r1") = w1; - register u32 r2 asm("r2") = w2; - register u32 r3 asm("r3") = w3; - register u32 r4 asm("r4") = w4; - register u32 r5 asm("r5") = w5; - register u32 r6 asm("r6") = 0; - - do { - asm volatile( - __asmeq("%0", R0_STR) - __asmeq("%1", R1_STR) - __asmeq("%2", R2_STR) - __asmeq("%3", R3_STR) - __asmeq("%4", R4_STR) - __asmeq("%5", R5_STR) - __asmeq("%6", R6_STR) - __asmeq("%7", R0_STR) - __asmeq("%8", R1_STR) - __asmeq("%9", R2_STR) - __asmeq("%10", R3_STR) - __asmeq("%11", R4_STR) - __asmeq("%12", R5_STR) - __asmeq("%13", R6_STR) -#ifdef REQUIRES_SEC - ".arch_extension sec\n" -#endif - "smc #0\n" - : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3), - "=r" (r4), "=r" (r5), "=r" (r6) - : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), - "r" (r5), "r" (r6)); - - } while (r0 == SCM_INTERRUPTED); - - if (ret1) - *ret1 = r1; - if (ret2) - *ret2 = r2; - if (ret3) - *ret3 = r3; - - return r0; -} - -static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, - u64 *ret1, u64 *ret2, u64 *ret3) -{ - return 0; -} -#endif - -struct scm_extra_arg { - union { - u32 args32[N_EXT_SCM_ARGS]; - u64 args64[N_EXT_SCM_ARGS]; - }; -}; - -static enum scm_interface_version { - SCM_UNKNOWN, - SCM_LEGACY, - SCM_ARMV8_32, - SCM_ARMV8_64, -} scm_version = SCM_UNKNOWN; - -/* This will be set to specify SMC32 or SMC64 */ -static u32 scm_version_mask; - -static noinline bool is_scm_armv8(void) -{ - int ret; - u64 ret1, x0; - - if (likely(scm_version != SCM_UNKNOWN)) - return (scm_version == SCM_ARMV8_32) || - (scm_version == SCM_ARMV8_64); - /* - * This is a one time check that runs on the first ever - * invocation of is_scm_armv8. We might be called in atomic - * context so no mutexes etc. Also, we can't use the scm_call2 - * or scm_call2_APIs directly since they depend on this init. - */ - - /* First try a SMC64 call */ - scm_version = SCM_ARMV8_64; - ret1 = 0; - x0 = SCM_SIP_FNID(SCM_SVC_INFO, IS_CALL_AVAIL_CMD) | SMC_ATOMIC_MASK; - ret = __scm_call_armv8_64(x0 | SMC64_MASK, SCM_ARGS(1), x0, 0, 0, 0, - &ret1, NULL, NULL); - if (ret || !ret1) { - /* Try SMC32 call */ - ret1 = 0; - ret = __scm_call_armv8_32(x0, SCM_ARGS(1), x0, 0, 0, 0, - &ret1, NULL, NULL); - if (ret || !ret1) - return -ENODEV; - - scm_version = SCM_ARMV8_32; - } else - scm_version_mask = SMC64_MASK; - - pr_debug("scm_call: scm version is %x, mask is %x\n", scm_version, - scm_version_mask); - - return (scm_version == SCM_ARMV8_32) || - (scm_version == SCM_ARMV8_64); -} - -/* - * If there are more than N_REGISTER_ARGS, allocate a buffer and place - * the additional arguments in it. The extra argument buffer will be - * pointed to by X5. - */ -static int allocate_extra_arg_buffer(struct scm_desc *desc, - struct scm_dma_buf *scm_dma_buf, gfp_t flags) -{ - int i, j; - struct scm_extra_arg *argbuf; - dma_addr_t argbuf_phy; - int arglen = desc->arginfo & 0xf; - size_t argbuflen = PAGE_ALIGN(sizeof(struct scm_extra_arg)); - - desc->x5 = desc->args[FIRST_EXT_ARG_IDX]; - - if (likely(arglen <= N_REGISTER_ARGS)) { - desc->extra_arg_buf = NULL; - return 0; - } - - if (!qcom_scm_dev) - return -EPROBE_DEFER; - - argbuf = kzalloc(argbuflen, flags); - if (!argbuf) - return -ENOMEM; - - desc->extra_arg_buf = argbuf; - - j = FIRST_EXT_ARG_IDX; - if (scm_version == SCM_ARMV8_64) - for (i = 0; i < N_EXT_SCM_ARGS; i++) - argbuf->args64[i] = desc->args[j++]; - else - for (i = 0; i < N_EXT_SCM_ARGS; i++) - argbuf->args32[i] = desc->args[j++]; - desc->x5 = virt_to_phys(argbuf); - - argbuf_phy = dma_map_single(qcom_scm_dev, argbuf, - argbuflen, DMA_TO_DEVICE); - if (dma_mapping_error(qcom_scm_dev, argbuf_phy)) { - kfree(argbuf); - return -ENOMEM; - } - - scm_dma_buf->extra_arg_buf_phy = argbuf_phy; - scm_dma_buf->size = argbuflen; - - outer_flush_range(virt_to_phys(argbuf), - virt_to_phys(argbuf) + argbuflen); - - return 0; -} - -static int __scm_call2(u32 fn_id, struct scm_desc *desc, bool retry) -{ - int arglen = desc->arginfo & 0xf; - int ret, retry_count = 0; - u64 x0; - struct scm_dma_buf scm_dma_buf = {0}; - - ret = allocate_extra_arg_buffer(desc, &scm_dma_buf, GFP_NOIO); - if (ret) - return ret; - - x0 = fn_id | scm_version_mask; - - trace_scm_call_start(x0, desc); - do { - mutex_lock(&scm_lock); - - desc->ret[0] = desc->ret[1] = desc->ret[2] = 0; - - if (scm_version == SCM_ARMV8_64) - ret = __scm_call_armv8_64(x0, desc->arginfo, - desc->args[0], desc->args[1], - desc->args[2], desc->x5, - &desc->ret[0], &desc->ret[1], - &desc->ret[2]); - else - ret = __scm_call_armv8_32(x0, desc->arginfo, - desc->args[0], desc->args[1], - desc->args[2], desc->x5, - &desc->ret[0], &desc->ret[1], - &desc->ret[2]); - - mutex_unlock(&scm_lock); - if (!retry) - goto out; - - if (ret == SCM_V2_EBUSY) - msleep(SCM_EBUSY_WAIT_MS); - if (retry_count == 33) - pr_warn("scm: secure world has been busy for 1 second!\n"); - } while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); -out: - trace_scm_call_end(desc); - if (ret < 0) - pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", - x0, ret, desc->ret[0], desc->ret[1], desc->ret[2]); - - if (arglen > N_REGISTER_ARGS) { - dma_unmap_single(qcom_scm_dev, scm_dma_buf.extra_arg_buf_phy, - scm_dma_buf.size, DMA_TO_DEVICE); - kfree(desc->extra_arg_buf); - } - if (ret < 0) - return scm_remap_error(ret); - return 0; -} - -/** - * scm_call2() - Invoke a syscall in the secure world - * @fn_id: The function ID for this syscall - * @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. - * - * A note on cache maintenance: - * Note that any buffers that are expected to be accessed by the secure world - * must be flushed before invoking scm_call and invalidated in the cache - * immediately after scm_call returns. An important point that must be noted - * is that on ARMV8 architectures, invalidation actually also causes a dirty - * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of - * paramount importance that the buffer be flushed before invoking scm_call2, - * even if you don't care about the contents of that buffer. - * - * Note that cache maintenance on the argument buffer (desc->args) is taken care - * of by scm_call2; however, callers are responsible for any other cached - * buffers passed over to the secure world. - */ -int scm_call2(u32 fn_id, struct scm_desc *desc) -{ - return __scm_call2(fn_id, desc, true); -} -EXPORT_SYMBOL(scm_call2); - -/** - * scm_call2_noretry() - Invoke a syscall in the secure world - * - * Similar to scm_call2 except that there is no retry mechanism - * implemented. - */ -int scm_call2_noretry(u32 fn_id, struct scm_desc *desc) -{ - return __scm_call2(fn_id, desc, false); -} -EXPORT_SYMBOL(scm_call2_noretry); - -/** - * scm_call2_atomic() - Invoke a syscall in the secure world - * - * Similar to scm_call2 except that this can be invoked in atomic context. - * There is also no retry mechanism implemented. Please ensure that the - * secure world syscall can be executed in such a context and can complete - * in a timely manner. - */ -int scm_call2_atomic(u32 fn_id, struct scm_desc *desc) -{ - int arglen = desc->arginfo & 0xf; - int ret; - u64 x0; - struct scm_dma_buf scm_dma_buf = {0}; - - ret = allocate_extra_arg_buffer(desc, &scm_dma_buf, GFP_ATOMIC); - if (ret) - return ret; - - x0 = fn_id | BIT(SMC_ATOMIC_SYSCALL) | scm_version_mask; - - trace_scm_call_start(x0, desc); - if (scm_version == SCM_ARMV8_64) - ret = __scm_call_armv8_64(x0, desc->arginfo, desc->args[0], - desc->args[1], desc->args[2], - desc->x5, &desc->ret[0], - &desc->ret[1], &desc->ret[2]); - else - ret = __scm_call_armv8_32(x0, desc->arginfo, desc->args[0], - desc->args[1], desc->args[2], - desc->x5, &desc->ret[0], - &desc->ret[1], &desc->ret[2]); - trace_scm_call_end(desc); - if (ret < 0) - pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", - x0, ret, desc->ret[0], - desc->ret[1], desc->ret[2]); - - if (arglen > N_REGISTER_ARGS) { - dma_unmap_single(qcom_scm_dev, scm_dma_buf.extra_arg_buf_phy, - scm_dma_buf.size, DMA_TO_DEVICE); - kfree(desc->extra_arg_buf); - } - if (ret < 0) - return scm_remap_error(ret); - return ret; -} -EXPORT_SYMBOL(scm_call2_atomic); - -#define SCM_IO_READ 0x1 -#define SCM_IO_WRITE 0x2 - -u32 scm_io_read(phys_addr_t address) -{ - struct scm_desc desc = { - .args[0] = address, - .arginfo = SCM_ARGS(1), - }; - - scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_IO, SCM_IO_READ), &desc); - return desc.ret[0]; -} -EXPORT_SYMBOL(scm_io_read); - -int scm_io_write(phys_addr_t address, u32 val) -{ - int ret; - struct scm_desc desc = { - .args[0] = address, - .args[1] = val, - .arginfo = SCM_ARGS(2), - }; - - ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_IO, SCM_IO_WRITE), - &desc); - return ret; -} -EXPORT_SYMBOL(scm_io_write); - -int scm_is_call_available(u32 svc_id, u32 cmd_id) -{ - int ret; - struct scm_desc desc = {0}; - - desc.arginfo = SCM_ARGS(1); - desc.args[0] = SCM_SIP_FNID(svc_id, cmd_id); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_INFO, IS_CALL_AVAIL_CMD), &desc); - if (ret) - return ret; - - return desc.ret[0]; -} -EXPORT_SYMBOL(scm_is_call_available); - -#define GET_FEAT_VERSION_CMD 3 -int scm_get_feat_version(u32 feat) -{ - struct scm_desc desc = {0}; - int ret; - - ret = scm_is_call_available(SCM_SVC_INFO, GET_FEAT_VERSION_CMD); - if (ret <= 0) - return 0; - - desc.args[0] = feat; - desc.arginfo = SCM_ARGS(1); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_INFO, GET_FEAT_VERSION_CMD), - &desc); - if (!ret) - return desc.ret[0]; - - return 0; -} -EXPORT_SYMBOL(scm_get_feat_version); - -static int qcom_scm_probe(struct platform_device *pdev) -{ - int ret = 0; - - if (unlikely(!is_scm_armv8())) { - dev_err(&pdev->dev, "SCM ARMv8 not supported\n"); - return -ENODEV; - } - -#ifdef CONFIG_ARM64 - ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); -#endif - if (!ret) - qcom_scm_dev = &pdev->dev; - - return ret; -} - -static const struct of_device_id qcom_scm_of_match[] = { - { .compatible = "qcom,secure-chan-manager"}, - {} -}; -MODULE_DEVICE_TABLE(of, qcom_scm_of_match); - -static struct platform_driver qcom_scm_driver = { - .probe = qcom_scm_probe, - .driver = { - .name = "qcom_secure_chan_manager", - .of_match_table = qcom_scm_of_match, - }, -}; - -module_platform_driver(qcom_scm_driver); - -MODULE_LICENSE("GPL v2"); diff --git a/include/soc/qcom/scm.h b/include/soc/qcom/scm.h deleted file mode 100644 index 1e7789c60fb7..000000000000 --- a/include/soc/qcom/scm.h +++ /dev/null @@ -1,141 +0,0 @@ -/* 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 - * @arginfo: Metadata describing the arguments in args[] - * @args: The array of arguments for the secure syscall - * @ret: The values returned by the secure syscall - * @extra_arg_buf: The buffer containing extra arguments - (that don't fit in available registers) - * @x5: The 4rd argument to the secure syscall or physical address of - extra_arg_buf - */ -struct scm_desc { - u32 arginfo; - u64 args[MAX_SCM_ARGS]; - u64 ret[MAX_SCM_RETS]; - - /* private */ - void *extra_arg_buf; - u64 x5; -}; - -#if IS_ENABLED(CONFIG_QCOM_SECURE_CHAN_MANAGER) - -#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) -extern int scm_call2(u32 cmd_id, struct scm_desc *desc); -extern int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc); -extern int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc); -extern int scm_is_call_available(u32 svc_id, u32 cmd_id); -extern u32 scm_io_read(phys_addr_t address); -extern int scm_io_write(phys_addr_t address, u32 val); -extern int scm_get_feat_version(u32 feat); - -#else - -static inline int scm_call2(u32 cmd_id, struct scm_desc *desc) -{ - return 0; -} - -static inline int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc) -{ - return 0; -} - -static inline int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc) -{ - return 0; -} - -static inline int scm_get_feat_version(u32 feat) -{ - return 0; -} - -static inline int scm_is_call_available(u32 svc_id, u32 cmd_id) -{ - return 0; -} - -static inline u32 scm_io_read(phys_addr_t address) -{ - return 0; -} - -static inline int scm_io_write(phys_addr_t address, u32 val) -{ - return 0; -} - -#endif -#endif diff --git a/include/trace/events/scm.h b/include/trace/events/scm.h index 860cb070cde3..ebca8f0ccf2b 100644 --- a/include/trace/events/scm.h +++ b/include/trace/events/scm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018-2019 The Linux Foundation. All rights reserved. */ #undef TRACE_SYSTEM @@ -10,50 +10,37 @@ #define _TRACE_SCM_H #include #include -#include +#include -TRACE_EVENT(scm_call_start, +TRACE_EVENT(scm_call, - TP_PROTO(u64 x0, struct scm_desc *p), + TP_PROTO(const unsigned long *a, const struct arm_smccc_res *r, + const s64 delta), - TP_ARGS(x0, p), + TP_ARGS(a, r, delta), TP_STRUCT__entry( - __field(u64, x0) - __field(u32, arginfo) - __array(u64, args, MAX_SCM_ARGS) - __field(u64, x5) + __array(u64, args, 8) + __array(unsigned long, ret, 4) + __field(s64, delta) ), TP_fast_assign( - __entry->x0 = x0; - __entry->arginfo = p->arginfo; - memcpy(__entry->args, p->args, sizeof(__entry->args)); - __entry->x5 = p->x5; + memcpy(__entry->args, a, sizeof(__entry->args)); + __entry->ret[0] = r->a0; + __entry->ret[1] = r->a1; + __entry->ret[2] = r->a2; + __entry->ret[3] = r->a3; + __entry->delta = delta; ), - TP_printk("func id=%#llx (args: %#x, %#llx, %#llx, %#llx, %#llx)", - __entry->x0, __entry->arginfo, __entry->args[0], - __entry->args[1], __entry->args[2], __entry->x5) -); - - -TRACE_EVENT(scm_call_end, - - TP_PROTO(struct scm_desc *p), - - TP_ARGS(p), - - TP_STRUCT__entry( - __array(u64, ret, MAX_SCM_RETS) - ), - - TP_fast_assign( - memcpy(__entry->ret, p->ret, sizeof(__entry->ret)); - ), - - TP_printk("ret: %#llx, %#llx, %#llx", - __entry->ret[0], __entry->ret[1], __entry->ret[2]) + TP_printk("%3ld [%#lx %#lx %#lx %#lx %#lx %#lx %#lx %#lx] (%#lx %#lx %#lx %#lx)", + __entry->delta, + __entry->args[0], __entry->args[1], __entry->args[2], + __entry->args[3], __entry->args[4], __entry->args[5], + __entry->args[6], __entry->args[7], + __entry->ret[0], __entry->ret[1], + __entry->ret[2], __entry->ret[3]) ); #endif /* _TRACE_SCM_H */