blob: 9854be1c54b1fefd63c0a46b7bc784cfc45e5882 [file] [log] [blame]
Patrick Williams2194f502022-10-16 14:26:09 -05001From 41cab33091954ec655e7fe567c345f5a44fea122 Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
3Date: Fri, 14 Jan 2022 14:02:39 +0000
Patrick Williams2194f502022-10-16 14:26:09 -05004Subject: [PATCH 30/40] ANDROID: trusty: Separate out SMC based transport
Brad Bishopbec4ebc2022-08-03 09:55:16 -04005
6This commit refactors SMC based transport operation like
7smc_fastcalls, smc memory operations in a separate file.
8
9Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
10Change-Id: Iebee505b7172f6247186e3bf1e0b50740b2e4dfa
11Upstream-Status: Pending [Not submitted to upstream yet]
Patrick Williams2194f502022-10-16 14:26:09 -050012Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com
Brad Bishopbec4ebc2022-08-03 09:55:16 -040013---
14 drivers/trusty/Makefile | 1 +
15 drivers/trusty/trusty-private.h | 61 ++++++++++++++
16 drivers/trusty/trusty-smc.c | 136 ++++++++++++++++++++++++++++++
17 drivers/trusty/trusty.c | 144 +++++++++-----------------------
18 4 files changed, 237 insertions(+), 105 deletions(-)
19 create mode 100644 drivers/trusty/trusty-private.h
20 create mode 100644 drivers/trusty/trusty-smc.c
21
22diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile
23index 2cf1cfccf97b..fbb53ee93003 100644
24--- a/drivers/trusty/Makefile
25+++ b/drivers/trusty/Makefile
26@@ -5,6 +5,7 @@
27
28 obj-$(CONFIG_TRUSTY) += trusty-core.o
29 trusty-core-objs += trusty.o trusty-mem.o
30+trusty-core-objs += trusty-smc.o
31 trusty-core-$(CONFIG_ARM) += trusty-smc-arm.o
32 trusty-core-$(CONFIG_ARM64) += trusty-smc-arm64.o
33 obj-$(CONFIG_TRUSTY_IRQ) += trusty-irq.o
34diff --git a/drivers/trusty/trusty-private.h b/drivers/trusty/trusty-private.h
35new file mode 100644
36index 000000000000..4d73c6ae35d4
37--- /dev/null
38+++ b/drivers/trusty/trusty-private.h
39@@ -0,0 +1,61 @@
40+/* SPDX-License-Identifier: GPL-2.0-only */
41+/*
42+ * Copyright (C) 2022 ARM Ltd.
43+ */
44+
45+#ifndef _TRUSTY_PRIVATE_H
46+#define _TRUSTY_PRIVATE_H
47+
48+#include <linux/types.h>
49+
50+struct trusty_work {
51+ struct trusty_state *ts;
52+ struct work_struct work;
53+};
54+
55+struct trusty_msg_ops {
56+ u32 (*send_direct_msg)(struct device *dev, unsigned long fid,
57+ unsigned long a0, unsigned long a1,
58+ unsigned long a2);
59+};
60+
61+struct trusty_mem_ops {
62+ int (*trusty_share_memory)(struct device *dev, u64 *id,
63+ struct scatterlist *sglist,
64+ unsigned int nents, pgprot_t pgprot, u64 tag);
65+ int (*trusty_lend_memory)(struct device *dev, u64 *id,
66+ struct scatterlist *sglist,
67+ unsigned int nents, pgprot_t pgprot, u64 tag);
68+ int (*trusty_reclaim_memory)(struct device *dev, u64 id,
69+ struct scatterlist *sglist,
70+ unsigned int nents);
71+};
72+
73+struct trusty_state {
74+ struct mutex smc_lock;
75+ struct atomic_notifier_head notifier;
76+ struct completion cpu_idle_completion;
77+ char *version_str;
78+ u32 api_version;
79+ bool trusty_panicked;
80+ struct device *dev;
81+ struct workqueue_struct *nop_wq;
82+ struct trusty_work __percpu *nop_works;
83+ struct list_head nop_queue;
84+ spinlock_t nop_lock; /* protects nop_queue */
85+ struct device_dma_parameters dma_parms;
86+ const struct trusty_msg_ops *msg_ops;
87+ const struct trusty_mem_ops *mem_ops;
88+};
89+
90+int trusty_init_api_version(struct trusty_state *s, struct device *dev,
91+ u32 (*send_direct_msg)(struct device *dev,
92+ unsigned long fid,
93+ unsigned long a0,
94+ unsigned long a1,
95+ unsigned long a2));
96+
97+int trusty_smc_transport_setup(struct device *dev);
98+void trusty_smc_transport_cleanup(struct device *dev);
99+
100+#endif /* _TRUSTY_PRIVATE_H */
101diff --git a/drivers/trusty/trusty-smc.c b/drivers/trusty/trusty-smc.c
102new file mode 100644
103index 000000000000..8fa841e0e253
104--- /dev/null
105+++ b/drivers/trusty/trusty-smc.c
106@@ -0,0 +1,136 @@
107+// SPDX-License-Identifier: GPL-2.0-only
108+/*
109+ * Copyright (C) 2013 Google, Inc.
110+ */
111+
112+#include <linux/platform_device.h>
113+#include <linux/trusty/smcall.h>
114+#include <linux/trusty/trusty.h>
115+
116+#include <linux/scatterlist.h>
117+#include <linux/dma-mapping.h>
118+
119+#include "trusty-smc.h"
120+#include "trusty-private.h"
121+
122+static u32 trusty_smc_send_direct_msg(struct device *dev, unsigned long fid,
123+ unsigned long a0, unsigned long a1,
124+ unsigned long a2)
125+{
126+ return trusty_smc8(fid, a0, a1, a2, 0, 0, 0, 0).r0;
127+}
128+
129+static int trusty_smc_share_memory(struct device *dev, u64 *id,
130+ struct scatterlist *sglist,
131+ unsigned int nents, pgprot_t pgprot, u64 tag)
132+{
133+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
134+ int ret;
135+ struct ns_mem_page_info pg_inf;
136+ struct scatterlist *sg;
137+ size_t count;
138+
139+ if (WARN_ON(nents < 1))
140+ return -EINVAL;
141+
142+ if (nents != 1) {
143+ dev_err(s->dev, "%s: old trusty version does not support "
144+ "non-contiguous memory objects\n", __func__);
145+ return -EOPNOTSUPP;
146+ }
147+
148+ count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
149+ if (count != nents) {
150+ dev_err(s->dev, "failed to dma map sg_table\n");
151+ return -EINVAL;
152+ }
153+
154+ sg = sglist;
155+ ret = trusty_encode_page_info(&pg_inf, phys_to_page(sg_dma_address(sg)),
156+ pgprot);
157+ if (ret) {
158+ dev_err(s->dev, "%s: trusty_encode_page_info failed\n",
159+ __func__);
160+ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
161+ return ret;
162+ }
163+
164+ *id = pg_inf.compat_attr;
165+ return 0;
166+}
167+
168+static int trusty_smc_lend_memory(struct device *dev, u64 *id,
169+ struct scatterlist *sglist,
170+ unsigned int nents, pgprot_t pgprot, u64 tag)
171+{
172+ return -EOPNOTSUPP;
173+}
174+
175+static int trusty_smc_reclaim_memory(struct device *dev, u64 id,
176+ struct scatterlist *sglist,
177+ unsigned int nents)
178+{
179+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
180+
181+ if (WARN_ON(nents < 1))
182+ return -EINVAL;
183+
184+ if (WARN_ON(s->api_version >= TRUSTY_API_VERSION_MEM_OBJ))
185+ return -EINVAL;
186+
187+ if (nents != 1) {
188+ dev_err(s->dev, "%s: not supported\n", __func__);
189+ return -EOPNOTSUPP;
190+ }
191+
192+ dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
193+
194+ dev_dbg(s->dev, "%s: done\n", __func__);
195+ return 0;
196+}
197+
198+static const struct trusty_msg_ops trusty_smc_msg_ops = {
199+ .send_direct_msg = &trusty_smc_send_direct_msg,
200+};
201+
202+static const struct trusty_mem_ops trusty_smc_mem_ops = {
203+ .trusty_share_memory = &trusty_smc_share_memory,
204+ .trusty_lend_memory = &trusty_smc_lend_memory,
205+ .trusty_reclaim_memory = &trusty_smc_reclaim_memory,
206+};
207+
208+int trusty_smc_transport_setup(struct device *dev)
209+{
210+ int rc;
211+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
212+
213+ rc = trusty_init_api_version(s, dev, &trusty_smc_send_direct_msg);
214+ if (rc != 0) {
215+ return rc;
216+ }
217+
218+ /*
219+ * Initialize Trusty msg calls with Trusty SMC ABI
220+ */
221+ s->msg_ops = &trusty_smc_msg_ops;
222+
223+ /*
224+ * Initialize Trusty memory operations with Trusty SMC ABI only when
225+ * Trusty API version is below TRUSTY_API_VERSION_MEM_OBJ.
226+ */
227+ if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ)
228+ s->mem_ops = &trusty_smc_mem_ops;
229+
230+ return 0;
231+}
232+
233+void trusty_smc_transport_cleanup(struct device *dev)
234+{
235+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
236+
237+ if (s->msg_ops == &trusty_smc_msg_ops)
238+ s->msg_ops = NULL;
239+
240+ if (s->mem_ops == &trusty_smc_mem_ops)
241+ s->mem_ops = NULL;
242+}
243diff --git a/drivers/trusty/trusty.c b/drivers/trusty/trusty.c
244index 6bd30bc1bbc9..0486827a45ca 100644
245--- a/drivers/trusty/trusty.c
246+++ b/drivers/trusty/trusty.c
247@@ -18,37 +18,10 @@
248 #include <linux/scatterlist.h>
249 #include <linux/dma-mapping.h>
250
251-#include "trusty-smc.h"
252+#include "trusty-private.h"
253
254-struct trusty_state;
255 static struct platform_driver trusty_driver;
256
257-struct trusty_work {
258- struct trusty_state *ts;
259- struct work_struct work;
260-};
261-
262-struct trusty_state {
263- struct mutex smc_lock;
264- struct atomic_notifier_head notifier;
265- struct completion cpu_idle_completion;
266- char *version_str;
267- u32 api_version;
268- bool trusty_panicked;
269- struct device *dev;
270- struct workqueue_struct *nop_wq;
271- struct trusty_work __percpu *nop_works;
272- struct list_head nop_queue;
273- spinlock_t nop_lock; /* protects nop_queue */
274- struct device_dma_parameters dma_parms;
275-};
276-
277-static inline unsigned long smc(unsigned long r0, unsigned long r1,
278- unsigned long r2, unsigned long r3)
279-{
280- return trusty_smc8(r0, r1, r2, r3, 0, 0, 0, 0).r0;
281-}
282-
283 s32 trusty_fast_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
284 {
285 struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
286@@ -60,7 +33,7 @@ s32 trusty_fast_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
287 if (WARN_ON(SMC_IS_SMC64(smcnr)))
288 return SM_ERR_INVALID_PARAMETERS;
289
290- return smc(smcnr, a0, a1, a2);
291+ return s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2);
292 }
293 EXPORT_SYMBOL(trusty_fast_call32);
294
295@@ -76,7 +49,7 @@ s64 trusty_fast_call64(struct device *dev, u64 smcnr, u64 a0, u64 a1, u64 a2)
296 if (WARN_ON(!SMC_IS_SMC64(smcnr)))
297 return SM_ERR_INVALID_PARAMETERS;
298
299- return smc(smcnr, a0, a1, a2);
300+ return s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2);
301 }
302 EXPORT_SYMBOL(trusty_fast_call64);
303 #endif
304@@ -88,13 +61,16 @@ static unsigned long trusty_std_call_inner(struct device *dev,
305 {
306 unsigned long ret;
307 int retry = 5;
308+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
309
310 dev_dbg(dev, "%s(0x%lx 0x%lx 0x%lx 0x%lx)\n",
311 __func__, smcnr, a0, a1, a2);
312 while (true) {
313- ret = smc(smcnr, a0, a1, a2);
314+ ret = s->msg_ops->send_direct_msg(dev, smcnr, a0, a1, a2);
315 while ((s32)ret == SM_ERR_FIQ_INTERRUPTED)
316- ret = smc(SMC_SC_RESTART_FIQ, 0, 0, 0);
317+ ret = s->msg_ops->send_direct_msg(dev,
318+ SMC_SC_RESTART_FIQ,
319+ 0, 0, 0);
320 if ((int)ret != SM_ERR_BUSY || !retry)
321 break;
322
323@@ -222,58 +198,17 @@ s32 trusty_std_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2)
324 }
325 EXPORT_SYMBOL(trusty_std_call32);
326
327-static int __trusty_share_memory(struct device *dev, u64 *id,
328- struct scatterlist *sglist, unsigned int nents,
329- pgprot_t pgprot, u64 tag, bool mem_share)
330+int trusty_share_memory(struct device *dev, u64 *id,
331+ struct scatterlist *sglist, unsigned int nents,
332+ pgprot_t pgprot, u64 tag)
333 {
334 struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
335- int ret;
336- struct ns_mem_page_info pg_inf;
337- struct scatterlist *sg;
338- size_t count;
339
340 if (WARN_ON(dev->driver != &trusty_driver.driver))
341 return -EINVAL;
342
343- if (WARN_ON(nents < 1))
344- return -EINVAL;
345-
346- if (nents != 1 && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
347- dev_err(s->dev, "%s: old trusty version does not support non-contiguous memory objects\n",
348- __func__);
349- return -EOPNOTSUPP;
350- }
351-
352- if (mem_share == false && s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
353- dev_err(s->dev, "%s: old trusty version does not support lending memory objects\n",
354- __func__);
355- return -EOPNOTSUPP;
356- }
357-
358- count = dma_map_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
359- if (count != nents) {
360- dev_err(s->dev, "failed to dma map sg_table\n");
361- return -EINVAL;
362- }
363-
364- sg = sglist;
365- ret = trusty_encode_page_info(&pg_inf, phys_to_page(sg_dma_address(sg)),
366- pgprot);
367- if (ret) {
368- dev_err(s->dev, "%s: trusty_encode_page_info failed\n",
369- __func__);
370- return ret;
371- }
372-
373- *id = pg_inf.compat_attr;
374- return 0;
375-}
376-
377-int trusty_share_memory(struct device *dev, u64 *id,
378- struct scatterlist *sglist, unsigned int nents,
379- pgprot_t pgprot, u64 tag)
380-{
381- return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, true);
382+ return s->mem_ops->trusty_share_memory(dev, id, sglist, nents, pgprot,
383+ tag);
384 }
385 EXPORT_SYMBOL(trusty_share_memory);
386
387@@ -281,7 +216,13 @@ int trusty_lend_memory(struct device *dev, u64 *id,
388 struct scatterlist *sglist, unsigned int nents,
389 pgprot_t pgprot, u64 tag)
390 {
391- return __trusty_share_memory(dev, id, sglist, nents, pgprot, tag, false);
392+ struct trusty_state *s = platform_get_drvdata(to_platform_device(dev));
393+
394+ if (WARN_ON(dev->driver != &trusty_driver.driver))
395+ return -EINVAL;
396+
397+ return s->mem_ops->trusty_lend_memory(dev, id, sglist, nents, pgprot,
398+ tag);
399 }
400 EXPORT_SYMBOL(trusty_lend_memory);
401
402@@ -316,22 +257,7 @@ int trusty_reclaim_memory(struct device *dev, u64 id,
403 if (WARN_ON(dev->driver != &trusty_driver.driver))
404 return -EINVAL;
405
406- if (WARN_ON(nents < 1))
407- return -EINVAL;
408-
409- if (s->api_version < TRUSTY_API_VERSION_MEM_OBJ) {
410- if (nents != 1) {
411- dev_err(s->dev, "%s: not supported\n", __func__);
412- return -EOPNOTSUPP;
413- }
414-
415- dma_unmap_sg(dev, sglist, nents, DMA_BIDIRECTIONAL);
416-
417- dev_dbg(s->dev, "%s: done\n", __func__);
418- return 0;
419- }
420-
421- return 0;
422+ return s->mem_ops->trusty_reclaim_memory(dev, id, sglist, nents);
423 }
424 EXPORT_SYMBOL(trusty_reclaim_memory);
425
426@@ -382,7 +308,7 @@ const char *trusty_version_str_get(struct device *dev)
427 }
428 EXPORT_SYMBOL(trusty_version_str_get);
429
430-static void trusty_init_version(struct trusty_state *s, struct device *dev)
431+static void trusty_init_version_str(struct trusty_state *s, struct device *dev)
432 {
433 int ret;
434 int i;
435@@ -430,12 +356,17 @@ bool trusty_get_panic_status(struct device *dev)
436 }
437 EXPORT_SYMBOL(trusty_get_panic_status);
438
439-static int trusty_init_api_version(struct trusty_state *s, struct device *dev)
440+int trusty_init_api_version(struct trusty_state *s, struct device *dev,
441+ u32 (*send_direct_msg)(struct device *dev,
442+ unsigned long fid,
443+ unsigned long a0,
444+ unsigned long a1,
445+ unsigned long a2))
446 {
447 u32 api_version;
448
449- api_version = trusty_fast_call32(dev, SMC_FC_API_VERSION,
450- TRUSTY_API_VERSION_CURRENT, 0, 0);
451+ api_version = send_direct_msg(dev, SMC_FC_API_VERSION,
452+ TRUSTY_API_VERSION_CURRENT, 0, 0);
453 if (api_version == SM_ERR_UNDEFINED_SMC)
454 api_version = 0;
455
456@@ -598,11 +529,12 @@ static int trusty_probe(struct platform_device *pdev)
457
458 platform_set_drvdata(pdev, s);
459
460- trusty_init_version(s, &pdev->dev);
461+ /* Initialize SMC transport */
462+ ret = trusty_smc_transport_setup(s->dev);
463+ if (ret != 0 || s->msg_ops == NULL || s->mem_ops == NULL)
464+ goto err_transport_setup;
465
466- ret = trusty_init_api_version(s, &pdev->dev);
467- if (ret < 0)
468- goto err_api_version;
469+ trusty_init_version_str(s, &pdev->dev);
470
471 s->nop_wq = alloc_workqueue("trusty-nop-wq", WQ_CPU_INTENSIVE, 0);
472 if (!s->nop_wq) {
473@@ -648,9 +580,10 @@ static int trusty_probe(struct platform_device *pdev)
474 err_alloc_works:
475 destroy_workqueue(s->nop_wq);
476 err_create_nop_wq:
477-err_api_version:
478- s->dev->dma_parms = NULL;
479 kfree(s->version_str);
480+ trusty_smc_transport_cleanup(s->dev);
481+err_transport_setup:
482+ s->dev->dma_parms = NULL;
483 device_for_each_child(&pdev->dev, NULL, trusty_remove_child);
484 mutex_destroy(&s->smc_lock);
485 kfree(s);
486@@ -673,6 +606,7 @@ static int trusty_remove(struct platform_device *pdev)
487 free_percpu(s->nop_works);
488 destroy_workqueue(s->nop_wq);
489
490+ trusty_smc_transport_cleanup(s->dev);
491 mutex_destroy(&s->smc_lock);
492 s->dev->dma_parms = NULL;
493 kfree(s->version_str);
494--
Patrick Williams2194f502022-10-16 14:26:09 -05004952.34.1
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400496