clear-pkgs-linux-iot-lts2018/0884-trusty-add-couple-non-...

208 lines
5.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Michael Ryleev <gmar@google.com>
Date: Thu, 26 Mar 2015 19:31:25 -0700
Subject: [PATCH] trusty: add couple non-secure memory related helper routines
trusty_encode_page_info - encodes page physical address, memory
type and other attributes into architecture specific structure
that can be parsed by secure side.
trusty_call32_mem_buf - can be used by drivers to make
specified smc call with physicaly contigues memory buffer as
an argument. Memory buffer info in retrieved by trusty_encode_page_info
and along with buffer size is encoded into series of 32-bit
smc call parameters.
Change-Id: I79aadca85e2329bb89469b4c8f183cf0752f7641
Signed-off-by: Michael Ryleev <gmar@google.com>
---
drivers/trusty/Makefile | 1 +
drivers/trusty/trusty-mem.c | 134 ++++++++++++++++++++++++++++++++++
include/linux/trusty/trusty.h | 15 ++++
3 files changed, 150 insertions(+)
create mode 100644 drivers/trusty/trusty-mem.c
diff --git a/drivers/trusty/Makefile b/drivers/trusty/Makefile
index 641ee2a6e830..e527a237cb5d 100644
--- a/drivers/trusty/Makefile
+++ b/drivers/trusty/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_TRUSTY_FIQ) += trusty-fiq.o
obj-$(CONFIG_TRUSTY_FIQ_ARM) += trusty-fiq-arm.o
obj-$(CONFIG_TRUSTY_FIQ_ARM64) += trusty-fiq-arm64.o trusty-fiq-arm64-glue.o
obj-$(CONFIG_TRUSTY_LOG) += trusty-log.o
+obj-$(CONFIG_TRUSTY) += trusty-mem.o
diff --git a/drivers/trusty/trusty-mem.c b/drivers/trusty/trusty-mem.c
new file mode 100644
index 000000000000..c55ace25beed
--- /dev/null
+++ b/drivers/trusty/trusty-mem.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/printk.h>
+#include <linux/trusty/trusty.h>
+#include <linux/trusty/smcall.h>
+
+static int get_mem_attr(struct page *page, pgprot_t pgprot)
+{
+#if defined(CONFIG_ARM64)
+ uint64_t mair;
+ uint attr_index = (pgprot_val(pgprot) & PTE_ATTRINDX_MASK) >> 2;
+
+ asm ("mrs %0, mair_el1\n" : "=&r" (mair));
+ return (mair >> (attr_index * 8)) & 0xff;
+
+#elif defined(CONFIG_ARM_LPAE)
+ uint32_t mair;
+ uint attr_index = ((pgprot_val(pgprot) & L_PTE_MT_MASK) >> 2);
+
+ if (attr_index >= 4) {
+ attr_index -= 4;
+ asm volatile("mrc p15, 0, %0, c10, c2, 1\n" : "=&r" (mair));
+ } else {
+ asm volatile("mrc p15, 0, %0, c10, c2, 0\n" : "=&r" (mair));
+ }
+ return (mair >> (attr_index * 8)) & 0xff;
+
+#elif defined(CONFIG_ARM)
+ /* check memory type */
+ switch (pgprot_val(pgprot) & L_PTE_MT_MASK) {
+ case L_PTE_MT_WRITEALLOC:
+ /* Normal: write back write allocate */
+ return 0xFF;
+
+ case L_PTE_MT_BUFFERABLE:
+ /* Normal: non-cacheble */
+ return 0x44;
+
+ case L_PTE_MT_WRITEBACK:
+ /* Normal: writeback, read allocate */
+ return 0xEE;
+
+ case L_PTE_MT_WRITETHROUGH:
+ /* Normal: write through */
+ return 0xAA;
+
+ case L_PTE_MT_UNCACHED:
+ /* strongly ordered */
+ return 0x00;
+
+ case L_PTE_MT_DEV_SHARED:
+ case L_PTE_MT_DEV_NONSHARED:
+ /* device */
+ return 0x04;
+
+ default:
+ return -EINVAL;
+ }
+#else
+ return 0;
+#endif
+}
+
+int trusty_encode_page_info(struct ns_mem_page_info *inf,
+ struct page *page, pgprot_t pgprot)
+{
+ int mem_attr;
+ uint64_t pte;
+
+ if (!inf || !page)
+ return -EINVAL;
+
+ /* get physical address */
+ pte = (uint64_t) page_to_phys(page);
+
+ /* get memory attributes */
+ mem_attr = get_mem_attr(page, pgprot);
+ if (mem_attr < 0)
+ return mem_attr;
+
+ /* add other attributes */
+#if defined(CONFIG_ARM64) || defined(CONFIG_ARM_LPAE)
+ pte |= pgprot_val(pgprot);
+#elif defined(CONFIG_ARM)
+ if (pgprot_val(pgprot) & L_PTE_USER)
+ pte |= (1 << 6);
+ if (pgprot_val(pgprot) & L_PTE_RDONLY)
+ pte |= (1 << 7);
+ if (pgprot_val(pgprot) & L_PTE_SHARED)
+ pte |= (3 << 8); /* inner sharable */
+#endif
+
+ inf->attr = (pte & 0x0000FFFFFFFFFFFFull) | ((uint64_t)mem_attr << 48);
+ return 0;
+}
+
+int trusty_call32_mem_buf(struct device *dev, u32 smcnr,
+ struct page *page, u32 size,
+ pgprot_t pgprot)
+{
+ int ret;
+ struct ns_mem_page_info pg_inf;
+
+ if (!dev || !page)
+ return -EINVAL;
+
+ ret = trusty_encode_page_info(&pg_inf, page, pgprot);
+ if (ret)
+ return ret;
+
+ if (SMC_IS_FASTCALL(smcnr)) {
+ return trusty_fast_call32(dev, smcnr,
+ (u32)pg_inf.attr,
+ (u32)(pg_inf.attr >> 32), size);
+ } else {
+ return trusty_std_call32(dev, smcnr,
+ (u32)pg_inf.attr,
+ (u32)(pg_inf.attr >> 32), size);
+ }
+}
+
diff --git a/include/linux/trusty/trusty.h b/include/linux/trusty/trusty.h
index abb77f1db74d..d084d9d68a7b 100644
--- a/include/linux/trusty/trusty.h
+++ b/include/linux/trusty/trusty.h
@@ -16,6 +16,9 @@
#include <linux/kernel.h>
#include <linux/trusty/sm_err.h>
+#include <linux/device.h>
+#include <linux/pagemap.h>
+
#ifdef CONFIG_TRUSTY
s32 trusty_std_call32(struct device *dev, u32 smcnr, u32 a0, u32 a1, u32 a2);
@@ -53,4 +56,16 @@ int trusty_call_notifier_register(struct device *dev,
int trusty_call_notifier_unregister(struct device *dev,
struct notifier_block *n);
const char *trusty_version_str_get(struct device *dev);
+
+struct ns_mem_page_info {
+ uint64_t attr;
+};
+
+int trusty_encode_page_info(struct ns_mem_page_info *inf,
+ struct page *page, pgprot_t pgprot);
+
+int trusty_call32_mem_buf(struct device *dev, u32 smcnr,
+ struct page *page, u32 size,
+ pgprot_t pgprot);
+
#endif
--
https://clearlinux.org