diff options
Diffstat (limited to 'meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch')
-rw-r--r-- | meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch b/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch new file mode 100644 index 0000000000..9854be1c54 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch @@ -0,0 +1,496 @@ +From 41cab33091954ec655e7fe567c345f5a44fea122 Mon Sep 17 00:00:00 2001 +From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com> +Date: Fri, 14 Jan 2022 14:02:39 +0000 +Subject: [PATCH 30/40] ANDROID: trusty: Separate out SMC based transport + +This commit refactors SMC based transport operation like +smc_fastcalls, smc memory operations in a separate file. + +Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com> +Change-Id: Iebee505b7172f6247186e3bf1e0b50740b2e4dfa +Upstream-Status: Pending [Not submitted to upstream yet] +Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com +--- + drivers/trusty/Makefile | 1 + + drivers/trusty/trusty-private.h | 61 ++++++++++++++ + drivers/trusty/trusty-smc.c | 136 ++++++++++++++++++++++++++++++ + drivers/trusty/trusty.c | 144 +++++++++----------------------- + 4 files changed, 237 insertions(+), 105 deletions(-) + create mode 100644 drivers/trusty/trusty-private.h + create mode 100644 drivers/trusty/trusty-smc.c + +diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile +index 2cf1cfccf97b..fbb53ee93003 100644 +--- a/drivers/trusty/Makefile ++++ b/drivers/trusty/Makefile +@@ -5,6 +5,7 @@ + + obj-$(CONFIG_TRUSTY) += trusty-core.o + trusty-core-objs += trusty.o trusty-mem.o ++trusty-core-objs += trusty-smc.o + trusty-core-$(CONFIG_ARM) += trusty-smc-arm.o + trusty-core-$(CONFIG_ARM64) += trusty-smc-arm64.o + obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o +diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h +new file mode 100644 +index 000000000000..4d73c6ae35d4 +--- /dev/null ++++ b/drivers/trusty/trusty-private.h +@@ -0,0 +1,61 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2022 ARM Ltd. ++ */ ++ ++#ifndef _TRUSTY_PRIVATE_H ++#define _TRUSTY_PRIVATE_H ++ ++#include <linux/types.h> ++ ++struct trusty_work { ++ struct trusty_state *ts; ++ struct work_struct work; ++}; ++ ++struct trusty_msg_ops { ++ u32 (*send_direct_msg)(struct device *dev, unsigned long fid, ++ unsigned long a0, unsigned long a1, ++ unsigned long a2); ++}; ++ ++struct trusty_mem_ops { ++ int (*trusty_share_memory)(struct device *dev, u64 *id, ++ struct scatterlist *sglist, ++ unsigned int nents, pgprot_t pgprot, u64 tag); ++ int (*trusty_lend_memory)(struct device *dev, u64 *id, ++ struct scatterlist *sglist, ++ unsigned int nents, pgprot_t pgprot, u64 tag); ++ int (*trusty_reclaim_memory)(struct device *dev, u64 id, ++ struct scatterlist *sglist, ++ unsigned int nents); ++}; ++ ++struct trusty_state { ++ struct mutex smc_lock; ++ struct atomic_notifier_head notifier; ++ struct completion cpu_idle_completion; ++ char *version_str; ++ u32 api_version; ++ bool trusty_panicked; ++ struct device *dev; ++ struct workqueue_struct *nop_wq; ++ struct trusty_work __percpu *nop_works; ++ struct list_head nop_queue; ++ spinlock_t nop_lock; /* protects nop_queue */ ++ struct device_dma_parameters dma_parms; ++ const struct trusty_msg_ops *msg_ops; ++ const struct trusty_mem_ops *mem_ops; ++}; ++ ++int trusty_init_api_version(struct trusty_state *s, struct device *dev, ++ u32 (*send_direct_msg)(struct device *dev, ++ unsigned long fid, ++ unsigned long a0, ++ unsigned long a1, ++ unsigned long a2)); ++ ++int trusty_smc_transport_setup(struct device *dev); ++void trusty_smc_transport_cleanup(struct device *dev); ++ ++#endif /* _TRUSTY_PRIVATE_H */ +diff --git a/drivers/trusty/trusty-smc.c b/drivers/trusty/trusty-smc.c +new file mode 100644 +index 000000000000..8fa841e0e253 +--- /dev/null ++++ b/drivers/trusty/trusty-smc.c +@@ -0,0 +1,136 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 Google, Inc. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/trusty/smcall.h> ++#include <linux/trusty/trusty.h> ++ ++#include <linux/scatterlist.h> ++#include <linux/dma-mapping.h> ++ ++#include "trusty-smc.h" ++#include "trusty-private.h" ++ ++static u32 trusty_smc_send_direct_msg(struct device *dev, unsigned long fid, ++ unsigned long a0, unsigned long a1, ++ unsigned long a2) ++{ ++ return trusty_smc8(fid, a0, a1, a2, 0, 0, 0, 0).r0; ++} ++ ++static int trusty_smc_share_memory(struct device *dev, u64 *id, ++ struct scatterlist *sglist, ++ unsigned int nents, pgprot_t pgprot, u64 tag) ++{ ++ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); ++ int ret; ++ struct ns_mem_page_info pg_inf; ++ struct scatterlist *sg; ++ size_t count; ++ ++ if (WARN_ON(nents < 1)) ++ return -EINVAL; ++ ++ if (nents != 1) { ++ dev_err(s->dev, "%s: old trusty version does not support " ++ "non-contiguous memory objects\n", __func__); ++ return -EOPNOTSUPP; ++ } ++ ++ count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL); ++ if (count != nents) { ++ dev_err(s->dev, "failed to dma map sg_table\n"); ++ return -EINVAL; ++ } ++ ++ sg = sglist; ++ ret = trusty_encode_page_info(&pg_inf, phys_to_page(sg_dma_address(sg)), ++ pgprot); ++ if (ret) { ++ dev_err(s->dev, "%s: trusty_encode_page_info failed\n", ++ __func__); ++ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL); ++ return ret; ++ } ++ ++ *id = pg_inf.compat_attr; ++ return 0; ++} ++ ++static int trusty_smc_lend_memory(struct device *dev, u64 *id, ++ struct scatterlist *sglist, ++ unsigned int nents, pgprot_t pgprot, u64 tag) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static int trusty_smc_reclaim_memory(struct device *dev, u64 id, ++ struct scatterlist *sglist, ++ unsigned int nents) ++{ ++ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); ++ ++ if (WARN_ON(nents < 1)) ++ return -EINVAL; ++ ++ if (WARN_ON(s->api_version >= TRUSTY_API_VERSION_MEM_OBJ)) ++ return -EINVAL; ++ ++ if (nents != 1) { ++ dev_err(s->dev, "%s: not supported\n", __func__); ++ return -EOPNOTSUPP; ++ } ++ ++ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL); ++ ++ dev_dbg(s->dev, "%s: done\n", __func__); ++ return 0; ++} ++ ++static const struct trusty_msg_ops trusty_smc_msg_ops = { ++ .send_direct_msg = &trusty_smc_send_direct_msg, ++}; ++ ++static const struct trusty_mem_ops trusty_smc_mem_ops = { ++ .trusty_share_memory = &trusty_smc_share_memory, ++ .trusty_lend_memory = &trusty_smc_lend_memory, ++ .trusty_reclaim_memory = &trusty_smc_reclaim_memory, ++}; ++ ++int trusty_smc_transport_setup(struct device *dev) ++{ ++ int rc; ++ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); ++ ++ rc = trusty_init_api_version(s, dev, &trusty_smc_send_direct_msg); ++ if (rc != 0) { ++ return rc; ++ } ++ ++ /* ++ * Initialize Trusty msg calls with Trusty SMC ABI ++ */ ++ s->msg_ops = &trusty_smc_msg_ops; ++ ++ /* ++ * Initialize Trusty memory operations with Trusty SMC ABI only when ++ * Trusty API version is below TRUSTY_API_VERSION_MEM_OBJ. ++ */ ++ if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ) ++ s->mem_ops = &trusty_smc_mem_ops; ++ ++ return 0; ++} ++ ++void trusty_smc_transport_cleanup(struct device *dev) ++{ ++ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); ++ ++ if (s->msg_ops == &trusty_smc_msg_ops) ++ s->msg_ops = NULL; ++ ++ if (s->mem_ops == &trusty_smc_mem_ops) ++ s->mem_ops = NULL; ++} +diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c +index 6bd30bc1bbc9..0486827a45ca 100644 +--- a/drivers/trusty/trusty.c ++++ b/drivers/trusty/trusty.c +@@ -18,37 +18,10 @@ + #include <linux/scatterlist.h> + #include <linux/dma-mapping.h> + +-#include "trusty-smc.h" ++#include "trusty-private.h" + +-struct trusty_state; + static struct platform_driver trusty_driver; + +-struct trusty_work { +- struct trusty_state *ts; +- struct work_struct work; +-}; +- +-struct trusty_state { +- struct mutex smc_lock; +- struct atomic_notifier_head notifier; +- struct completion cpu_idle_completion; +- char *version_str; +- u32 api_version; +- bool trusty_panicked; +- struct device *dev; +- struct workqueue_struct *nop_wq; +- struct trusty_work __percpu *nop_works; +- struct list_head nop_queue; +- spinlock_t nop_lock; /* protects nop_queue */ +- struct device_dma_parameters dma_parms; +-}; +- +-static inline unsigned long smc(unsigned long r0, unsigned long r1, +- unsigned long r2, unsigned long r3) +-{ +- return trusty_smc8(r0, r1, r2, r3, 0, 0, 0, 0).r0; +-} +- + s32 trusty_fast_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2) + { + struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); +@@ -60,7 +33,7 @@ s32 trusty_fast_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2) + if (WARN_ON(SMC_IS_SMC64(smcnr))) + return SM_ERR_INVALID_PARAMETERS; + +- return smc(smcnr, a0, a1, a2); ++ return s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2); + } + EXPORT_SYMBOL(trusty_fast_call32); + +@@ -76,7 +49,7 @@ s64 trusty_fast_call64(struct device *dev, u64 smcnr, u64 a0, u64 a1, u64 a2) + if (WARN_ON(!SMC_IS_SMC64(smcnr))) + return SM_ERR_INVALID_PARAMETERS; + +- return smc(smcnr, a0, a1, a2); ++ return s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2); + } + EXPORT_SYMBOL(trusty_fast_call64); + #endif +@@ -88,13 +61,16 @@ static unsigned long trusty_std_call_inner(struct device *dev, + { + unsigned long ret; + int retry = 5; ++ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); + + dev_dbg(dev, "%s(0x%lx 0x%lx 0x%lx 0x%lx)\n", + __func__, smcnr, a0, a1, a2); + while (true) { +- ret = smc(smcnr, a0, a1, a2); ++ ret = s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2); + while ((s32)ret == SM_ERR_FIQ_INTERRUPTED) +- ret = smc(SMC_SC_RESTART_FIQ, 0, 0, 0); ++ ret = s->msg_ops->send_direct_msg(dev, ++ SMC_SC_RESTART_FIQ, ++ 0, 0, 0); + if ((int)ret != SM_ERR_BUSY || !retry) + break; + +@@ -222,58 +198,17 @@ s32 trusty_std_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2) + } + EXPORT_SYMBOL(trusty_std_call32); + +-static int __trusty_share_memory(struct device *dev, u64 *id, +- struct scatterlist *sglist, unsigned int nents, +- pgprot_t pgprot, u64 tag, bool mem_share) ++int trusty_share_memory(struct device *dev, u64 *id, ++ struct scatterlist *sglist, unsigned int nents, ++ pgprot_t pgprot, u64 tag) + { + struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); +- int ret; +- struct ns_mem_page_info pg_inf; +- struct scatterlist *sg; +- size_t count; + + if (WARN_ON(dev->driver != &trusty_driver.driver)) + return -EINVAL; + +- if (WARN_ON(nents < 1)) +- return -EINVAL; +- +- if (nents != 1 && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) { +- dev_err(s->dev, "%s: old trusty version does not support non-contiguous memory objects\n", +- __func__); +- return -EOPNOTSUPP; +- } +- +- if (mem_share == false && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) { +- dev_err(s->dev, "%s: old trusty version does not support lending memory objects\n", +- __func__); +- return -EOPNOTSUPP; +- } +- +- count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL); +- if (count != nents) { +- dev_err(s->dev, "failed to dma map sg_table\n"); +- return -EINVAL; +- } +- +- sg = sglist; +- ret = trusty_encode_page_info(&pg_inf, phys_to_page(sg_dma_address(sg)), +- pgprot); +- if (ret) { +- dev_err(s->dev, "%s: trusty_encode_page_info failed\n", +- __func__); +- return ret; +- } +- +- *id = pg_inf.compat_attr; +- return 0; +-} +- +-int trusty_share_memory(struct device *dev, u64 *id, +- struct scatterlist *sglist, unsigned int nents, +- pgprot_t pgprot, u64 tag) +-{ +- return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, true); ++ return s->mem_ops->trusty_share_memory(dev, id, sglist, nents, pgprot, ++ tag); + } + EXPORT_SYMBOL(trusty_share_memory); + +@@ -281,7 +216,13 @@ int trusty_lend_memory(struct device *dev, u64 *id, + struct scatterlist *sglist, unsigned int nents, + pgprot_t pgprot, u64 tag) + { +- return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, false); ++ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev)); ++ ++ if (WARN_ON(dev->driver != &trusty_driver.driver)) ++ return -EINVAL; ++ ++ return s->mem_ops->trusty_lend_memory(dev, id, sglist, nents, pgprot, ++ tag); + } + EXPORT_SYMBOL(trusty_lend_memory); + +@@ -316,22 +257,7 @@ int trusty_reclaim_memory(struct device *dev, u64 id, + if (WARN_ON(dev->driver != &trusty_driver.driver)) + return -EINVAL; + +- if (WARN_ON(nents < 1)) +- return -EINVAL; +- +- if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ) { +- if (nents != 1) { +- dev_err(s->dev, "%s: not supported\n", __func__); +- return -EOPNOTSUPP; +- } +- +- dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL); +- +- dev_dbg(s->dev, "%s: done\n", __func__); +- return 0; +- } +- +- return 0; ++ return s->mem_ops->trusty_reclaim_memory(dev, id, sglist, nents); + } + EXPORT_SYMBOL(trusty_reclaim_memory); + +@@ -382,7 +308,7 @@ const char *trusty_version_str_get(struct device *dev) + } + EXPORT_SYMBOL(trusty_version_str_get); + +-static void trusty_init_version(struct trusty_state *s, struct device *dev) ++static void trusty_init_version_str(struct trusty_state *s, struct device *dev) + { + int ret; + int i; +@@ -430,12 +356,17 @@ bool trusty_get_panic_status(struct device *dev) + } + EXPORT_SYMBOL(trusty_get_panic_status); + +-static int trusty_init_api_version(struct trusty_state *s, struct device *dev) ++int trusty_init_api_version(struct trusty_state *s, struct device *dev, ++ u32 (*send_direct_msg)(struct device *dev, ++ unsigned long fid, ++ unsigned long a0, ++ unsigned long a1, ++ unsigned long a2)) + { + u32 api_version; + +- api_version = trusty_fast_call32(dev, SMC_FC_API_VERSION, +- TRUSTY_API_VERSION_CURRENT, 0, 0); ++ api_version = send_direct_msg(dev, SMC_FC_API_VERSION, ++ TRUSTY_API_VERSION_CURRENT, 0, 0); + if (api_version == SM_ERR_UNDEFINED_SMC) + api_version = 0; + +@@ -598,11 +529,12 @@ static int trusty_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, s); + +- trusty_init_version(s, &pdev->dev); ++ /* Initialize SMC transport */ ++ ret = trusty_smc_transport_setup(s->dev); ++ if (ret != 0 || s->msg_ops == NULL || s->mem_ops == NULL) ++ goto err_transport_setup; + +- ret = trusty_init_api_version(s, &pdev->dev); +- if (ret < 0) +- goto err_api_version; ++ trusty_init_version_str(s, &pdev->dev); + + s->nop_wq = alloc_workqueue("trusty-nop-wq", WQ_CPU_INTENSIVE, 0); + if (!s->nop_wq) { +@@ -648,9 +580,10 @@ static int trusty_probe(struct platform_device *pdev) + err_alloc_works: + destroy_workqueue(s->nop_wq); + err_create_nop_wq: +-err_api_version: +- s->dev->dma_parms = NULL; + kfree(s->version_str); ++ trusty_smc_transport_cleanup(s->dev); ++err_transport_setup: ++ s->dev->dma_parms = NULL; + device_for_each_child(&pdev->dev, NULL, trusty_remove_child); + mutex_destroy(&s->smc_lock); + kfree(s); +@@ -673,6 +606,7 @@ static int trusty_remove(struct platform_device *pdev) + free_percpu(s->nop_works); + destroy_workqueue(s->nop_wq); + ++ trusty_smc_transport_cleanup(s->dev); + mutex_destroy(&s->smc_lock); + s->dev->dma_parms = NULL; + kfree(s->version_str); +-- +2.34.1 + |