summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.15/tc/0030-ANDROID-trusty-Separate-out-SMC-based-transport.patch
diff options
context:
space:
mode:
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.patch496
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
+