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