lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 26 Aug 2016 22:19:55 +0200
From:   Loic Pallardy <loic.pallardy@...com>
To:     <bjorn.andersson@...aro.org>, <ohad@...ery.com>,
        <lee.jones@...aro.org>
CC:     <loic.pallardy@...com>, <linux-remoteproc@...r.kernel.org>,
        <linux-kernel@...r.kernel.org>
Subject: [PATCH 2/2] remoteproc: core: Add fixed memory region support

Some coprocessors request fixed memory mapping for firmware execution
and associated communication linked.
Memory resources are defined in firmware resource table.
Resource address different from 0x0 and 0xFFFFFFFF is considered as predefined
and already reserved at system level.
In that case, remoteproc core doesn't need to perform any allocation.
Memory region access can be managed using memremap/memunmap functions

Signed-off-by: Loic Pallardy <loic.pallardy@...com>
---
 drivers/remoteproc/remoteproc_core.c | 61 ++++++++++++++++++++++++++----------
 include/linux/remoteproc.h           |  4 +++
 2 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 18f4286..0ddbb92 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -213,13 +213,25 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	/* actual size of vring (in bytes) */
 	size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
 
-	/*
-	 * Allocate non-cacheable memory for the vring. In the future
-	 * this call will also configure the IOMMU for us
-	 */
-	va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL);
+	rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
+
+	/* check if specific memory region requested by firmware */
+	if (rsc->vring[i].da != 0 && rsc->vring[i].da != FW_RSC_ADDR_ANY) {
+		va = memremap(rsc->vring[i].da, size, MEMREMAP_WC);
+		rvring->dma = rsc->vring[i].da;
+		rvring->memmap = true;
+	} else {
+		/*
+		 * Allocate non-cacheable memory for the vring. In the future
+		 * this call will also configure the IOMMU for us
+		 */
+		va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL);
+		rvring->dma = dma;
+		rsc->vring[i].da = dma;
+	}
+
 	if (!va) {
-		dev_err(dev->parent, "dma_alloc_coherent failed\n");
+		dev_err(dev->parent, "Failed to get valid ving[%d] va\n", i);
 		return -EINVAL;
 	}
 
@@ -231,7 +243,10 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
 	if (ret < 0) {
 		dev_err(dev, "idr_alloc failed: %d\n", ret);
-		dma_free_coherent(dev->parent, size, va, dma);
+		if (rvring->memmap)
+			memunmap(rvring->va);
+		else
+			dma_free_coherent(dev->parent, size, va, dma);
 		return ret;
 	}
 	notifyid = ret;
@@ -240,7 +255,6 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 		i, va, &dma, size, notifyid);
 
 	rvring->va = va;
-	rvring->dma = dma;
 	rvring->notifyid = notifyid;
 
 	/*
@@ -249,8 +263,6 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	 * set up the iommu. In this case the device address (da) will
 	 * hold the physical address and not the device address.
 	 */
-	rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
-	rsc->vring[i].da = dma;
 	rsc->vring[i].notifyid = notifyid;
 	return 0;
 }
@@ -293,7 +305,11 @@ void rproc_free_vring(struct rproc_vring *rvring)
 	int idx = rvring->rvdev->vring - rvring;
 	struct fw_rsc_vdev *rsc;
 
-	dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma);
+	if (rvring->memmap)
+		memunmap(rvring->va);
+	else
+		dma_free_coherent(rproc->dev.parent, size, rvring->va,
+				  rvring->dma);
 	idr_remove(&rproc->notifyids, rvring->notifyid);
 
 	/* reset resource entry info */
@@ -585,7 +601,15 @@ static int rproc_handle_carveout(struct rproc *rproc,
 	if (!carveout)
 		return -ENOMEM;
 
-	va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL);
+	/* check if specific memory region requested by firmware */
+	if (rsc->pa != 0 && rsc->pa != FW_RSC_ADDR_ANY) {
+		va = memremap(rsc->pa, rsc->len, MEMREMAP_WC);
+		carveout->memmap = true;
+		dma = rsc->pa;
+	} else {
+		va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL);
+		rsc->pa = dma;
+	}
 	if (!va) {
 		dev_err(dev->parent,
 			"failed to allocate dma memory: len 0x%x\n", rsc->len);
@@ -659,7 +683,6 @@ static int rproc_handle_carveout(struct rproc *rproc,
 	 * In this case, the device address and the physical address
 	 * are the same.
 	 */
-	rsc->pa = dma;
 
 	carveout->va = va;
 	carveout->len = rsc->len;
@@ -673,7 +696,10 @@ static int rproc_handle_carveout(struct rproc *rproc,
 free_mapping:
 	kfree(mapping);
 dma_free:
-	dma_free_coherent(dev->parent, rsc->len, va, dma);
+	if (carveout->memmap)
+		memunmap(va);
+	else
+		dma_free_coherent(dev->parent, rsc->len, va, dma);
 free_carv:
 	kfree(carveout);
 	return ret;
@@ -780,8 +806,11 @@ static void rproc_resource_cleanup(struct rproc *rproc)
 
 	/* clean up carveout allocations */
 	list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) {
-		dma_free_coherent(dev->parent, entry->len, entry->va,
-				  entry->dma);
+		if (entry->memmap)
+			memunmap(entry->va);
+		else
+			dma_free_coherent(dev->parent, entry->len, entry->va,
+					  entry->dma);
 		list_del(&entry->node);
 		kfree(entry);
 	}
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 80e1cba..ff1fb59 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -312,6 +312,7 @@ struct fw_rsc_vdev {
  * @len: length, in bytes
  * @da: device address
  * @priv: associated data
+ * @memmap: true if memory is memremapped
  * @node: list node
  */
 struct rproc_mem_entry {
@@ -320,6 +321,7 @@ struct rproc_mem_entry {
 	int len;
 	u32 da;
 	void *priv;
+	bool memmap;
 	struct list_head node;
 };
 
@@ -458,6 +460,7 @@ struct rproc {
  * @notifyid: rproc-specific unique vring index
  * @rvdev: remote vdev
  * @vq: the virtqueue of this vring
+ * @memmap: true if memory is memremapped
  */
 struct rproc_vring {
 	void *va;
@@ -468,6 +471,7 @@ struct rproc_vring {
 	int notifyid;
 	struct rproc_vdev *rvdev;
 	struct virtqueue *vq;
+	bool memmap;
 };
 
 /**
-- 
1.9.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ