Linux-Doc Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va
       [not found] <20200129163013.GA16538@xps15>
@ 2020-02-04 14:33 ` Clement Leger
  2020-02-04 14:33   ` [PATCH v2 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
  2020-02-04 16:27   ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Arnaud POULIQUEN
  2020-02-04 17:44 ` [PATCH v3 0/2] remoteproc: Add elf64 support to elf loader Clement Leger
  1 sibling, 2 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-04 14:33 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

With upcoming changes in elf loader for elf64 support, section size will
be a u64. When used with da_to_va, this will potentially lead to
overflow if using the current "int" type for len argument. Change
da_to_va prototype to use a u64 for len and fix all users of this
function.

Signed-off-by: Clement Leger <cleger@kalray.eu>
---
V2:
 - Change len type from int to u64

 drivers/remoteproc/imx_rproc.c           | 5 +++--
 drivers/remoteproc/keystone_remoteproc.c | 2 +-
 drivers/remoteproc/qcom_q6v5_adsp.c      | 2 +-
 drivers/remoteproc/qcom_q6v5_mss.c       | 2 +-
 drivers/remoteproc/qcom_q6v5_pas.c       | 2 +-
 drivers/remoteproc/qcom_q6v5_wcss.c      | 2 +-
 drivers/remoteproc/qcom_wcnss.c          | 2 +-
 drivers/remoteproc/remoteproc_core.c     | 2 +-
 drivers/remoteproc/remoteproc_internal.h | 2 +-
 drivers/remoteproc/st_slim_rproc.c       | 2 +-
 drivers/remoteproc/wkup_m3_rproc.c       | 2 +-
 include/linux/remoteproc.h               | 2 +-
 12 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 3e72b6f38d4b..7ec79be5eb5d 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -208,7 +208,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
 	return -ENOENT;
 }
 
-static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct imx_rproc *priv = rproc->priv;
 	void *va = NULL;
@@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
 		}
 	}
 
-	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
+	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n", da, len,
+		va);
 
 	return va;
 }
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index 5c4658f00b3d..25c01df47eba 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct keystone_rproc *ksproc = rproc->priv;
 	void __iomem *va = NULL;
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index e953886b2eb7..7518e67a49e5 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 471128a2e723..248febde6fc1 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct q6v5 *qproc = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index db4b3c4bacd7..cf2cd609c90d 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
index f93e1e4a1cc0..3a6b82a16961 100644
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct q6v5_wcss *wcss = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index dc135754bb9c..f893219e45a8 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 307df98347ba..9e6d3c6a60ee 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
  * here the output of the DMA API for the carveouts, which should be more
  * correct.
  */
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct rproc_mem_entry *carveout;
 	void *ptr = NULL;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 493ef9262411..004867061721 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
 void rproc_free_vring(struct rproc_vring *rvring);
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
 
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
+void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
 phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
index 04492fead3c8..2fd14afb3157 100644
--- a/drivers/remoteproc/st_slim_rproc.c
+++ b/drivers/remoteproc/st_slim_rproc.c
@@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct st_slim_rproc *slim_rproc = rproc->priv;
 	void *va = NULL;
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index 3984e585c847..0e8082948489 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -80,7 +80,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct wkup_m3_rproc *wkupm3 = rproc->priv;
 	void *va = NULL;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 16ad66683ad0..f84bd5fe0211 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -374,7 +374,7 @@ struct rproc_ops {
 	int (*start)(struct rproc *rproc);
 	int (*stop)(struct rproc *rproc);
 	void (*kick)(struct rproc *rproc, int vqid);
-	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
+	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
 	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
 	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
 			  int offset, int avail);
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v2 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-04 14:33 ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
@ 2020-02-04 14:33   ` Clement Leger
  2020-02-04 16:27   ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Arnaud POULIQUEN
  1 sibling, 0 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-04 14:33 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clément Leger

From: Clément Leger <cleger@kalray.eu>

elf32 and elf64 mainly differ by their types. In order to avoid
copy/pasting the whole loader code, generate static inline functions
which will access values according to the elf class. It allows to keep a
common loader basis.
In order to accommodate both elf types sizes, the maximum size for a
elf header member is chosen using the maximum value of both elf class.

Signed-off-by: Clement Leger <cleger@kalray.eu>
Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
---
V2:
 - Add check for elf64 header size
 - Add comments for name table parsing
 - Fix typo in "accommodate"

 Documentation/remoteproc.txt               |   2 +-
 drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
 drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
 drivers/remoteproc/remoteproc_internal.h   |   2 +-
 drivers/remoteproc/st_remoteproc.c         |   2 +-
 include/linux/remoteproc.h                 |   4 +-
 6 files changed, 167 insertions(+), 59 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h

diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
index 03c3d2e568b0..2be1147256e0 100644
--- a/Documentation/remoteproc.txt
+++ b/Documentation/remoteproc.txt
@@ -230,7 +230,7 @@ in the used rings.
 Binary Firmware Structure
 =========================
 
-At this point remoteproc only supports ELF32 firmware binaries. However,
+At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
 it is quite expected that other platforms/devices which we'd want to
 support with this framework will be based on different binary formats.
 
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 606aae166eba..21fd2b2fe5ae 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -23,6 +23,7 @@
 #include <linux/elf.h>
 
 #include "remoteproc_internal.h"
+#include "remoteproc_elf_loader.h"
 
 /**
  * rproc_elf_sanity_check() - Sanity Check ELF firmware image
@@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 {
 	const char *name = rproc->firmware;
 	struct device *dev = &rproc->dev;
+	/*
+	 * Elf files are beginning with the same structure. Thus, to simplify
+	 * header parsing, we can use the elf32_hdr one for both elf64 and
+	 * elf32.
+	 */
 	struct elf32_hdr *ehdr;
+	u32 elf_shdr_size;
+	u64 phoff, shoff;
 	char class;
+	u16 phnum;
 
 	if (!fw) {
 		dev_err(dev, "failed to load %s\n", name);
@@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 
 	ehdr = (struct elf32_hdr *)fw->data;
 
-	/* We only support ELF32 at this point */
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		dev_err(dev, "Image is corrupted (bad magic)\n");
+		return -EINVAL;
+	}
+
 	class = ehdr->e_ident[EI_CLASS];
-	if (class != ELFCLASS32) {
+	if (class != ELFCLASS32 && class != ELFCLASS64) {
 		dev_err(dev, "Unsupported class: %d\n", class);
 		return -EINVAL;
 	}
 
+	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
+		dev_err(dev, "elf64 header is too small\n");
+		return -EINVAL;
+	}
+
 	/* We assume the firmware has the same endianness as the host */
 # ifdef __LITTLE_ENDIAN
 	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
@@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 		return -EINVAL;
 	}
 
-	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
-		dev_err(dev, "Image is too small\n");
-		return -EINVAL;
-	}
+	phoff = elf_hdr_e_phoff(class, fw->data);
+	shoff = elf_hdr_e_shoff(class, fw->data);
+	phnum =  elf_hdr_e_phnum(class, fw->data);
+	elf_shdr_size = elf_size_of_shdr(class);
 
-	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
-		dev_err(dev, "Image is corrupted (bad magic)\n");
+	if (fw->size < shoff + elf_shdr_size) {
+		dev_err(dev, "Image is too small\n");
 		return -EINVAL;
 	}
 
-	if (ehdr->e_phnum == 0) {
+	if (phnum == 0) {
 		dev_err(dev, "No loadable segments\n");
 		return -EINVAL;
 	}
 
-	if (ehdr->e_phoff > fw->size) {
+	if (phoff > fw->size) {
 		dev_err(dev, "Firmware size is too small\n");
 		return -EINVAL;
 	}
 
+	dev_dbg(dev, "Firmware is an elf%d file\n",
+		class == ELFCLASS32 ? 32 : 64);
+
 	return 0;
 }
 EXPORT_SYMBOL(rproc_elf_sanity_check);
@@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
  * Note that the boot address is not a configurable property of all remote
  * processors. Some will always boot at a specific hard-coded address.
  */
-u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
-
-	return ehdr->e_entry;
+	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
 }
 EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 
@@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = &rproc->dev;
-	struct elf32_hdr *ehdr;
-	struct elf32_phdr *phdr;
+	const void *ehdr, *phdr;
 	int i, ret = 0;
+	u16 phnum;
 	const u8 *elf_data = fw->data;
+	u8 class = fw_elf_get_class(fw);
+	u32 elf_phdr_size = elf_size_of_phdr(class);
 
-	ehdr = (struct elf32_hdr *)elf_data;
-	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
+	ehdr = elf_data;
+	phnum = elf_hdr_e_phnum(class, ehdr);
+	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
 
 	/* go through the available ELF segments */
-	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
-		u32 da = phdr->p_paddr;
-		u32 memsz = phdr->p_memsz;
-		u32 filesz = phdr->p_filesz;
-		u32 offset = phdr->p_offset;
+	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
+		u64 da = elf_phdr_p_paddr(class, phdr);
+		u64 memsz = elf_phdr_p_memsz(class, phdr);
+		u64 filesz = elf_phdr_p_filesz(class, phdr);
+		u64 offset = elf_phdr_p_offset(class, phdr);
+		u32 type = elf_phdr_p_type(class, phdr);
 		void *ptr;
 
-		if (phdr->p_type != PT_LOAD)
+		if (type != PT_LOAD)
 			continue;
 
-		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
-			phdr->p_type, da, memsz, filesz);
+		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
+			type, da, memsz, filesz);
 
 		if (filesz > memsz) {
-			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
+			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
 				filesz, memsz);
 			ret = -EINVAL;
 			break;
 		}
 
 		if (offset + filesz > fw->size) {
-			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
+			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
 				offset + filesz, fw->size);
 			ret = -EINVAL;
 			break;
@@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		/* grab the kernel address for this device address */
 		ptr = rproc_da_to_va(rproc, da, memsz);
 		if (!ptr) {
-			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
+			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
+				memsz);
 			ret = -EINVAL;
 			break;
 		}
 
 		/* put the segment where the remote processor expects it */
-		if (phdr->p_filesz)
-			memcpy(ptr, elf_data + phdr->p_offset, filesz);
+		if (filesz)
+			memcpy(ptr, elf_data + offset, filesz);
 
 		/*
 		 * Zero out remaining memory for this segment.
@@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 }
 EXPORT_SYMBOL(rproc_elf_load_segments);
 
-static struct elf32_shdr *
-find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
+static const void *
+find_table(struct device *dev, const struct firmware *fw)
 {
-	struct elf32_shdr *shdr;
+	const void *shdr, *name_table_shdr;
 	int i;
 	const char *name_table;
 	struct resource_table *table = NULL;
-	const u8 *elf_data = (void *)ehdr;
+	const u8 *elf_data = (void *)fw->data;
+	u8 class = fw_elf_get_class(fw);
+	size_t fw_size = fw->size;
+	const void *ehdr = elf_data;
+	u16 shnum = elf_hdr_e_shnum(class, ehdr);
+	u32 elf_shdr_size = elf_size_of_shdr(class);
+	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
 
 	/* look for the resource table and handle it */
-	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
-	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
-
-	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
-		u32 size = shdr->sh_size;
-		u32 offset = shdr->sh_offset;
-
-		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
+	/* First, get the section header according to the elf class */
+	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
+	/* Compute name table section header entry in shdr array */
+	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
+	/* Finally, compute the name table section address in elf */
+	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
+
+	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
+		u64 size = elf_shdr_sh_size(class, shdr);
+		u64 offset = elf_shdr_sh_offset(class, shdr);
+		u32 name = elf_shdr_sh_name(class, shdr);
+
+		if (strcmp(name_table + name, ".resource_table"))
 			continue;
 
 		table = (struct resource_table *)(elf_data + offset);
@@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
  */
 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr;
-	struct elf32_shdr *shdr;
+	const void *shdr;
 	struct device *dev = &rproc->dev;
 	struct resource_table *table = NULL;
 	const u8 *elf_data = fw->data;
 	size_t tablesz;
+	u8 class = fw_elf_get_class(fw);
+	u64 sh_offset;
 
-	ehdr = (struct elf32_hdr *)elf_data;
-
-	shdr = find_table(dev, ehdr, fw->size);
+	shdr = find_table(dev, fw);
 	if (!shdr)
 		return -EINVAL;
 
-	table = (struct resource_table *)(elf_data + shdr->sh_offset);
-	tablesz = shdr->sh_size;
+	sh_offset = elf_shdr_sh_offset(class, shdr);
+	table = (struct resource_table *)(elf_data + sh_offset);
+	tablesz = elf_shdr_sh_size(class, shdr);
 
 	/*
 	 * Create a copy of the resource table. When a virtio device starts
@@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
 						       const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
-	struct elf32_shdr *shdr;
+	const void *shdr;
+	u64 sh_addr, sh_size;
+	u8 class = fw_elf_get_class(fw);
 
-	shdr = find_table(&rproc->dev, ehdr, fw->size);
+	shdr = find_table(&rproc->dev, fw);
 	if (!shdr)
 		return NULL;
 
-	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
+	sh_addr = elf_shdr_sh_addr(class, shdr);
+	sh_size = elf_shdr_sh_size(class, shdr);
+
+	return rproc_da_to_va(rproc, sh_addr, sh_size);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
diff --git a/drivers/remoteproc/remoteproc_elf_loader.h b/drivers/remoteproc/remoteproc_elf_loader.h
new file mode 100644
index 000000000000..fac3565734f9
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_elf_loader.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Remote processor elf loader defines
+ *
+ * Copyright (C) 2019 Kalray, Inc.
+ */
+
+#ifndef REMOTEPROC_ELF_LOADER_H
+#define REMOTEPROC_ELF_LOADER_H
+
+#include <linux/elf.h>
+#include <linux/types.h>
+
+/**
+ * fw_elf_get_class - Get elf class
+ * @fw: the ELF firmware image
+ *
+ * Note that we use and elf32_hdr to access the class since the start of the
+ * struct is the same for both elf class
+ *
+ * Return: elf class of the firmware
+ */
+static inline u8 fw_elf_get_class(const struct firmware *fw)
+{
+	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
+
+	return ehdr->e_ident[EI_CLASS];
+}
+
+#define ELF_GET_FIELD(__s, __field, __type) \
+static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
+{ \
+	if (class == ELFCLASS32) \
+		return (__type) ((const struct elf32_##__s *) arg)->__field; \
+	else \
+		return (__type) ((const struct elf64_##__s *) arg)->__field; \
+}
+
+ELF_GET_FIELD(hdr, e_entry, u64)
+ELF_GET_FIELD(hdr, e_phnum, u16)
+ELF_GET_FIELD(hdr, e_shnum, u16)
+ELF_GET_FIELD(hdr, e_phoff, u64)
+ELF_GET_FIELD(hdr, e_shoff, u64)
+ELF_GET_FIELD(hdr, e_shstrndx, u16)
+
+ELF_GET_FIELD(phdr, p_paddr, u64)
+ELF_GET_FIELD(phdr, p_filesz, u64)
+ELF_GET_FIELD(phdr, p_memsz, u64)
+ELF_GET_FIELD(phdr, p_type, u32)
+ELF_GET_FIELD(phdr, p_offset, u64)
+
+ELF_GET_FIELD(shdr, sh_size, u64)
+ELF_GET_FIELD(shdr, sh_offset, u64)
+ELF_GET_FIELD(shdr, sh_name, u32)
+ELF_GET_FIELD(shdr, sh_addr, u64)
+
+#define ELF_STRUCT_SIZE(__s) \
+static inline unsigned long elf_size_of_##__s(u8 class) \
+{ \
+	if (class == ELFCLASS32)\
+		return sizeof(struct elf32_##__s); \
+	else \
+		return sizeof(struct elf64_##__s); \
+}
+
+ELF_STRUCT_SIZE(shdr)
+ELF_STRUCT_SIZE(phdr)
+
+#endif /* REMOTEPROC_ELF_LOADER_H */
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 004867061721..eeb26434220e 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
-u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
+u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index ee13d23b43a9..a3268d95a50e 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
 		}
 	}
 
-	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
+	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
 
 	return 0;
 
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index f84bd5fe0211..82cebca9344c 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -382,7 +382,7 @@ struct rproc_ops {
 				struct rproc *rproc, const struct firmware *fw);
 	int (*load)(struct rproc *rproc, const struct firmware *fw);
 	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
-	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
+	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
 };
 
 /**
@@ -498,7 +498,7 @@ struct rproc {
 	int num_traces;
 	struct list_head carveouts;
 	struct list_head mappings;
-	u32 bootaddr;
+	u64 bootaddr;
 	struct list_head rvdevs;
 	struct list_head subdevs;
 	struct idr notifyids;
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va
  2020-02-04 14:33 ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
  2020-02-04 14:33   ` [PATCH v2 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
@ 2020-02-04 16:27   ` Arnaud POULIQUEN
  2020-02-04 17:10     ` Clément Leger
  1 sibling, 1 reply; 32+ messages in thread
From: Arnaud POULIQUEN @ 2020-02-04 16:27 UTC (permalink / raw)
  To: Clement Leger, Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet,
	Shawn Guo, Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna,
	Mathieu Poirier

Hi Clément,

Is it v2 or V3? 
I also suggest you add a cover letter when you post more than one patch in a thread.

On 2/4/20 3:33 PM, Clement Leger wrote:
> With upcoming changes in elf loader for elf64 support, section size will
> be a u64. When used with da_to_va, this will potentially lead to
> overflow if using the current "int" type for len argument. Change
> da_to_va prototype to use a u64 for len and fix all users of this
> function.
> 
> Signed-off-by: Clement Leger <cleger@kalray.eu>
> ---
> V2:
>  - Change len type from int to u64
> 
>  drivers/remoteproc/imx_rproc.c           | 5 +++--
>  drivers/remoteproc/keystone_remoteproc.c | 2 +-
>  drivers/remoteproc/qcom_q6v5_adsp.c      | 2 +-
>  drivers/remoteproc/qcom_q6v5_mss.c       | 2 +-
>  drivers/remoteproc/qcom_q6v5_pas.c       | 2 +-
>  drivers/remoteproc/qcom_q6v5_wcss.c      | 2 +-
>  drivers/remoteproc/qcom_wcnss.c          | 2 +-
>  drivers/remoteproc/remoteproc_core.c     | 2 +-
>  drivers/remoteproc/remoteproc_internal.h | 2 +-
>  drivers/remoteproc/st_slim_rproc.c       | 2 +-
>  drivers/remoteproc/wkup_m3_rproc.c       | 2 +-
>  include/linux/remoteproc.h               | 2 +-
>  12 files changed, 14 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 3e72b6f38d4b..7ec79be5eb5d 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -208,7 +208,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>  	return -ENOENT;
>  }
>  
> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
I wonder if you could use size_t instead?
Does it make sense for 32-bit system to have a physical address space higher?
it's an open question I won't pretend to have the answer...:)
 

>  {
>  	struct imx_rproc *priv = rproc->priv;
>  	void *va = NULL;
> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
len type to update

Regards,
Arnaud
>  		}
>  	}
>  
> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n", da, len,
> +		va);
>  
>  	return va;
>  }
> diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
> index 5c4658f00b3d..25c01df47eba 100644
> --- a/drivers/remoteproc/keystone_remoteproc.c
> +++ b/drivers/remoteproc/keystone_remoteproc.c
> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
>   * can be used either by the remoteproc core for loading (when using kernel
>   * remoteproc loader), or by any rpmsg bus drivers.
>   */
> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct keystone_rproc *ksproc = rproc->priv;
>  	void __iomem *va = NULL;
> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
> index e953886b2eb7..7518e67a49e5 100644
> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
> index 471128a2e723..248febde6fc1 100644
> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct q6v5 *qproc = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index db4b3c4bacd7..cf2cd609c90d 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
> index f93e1e4a1cc0..3a6b82a16961 100644
> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct q6v5_wcss *wcss = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> index dc135754bb9c..f893219e45a8 100644
> --- a/drivers/remoteproc/qcom_wcnss.c
> +++ b/drivers/remoteproc/qcom_wcnss.c
> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 307df98347ba..9e6d3c6a60ee 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>   * here the output of the DMA API for the carveouts, which should be more
>   * correct.
>   */
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct rproc_mem_entry *carveout;
>  	void *ptr = NULL;
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 493ef9262411..004867061721 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>  void rproc_free_vring(struct rproc_vring *rvring);
>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>  
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>  int rproc_trigger_recovery(struct rproc *rproc);
>  
> diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
> index 04492fead3c8..2fd14afb3157 100644
> --- a/drivers/remoteproc/st_slim_rproc.c
> +++ b/drivers/remoteproc/st_slim_rproc.c
> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>  	void *va = NULL;
> diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
> index 3984e585c847..0e8082948489 100644
> --- a/drivers/remoteproc/wkup_m3_rproc.c
> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> @@ -80,7 +80,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>  	void *va = NULL;
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index 16ad66683ad0..f84bd5fe0211 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -374,7 +374,7 @@ struct rproc_ops {
>  	int (*start)(struct rproc *rproc);
>  	int (*stop)(struct rproc *rproc);
>  	void (*kick)(struct rproc *rproc, int vqid);
> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>  			  int offset, int avail);
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va
  2020-02-04 16:27   ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Arnaud POULIQUEN
@ 2020-02-04 17:10     ` Clément Leger
  2020-02-04 17:42       ` Arnaud POULIQUEN
  0 siblings, 1 reply; 32+ messages in thread
From: Clément Leger @ 2020-02-04 17:10 UTC (permalink / raw)
  To: Arnaud Pouliquen
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Loic PALLARDY, s-anna, Mathieu Poirier

Hi Arnaud,

My bad, I thought it was only V1.
I will resend it as a V3 with a cover letter.

----- On 4 Feb, 2020, at 17:27, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:

> Hi Clément,
> 
> Is it v2 or V3?
> I also suggest you add a cover letter when you post more than one patch in a
> thread.
> 
> On 2/4/20 3:33 PM, Clement Leger wrote:
>> With upcoming changes in elf loader for elf64 support, section size will
>> be a u64. When used with da_to_va, this will potentially lead to
>> overflow if using the current "int" type for len argument. Change
>> da_to_va prototype to use a u64 for len and fix all users of this
>> function.
>> 
>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>> ---
>> V2:
>>  - Change len type from int to u64
>> 
>>  drivers/remoteproc/imx_rproc.c           | 5 +++--
>>  drivers/remoteproc/keystone_remoteproc.c | 2 +-
>>  drivers/remoteproc/qcom_q6v5_adsp.c      | 2 +-
>>  drivers/remoteproc/qcom_q6v5_mss.c       | 2 +-
>>  drivers/remoteproc/qcom_q6v5_pas.c       | 2 +-
>>  drivers/remoteproc/qcom_q6v5_wcss.c      | 2 +-
>>  drivers/remoteproc/qcom_wcnss.c          | 2 +-
>>  drivers/remoteproc/remoteproc_core.c     | 2 +-
>>  drivers/remoteproc/remoteproc_internal.h | 2 +-
>>  drivers/remoteproc/st_slim_rproc.c       | 2 +-
>>  drivers/remoteproc/wkup_m3_rproc.c       | 2 +-
>>  include/linux/remoteproc.h               | 2 +-
>>  12 files changed, 14 insertions(+), 13 deletions(-)
>> 
>> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> index 3e72b6f38d4b..7ec79be5eb5d 100644
>> --- a/drivers/remoteproc/imx_rproc.c
>> +++ b/drivers/remoteproc/imx_rproc.c
>> @@ -208,7 +208,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
>> da,
>>  	return -ENOENT;
>>  }
>>  
>> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> I wonder if you could use size_t instead?

I wondered too but size_t is a unsigned int on 32 bits system. So if they load
a elf64 binary (which might be in 32bits zone), the segment size will be
a u64 type.

> Does it make sense for 32-bit system to have a physical address space higher?
> it's an open question I won't pretend to have the answer...:)

I agree that it does not make a lot of sense... But when we discussed it in
OpenAMP WG, it was mentionned that this should be supported. 

> 
> 
>>  {
>>  	struct imx_rproc *priv = rproc->priv;
>>  	void *va = NULL;
>> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
>> int len)
> len type to update

I missed this one and I will double check all other callers

Thanks,

Clément. 

> 
> Regards,
> Arnaud
>>  		}
>>  	}
>>  
>> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
>> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n", da, len,
>> +		va);
>>  
>>  	return va;
>>  }
>> diff --git a/drivers/remoteproc/keystone_remoteproc.c
>> b/drivers/remoteproc/keystone_remoteproc.c
>> index 5c4658f00b3d..25c01df47eba 100644
>> --- a/drivers/remoteproc/keystone_remoteproc.c
>> +++ b/drivers/remoteproc/keystone_remoteproc.c
>> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
>> vqid)
>>   * can be used either by the remoteproc core for loading (when using kernel
>>   * remoteproc loader), or by any rpmsg bus drivers.
>>   */
>> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct keystone_rproc *ksproc = rproc->priv;
>>  	void __iomem *va = NULL;
>> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
>> b/drivers/remoteproc/qcom_q6v5_adsp.c
>> index e953886b2eb7..7518e67a49e5 100644
>> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
>> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
>> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>>  	return ret;
>>  }
>>  
>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
>> b/drivers/remoteproc/qcom_q6v5_mss.c
>> index 471128a2e723..248febde6fc1 100644
>> --- a/drivers/remoteproc/qcom_q6v5_mss.c
>> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
>> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct q6v5 *qproc = rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
>> b/drivers/remoteproc/qcom_q6v5_pas.c
>> index db4b3c4bacd7..cf2cd609c90d 100644
>> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
>> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>>  	return ret;
>>  }
>>  
>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
>> b/drivers/remoteproc/qcom_q6v5_wcss.c
>> index f93e1e4a1cc0..3a6b82a16961 100644
>> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
>> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
>> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct q6v5_wcss *wcss = rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
>> index dc135754bb9c..f893219e45a8 100644
>> --- a/drivers/remoteproc/qcom_wcnss.c
>> +++ b/drivers/remoteproc/qcom_wcnss.c
>> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>>  	return ret;
>>  }
>>  
>> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/remoteproc_core.c
>> b/drivers/remoteproc/remoteproc_core.c
>> index 307df98347ba..9e6d3c6a60ee 100644
>> --- a/drivers/remoteproc/remoteproc_core.c
>> +++ b/drivers/remoteproc/remoteproc_core.c
>> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>>   * here the output of the DMA API for the carveouts, which should be more
>>   * correct.
>>   */
>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct rproc_mem_entry *carveout;
>>  	void *ptr = NULL;
>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>> b/drivers/remoteproc/remoteproc_internal.h
>> index 493ef9262411..004867061721 100644
>> --- a/drivers/remoteproc/remoteproc_internal.h
>> +++ b/drivers/remoteproc/remoteproc_internal.h
>> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>>  void rproc_free_vring(struct rproc_vring *rvring);
>>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>>  
>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>>  int rproc_trigger_recovery(struct rproc *rproc);
>>  
>> diff --git a/drivers/remoteproc/st_slim_rproc.c
>> b/drivers/remoteproc/st_slim_rproc.c
>> index 04492fead3c8..2fd14afb3157 100644
>> --- a/drivers/remoteproc/st_slim_rproc.c
>> +++ b/drivers/remoteproc/st_slim_rproc.c
>> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>>  	void *va = NULL;
>> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
>> b/drivers/remoteproc/wkup_m3_rproc.c
>> index 3984e585c847..0e8082948489 100644
>> --- a/drivers/remoteproc/wkup_m3_rproc.c
>> +++ b/drivers/remoteproc/wkup_m3_rproc.c
>> @@ -80,7 +80,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>>  	void *va = NULL;
>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>> index 16ad66683ad0..f84bd5fe0211 100644
>> --- a/include/linux/remoteproc.h
>> +++ b/include/linux/remoteproc.h
>> @@ -374,7 +374,7 @@ struct rproc_ops {
>>  	int (*start)(struct rproc *rproc);
>>  	int (*stop)(struct rproc *rproc);
>>  	void (*kick)(struct rproc *rproc, int vqid);
>> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
>> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>>  			  int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va
  2020-02-04 17:10     ` Clément Leger
@ 2020-02-04 17:42       ` Arnaud POULIQUEN
  0 siblings, 0 replies; 32+ messages in thread
From: Arnaud POULIQUEN @ 2020-02-04 17:42 UTC (permalink / raw)
  To: Clément Leger
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Loic PALLARDY, s-anna, Mathieu Poirier



On 2/4/20 6:10 PM, Clément Leger wrote:
> Hi Arnaud,
> 
> My bad, I thought it was only V1.
> I will resend it as a V3 with a cover letter.
> 
> ----- On 4 Feb, 2020, at 17:27, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
> 
>> Hi Clément,
>>
>> Is it v2 or V3?
>> I also suggest you add a cover letter when you post more than one patch in a
>> thread.
>>
>> On 2/4/20 3:33 PM, Clement Leger wrote:
>>> With upcoming changes in elf loader for elf64 support, section size will
>>> be a u64. When used with da_to_va, this will potentially lead to
>>> overflow if using the current "int" type for len argument. Change
>>> da_to_va prototype to use a u64 for len and fix all users of this
>>> function.
>>>
>>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>>> ---
>>> V2:
>>>  - Change len type from int to u64
>>>
>>>  drivers/remoteproc/imx_rproc.c           | 5 +++--
>>>  drivers/remoteproc/keystone_remoteproc.c | 2 +-
>>>  drivers/remoteproc/qcom_q6v5_adsp.c      | 2 +-
>>>  drivers/remoteproc/qcom_q6v5_mss.c       | 2 +-
>>>  drivers/remoteproc/qcom_q6v5_pas.c       | 2 +-
>>>  drivers/remoteproc/qcom_q6v5_wcss.c      | 2 +-
>>>  drivers/remoteproc/qcom_wcnss.c          | 2 +-
>>>  drivers/remoteproc/remoteproc_core.c     | 2 +-
>>>  drivers/remoteproc/remoteproc_internal.h | 2 +-
>>>  drivers/remoteproc/st_slim_rproc.c       | 2 +-
>>>  drivers/remoteproc/wkup_m3_rproc.c       | 2 +-
>>>  include/linux/remoteproc.h               | 2 +-
>>>  12 files changed, 14 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>>> index 3e72b6f38d4b..7ec79be5eb5d 100644
>>> --- a/drivers/remoteproc/imx_rproc.c
>>> +++ b/drivers/remoteproc/imx_rproc.c
>>> @@ -208,7 +208,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
>>> da,
>>>  	return -ENOENT;
>>>  }
>>>  
>>> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> I wonder if you could use size_t instead?
> 
> I wondered too but size_t is a unsigned int on 32 bits system. So if they load
> a elf64 binary (which might be in 32bits zone), the segment size will be
> a u64 type.
If we consider that 32-bit processor can not address a memory space size higher than sizeof(size_t), this could be solved by adding a test and a cast.
> 
>> Does it make sense for 32-bit system to have a physical address space higher?
>> it's an open question I won't pretend to have the answer...:)
> 
> I agree that it does not make a lot of sense... But when we discussed it in
> OpenAMP WG, it was mentionned that this should be supported. 
My apologize, i don't remember the discussion around the size.
So if a requirement exists and size_t does not fit, let's use u64.
Nevertheless i'm interested to know the rational, if you remember...

Regards
Arnaud
> 
>>
>>
>>>  {
>>>  	struct imx_rproc *priv = rproc->priv;
>>>  	void *va = NULL;
>>> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
>>> int len)
>> len type to update
> 
> I missed this one and I will double check all other callers
> 
> Thanks,
> 
> Clément. 
> 
>>
>> Regards,
>> Arnaud
>>>  		}
>>>  	}
>>>  
>>> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
>>> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n", da, len,
>>> +		va);
>>>  
>>>  	return va;
>>>  }
>>> diff --git a/drivers/remoteproc/keystone_remoteproc.c
>>> b/drivers/remoteproc/keystone_remoteproc.c
>>> index 5c4658f00b3d..25c01df47eba 100644
>>> --- a/drivers/remoteproc/keystone_remoteproc.c
>>> +++ b/drivers/remoteproc/keystone_remoteproc.c
>>> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
>>> vqid)
>>>   * can be used either by the remoteproc core for loading (when using kernel
>>>   * remoteproc loader), or by any rpmsg bus drivers.
>>>   */
>>> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct keystone_rproc *ksproc = rproc->priv;
>>>  	void __iomem *va = NULL;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
>>> b/drivers/remoteproc/qcom_q6v5_adsp.c
>>> index e953886b2eb7..7518e67a49e5 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
>>> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>>>  	return ret;
>>>  }
>>>  
>>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
>>> b/drivers/remoteproc/qcom_q6v5_mss.c
>>> index 471128a2e723..248febde6fc1 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_mss.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
>>> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct q6v5 *qproc = rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
>>> b/drivers/remoteproc/qcom_q6v5_pas.c
>>> index db4b3c4bacd7..cf2cd609c90d 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
>>> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>>>  	return ret;
>>>  }
>>>  
>>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
>>> b/drivers/remoteproc/qcom_q6v5_wcss.c
>>> index f93e1e4a1cc0..3a6b82a16961 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
>>> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct q6v5_wcss *wcss = rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
>>> index dc135754bb9c..f893219e45a8 100644
>>> --- a/drivers/remoteproc/qcom_wcnss.c
>>> +++ b/drivers/remoteproc/qcom_wcnss.c
>>> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>>>  	return ret;
>>>  }
>>>  
>>> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/remoteproc_core.c
>>> b/drivers/remoteproc/remoteproc_core.c
>>> index 307df98347ba..9e6d3c6a60ee 100644
>>> --- a/drivers/remoteproc/remoteproc_core.c
>>> +++ b/drivers/remoteproc/remoteproc_core.c
>>> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>>>   * here the output of the DMA API for the carveouts, which should be more
>>>   * correct.
>>>   */
>>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct rproc_mem_entry *carveout;
>>>  	void *ptr = NULL;
>>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>>> b/drivers/remoteproc/remoteproc_internal.h
>>> index 493ef9262411..004867061721 100644
>>> --- a/drivers/remoteproc/remoteproc_internal.h
>>> +++ b/drivers/remoteproc/remoteproc_internal.h
>>> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>>>  void rproc_free_vring(struct rproc_vring *rvring);
>>>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>>>  
>>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
>>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>>>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>>>  int rproc_trigger_recovery(struct rproc *rproc);
>>>  
>>> diff --git a/drivers/remoteproc/st_slim_rproc.c
>>> b/drivers/remoteproc/st_slim_rproc.c
>>> index 04492fead3c8..2fd14afb3157 100644
>>> --- a/drivers/remoteproc/st_slim_rproc.c
>>> +++ b/drivers/remoteproc/st_slim_rproc.c
>>> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>>>  	void *va = NULL;
>>> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
>>> b/drivers/remoteproc/wkup_m3_rproc.c
>>> index 3984e585c847..0e8082948489 100644
>>> --- a/drivers/remoteproc/wkup_m3_rproc.c
>>> +++ b/drivers/remoteproc/wkup_m3_rproc.c
>>> @@ -80,7 +80,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>>>  	void *va = NULL;
>>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>>> index 16ad66683ad0..f84bd5fe0211 100644
>>> --- a/include/linux/remoteproc.h
>>> +++ b/include/linux/remoteproc.h
>>> @@ -374,7 +374,7 @@ struct rproc_ops {
>>>  	int (*start)(struct rproc *rproc);
>>>  	int (*stop)(struct rproc *rproc);
>>>  	void (*kick)(struct rproc *rproc, int vqid);
>>> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
>>> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>>>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>>>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>>>  			  int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 0/2] remoteproc: Add elf64 support to elf loader
       [not found] <20200129163013.GA16538@xps15>
  2020-02-04 14:33 ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
@ 2020-02-04 17:44 ` Clement Leger
  2020-02-04 17:44   ` [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
  2020-02-04 17:44   ` [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
  1 sibling, 2 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-04 17:44 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

This serie add support for elf64 in remoteproc elf loader. 
First patch modifies the type of len argument (in da_to_va) in order
to allow loading elf64 segment with a u64 size.
Second patch is the actual modification in the elf loader to support
elf64 type by using a set of generic macros.

Changes from V2:
 - da_to_va len type changed from int to u64
 - Add check for elf64 header size
 - Add comments for name table parsing
 - Fix typo in "accommodate"

Clement Leger (2):
  remoteproc: Use u64 len for da_to_va
  remoteproc: Add elf64 support in elf loader

 Documentation/remoteproc.txt               |   2 +-
 drivers/remoteproc/imx_rproc.c             |   9 +-
 drivers/remoteproc/keystone_remoteproc.c   |   2 +-
 drivers/remoteproc/qcom_q6v5_adsp.c        |   2 +-
 drivers/remoteproc/qcom_q6v5_mss.c         |   2 +-
 drivers/remoteproc/qcom_q6v5_pas.c         |   2 +-
 drivers/remoteproc/qcom_q6v5_wcss.c        |   2 +-
 drivers/remoteproc/qcom_wcnss.c            |   2 +-
 drivers/remoteproc/remoteproc_core.c       |   2 +-
 drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
 drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
 drivers/remoteproc/remoteproc_internal.h   |   4 +-
 drivers/remoteproc/st_remoteproc.c         |   2 +-
 drivers/remoteproc/st_slim_rproc.c         |   4 +-
 drivers/remoteproc/wkup_m3_rproc.c         |   2 +-
 include/linux/remoteproc.h                 |   6 +-
 16 files changed, 184 insertions(+), 75 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h

-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va
  2020-02-04 17:44 ` [PATCH v3 0/2] remoteproc: Add elf64 support to elf loader Clement Leger
@ 2020-02-04 17:44   ` Clement Leger
  2020-02-05 21:06     ` Mathieu Poirier
  2020-02-04 17:44   ` [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
  1 sibling, 1 reply; 32+ messages in thread
From: Clement Leger @ 2020-02-04 17:44 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

With upcoming changes in elf loader for elf64 support, section size will
be a u64. When used with da_to_va, this will potentially lead to
overflow if using the current "int" type for len argument. Change
da_to_va prototype to use a u64 for len and fix all users of this
function.

Signed-off-by: Clement Leger <cleger@kalray.eu>
---
 drivers/remoteproc/imx_rproc.c           | 9 +++++----
 drivers/remoteproc/keystone_remoteproc.c | 2 +-
 drivers/remoteproc/qcom_q6v5_adsp.c      | 2 +-
 drivers/remoteproc/qcom_q6v5_mss.c       | 2 +-
 drivers/remoteproc/qcom_q6v5_pas.c       | 2 +-
 drivers/remoteproc/qcom_q6v5_wcss.c      | 2 +-
 drivers/remoteproc/qcom_wcnss.c          | 2 +-
 drivers/remoteproc/remoteproc_core.c     | 2 +-
 drivers/remoteproc/remoteproc_internal.h | 2 +-
 drivers/remoteproc/st_slim_rproc.c       | 4 ++--
 drivers/remoteproc/wkup_m3_rproc.c       | 2 +-
 include/linux/remoteproc.h               | 2 +-
 12 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 3e72b6f38d4b..1e895d5cf918 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
 }
 
 static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
-			       int len, u64 *sys)
+			       u64 len, u64 *sys)
 {
 	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
 	int i;
@@ -203,12 +203,12 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
 		}
 	}
 
-	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
+	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
 		 da, len);
 	return -ENOENT;
 }
 
-static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct imx_rproc *priv = rproc->priv;
 	void *va = NULL;
@@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
 		}
 	}
 
-	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
+	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
+		da, len, va);
 
 	return va;
 }
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index 5c4658f00b3d..25c01df47eba 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct keystone_rproc *ksproc = rproc->priv;
 	void __iomem *va = NULL;
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index e953886b2eb7..7518e67a49e5 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 471128a2e723..248febde6fc1 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct q6v5 *qproc = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index db4b3c4bacd7..cf2cd609c90d 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
index f93e1e4a1cc0..3a6b82a16961 100644
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct q6v5_wcss *wcss = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index dc135754bb9c..f893219e45a8 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 307df98347ba..9e6d3c6a60ee 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
  * here the output of the DMA API for the carveouts, which should be more
  * correct.
  */
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct rproc_mem_entry *carveout;
 	void *ptr = NULL;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 493ef9262411..004867061721 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
 void rproc_free_vring(struct rproc_vring *rvring);
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
 
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
+void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
 phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
index 04492fead3c8..fc01cd879b60 100644
--- a/drivers/remoteproc/st_slim_rproc.c
+++ b/drivers/remoteproc/st_slim_rproc.c
@@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct st_slim_rproc *slim_rproc = rproc->priv;
 	void *va = NULL;
@@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
 		}
 	}
 
-	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
+	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
 		da, len, va);
 
 	return va;
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index 3984e585c847..0e8082948489 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -80,7 +80,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct wkup_m3_rproc *wkupm3 = rproc->priv;
 	void *va = NULL;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 16ad66683ad0..f84bd5fe0211 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -374,7 +374,7 @@ struct rproc_ops {
 	int (*start)(struct rproc *rproc);
 	int (*stop)(struct rproc *rproc);
 	void (*kick)(struct rproc *rproc, int vqid);
-	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
+	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
 	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
 	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
 			  int offset, int avail);
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-04 17:44 ` [PATCH v3 0/2] remoteproc: Add elf64 support to elf loader Clement Leger
  2020-02-04 17:44   ` [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
@ 2020-02-04 17:44   ` Clement Leger
  2020-02-05 22:49     ` Mathieu Poirier
  1 sibling, 1 reply; 32+ messages in thread
From: Clement Leger @ 2020-02-04 17:44 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

elf32 and elf64 mainly differ by their types. In order to avoid
copy/pasting the whole loader code, generate static inline functions
which will access values according to the elf class. It allows to keep a
common loader basis.
In order to accommodate both elf types sizes, the maximum size for a
elf header member is chosen using the maximum value of both elf class.

Signed-off-by: Clement Leger <cleger@kalray.eu>
Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
---
 Documentation/remoteproc.txt               |   2 +-
 drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
 drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
 drivers/remoteproc/remoteproc_internal.h   |   2 +-
 drivers/remoteproc/st_remoteproc.c         |   2 +-
 include/linux/remoteproc.h                 |   4 +-
 6 files changed, 167 insertions(+), 59 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h

diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
index 03c3d2e568b0..2be1147256e0 100644
--- a/Documentation/remoteproc.txt
+++ b/Documentation/remoteproc.txt
@@ -230,7 +230,7 @@ in the used rings.
 Binary Firmware Structure
 =========================
 
-At this point remoteproc only supports ELF32 firmware binaries. However,
+At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
 it is quite expected that other platforms/devices which we'd want to
 support with this framework will be based on different binary formats.
 
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 606aae166eba..21fd2b2fe5ae 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -23,6 +23,7 @@
 #include <linux/elf.h>
 
 #include "remoteproc_internal.h"
+#include "remoteproc_elf_loader.h"
 
 /**
  * rproc_elf_sanity_check() - Sanity Check ELF firmware image
@@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 {
 	const char *name = rproc->firmware;
 	struct device *dev = &rproc->dev;
+	/*
+	 * Elf files are beginning with the same structure. Thus, to simplify
+	 * header parsing, we can use the elf32_hdr one for both elf64 and
+	 * elf32.
+	 */
 	struct elf32_hdr *ehdr;
+	u32 elf_shdr_size;
+	u64 phoff, shoff;
 	char class;
+	u16 phnum;
 
 	if (!fw) {
 		dev_err(dev, "failed to load %s\n", name);
@@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 
 	ehdr = (struct elf32_hdr *)fw->data;
 
-	/* We only support ELF32 at this point */
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		dev_err(dev, "Image is corrupted (bad magic)\n");
+		return -EINVAL;
+	}
+
 	class = ehdr->e_ident[EI_CLASS];
-	if (class != ELFCLASS32) {
+	if (class != ELFCLASS32 && class != ELFCLASS64) {
 		dev_err(dev, "Unsupported class: %d\n", class);
 		return -EINVAL;
 	}
 
+	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
+		dev_err(dev, "elf64 header is too small\n");
+		return -EINVAL;
+	}
+
 	/* We assume the firmware has the same endianness as the host */
 # ifdef __LITTLE_ENDIAN
 	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
@@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 		return -EINVAL;
 	}
 
-	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
-		dev_err(dev, "Image is too small\n");
-		return -EINVAL;
-	}
+	phoff = elf_hdr_e_phoff(class, fw->data);
+	shoff = elf_hdr_e_shoff(class, fw->data);
+	phnum =  elf_hdr_e_phnum(class, fw->data);
+	elf_shdr_size = elf_size_of_shdr(class);
 
-	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
-		dev_err(dev, "Image is corrupted (bad magic)\n");
+	if (fw->size < shoff + elf_shdr_size) {
+		dev_err(dev, "Image is too small\n");
 		return -EINVAL;
 	}
 
-	if (ehdr->e_phnum == 0) {
+	if (phnum == 0) {
 		dev_err(dev, "No loadable segments\n");
 		return -EINVAL;
 	}
 
-	if (ehdr->e_phoff > fw->size) {
+	if (phoff > fw->size) {
 		dev_err(dev, "Firmware size is too small\n");
 		return -EINVAL;
 	}
 
+	dev_dbg(dev, "Firmware is an elf%d file\n",
+		class == ELFCLASS32 ? 32 : 64);
+
 	return 0;
 }
 EXPORT_SYMBOL(rproc_elf_sanity_check);
@@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
  * Note that the boot address is not a configurable property of all remote
  * processors. Some will always boot at a specific hard-coded address.
  */
-u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
-
-	return ehdr->e_entry;
+	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
 }
 EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 
@@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = &rproc->dev;
-	struct elf32_hdr *ehdr;
-	struct elf32_phdr *phdr;
+	const void *ehdr, *phdr;
 	int i, ret = 0;
+	u16 phnum;
 	const u8 *elf_data = fw->data;
+	u8 class = fw_elf_get_class(fw);
+	u32 elf_phdr_size = elf_size_of_phdr(class);
 
-	ehdr = (struct elf32_hdr *)elf_data;
-	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
+	ehdr = elf_data;
+	phnum = elf_hdr_e_phnum(class, ehdr);
+	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
 
 	/* go through the available ELF segments */
-	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
-		u32 da = phdr->p_paddr;
-		u32 memsz = phdr->p_memsz;
-		u32 filesz = phdr->p_filesz;
-		u32 offset = phdr->p_offset;
+	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
+		u64 da = elf_phdr_p_paddr(class, phdr);
+		u64 memsz = elf_phdr_p_memsz(class, phdr);
+		u64 filesz = elf_phdr_p_filesz(class, phdr);
+		u64 offset = elf_phdr_p_offset(class, phdr);
+		u32 type = elf_phdr_p_type(class, phdr);
 		void *ptr;
 
-		if (phdr->p_type != PT_LOAD)
+		if (type != PT_LOAD)
 			continue;
 
-		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
-			phdr->p_type, da, memsz, filesz);
+		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
+			type, da, memsz, filesz);
 
 		if (filesz > memsz) {
-			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
+			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
 				filesz, memsz);
 			ret = -EINVAL;
 			break;
 		}
 
 		if (offset + filesz > fw->size) {
-			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
+			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
 				offset + filesz, fw->size);
 			ret = -EINVAL;
 			break;
@@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		/* grab the kernel address for this device address */
 		ptr = rproc_da_to_va(rproc, da, memsz);
 		if (!ptr) {
-			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
+			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
+				memsz);
 			ret = -EINVAL;
 			break;
 		}
 
 		/* put the segment where the remote processor expects it */
-		if (phdr->p_filesz)
-			memcpy(ptr, elf_data + phdr->p_offset, filesz);
+		if (filesz)
+			memcpy(ptr, elf_data + offset, filesz);
 
 		/*
 		 * Zero out remaining memory for this segment.
@@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 }
 EXPORT_SYMBOL(rproc_elf_load_segments);
 
-static struct elf32_shdr *
-find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
+static const void *
+find_table(struct device *dev, const struct firmware *fw)
 {
-	struct elf32_shdr *shdr;
+	const void *shdr, *name_table_shdr;
 	int i;
 	const char *name_table;
 	struct resource_table *table = NULL;
-	const u8 *elf_data = (void *)ehdr;
+	const u8 *elf_data = (void *)fw->data;
+	u8 class = fw_elf_get_class(fw);
+	size_t fw_size = fw->size;
+	const void *ehdr = elf_data;
+	u16 shnum = elf_hdr_e_shnum(class, ehdr);
+	u32 elf_shdr_size = elf_size_of_shdr(class);
+	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
 
 	/* look for the resource table and handle it */
-	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
-	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
-
-	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
-		u32 size = shdr->sh_size;
-		u32 offset = shdr->sh_offset;
-
-		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
+	/* First, get the section header according to the elf class */
+	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
+	/* Compute name table section header entry in shdr array */
+	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
+	/* Finally, compute the name table section address in elf */
+	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
+
+	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
+		u64 size = elf_shdr_sh_size(class, shdr);
+		u64 offset = elf_shdr_sh_offset(class, shdr);
+		u32 name = elf_shdr_sh_name(class, shdr);
+
+		if (strcmp(name_table + name, ".resource_table"))
 			continue;
 
 		table = (struct resource_table *)(elf_data + offset);
@@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
  */
 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr;
-	struct elf32_shdr *shdr;
+	const void *shdr;
 	struct device *dev = &rproc->dev;
 	struct resource_table *table = NULL;
 	const u8 *elf_data = fw->data;
 	size_t tablesz;
+	u8 class = fw_elf_get_class(fw);
+	u64 sh_offset;
 
-	ehdr = (struct elf32_hdr *)elf_data;
-
-	shdr = find_table(dev, ehdr, fw->size);
+	shdr = find_table(dev, fw);
 	if (!shdr)
 		return -EINVAL;
 
-	table = (struct resource_table *)(elf_data + shdr->sh_offset);
-	tablesz = shdr->sh_size;
+	sh_offset = elf_shdr_sh_offset(class, shdr);
+	table = (struct resource_table *)(elf_data + sh_offset);
+	tablesz = elf_shdr_sh_size(class, shdr);
 
 	/*
 	 * Create a copy of the resource table. When a virtio device starts
@@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
 						       const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
-	struct elf32_shdr *shdr;
+	const void *shdr;
+	u64 sh_addr, sh_size;
+	u8 class = fw_elf_get_class(fw);
 
-	shdr = find_table(&rproc->dev, ehdr, fw->size);
+	shdr = find_table(&rproc->dev, fw);
 	if (!shdr)
 		return NULL;
 
-	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
+	sh_addr = elf_shdr_sh_addr(class, shdr);
+	sh_size = elf_shdr_sh_size(class, shdr);
+
+	return rproc_da_to_va(rproc, sh_addr, sh_size);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
diff --git a/drivers/remoteproc/remoteproc_elf_loader.h b/drivers/remoteproc/remoteproc_elf_loader.h
new file mode 100644
index 000000000000..fac3565734f9
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_elf_loader.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Remote processor elf loader defines
+ *
+ * Copyright (C) 2019 Kalray, Inc.
+ */
+
+#ifndef REMOTEPROC_ELF_LOADER_H
+#define REMOTEPROC_ELF_LOADER_H
+
+#include <linux/elf.h>
+#include <linux/types.h>
+
+/**
+ * fw_elf_get_class - Get elf class
+ * @fw: the ELF firmware image
+ *
+ * Note that we use and elf32_hdr to access the class since the start of the
+ * struct is the same for both elf class
+ *
+ * Return: elf class of the firmware
+ */
+static inline u8 fw_elf_get_class(const struct firmware *fw)
+{
+	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
+
+	return ehdr->e_ident[EI_CLASS];
+}
+
+#define ELF_GET_FIELD(__s, __field, __type) \
+static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
+{ \
+	if (class == ELFCLASS32) \
+		return (__type) ((const struct elf32_##__s *) arg)->__field; \
+	else \
+		return (__type) ((const struct elf64_##__s *) arg)->__field; \
+}
+
+ELF_GET_FIELD(hdr, e_entry, u64)
+ELF_GET_FIELD(hdr, e_phnum, u16)
+ELF_GET_FIELD(hdr, e_shnum, u16)
+ELF_GET_FIELD(hdr, e_phoff, u64)
+ELF_GET_FIELD(hdr, e_shoff, u64)
+ELF_GET_FIELD(hdr, e_shstrndx, u16)
+
+ELF_GET_FIELD(phdr, p_paddr, u64)
+ELF_GET_FIELD(phdr, p_filesz, u64)
+ELF_GET_FIELD(phdr, p_memsz, u64)
+ELF_GET_FIELD(phdr, p_type, u32)
+ELF_GET_FIELD(phdr, p_offset, u64)
+
+ELF_GET_FIELD(shdr, sh_size, u64)
+ELF_GET_FIELD(shdr, sh_offset, u64)
+ELF_GET_FIELD(shdr, sh_name, u32)
+ELF_GET_FIELD(shdr, sh_addr, u64)
+
+#define ELF_STRUCT_SIZE(__s) \
+static inline unsigned long elf_size_of_##__s(u8 class) \
+{ \
+	if (class == ELFCLASS32)\
+		return sizeof(struct elf32_##__s); \
+	else \
+		return sizeof(struct elf64_##__s); \
+}
+
+ELF_STRUCT_SIZE(shdr)
+ELF_STRUCT_SIZE(phdr)
+
+#endif /* REMOTEPROC_ELF_LOADER_H */
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 004867061721..eeb26434220e 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
-u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
+u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index ee13d23b43a9..a3268d95a50e 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
 		}
 	}
 
-	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
+	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
 
 	return 0;
 
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index f84bd5fe0211..82cebca9344c 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -382,7 +382,7 @@ struct rproc_ops {
 				struct rproc *rproc, const struct firmware *fw);
 	int (*load)(struct rproc *rproc, const struct firmware *fw);
 	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
-	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
+	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
 };
 
 /**
@@ -498,7 +498,7 @@ struct rproc {
 	int num_traces;
 	struct list_head carveouts;
 	struct list_head mappings;
-	u32 bootaddr;
+	u64 bootaddr;
 	struct list_head rvdevs;
 	struct list_head subdevs;
 	struct idr notifyids;
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va
  2020-02-04 17:44   ` [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
@ 2020-02-05 21:06     ` Mathieu Poirier
  0 siblings, 0 replies; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-05 21:06 UTC (permalink / raw)
  To: Clement Leger
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna

Hi Clement,

On Tue, Feb 04, 2020 at 06:44:11PM +0100, Clement Leger wrote:
> With upcoming changes in elf loader for elf64 support, section size will
> be a u64. When used with da_to_va, this will potentially lead to
> overflow if using the current "int" type for len argument. Change
> da_to_va prototype to use a u64 for len and fix all users of this
> function.
> 
> Signed-off-by: Clement Leger <cleger@kalray.eu>
> ---
>  drivers/remoteproc/imx_rproc.c           | 9 +++++----
>  drivers/remoteproc/keystone_remoteproc.c | 2 +-
>  drivers/remoteproc/qcom_q6v5_adsp.c      | 2 +-
>  drivers/remoteproc/qcom_q6v5_mss.c       | 2 +-
>  drivers/remoteproc/qcom_q6v5_pas.c       | 2 +-
>  drivers/remoteproc/qcom_q6v5_wcss.c      | 2 +-
>  drivers/remoteproc/qcom_wcnss.c          | 2 +-
>  drivers/remoteproc/remoteproc_core.c     | 2 +-
>  drivers/remoteproc/remoteproc_internal.h | 2 +-
>  drivers/remoteproc/st_slim_rproc.c       | 4 ++--
>  drivers/remoteproc/wkup_m3_rproc.c       | 2 +-
>  include/linux/remoteproc.h               | 2 +-
>  12 files changed, 17 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 3e72b6f38d4b..1e895d5cf918 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
>  }
>  
>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
> -			       int len, u64 *sys)
> +			       u64 len, u64 *sys)
>  {
>  	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
>  	int i;
> @@ -203,12 +203,12 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>  		}
>  	}
>  
> -	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
> +	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
>  		 da, len);
>  	return -ENOENT;
>  }
>  
> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct imx_rproc *priv = rproc->priv;
>  	void *va = NULL;

The condition "if (len <= 0)" at the beginning of the function needs to be
fixed.  


> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>  		}
>  	}
>  
> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
> +		da, len, va);
>  
>  	return va;
>  }
> diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
> index 5c4658f00b3d..25c01df47eba 100644
> --- a/drivers/remoteproc/keystone_remoteproc.c
> +++ b/drivers/remoteproc/keystone_remoteproc.c
> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
>   * can be used either by the remoteproc core for loading (when using kernel
>   * remoteproc loader), or by any rpmsg bus drivers.
>   */
> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {

Same comment as above.

>  	struct keystone_rproc *ksproc = rproc->priv;
>  	void __iomem *va = NULL;
> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
> index e953886b2eb7..7518e67a49e5 100644
> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
> index 471128a2e723..248febde6fc1 100644
> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct q6v5 *qproc = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index db4b3c4bacd7..cf2cd609c90d 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
> index f93e1e4a1cc0..3a6b82a16961 100644
> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct q6v5_wcss *wcss = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> index dc135754bb9c..f893219e45a8 100644
> --- a/drivers/remoteproc/qcom_wcnss.c
> +++ b/drivers/remoteproc/qcom_wcnss.c
> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 307df98347ba..9e6d3c6a60ee 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>   * here the output of the DMA API for the carveouts, which should be more
>   * correct.
>   */
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct rproc_mem_entry *carveout;
>  	void *ptr = NULL;
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 493ef9262411..004867061721 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>  void rproc_free_vring(struct rproc_vring *rvring);
>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>  
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>  int rproc_trigger_recovery(struct rproc *rproc);
>  
> diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
> index 04492fead3c8..fc01cd879b60 100644
> --- a/drivers/remoteproc/st_slim_rproc.c
> +++ b/drivers/remoteproc/st_slim_rproc.c
> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>  	void *va = NULL;
> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>  		}
>  	}
>  
> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
>  		da, len, va);
>  
>  	return va;
> diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
> index 3984e585c847..0e8082948489 100644
> --- a/drivers/remoteproc/wkup_m3_rproc.c
> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> @@ -80,7 +80,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {

Same comment as above.

>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>  	void *va = NULL;
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index 16ad66683ad0..f84bd5fe0211 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -374,7 +374,7 @@ struct rproc_ops {
>  	int (*start)(struct rproc *rproc);
>  	int (*stop)(struct rproc *rproc);
>  	void (*kick)(struct rproc *rproc, int vqid);
> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>  			  int offset, int avail);
> -- 
> 2.15.0.276.g89ea799
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-04 17:44   ` [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
@ 2020-02-05 22:49     ` Mathieu Poirier
  2020-02-06  8:37       ` Clément Leger
  0 siblings, 1 reply; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-05 22:49 UTC (permalink / raw)
  To: Clement Leger
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna

On Tue, Feb 04, 2020 at 06:44:12PM +0100, Clement Leger wrote:
> elf32 and elf64 mainly differ by their types. In order to avoid
> copy/pasting the whole loader code, generate static inline functions
> which will access values according to the elf class. It allows to keep a
> common loader basis.
> In order to accommodate both elf types sizes, the maximum size for a
> elf header member is chosen using the maximum value of both elf class.
> 
> Signed-off-by: Clement Leger <cleger@kalray.eu>
> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
> ---
>  Documentation/remoteproc.txt               |   2 +-
>  drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
>  drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
>  drivers/remoteproc/remoteproc_internal.h   |   2 +-
>  drivers/remoteproc/st_remoteproc.c         |   2 +-
>  include/linux/remoteproc.h                 |   4 +-
>  6 files changed, 167 insertions(+), 59 deletions(-)
>  create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h
> 
> diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
> index 03c3d2e568b0..2be1147256e0 100644
> --- a/Documentation/remoteproc.txt
> +++ b/Documentation/remoteproc.txt
> @@ -230,7 +230,7 @@ in the used rings.
>  Binary Firmware Structure
>  =========================
>  
> -At this point remoteproc only supports ELF32 firmware binaries. However,
> +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
>  it is quite expected that other platforms/devices which we'd want to
>  support with this framework will be based on different binary formats.
>  
> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
> index 606aae166eba..21fd2b2fe5ae 100644
> --- a/drivers/remoteproc/remoteproc_elf_loader.c
> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
> @@ -23,6 +23,7 @@
>  #include <linux/elf.h>
>  
>  #include "remoteproc_internal.h"
> +#include "remoteproc_elf_loader.h"
>  
>  /**
>   * rproc_elf_sanity_check() - Sanity Check ELF firmware image
> @@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
>  {
>  	const char *name = rproc->firmware;
>  	struct device *dev = &rproc->dev;
> +	/*
> +	 * Elf files are beginning with the same structure. Thus, to simplify
> +	 * header parsing, we can use the elf32_hdr one for both elf64 and
> +	 * elf32.
> +	 */
>  	struct elf32_hdr *ehdr;
> +	u32 elf_shdr_size;
> +	u64 phoff, shoff;
>  	char class;
> +	u16 phnum;
>  
>  	if (!fw) {
>  		dev_err(dev, "failed to load %s\n", name);
> @@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
>  
>  	ehdr = (struct elf32_hdr *)fw->data;
>  
> -	/* We only support ELF32 at this point */
> +	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
> +		dev_err(dev, "Image is corrupted (bad magic)\n");
> +		return -EINVAL;
> +	}
> +
>  	class = ehdr->e_ident[EI_CLASS];
> -	if (class != ELFCLASS32) {
> +	if (class != ELFCLASS32 && class != ELFCLASS64) {
>  		dev_err(dev, "Unsupported class: %d\n", class);
>  		return -EINVAL;
>  	}
>  
> +	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
> +		dev_err(dev, "elf64 header is too small\n");
> +		return -EINVAL;
> +	}
> +
>  	/* We assume the firmware has the same endianness as the host */
>  # ifdef __LITTLE_ENDIAN
>  	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
> @@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
>  		return -EINVAL;
>  	}
>  
> -	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
> -		dev_err(dev, "Image is too small\n");
> -		return -EINVAL;
> -	}
> +	phoff = elf_hdr_e_phoff(class, fw->data);
> +	shoff = elf_hdr_e_shoff(class, fw->data);
> +	phnum =  elf_hdr_e_phnum(class, fw->data);
> +	elf_shdr_size = elf_size_of_shdr(class);
>  
> -	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
> -		dev_err(dev, "Image is corrupted (bad magic)\n");
> +	if (fw->size < shoff + elf_shdr_size) {
> +		dev_err(dev, "Image is too small\n");
>  		return -EINVAL;
>  	}
>  
> -	if (ehdr->e_phnum == 0) {
> +	if (phnum == 0) {
>  		dev_err(dev, "No loadable segments\n");
>  		return -EINVAL;
>  	}
>  
> -	if (ehdr->e_phoff > fw->size) {
> +	if (phoff > fw->size) {
>  		dev_err(dev, "Firmware size is too small\n");
>  		return -EINVAL;
>  	}
>  
> +	dev_dbg(dev, "Firmware is an elf%d file\n",
> +		class == ELFCLASS32 ? 32 : 64);
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL(rproc_elf_sanity_check);
> @@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
>   * Note that the boot address is not a configurable property of all remote
>   * processors. Some will always boot at a specific hard-coded address.
>   */
> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>  {
> -	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
> -
> -	return ehdr->e_entry;
> +	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
>  }
>  EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>  
> @@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  {
>  	struct device *dev = &rproc->dev;
> -	struct elf32_hdr *ehdr;
> -	struct elf32_phdr *phdr;
> +	const void *ehdr, *phdr;
>  	int i, ret = 0;
> +	u16 phnum;
>  	const u8 *elf_data = fw->data;
> +	u8 class = fw_elf_get_class(fw);
> +	u32 elf_phdr_size = elf_size_of_phdr(class);
>  
> -	ehdr = (struct elf32_hdr *)elf_data;
> -	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
> +	ehdr = elf_data;
> +	phnum = elf_hdr_e_phnum(class, ehdr);
> +	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
>  
>  	/* go through the available ELF segments */
> -	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
> -		u32 da = phdr->p_paddr;
> -		u32 memsz = phdr->p_memsz;
> -		u32 filesz = phdr->p_filesz;
> -		u32 offset = phdr->p_offset;
> +	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
> +		u64 da = elf_phdr_p_paddr(class, phdr);
> +		u64 memsz = elf_phdr_p_memsz(class, phdr);
> +		u64 filesz = elf_phdr_p_filesz(class, phdr);
> +		u64 offset = elf_phdr_p_offset(class, phdr);
> +		u32 type = elf_phdr_p_type(class, phdr);
>  		void *ptr;
>  
> -		if (phdr->p_type != PT_LOAD)
> +		if (type != PT_LOAD)
>  			continue;
>  
> -		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
> -			phdr->p_type, da, memsz, filesz);
> +		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
> +			type, da, memsz, filesz);
>  
>  		if (filesz > memsz) {
> -			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
> +			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
>  				filesz, memsz);
>  			ret = -EINVAL;
>  			break;
>  		}
>  
>  		if (offset + filesz > fw->size) {
> -			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
> +			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
>  				offset + filesz, fw->size);
>  			ret = -EINVAL;
>  			break;
> @@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  		/* grab the kernel address for this device address */
>  		ptr = rproc_da_to_va(rproc, da, memsz);
>  		if (!ptr) {
> -			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
> +			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
> +				memsz);
>  			ret = -EINVAL;
>  			break;
>  		}
>  
>  		/* put the segment where the remote processor expects it */
> -		if (phdr->p_filesz)
> -			memcpy(ptr, elf_data + phdr->p_offset, filesz);
> +		if (filesz)
> +			memcpy(ptr, elf_data + offset, filesz);
>  
>  		/*
>  		 * Zero out remaining memory for this segment.
> @@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  }
>  EXPORT_SYMBOL(rproc_elf_load_segments);
>  
> -static struct elf32_shdr *
> -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
> +static const void *
> +find_table(struct device *dev, const struct firmware *fw)
>  {
> -	struct elf32_shdr *shdr;
> +	const void *shdr, *name_table_shdr;
>  	int i;
>  	const char *name_table;
>  	struct resource_table *table = NULL;
> -	const u8 *elf_data = (void *)ehdr;
> +	const u8 *elf_data = (void *)fw->data;
> +	u8 class = fw_elf_get_class(fw);
> +	size_t fw_size = fw->size;
> +	const void *ehdr = elf_data;
> +	u16 shnum = elf_hdr_e_shnum(class, ehdr);
> +	u32 elf_shdr_size = elf_size_of_shdr(class);
> +	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
>  
>  	/* look for the resource table and handle it */
> -	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
> -	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
> -
> -	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
> -		u32 size = shdr->sh_size;
> -		u32 offset = shdr->sh_offset;
> -
> -		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
> +	/* First, get the section header according to the elf class */
> +	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
> +	/* Compute name table section header entry in shdr array */
> +	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
> +	/* Finally, compute the name table section address in elf */
> +	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
> +
> +	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
> +		u64 size = elf_shdr_sh_size(class, shdr);
> +		u64 offset = elf_shdr_sh_offset(class, shdr);
> +		u32 name = elf_shdr_sh_name(class, shdr);
> +
> +		if (strcmp(name_table + name, ".resource_table"))
>  			continue;
>  
>  		table = (struct resource_table *)(elf_data + offset);
> @@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
>   */
>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
>  {
> -	struct elf32_hdr *ehdr;
> -	struct elf32_shdr *shdr;
> +	const void *shdr;
>  	struct device *dev = &rproc->dev;
>  	struct resource_table *table = NULL;
>  	const u8 *elf_data = fw->data;
>  	size_t tablesz;
> +	u8 class = fw_elf_get_class(fw);
> +	u64 sh_offset;
>  
> -	ehdr = (struct elf32_hdr *)elf_data;
> -
> -	shdr = find_table(dev, ehdr, fw->size);
> +	shdr = find_table(dev, fw);
>  	if (!shdr)
>  		return -EINVAL;
>  
> -	table = (struct resource_table *)(elf_data + shdr->sh_offset);
> -	tablesz = shdr->sh_size;
> +	sh_offset = elf_shdr_sh_offset(class, shdr);
> +	table = (struct resource_table *)(elf_data + sh_offset);
> +	tablesz = elf_shdr_sh_size(class, shdr);
>  
>  	/*
>  	 * Create a copy of the resource table. When a virtio device starts
> @@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>  						       const struct firmware *fw)
>  {
> -	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
> -	struct elf32_shdr *shdr;
> +	const void *shdr;
> +	u64 sh_addr, sh_size;
> +	u8 class = fw_elf_get_class(fw);
>  
> -	shdr = find_table(&rproc->dev, ehdr, fw->size);
> +	shdr = find_table(&rproc->dev, fw);
>  	if (!shdr)
>  		return NULL;
>  
> -	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
> +	sh_addr = elf_shdr_sh_addr(class, shdr);
> +	sh_size = elf_shdr_sh_size(class, shdr);
> +
> +	return rproc_da_to_va(rproc, sh_addr, sh_size);
>  }
>  EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
> diff --git a/drivers/remoteproc/remoteproc_elf_loader.h b/drivers/remoteproc/remoteproc_elf_loader.h
> new file mode 100644
> index 000000000000..fac3565734f9
> --- /dev/null
> +++ b/drivers/remoteproc/remoteproc_elf_loader.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Remote processor elf loader defines
> + *
> + * Copyright (C) 2019 Kalray, Inc.
> + */
> +
> +#ifndef REMOTEPROC_ELF_LOADER_H
> +#define REMOTEPROC_ELF_LOADER_H
> +
> +#include <linux/elf.h>
> +#include <linux/types.h>
> +
> +/**
> + * fw_elf_get_class - Get elf class
> + * @fw: the ELF firmware image
> + *
> + * Note that we use and elf32_hdr to access the class since the start of the
> + * struct is the same for both elf class
> + *
> + * Return: elf class of the firmware
> + */
> +static inline u8 fw_elf_get_class(const struct firmware *fw)
> +{
> +	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
> +
> +	return ehdr->e_ident[EI_CLASS];
> +}
> +
> +#define ELF_GET_FIELD(__s, __field, __type) \
> +static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
> +{ \
> +	if (class == ELFCLASS32) \
> +		return (__type) ((const struct elf32_##__s *) arg)->__field; \
> +	else \
> +		return (__type) ((const struct elf64_##__s *) arg)->__field; \
> +}
> +
> +ELF_GET_FIELD(hdr, e_entry, u64)
> +ELF_GET_FIELD(hdr, e_phnum, u16)
> +ELF_GET_FIELD(hdr, e_shnum, u16)
> +ELF_GET_FIELD(hdr, e_phoff, u64)
> +ELF_GET_FIELD(hdr, e_shoff, u64)
> +ELF_GET_FIELD(hdr, e_shstrndx, u16)
> +
> +ELF_GET_FIELD(phdr, p_paddr, u64)
> +ELF_GET_FIELD(phdr, p_filesz, u64)
> +ELF_GET_FIELD(phdr, p_memsz, u64)
> +ELF_GET_FIELD(phdr, p_type, u32)
> +ELF_GET_FIELD(phdr, p_offset, u64)
> +
> +ELF_GET_FIELD(shdr, sh_size, u64)
> +ELF_GET_FIELD(shdr, sh_offset, u64)
> +ELF_GET_FIELD(shdr, sh_name, u32)
> +ELF_GET_FIELD(shdr, sh_addr, u64)
> +
> +#define ELF_STRUCT_SIZE(__s) \
> +static inline unsigned long elf_size_of_##__s(u8 class) \
> +{ \
> +	if (class == ELFCLASS32)\
> +		return sizeof(struct elf32_##__s); \
> +	else \
> +		return sizeof(struct elf64_##__s); \
> +}
> +
> +ELF_STRUCT_SIZE(shdr)
> +ELF_STRUCT_SIZE(phdr)
> +
> +#endif /* REMOTEPROC_ELF_LOADER_H */
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 004867061721..eeb26434220e 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
>  int rproc_trigger_recovery(struct rproc *rproc);
>  
>  int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
> diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
> index ee13d23b43a9..a3268d95a50e 100644
> --- a/drivers/remoteproc/st_remoteproc.c
> +++ b/drivers/remoteproc/st_remoteproc.c
> @@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
>  		}
>  	}
>  
> -	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
> +	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
>  
>  	return 0;
>  
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index f84bd5fe0211..82cebca9344c 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -382,7 +382,7 @@ struct rproc_ops {
>  				struct rproc *rproc, const struct firmware *fw);
>  	int (*load)(struct rproc *rproc, const struct firmware *fw);
>  	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
> -	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
> +	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>  };
>  
>  /**
> @@ -498,7 +498,7 @@ struct rproc {
>  	int num_traces;
>  	struct list_head carveouts;
>  	struct list_head mappings;
> -	u32 bootaddr;
> +	u64 bootaddr;

That will cause problems for rproc_coredump()[1] and fixing it properly 
likely means that a 32 or 64 elf should be generated based on the type of image
that was loaded.  This is also true if ->p_vaddr and ->p_paddr (also in the same
function) are to be handled properly.

I'm interested in your opinion on this.

Thanks,
Mathieu

[1]. https://elixir.bootlin.com/linux/latest/source/drivers/remoteproc/remoteproc_core.c#L1600

>  	struct list_head rvdevs;
>  	struct list_head subdevs;
>  	struct idr notifyids;
> -- 
> 2.15.0.276.g89ea799
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-05 22:49     ` Mathieu Poirier
@ 2020-02-06  8:37       ` Clément Leger
  2020-02-06 15:05         ` Clément Leger
  0 siblings, 1 reply; 32+ messages in thread
From: Clément Leger @ 2020-02-06  8:37 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna

Hi Mathieu,

----- On 5 Feb, 2020, at 23:49, Mathieu Poirier mathieu.poirier@linaro.org wrote:

> On Tue, Feb 04, 2020 at 06:44:12PM +0100, Clement Leger wrote:
>> elf32 and elf64 mainly differ by their types. In order to avoid
>> copy/pasting the whole loader code, generate static inline functions
>> which will access values according to the elf class. It allows to keep a
>> common loader basis.
>> In order to accommodate both elf types sizes, the maximum size for a
>> elf header member is chosen using the maximum value of both elf class.
>> 
>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
>> ---
>>  Documentation/remoteproc.txt               |   2 +-
>>  drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
>>  drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
>>  drivers/remoteproc/remoteproc_internal.h   |   2 +-
>>  drivers/remoteproc/st_remoteproc.c         |   2 +-
>>  include/linux/remoteproc.h                 |   4 +-
>>  6 files changed, 167 insertions(+), 59 deletions(-)
>>  create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h
>> 
>> diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
>> index 03c3d2e568b0..2be1147256e0 100644
>> --- a/Documentation/remoteproc.txt
>> +++ b/Documentation/remoteproc.txt
>> @@ -230,7 +230,7 @@ in the used rings.
>>  Binary Firmware Structure
>>  =========================
>>  
>> -At this point remoteproc only supports ELF32 firmware binaries. However,
>> +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
>>  it is quite expected that other platforms/devices which we'd want to
>>  support with this framework will be based on different binary formats.
>>  
>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c
>> b/drivers/remoteproc/remoteproc_elf_loader.c
>> index 606aae166eba..21fd2b2fe5ae 100644
>> --- a/drivers/remoteproc/remoteproc_elf_loader.c
>> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
>> @@ -23,6 +23,7 @@
>>  #include <linux/elf.h>
>>  
>>  #include "remoteproc_internal.h"
>> +#include "remoteproc_elf_loader.h"
>>  
>>  /**
>>   * rproc_elf_sanity_check() - Sanity Check ELF firmware image
>> @@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>> firmware *fw)
>>  {
>>  	const char *name = rproc->firmware;
>>  	struct device *dev = &rproc->dev;
>> +	/*
>> +	 * Elf files are beginning with the same structure. Thus, to simplify
>> +	 * header parsing, we can use the elf32_hdr one for both elf64 and
>> +	 * elf32.
>> +	 */
>>  	struct elf32_hdr *ehdr;
>> +	u32 elf_shdr_size;
>> +	u64 phoff, shoff;
>>  	char class;
>> +	u16 phnum;
>>  
>>  	if (!fw) {
>>  		dev_err(dev, "failed to load %s\n", name);
>> @@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>> firmware *fw)
>>  
>>  	ehdr = (struct elf32_hdr *)fw->data;
>>  
>> -	/* We only support ELF32 at this point */
>> +	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
>> +		dev_err(dev, "Image is corrupted (bad magic)\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	class = ehdr->e_ident[EI_CLASS];
>> -	if (class != ELFCLASS32) {
>> +	if (class != ELFCLASS32 && class != ELFCLASS64) {
>>  		dev_err(dev, "Unsupported class: %d\n", class);
>>  		return -EINVAL;
>>  	}
>>  
>> +	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
>> +		dev_err(dev, "elf64 header is too small\n");
>> +		return -EINVAL;
>> +	}
>> +
>>  	/* We assume the firmware has the same endianness as the host */
>>  # ifdef __LITTLE_ENDIAN
>>  	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
>> @@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>> firmware *fw)
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
>> -		dev_err(dev, "Image is too small\n");
>> -		return -EINVAL;
>> -	}
>> +	phoff = elf_hdr_e_phoff(class, fw->data);
>> +	shoff = elf_hdr_e_shoff(class, fw->data);
>> +	phnum =  elf_hdr_e_phnum(class, fw->data);
>> +	elf_shdr_size = elf_size_of_shdr(class);
>>  
>> -	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
>> -		dev_err(dev, "Image is corrupted (bad magic)\n");
>> +	if (fw->size < shoff + elf_shdr_size) {
>> +		dev_err(dev, "Image is too small\n");
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (ehdr->e_phnum == 0) {
>> +	if (phnum == 0) {
>>  		dev_err(dev, "No loadable segments\n");
>>  		return -EINVAL;
>>  	}
>>  
>> -	if (ehdr->e_phoff > fw->size) {
>> +	if (phoff > fw->size) {
>>  		dev_err(dev, "Firmware size is too small\n");
>>  		return -EINVAL;
>>  	}
>>  
>> +	dev_dbg(dev, "Firmware is an elf%d file\n",
>> +		class == ELFCLASS32 ? 32 : 64);
>> +
>>  	return 0;
>>  }
>>  EXPORT_SYMBOL(rproc_elf_sanity_check);
>> @@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
>>   * Note that the boot address is not a configurable property of all remote
>>   * processors. Some will always boot at a specific hard-coded address.
>>   */
>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>>  {
>> -	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
>> -
>> -	return ehdr->e_entry;
>> +	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
>>  }
>>  EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>>  
>> @@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>>  {
>>  	struct device *dev = &rproc->dev;
>> -	struct elf32_hdr *ehdr;
>> -	struct elf32_phdr *phdr;
>> +	const void *ehdr, *phdr;
>>  	int i, ret = 0;
>> +	u16 phnum;
>>  	const u8 *elf_data = fw->data;
>> +	u8 class = fw_elf_get_class(fw);
>> +	u32 elf_phdr_size = elf_size_of_phdr(class);
>>  
>> -	ehdr = (struct elf32_hdr *)elf_data;
>> -	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
>> +	ehdr = elf_data;
>> +	phnum = elf_hdr_e_phnum(class, ehdr);
>> +	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
>>  
>>  	/* go through the available ELF segments */
>> -	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
>> -		u32 da = phdr->p_paddr;
>> -		u32 memsz = phdr->p_memsz;
>> -		u32 filesz = phdr->p_filesz;
>> -		u32 offset = phdr->p_offset;
>> +	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
>> +		u64 da = elf_phdr_p_paddr(class, phdr);
>> +		u64 memsz = elf_phdr_p_memsz(class, phdr);
>> +		u64 filesz = elf_phdr_p_filesz(class, phdr);
>> +		u64 offset = elf_phdr_p_offset(class, phdr);
>> +		u32 type = elf_phdr_p_type(class, phdr);
>>  		void *ptr;
>>  
>> -		if (phdr->p_type != PT_LOAD)
>> +		if (type != PT_LOAD)
>>  			continue;
>>  
>> -		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
>> -			phdr->p_type, da, memsz, filesz);
>> +		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
>> +			type, da, memsz, filesz);
>>  
>>  		if (filesz > memsz) {
>> -			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
>> +			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
>>  				filesz, memsz);
>>  			ret = -EINVAL;
>>  			break;
>>  		}
>>  
>>  		if (offset + filesz > fw->size) {
>> -			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
>> +			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
>>  				offset + filesz, fw->size);
>>  			ret = -EINVAL;
>>  			break;
>> @@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const
>> struct firmware *fw)
>>  		/* grab the kernel address for this device address */
>>  		ptr = rproc_da_to_va(rproc, da, memsz);
>>  		if (!ptr) {
>> -			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
>> +			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
>> +				memsz);
>>  			ret = -EINVAL;
>>  			break;
>>  		}
>>  
>>  		/* put the segment where the remote processor expects it */
>> -		if (phdr->p_filesz)
>> -			memcpy(ptr, elf_data + phdr->p_offset, filesz);
>> +		if (filesz)
>> +			memcpy(ptr, elf_data + offset, filesz);
>>  
>>  		/*
>>  		 * Zero out remaining memory for this segment.
>> @@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const
>> struct firmware *fw)
>>  }
>>  EXPORT_SYMBOL(rproc_elf_load_segments);
>>  
>> -static struct elf32_shdr *
>> -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
>> +static const void *
>> +find_table(struct device *dev, const struct firmware *fw)
>>  {
>> -	struct elf32_shdr *shdr;
>> +	const void *shdr, *name_table_shdr;
>>  	int i;
>>  	const char *name_table;
>>  	struct resource_table *table = NULL;
>> -	const u8 *elf_data = (void *)ehdr;
>> +	const u8 *elf_data = (void *)fw->data;
>> +	u8 class = fw_elf_get_class(fw);
>> +	size_t fw_size = fw->size;
>> +	const void *ehdr = elf_data;
>> +	u16 shnum = elf_hdr_e_shnum(class, ehdr);
>> +	u32 elf_shdr_size = elf_size_of_shdr(class);
>> +	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
>>  
>>  	/* look for the resource table and handle it */
>> -	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
>> -	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
>> -
>> -	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
>> -		u32 size = shdr->sh_size;
>> -		u32 offset = shdr->sh_offset;
>> -
>> -		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
>> +	/* First, get the section header according to the elf class */
>> +	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
>> +	/* Compute name table section header entry in shdr array */
>> +	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
>> +	/* Finally, compute the name table section address in elf */
>> +	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
>> +
>> +	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
>> +		u64 size = elf_shdr_sh_size(class, shdr);
>> +		u64 offset = elf_shdr_sh_offset(class, shdr);
>> +		u32 name = elf_shdr_sh_name(class, shdr);
>> +
>> +		if (strcmp(name_table + name, ".resource_table"))
>>  			continue;
>>  
>>  		table = (struct resource_table *)(elf_data + offset);
>> @@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr,
>> size_t fw_size)
>>   */
>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
>>  {
>> -	struct elf32_hdr *ehdr;
>> -	struct elf32_shdr *shdr;
>> +	const void *shdr;
>>  	struct device *dev = &rproc->dev;
>>  	struct resource_table *table = NULL;
>>  	const u8 *elf_data = fw->data;
>>  	size_t tablesz;
>> +	u8 class = fw_elf_get_class(fw);
>> +	u64 sh_offset;
>>  
>> -	ehdr = (struct elf32_hdr *)elf_data;
>> -
>> -	shdr = find_table(dev, ehdr, fw->size);
>> +	shdr = find_table(dev, fw);
>>  	if (!shdr)
>>  		return -EINVAL;
>>  
>> -	table = (struct resource_table *)(elf_data + shdr->sh_offset);
>> -	tablesz = shdr->sh_size;
>> +	sh_offset = elf_shdr_sh_offset(class, shdr);
>> +	table = (struct resource_table *)(elf_data + sh_offset);
>> +	tablesz = elf_shdr_sh_size(class, shdr);
>>  
>>  	/*
>>  	 * Create a copy of the resource table. When a virtio device starts
>> @@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>>  						       const struct firmware *fw)
>>  {
>> -	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
>> -	struct elf32_shdr *shdr;
>> +	const void *shdr;
>> +	u64 sh_addr, sh_size;
>> +	u8 class = fw_elf_get_class(fw);
>>  
>> -	shdr = find_table(&rproc->dev, ehdr, fw->size);
>> +	shdr = find_table(&rproc->dev, fw);
>>  	if (!shdr)
>>  		return NULL;
>>  
>> -	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
>> +	sh_addr = elf_shdr_sh_addr(class, shdr);
>> +	sh_size = elf_shdr_sh_size(class, shdr);
>> +
>> +	return rproc_da_to_va(rproc, sh_addr, sh_size);
>>  }
>>  EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.h
>> b/drivers/remoteproc/remoteproc_elf_loader.h
>> new file mode 100644
>> index 000000000000..fac3565734f9
>> --- /dev/null
>> +++ b/drivers/remoteproc/remoteproc_elf_loader.h
>> @@ -0,0 +1,69 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Remote processor elf loader defines
>> + *
>> + * Copyright (C) 2019 Kalray, Inc.
>> + */
>> +
>> +#ifndef REMOTEPROC_ELF_LOADER_H
>> +#define REMOTEPROC_ELF_LOADER_H
>> +
>> +#include <linux/elf.h>
>> +#include <linux/types.h>
>> +
>> +/**
>> + * fw_elf_get_class - Get elf class
>> + * @fw: the ELF firmware image
>> + *
>> + * Note that we use and elf32_hdr to access the class since the start of the
>> + * struct is the same for both elf class
>> + *
>> + * Return: elf class of the firmware
>> + */
>> +static inline u8 fw_elf_get_class(const struct firmware *fw)
>> +{
>> +	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
>> +
>> +	return ehdr->e_ident[EI_CLASS];
>> +}
>> +
>> +#define ELF_GET_FIELD(__s, __field, __type) \
>> +static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
>> +{ \
>> +	if (class == ELFCLASS32) \
>> +		return (__type) ((const struct elf32_##__s *) arg)->__field; \
>> +	else \
>> +		return (__type) ((const struct elf64_##__s *) arg)->__field; \
>> +}
>> +
>> +ELF_GET_FIELD(hdr, e_entry, u64)
>> +ELF_GET_FIELD(hdr, e_phnum, u16)
>> +ELF_GET_FIELD(hdr, e_shnum, u16)
>> +ELF_GET_FIELD(hdr, e_phoff, u64)
>> +ELF_GET_FIELD(hdr, e_shoff, u64)
>> +ELF_GET_FIELD(hdr, e_shstrndx, u16)
>> +
>> +ELF_GET_FIELD(phdr, p_paddr, u64)
>> +ELF_GET_FIELD(phdr, p_filesz, u64)
>> +ELF_GET_FIELD(phdr, p_memsz, u64)
>> +ELF_GET_FIELD(phdr, p_type, u32)
>> +ELF_GET_FIELD(phdr, p_offset, u64)
>> +
>> +ELF_GET_FIELD(shdr, sh_size, u64)
>> +ELF_GET_FIELD(shdr, sh_offset, u64)
>> +ELF_GET_FIELD(shdr, sh_name, u32)
>> +ELF_GET_FIELD(shdr, sh_addr, u64)
>> +
>> +#define ELF_STRUCT_SIZE(__s) \
>> +static inline unsigned long elf_size_of_##__s(u8 class) \
>> +{ \
>> +	if (class == ELFCLASS32)\
>> +		return sizeof(struct elf32_##__s); \
>> +	else \
>> +		return sizeof(struct elf64_##__s); \
>> +}
>> +
>> +ELF_STRUCT_SIZE(shdr)
>> +ELF_STRUCT_SIZE(phdr)
>> +
>> +#endif /* REMOTEPROC_ELF_LOADER_H */
>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>> b/drivers/remoteproc/remoteproc_internal.h
>> index 004867061721..eeb26434220e 100644
>> --- a/drivers/remoteproc/remoteproc_internal.h
>> +++ b/drivers/remoteproc/remoteproc_internal.h
>> @@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
>>  int rproc_trigger_recovery(struct rproc *rproc);
>>  
>>  int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>> diff --git a/drivers/remoteproc/st_remoteproc.c
>> b/drivers/remoteproc/st_remoteproc.c
>> index ee13d23b43a9..a3268d95a50e 100644
>> --- a/drivers/remoteproc/st_remoteproc.c
>> +++ b/drivers/remoteproc/st_remoteproc.c
>> @@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
>>  		}
>>  	}
>>  
>> -	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
>> +	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
>>  
>>  	return 0;
>>  
>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>> index f84bd5fe0211..82cebca9344c 100644
>> --- a/include/linux/remoteproc.h
>> +++ b/include/linux/remoteproc.h
>> @@ -382,7 +382,7 @@ struct rproc_ops {
>>  				struct rproc *rproc, const struct firmware *fw);
>>  	int (*load)(struct rproc *rproc, const struct firmware *fw);
>>  	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
>> -	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>> +	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>>  };
>>  
>>  /**
>> @@ -498,7 +498,7 @@ struct rproc {
>>  	int num_traces;
>>  	struct list_head carveouts;
>>  	struct list_head mappings;
>> -	u32 bootaddr;
>> +	u64 bootaddr;
> 
> That will cause problems for rproc_coredump()[1] and fixing it properly
> likely means that a 32 or 64 elf should be generated based on the type of image
> that was loaded.  This is also true if ->p_vaddr and ->p_paddr (also in the same
> function) are to be handled properly.
> 
> I'm interested in your opinion on this.

Indeed, you are right !

I'm "afraid" I will have to fix that !
Most sane thing to do is to dump an elf with the input elf class.
I will make a V4 with a patch for that.

Thanks,

Clément

> 
> Thanks,
> Mathieu
> 
> [1].
> https://elixir.bootlin.com/linux/latest/source/drivers/remoteproc/remoteproc_core.c#L1600
> 
>>  	struct list_head rvdevs;
>>  	struct list_head subdevs;
>>  	struct idr notifyids;
>> --
>> 2.15.0.276.g89ea799

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-06  8:37       ` Clément Leger
@ 2020-02-06 15:05         ` Clément Leger
  2020-02-06 17:48           ` Mathieu Poirier
  0 siblings, 1 reply; 32+ messages in thread
From: Clément Leger @ 2020-02-06 15:05 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna

Hi Mathieu,

----- On 6 Feb, 2020, at 09:37, Clément Leger cleger@kalray.eu wrote:

> Hi Mathieu,
> 
> ----- On 5 Feb, 2020, at 23:49, Mathieu Poirier mathieu.poirier@linaro.org
> wrote:
> 
>> On Tue, Feb 04, 2020 at 06:44:12PM +0100, Clement Leger wrote:
>>> elf32 and elf64 mainly differ by their types. In order to avoid
>>> copy/pasting the whole loader code, generate static inline functions
>>> which will access values according to the elf class. It allows to keep a
>>> common loader basis.
>>> In order to accommodate both elf types sizes, the maximum size for a
>>> elf header member is chosen using the maximum value of both elf class.
>>> 
>>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>>> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
>>> ---
>>>  Documentation/remoteproc.txt               |   2 +-
>>>  drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
>>>  drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
>>>  drivers/remoteproc/remoteproc_internal.h   |   2 +-
>>>  drivers/remoteproc/st_remoteproc.c         |   2 +-
>>>  include/linux/remoteproc.h                 |   4 +-
>>>  6 files changed, 167 insertions(+), 59 deletions(-)
>>>  create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h
>>> 
>>> diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
>>> index 03c3d2e568b0..2be1147256e0 100644
>>> --- a/Documentation/remoteproc.txt
>>> +++ b/Documentation/remoteproc.txt
>>> @@ -230,7 +230,7 @@ in the used rings.
>>>  Binary Firmware Structure
>>>  =========================
>>>  
>>> -At this point remoteproc only supports ELF32 firmware binaries. However,
>>> +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
>>>  it is quite expected that other platforms/devices which we'd want to
>>>  support with this framework will be based on different binary formats.
>>>  
>>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c
>>> b/drivers/remoteproc/remoteproc_elf_loader.c
>>> index 606aae166eba..21fd2b2fe5ae 100644
>>> --- a/drivers/remoteproc/remoteproc_elf_loader.c
>>> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
>>> @@ -23,6 +23,7 @@
>>>  #include <linux/elf.h>
>>>  
>>>  #include "remoteproc_internal.h"
>>> +#include "remoteproc_elf_loader.h"
>>>  
>>>  /**
>>>   * rproc_elf_sanity_check() - Sanity Check ELF firmware image
>>> @@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>>> firmware *fw)
>>>  {
>>>  	const char *name = rproc->firmware;
>>>  	struct device *dev = &rproc->dev;
>>> +	/*
>>> +	 * Elf files are beginning with the same structure. Thus, to simplify
>>> +	 * header parsing, we can use the elf32_hdr one for both elf64 and
>>> +	 * elf32.
>>> +	 */
>>>  	struct elf32_hdr *ehdr;
>>> +	u32 elf_shdr_size;
>>> +	u64 phoff, shoff;
>>>  	char class;
>>> +	u16 phnum;
>>>  
>>>  	if (!fw) {
>>>  		dev_err(dev, "failed to load %s\n", name);
>>> @@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>>> firmware *fw)
>>>  
>>>  	ehdr = (struct elf32_hdr *)fw->data;
>>>  
>>> -	/* We only support ELF32 at this point */
>>> +	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
>>> +		dev_err(dev, "Image is corrupted (bad magic)\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>  	class = ehdr->e_ident[EI_CLASS];
>>> -	if (class != ELFCLASS32) {
>>> +	if (class != ELFCLASS32 && class != ELFCLASS64) {
>>>  		dev_err(dev, "Unsupported class: %d\n", class);
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> +	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
>>> +		dev_err(dev, "elf64 header is too small\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>>  	/* We assume the firmware has the same endianness as the host */
>>>  # ifdef __LITTLE_ENDIAN
>>>  	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
>>> @@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>>> firmware *fw)
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> -	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
>>> -		dev_err(dev, "Image is too small\n");
>>> -		return -EINVAL;
>>> -	}
>>> +	phoff = elf_hdr_e_phoff(class, fw->data);
>>> +	shoff = elf_hdr_e_shoff(class, fw->data);
>>> +	phnum =  elf_hdr_e_phnum(class, fw->data);
>>> +	elf_shdr_size = elf_size_of_shdr(class);
>>>  
>>> -	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
>>> -		dev_err(dev, "Image is corrupted (bad magic)\n");
>>> +	if (fw->size < shoff + elf_shdr_size) {
>>> +		dev_err(dev, "Image is too small\n");
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> -	if (ehdr->e_phnum == 0) {
>>> +	if (phnum == 0) {
>>>  		dev_err(dev, "No loadable segments\n");
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> -	if (ehdr->e_phoff > fw->size) {
>>> +	if (phoff > fw->size) {
>>>  		dev_err(dev, "Firmware size is too small\n");
>>>  		return -EINVAL;
>>>  	}
>>>  
>>> +	dev_dbg(dev, "Firmware is an elf%d file\n",
>>> +		class == ELFCLASS32 ? 32 : 64);
>>> +
>>>  	return 0;
>>>  }
>>>  EXPORT_SYMBOL(rproc_elf_sanity_check);
>>> @@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
>>>   * Note that the boot address is not a configurable property of all remote
>>>   * processors. Some will always boot at a specific hard-coded address.
>>>   */
>>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>>>  {
>>> -	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
>>> -
>>> -	return ehdr->e_entry;
>>> +	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
>>>  }
>>>  EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>>>  
>>> @@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>>>  {
>>>  	struct device *dev = &rproc->dev;
>>> -	struct elf32_hdr *ehdr;
>>> -	struct elf32_phdr *phdr;
>>> +	const void *ehdr, *phdr;
>>>  	int i, ret = 0;
>>> +	u16 phnum;
>>>  	const u8 *elf_data = fw->data;
>>> +	u8 class = fw_elf_get_class(fw);
>>> +	u32 elf_phdr_size = elf_size_of_phdr(class);
>>>  
>>> -	ehdr = (struct elf32_hdr *)elf_data;
>>> -	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
>>> +	ehdr = elf_data;
>>> +	phnum = elf_hdr_e_phnum(class, ehdr);
>>> +	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
>>>  
>>>  	/* go through the available ELF segments */
>>> -	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
>>> -		u32 da = phdr->p_paddr;
>>> -		u32 memsz = phdr->p_memsz;
>>> -		u32 filesz = phdr->p_filesz;
>>> -		u32 offset = phdr->p_offset;
>>> +	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
>>> +		u64 da = elf_phdr_p_paddr(class, phdr);
>>> +		u64 memsz = elf_phdr_p_memsz(class, phdr);
>>> +		u64 filesz = elf_phdr_p_filesz(class, phdr);
>>> +		u64 offset = elf_phdr_p_offset(class, phdr);
>>> +		u32 type = elf_phdr_p_type(class, phdr);
>>>  		void *ptr;
>>>  
>>> -		if (phdr->p_type != PT_LOAD)
>>> +		if (type != PT_LOAD)
>>>  			continue;
>>>  
>>> -		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
>>> -			phdr->p_type, da, memsz, filesz);
>>> +		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
>>> +			type, da, memsz, filesz);
>>>  
>>>  		if (filesz > memsz) {
>>> -			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
>>> +			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
>>>  				filesz, memsz);
>>>  			ret = -EINVAL;
>>>  			break;
>>>  		}
>>>  
>>>  		if (offset + filesz > fw->size) {
>>> -			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
>>> +			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
>>>  				offset + filesz, fw->size);
>>>  			ret = -EINVAL;
>>>  			break;
>>> @@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const
>>> struct firmware *fw)
>>>  		/* grab the kernel address for this device address */
>>>  		ptr = rproc_da_to_va(rproc, da, memsz);
>>>  		if (!ptr) {
>>> -			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
>>> +			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
>>> +				memsz);
>>>  			ret = -EINVAL;
>>>  			break;
>>>  		}
>>>  
>>>  		/* put the segment where the remote processor expects it */
>>> -		if (phdr->p_filesz)
>>> -			memcpy(ptr, elf_data + phdr->p_offset, filesz);
>>> +		if (filesz)
>>> +			memcpy(ptr, elf_data + offset, filesz);
>>>  
>>>  		/*
>>>  		 * Zero out remaining memory for this segment.
>>> @@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const
>>> struct firmware *fw)
>>>  }
>>>  EXPORT_SYMBOL(rproc_elf_load_segments);
>>>  
>>> -static struct elf32_shdr *
>>> -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
>>> +static const void *
>>> +find_table(struct device *dev, const struct firmware *fw)
>>>  {
>>> -	struct elf32_shdr *shdr;
>>> +	const void *shdr, *name_table_shdr;
>>>  	int i;
>>>  	const char *name_table;
>>>  	struct resource_table *table = NULL;
>>> -	const u8 *elf_data = (void *)ehdr;
>>> +	const u8 *elf_data = (void *)fw->data;
>>> +	u8 class = fw_elf_get_class(fw);
>>> +	size_t fw_size = fw->size;
>>> +	const void *ehdr = elf_data;
>>> +	u16 shnum = elf_hdr_e_shnum(class, ehdr);
>>> +	u32 elf_shdr_size = elf_size_of_shdr(class);
>>> +	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
>>>  
>>>  	/* look for the resource table and handle it */
>>> -	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
>>> -	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
>>> -
>>> -	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
>>> -		u32 size = shdr->sh_size;
>>> -		u32 offset = shdr->sh_offset;
>>> -
>>> -		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
>>> +	/* First, get the section header according to the elf class */
>>> +	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
>>> +	/* Compute name table section header entry in shdr array */
>>> +	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
>>> +	/* Finally, compute the name table section address in elf */
>>> +	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
>>> +
>>> +	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
>>> +		u64 size = elf_shdr_sh_size(class, shdr);
>>> +		u64 offset = elf_shdr_sh_offset(class, shdr);
>>> +		u32 name = elf_shdr_sh_name(class, shdr);
>>> +
>>> +		if (strcmp(name_table + name, ".resource_table"))
>>>  			continue;
>>>  
>>>  		table = (struct resource_table *)(elf_data + offset);
>>> @@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr,
>>> size_t fw_size)
>>>   */
>>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
>>>  {
>>> -	struct elf32_hdr *ehdr;
>>> -	struct elf32_shdr *shdr;
>>> +	const void *shdr;
>>>  	struct device *dev = &rproc->dev;
>>>  	struct resource_table *table = NULL;
>>>  	const u8 *elf_data = fw->data;
>>>  	size_t tablesz;
>>> +	u8 class = fw_elf_get_class(fw);
>>> +	u64 sh_offset;
>>>  
>>> -	ehdr = (struct elf32_hdr *)elf_data;
>>> -
>>> -	shdr = find_table(dev, ehdr, fw->size);
>>> +	shdr = find_table(dev, fw);
>>>  	if (!shdr)
>>>  		return -EINVAL;
>>>  
>>> -	table = (struct resource_table *)(elf_data + shdr->sh_offset);
>>> -	tablesz = shdr->sh_size;
>>> +	sh_offset = elf_shdr_sh_offset(class, shdr);
>>> +	table = (struct resource_table *)(elf_data + sh_offset);
>>> +	tablesz = elf_shdr_sh_size(class, shdr);
>>>  
>>>  	/*
>>>  	 * Create a copy of the resource table. When a virtio device starts
>>> @@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
>>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>>>  						       const struct firmware *fw)
>>>  {
>>> -	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
>>> -	struct elf32_shdr *shdr;
>>> +	const void *shdr;
>>> +	u64 sh_addr, sh_size;
>>> +	u8 class = fw_elf_get_class(fw);
>>>  
>>> -	shdr = find_table(&rproc->dev, ehdr, fw->size);
>>> +	shdr = find_table(&rproc->dev, fw);
>>>  	if (!shdr)
>>>  		return NULL;
>>>  
>>> -	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
>>> +	sh_addr = elf_shdr_sh_addr(class, shdr);
>>> +	sh_size = elf_shdr_sh_size(class, shdr);
>>> +
>>> +	return rproc_da_to_va(rproc, sh_addr, sh_size);
>>>  }
>>>  EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
>>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.h
>>> b/drivers/remoteproc/remoteproc_elf_loader.h
>>> new file mode 100644
>>> index 000000000000..fac3565734f9
>>> --- /dev/null
>>> +++ b/drivers/remoteproc/remoteproc_elf_loader.h
>>> @@ -0,0 +1,69 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/*
>>> + * Remote processor elf loader defines
>>> + *
>>> + * Copyright (C) 2019 Kalray, Inc.
>>> + */
>>> +
>>> +#ifndef REMOTEPROC_ELF_LOADER_H
>>> +#define REMOTEPROC_ELF_LOADER_H
>>> +
>>> +#include <linux/elf.h>
>>> +#include <linux/types.h>
>>> +
>>> +/**
>>> + * fw_elf_get_class - Get elf class
>>> + * @fw: the ELF firmware image
>>> + *
>>> + * Note that we use and elf32_hdr to access the class since the start of the
>>> + * struct is the same for both elf class
>>> + *
>>> + * Return: elf class of the firmware
>>> + */
>>> +static inline u8 fw_elf_get_class(const struct firmware *fw)
>>> +{
>>> +	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
>>> +
>>> +	return ehdr->e_ident[EI_CLASS];
>>> +}
>>> +
>>> +#define ELF_GET_FIELD(__s, __field, __type) \
>>> +static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
>>> +{ \
>>> +	if (class == ELFCLASS32) \
>>> +		return (__type) ((const struct elf32_##__s *) arg)->__field; \
>>> +	else \
>>> +		return (__type) ((const struct elf64_##__s *) arg)->__field; \
>>> +}
>>> +
>>> +ELF_GET_FIELD(hdr, e_entry, u64)
>>> +ELF_GET_FIELD(hdr, e_phnum, u16)
>>> +ELF_GET_FIELD(hdr, e_shnum, u16)
>>> +ELF_GET_FIELD(hdr, e_phoff, u64)
>>> +ELF_GET_FIELD(hdr, e_shoff, u64)
>>> +ELF_GET_FIELD(hdr, e_shstrndx, u16)
>>> +
>>> +ELF_GET_FIELD(phdr, p_paddr, u64)
>>> +ELF_GET_FIELD(phdr, p_filesz, u64)
>>> +ELF_GET_FIELD(phdr, p_memsz, u64)
>>> +ELF_GET_FIELD(phdr, p_type, u32)
>>> +ELF_GET_FIELD(phdr, p_offset, u64)
>>> +
>>> +ELF_GET_FIELD(shdr, sh_size, u64)
>>> +ELF_GET_FIELD(shdr, sh_offset, u64)
>>> +ELF_GET_FIELD(shdr, sh_name, u32)
>>> +ELF_GET_FIELD(shdr, sh_addr, u64)
>>> +
>>> +#define ELF_STRUCT_SIZE(__s) \
>>> +static inline unsigned long elf_size_of_##__s(u8 class) \
>>> +{ \
>>> +	if (class == ELFCLASS32)\
>>> +		return sizeof(struct elf32_##__s); \
>>> +	else \
>>> +		return sizeof(struct elf64_##__s); \
>>> +}
>>> +
>>> +ELF_STRUCT_SIZE(shdr)
>>> +ELF_STRUCT_SIZE(phdr)
>>> +
>>> +#endif /* REMOTEPROC_ELF_LOADER_H */
>>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>>> b/drivers/remoteproc/remoteproc_internal.h
>>> index 004867061721..eeb26434220e 100644
>>> --- a/drivers/remoteproc/remoteproc_internal.h
>>> +++ b/drivers/remoteproc/remoteproc_internal.h
>>> @@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
>>>  int rproc_trigger_recovery(struct rproc *rproc);
>>>  
>>>  int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
>>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
>>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
>>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>>> diff --git a/drivers/remoteproc/st_remoteproc.c
>>> b/drivers/remoteproc/st_remoteproc.c
>>> index ee13d23b43a9..a3268d95a50e 100644
>>> --- a/drivers/remoteproc/st_remoteproc.c
>>> +++ b/drivers/remoteproc/st_remoteproc.c
>>> @@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
>>>  		}
>>>  	}
>>>  
>>> -	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
>>> +	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
>>>  
>>>  	return 0;
>>>  
>>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>>> index f84bd5fe0211..82cebca9344c 100644
>>> --- a/include/linux/remoteproc.h
>>> +++ b/include/linux/remoteproc.h
>>> @@ -382,7 +382,7 @@ struct rproc_ops {
>>>  				struct rproc *rproc, const struct firmware *fw);
>>>  	int (*load)(struct rproc *rproc, const struct firmware *fw);
>>>  	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
>>> -	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>>> +	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>>>  };
>>>  
>>>  /**
>>> @@ -498,7 +498,7 @@ struct rproc {
>>>  	int num_traces;
>>>  	struct list_head carveouts;
>>>  	struct list_head mappings;
>>> -	u32 bootaddr;
>>> +	u64 bootaddr;
>> 
>> That will cause problems for rproc_coredump()[1] and fixing it properly
>> likely means that a 32 or 64 elf should be generated based on the type of image
>> that was loaded.  This is also true if ->p_vaddr and ->p_paddr (also in the same
>> function) are to be handled properly.
>> 
>> I'm interested in your opinion on this.
> 
> Indeed, you are right !
> 
> I'm "afraid" I will have to fix that !
> Most sane thing to do is to dump an elf with the input elf class.
> I will make a V4 with a patch for that.
> 

Actually, this does not seems directly related to elf loading.
The coredump mecanism dumps segment that have been registered
using rproc_coredump_add_*_segment and this is not done directly
by the elf loader.
I'm not 100% sure but the coredump elf format is not tied to
any machine (EM_NONE) and as a special type (ET_CORE) so the elf
type is probably not relevant adn elf64 would be generic.
If some coredump user could speak for that part, that would be
nice !

If needed, then we could add a rproc_coredump_set_format() function
to specify various parameters (machine, elf type, lsb/msb, etc).

Let me know what you think about it.

Clément

> Thanks,
> 
> Clément
> 
>> 
>> Thanks,
>> Mathieu
>> 
>> [1].
>> https://elixir.bootlin.com/linux/latest/source/drivers/remoteproc/remoteproc_core.c#L1600
>> 
>>>  	struct list_head rvdevs;
>>>  	struct list_head subdevs;
>>>  	struct idr notifyids;
>>> --
> >> 2.15.0.276.g89ea799

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-06 15:05         ` Clément Leger
@ 2020-02-06 17:48           ` Mathieu Poirier
  2020-02-07  7:57             ` Clément Leger
  0 siblings, 1 reply; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-06 17:48 UTC (permalink / raw)
  To: Clément Leger
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna

On Thu, Feb 06, 2020 at 04:05:44PM +0100, Clément Leger wrote:
> Hi Mathieu,
> 
> ----- On 6 Feb, 2020, at 09:37, Clément Leger cleger@kalray.eu wrote:
> 
> > Hi Mathieu,
> > 
> > ----- On 5 Feb, 2020, at 23:49, Mathieu Poirier mathieu.poirier@linaro.org
> > wrote:
> > 
> >> On Tue, Feb 04, 2020 at 06:44:12PM +0100, Clement Leger wrote:
> >>> elf32 and elf64 mainly differ by their types. In order to avoid
> >>> copy/pasting the whole loader code, generate static inline functions
> >>> which will access values according to the elf class. It allows to keep a
> >>> common loader basis.
> >>> In order to accommodate both elf types sizes, the maximum size for a
> >>> elf header member is chosen using the maximum value of both elf class.
> >>> 
> >>> Signed-off-by: Clement Leger <cleger@kalray.eu>
> >>> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
> >>> ---
> >>>  Documentation/remoteproc.txt               |   2 +-
> >>>  drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
> >>>  drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
> >>>  drivers/remoteproc/remoteproc_internal.h   |   2 +-
> >>>  drivers/remoteproc/st_remoteproc.c         |   2 +-
> >>>  include/linux/remoteproc.h                 |   4 +-
> >>>  6 files changed, 167 insertions(+), 59 deletions(-)
> >>>  create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h
> >>> 
> >>> diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
> >>> index 03c3d2e568b0..2be1147256e0 100644
> >>> --- a/Documentation/remoteproc.txt
> >>> +++ b/Documentation/remoteproc.txt
> >>> @@ -230,7 +230,7 @@ in the used rings.
> >>>  Binary Firmware Structure
> >>>  =========================
> >>>  
> >>> -At this point remoteproc only supports ELF32 firmware binaries. However,
> >>> +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
> >>>  it is quite expected that other platforms/devices which we'd want to
> >>>  support with this framework will be based on different binary formats.
> >>>  
> >>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c
> >>> b/drivers/remoteproc/remoteproc_elf_loader.c
> >>> index 606aae166eba..21fd2b2fe5ae 100644
> >>> --- a/drivers/remoteproc/remoteproc_elf_loader.c
> >>> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
> >>> @@ -23,6 +23,7 @@
> >>>  #include <linux/elf.h>
> >>>  
> >>>  #include "remoteproc_internal.h"
> >>> +#include "remoteproc_elf_loader.h"
> >>>  
> >>>  /**
> >>>   * rproc_elf_sanity_check() - Sanity Check ELF firmware image
> >>> @@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
> >>> firmware *fw)
> >>>  {
> >>>  	const char *name = rproc->firmware;
> >>>  	struct device *dev = &rproc->dev;
> >>> +	/*
> >>> +	 * Elf files are beginning with the same structure. Thus, to simplify
> >>> +	 * header parsing, we can use the elf32_hdr one for both elf64 and
> >>> +	 * elf32.
> >>> +	 */
> >>>  	struct elf32_hdr *ehdr;
> >>> +	u32 elf_shdr_size;
> >>> +	u64 phoff, shoff;
> >>>  	char class;
> >>> +	u16 phnum;
> >>>  
> >>>  	if (!fw) {
> >>>  		dev_err(dev, "failed to load %s\n", name);
> >>> @@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
> >>> firmware *fw)
> >>>  
> >>>  	ehdr = (struct elf32_hdr *)fw->data;
> >>>  
> >>> -	/* We only support ELF32 at this point */
> >>> +	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
> >>> +		dev_err(dev, "Image is corrupted (bad magic)\n");
> >>> +		return -EINVAL;
> >>> +	}
> >>> +
> >>>  	class = ehdr->e_ident[EI_CLASS];
> >>> -	if (class != ELFCLASS32) {
> >>> +	if (class != ELFCLASS32 && class != ELFCLASS64) {
> >>>  		dev_err(dev, "Unsupported class: %d\n", class);
> >>>  		return -EINVAL;
> >>>  	}
> >>>  
> >>> +	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
> >>> +		dev_err(dev, "elf64 header is too small\n");
> >>> +		return -EINVAL;
> >>> +	}
> >>> +
> >>>  	/* We assume the firmware has the same endianness as the host */
> >>>  # ifdef __LITTLE_ENDIAN
> >>>  	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
> >>> @@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
> >>> firmware *fw)
> >>>  		return -EINVAL;
> >>>  	}
> >>>  
> >>> -	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
> >>> -		dev_err(dev, "Image is too small\n");
> >>> -		return -EINVAL;
> >>> -	}
> >>> +	phoff = elf_hdr_e_phoff(class, fw->data);
> >>> +	shoff = elf_hdr_e_shoff(class, fw->data);
> >>> +	phnum =  elf_hdr_e_phnum(class, fw->data);
> >>> +	elf_shdr_size = elf_size_of_shdr(class);
> >>>  
> >>> -	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
> >>> -		dev_err(dev, "Image is corrupted (bad magic)\n");
> >>> +	if (fw->size < shoff + elf_shdr_size) {
> >>> +		dev_err(dev, "Image is too small\n");
> >>>  		return -EINVAL;
> >>>  	}
> >>>  
> >>> -	if (ehdr->e_phnum == 0) {
> >>> +	if (phnum == 0) {
> >>>  		dev_err(dev, "No loadable segments\n");
> >>>  		return -EINVAL;
> >>>  	}
> >>>  
> >>> -	if (ehdr->e_phoff > fw->size) {
> >>> +	if (phoff > fw->size) {
> >>>  		dev_err(dev, "Firmware size is too small\n");
> >>>  		return -EINVAL;
> >>>  	}
> >>>  
> >>> +	dev_dbg(dev, "Firmware is an elf%d file\n",
> >>> +		class == ELFCLASS32 ? 32 : 64);
> >>> +
> >>>  	return 0;
> >>>  }
> >>>  EXPORT_SYMBOL(rproc_elf_sanity_check);
> >>> @@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
> >>>   * Note that the boot address is not a configurable property of all remote
> >>>   * processors. Some will always boot at a specific hard-coded address.
> >>>   */
> >>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
> >>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
> >>>  {
> >>> -	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
> >>> -
> >>> -	return ehdr->e_entry;
> >>> +	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
> >>>  }
> >>>  EXPORT_SYMBOL(rproc_elf_get_boot_addr);
> >>>  
> >>> @@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
> >>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
> >>>  {
> >>>  	struct device *dev = &rproc->dev;
> >>> -	struct elf32_hdr *ehdr;
> >>> -	struct elf32_phdr *phdr;
> >>> +	const void *ehdr, *phdr;
> >>>  	int i, ret = 0;
> >>> +	u16 phnum;
> >>>  	const u8 *elf_data = fw->data;
> >>> +	u8 class = fw_elf_get_class(fw);
> >>> +	u32 elf_phdr_size = elf_size_of_phdr(class);
> >>>  
> >>> -	ehdr = (struct elf32_hdr *)elf_data;
> >>> -	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
> >>> +	ehdr = elf_data;
> >>> +	phnum = elf_hdr_e_phnum(class, ehdr);
> >>> +	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
> >>>  
> >>>  	/* go through the available ELF segments */
> >>> -	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
> >>> -		u32 da = phdr->p_paddr;
> >>> -		u32 memsz = phdr->p_memsz;
> >>> -		u32 filesz = phdr->p_filesz;
> >>> -		u32 offset = phdr->p_offset;
> >>> +	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
> >>> +		u64 da = elf_phdr_p_paddr(class, phdr);
> >>> +		u64 memsz = elf_phdr_p_memsz(class, phdr);
> >>> +		u64 filesz = elf_phdr_p_filesz(class, phdr);
> >>> +		u64 offset = elf_phdr_p_offset(class, phdr);
> >>> +		u32 type = elf_phdr_p_type(class, phdr);
> >>>  		void *ptr;
> >>>  
> >>> -		if (phdr->p_type != PT_LOAD)
> >>> +		if (type != PT_LOAD)
> >>>  			continue;
> >>>  
> >>> -		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
> >>> -			phdr->p_type, da, memsz, filesz);
> >>> +		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
> >>> +			type, da, memsz, filesz);
> >>>  
> >>>  		if (filesz > memsz) {
> >>> -			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
> >>> +			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
> >>>  				filesz, memsz);
> >>>  			ret = -EINVAL;
> >>>  			break;
> >>>  		}
> >>>  
> >>>  		if (offset + filesz > fw->size) {
> >>> -			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
> >>> +			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
> >>>  				offset + filesz, fw->size);
> >>>  			ret = -EINVAL;
> >>>  			break;
> >>> @@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const
> >>> struct firmware *fw)
> >>>  		/* grab the kernel address for this device address */
> >>>  		ptr = rproc_da_to_va(rproc, da, memsz);
> >>>  		if (!ptr) {
> >>> -			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
> >>> +			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
> >>> +				memsz);
> >>>  			ret = -EINVAL;
> >>>  			break;
> >>>  		}
> >>>  
> >>>  		/* put the segment where the remote processor expects it */
> >>> -		if (phdr->p_filesz)
> >>> -			memcpy(ptr, elf_data + phdr->p_offset, filesz);
> >>> +		if (filesz)
> >>> +			memcpy(ptr, elf_data + offset, filesz);
> >>>  
> >>>  		/*
> >>>  		 * Zero out remaining memory for this segment.
> >>> @@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const
> >>> struct firmware *fw)
> >>>  }
> >>>  EXPORT_SYMBOL(rproc_elf_load_segments);
> >>>  
> >>> -static struct elf32_shdr *
> >>> -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
> >>> +static const void *
> >>> +find_table(struct device *dev, const struct firmware *fw)
> >>>  {
> >>> -	struct elf32_shdr *shdr;
> >>> +	const void *shdr, *name_table_shdr;
> >>>  	int i;
> >>>  	const char *name_table;
> >>>  	struct resource_table *table = NULL;
> >>> -	const u8 *elf_data = (void *)ehdr;
> >>> +	const u8 *elf_data = (void *)fw->data;
> >>> +	u8 class = fw_elf_get_class(fw);
> >>> +	size_t fw_size = fw->size;
> >>> +	const void *ehdr = elf_data;
> >>> +	u16 shnum = elf_hdr_e_shnum(class, ehdr);
> >>> +	u32 elf_shdr_size = elf_size_of_shdr(class);
> >>> +	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
> >>>  
> >>>  	/* look for the resource table and handle it */
> >>> -	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
> >>> -	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
> >>> -
> >>> -	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
> >>> -		u32 size = shdr->sh_size;
> >>> -		u32 offset = shdr->sh_offset;
> >>> -
> >>> -		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
> >>> +	/* First, get the section header according to the elf class */
> >>> +	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
> >>> +	/* Compute name table section header entry in shdr array */
> >>> +	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
> >>> +	/* Finally, compute the name table section address in elf */
> >>> +	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
> >>> +
> >>> +	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
> >>> +		u64 size = elf_shdr_sh_size(class, shdr);
> >>> +		u64 offset = elf_shdr_sh_offset(class, shdr);
> >>> +		u32 name = elf_shdr_sh_name(class, shdr);
> >>> +
> >>> +		if (strcmp(name_table + name, ".resource_table"))
> >>>  			continue;
> >>>  
> >>>  		table = (struct resource_table *)(elf_data + offset);
> >>> @@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr,
> >>> size_t fw_size)
> >>>   */
> >>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
> >>>  {
> >>> -	struct elf32_hdr *ehdr;
> >>> -	struct elf32_shdr *shdr;
> >>> +	const void *shdr;
> >>>  	struct device *dev = &rproc->dev;
> >>>  	struct resource_table *table = NULL;
> >>>  	const u8 *elf_data = fw->data;
> >>>  	size_t tablesz;
> >>> +	u8 class = fw_elf_get_class(fw);
> >>> +	u64 sh_offset;
> >>>  
> >>> -	ehdr = (struct elf32_hdr *)elf_data;
> >>> -
> >>> -	shdr = find_table(dev, ehdr, fw->size);
> >>> +	shdr = find_table(dev, fw);
> >>>  	if (!shdr)
> >>>  		return -EINVAL;
> >>>  
> >>> -	table = (struct resource_table *)(elf_data + shdr->sh_offset);
> >>> -	tablesz = shdr->sh_size;
> >>> +	sh_offset = elf_shdr_sh_offset(class, shdr);
> >>> +	table = (struct resource_table *)(elf_data + sh_offset);
> >>> +	tablesz = elf_shdr_sh_size(class, shdr);
> >>>  
> >>>  	/*
> >>>  	 * Create a copy of the resource table. When a virtio device starts
> >>> @@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
> >>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
> >>>  						       const struct firmware *fw)
> >>>  {
> >>> -	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
> >>> -	struct elf32_shdr *shdr;
> >>> +	const void *shdr;
> >>> +	u64 sh_addr, sh_size;
> >>> +	u8 class = fw_elf_get_class(fw);
> >>>  
> >>> -	shdr = find_table(&rproc->dev, ehdr, fw->size);
> >>> +	shdr = find_table(&rproc->dev, fw);
> >>>  	if (!shdr)
> >>>  		return NULL;
> >>>  
> >>> -	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
> >>> +	sh_addr = elf_shdr_sh_addr(class, shdr);
> >>> +	sh_size = elf_shdr_sh_size(class, shdr);
> >>> +
> >>> +	return rproc_da_to_va(rproc, sh_addr, sh_size);
> >>>  }
> >>>  EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
> >>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.h
> >>> b/drivers/remoteproc/remoteproc_elf_loader.h
> >>> new file mode 100644
> >>> index 000000000000..fac3565734f9
> >>> --- /dev/null
> >>> +++ b/drivers/remoteproc/remoteproc_elf_loader.h
> >>> @@ -0,0 +1,69 @@
> >>> +/* SPDX-License-Identifier: GPL-2.0 */
> >>> +/*
> >>> + * Remote processor elf loader defines
> >>> + *
> >>> + * Copyright (C) 2019 Kalray, Inc.
> >>> + */
> >>> +
> >>> +#ifndef REMOTEPROC_ELF_LOADER_H
> >>> +#define REMOTEPROC_ELF_LOADER_H
> >>> +
> >>> +#include <linux/elf.h>
> >>> +#include <linux/types.h>
> >>> +
> >>> +/**
> >>> + * fw_elf_get_class - Get elf class
> >>> + * @fw: the ELF firmware image
> >>> + *
> >>> + * Note that we use and elf32_hdr to access the class since the start of the
> >>> + * struct is the same for both elf class
> >>> + *
> >>> + * Return: elf class of the firmware
> >>> + */
> >>> +static inline u8 fw_elf_get_class(const struct firmware *fw)
> >>> +{
> >>> +	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
> >>> +
> >>> +	return ehdr->e_ident[EI_CLASS];
> >>> +}
> >>> +
> >>> +#define ELF_GET_FIELD(__s, __field, __type) \
> >>> +static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
> >>> +{ \
> >>> +	if (class == ELFCLASS32) \
> >>> +		return (__type) ((const struct elf32_##__s *) arg)->__field; \
> >>> +	else \
> >>> +		return (__type) ((const struct elf64_##__s *) arg)->__field; \
> >>> +}
> >>> +
> >>> +ELF_GET_FIELD(hdr, e_entry, u64)
> >>> +ELF_GET_FIELD(hdr, e_phnum, u16)
> >>> +ELF_GET_FIELD(hdr, e_shnum, u16)
> >>> +ELF_GET_FIELD(hdr, e_phoff, u64)
> >>> +ELF_GET_FIELD(hdr, e_shoff, u64)
> >>> +ELF_GET_FIELD(hdr, e_shstrndx, u16)
> >>> +
> >>> +ELF_GET_FIELD(phdr, p_paddr, u64)
> >>> +ELF_GET_FIELD(phdr, p_filesz, u64)
> >>> +ELF_GET_FIELD(phdr, p_memsz, u64)
> >>> +ELF_GET_FIELD(phdr, p_type, u32)
> >>> +ELF_GET_FIELD(phdr, p_offset, u64)
> >>> +
> >>> +ELF_GET_FIELD(shdr, sh_size, u64)
> >>> +ELF_GET_FIELD(shdr, sh_offset, u64)
> >>> +ELF_GET_FIELD(shdr, sh_name, u32)
> >>> +ELF_GET_FIELD(shdr, sh_addr, u64)
> >>> +
> >>> +#define ELF_STRUCT_SIZE(__s) \
> >>> +static inline unsigned long elf_size_of_##__s(u8 class) \
> >>> +{ \
> >>> +	if (class == ELFCLASS32)\
> >>> +		return sizeof(struct elf32_##__s); \
> >>> +	else \
> >>> +		return sizeof(struct elf64_##__s); \
> >>> +}
> >>> +
> >>> +ELF_STRUCT_SIZE(shdr)
> >>> +ELF_STRUCT_SIZE(phdr)
> >>> +
> >>> +#endif /* REMOTEPROC_ELF_LOADER_H */
> >>> diff --git a/drivers/remoteproc/remoteproc_internal.h
> >>> b/drivers/remoteproc/remoteproc_internal.h
> >>> index 004867061721..eeb26434220e 100644
> >>> --- a/drivers/remoteproc/remoteproc_internal.h
> >>> +++ b/drivers/remoteproc/remoteproc_internal.h
> >>> @@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
> >>>  int rproc_trigger_recovery(struct rproc *rproc);
> >>>  
> >>>  int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
> >>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
> >>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
> >>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
> >>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
> >>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
> >>> diff --git a/drivers/remoteproc/st_remoteproc.c
> >>> b/drivers/remoteproc/st_remoteproc.c
> >>> index ee13d23b43a9..a3268d95a50e 100644
> >>> --- a/drivers/remoteproc/st_remoteproc.c
> >>> +++ b/drivers/remoteproc/st_remoteproc.c
> >>> @@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
> >>>  		}
> >>>  	}
> >>>  
> >>> -	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
> >>> +	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
> >>>  
> >>>  	return 0;
> >>>  
> >>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> >>> index f84bd5fe0211..82cebca9344c 100644
> >>> --- a/include/linux/remoteproc.h
> >>> +++ b/include/linux/remoteproc.h
> >>> @@ -382,7 +382,7 @@ struct rproc_ops {
> >>>  				struct rproc *rproc, const struct firmware *fw);
> >>>  	int (*load)(struct rproc *rproc, const struct firmware *fw);
> >>>  	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
> >>> -	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
> >>> +	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
> >>>  };
> >>>  
> >>>  /**
> >>> @@ -498,7 +498,7 @@ struct rproc {
> >>>  	int num_traces;
> >>>  	struct list_head carveouts;
> >>>  	struct list_head mappings;
> >>> -	u32 bootaddr;
> >>> +	u64 bootaddr;
> >> 
> >> That will cause problems for rproc_coredump()[1] and fixing it properly
> >> likely means that a 32 or 64 elf should be generated based on the type of image
> >> that was loaded.  This is also true if ->p_vaddr and ->p_paddr (also in the same
> >> function) are to be handled properly.
> >> 
> >> I'm interested in your opinion on this.
> > 
> > Indeed, you are right !
> > 
> > I'm "afraid" I will have to fix that !
> > Most sane thing to do is to dump an elf with the input elf class.
> > I will make a V4 with a patch for that.
> > 
> 
> Actually, this does not seems directly related to elf loading.
> The coredump mecanism dumps segment that have been registered
> using rproc_coredump_add_*_segment and this is not done directly
> by the elf loader.

Correct, but it is fair to assume rpoc_coredump_add_*_segment() is called for
the image that will run on the MCU (otherwiser doing so would be pointless).

> I'm not 100% sure but the coredump elf format is not tied to
> any machine (EM_NONE) and as a special type (ET_CORE) so the elf
> type is probably not relevant adn elf64 would be generic.
 
That is true, we could generate an elf64 core dump for both 32 and 64 bit MCU
image and be done with it.  But that is almost guaranteed to break some user
space that isn't tailored to deal with an elf64.

> If some coredump user could speak for that part, that would be
> nice !
> 
> If needed, then we could add a rproc_coredump_set_format() function
> to specify various parameters (machine, elf type, lsb/msb, etc).
> 

For this specific patchset I don't think you need to cover cases where this much
flexibility is needed (up to now it hasn't been a requiment).

Keeping track of the type of image being loaded in something like
rproc::elfclass and use that information to generate the right elf core in
rproc_coredump() is probably sufficient for the time being.

> Let me know what you think about it.
> 
> Clément
> 
> > Thanks,
> > 
> > Clément
> > 
> >> 
> >> Thanks,
> >> Mathieu
> >> 
> >> [1].
> >> https://elixir.bootlin.com/linux/latest/source/drivers/remoteproc/remoteproc_core.c#L1600
> >> 
> >>>  	struct list_head rvdevs;
> >>>  	struct list_head subdevs;
> >>>  	struct idr notifyids;
> >>> --
> > >> 2.15.0.276.g89ea799

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader
  2020-02-06 17:48           ` Mathieu Poirier
@ 2020-02-07  7:57             ` Clément Leger
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
  0 siblings, 1 reply; 32+ messages in thread
From: Clément Leger @ 2020-02-07  7:57 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna



----- On 6 Feb, 2020, at 18:48, Mathieu Poirier mathieu.poirier@linaro.org wrote:

> On Thu, Feb 06, 2020 at 04:05:44PM +0100, Clément Leger wrote:
>> Hi Mathieu,
>> 
>> ----- On 6 Feb, 2020, at 09:37, Clément Leger cleger@kalray.eu wrote:
>> 
>> > Hi Mathieu,
>> > 
>> > ----- On 5 Feb, 2020, at 23:49, Mathieu Poirier mathieu.poirier@linaro.org
>> > wrote:
>> > 
>> >> On Tue, Feb 04, 2020 at 06:44:12PM +0100, Clement Leger wrote:
>> >>> elf32 and elf64 mainly differ by their types. In order to avoid
>> >>> copy/pasting the whole loader code, generate static inline functions
>> >>> which will access values according to the elf class. It allows to keep a
>> >>> common loader basis.
>> >>> In order to accommodate both elf types sizes, the maximum size for a
>> >>> elf header member is chosen using the maximum value of both elf class.
>> >>> 
>> >>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>> >>> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
>> >>> ---
>> >>>  Documentation/remoteproc.txt               |   2 +-
>> >>>  drivers/remoteproc/remoteproc_elf_loader.c | 147 ++++++++++++++++++-----------
>> >>>  drivers/remoteproc/remoteproc_elf_loader.h |  69 ++++++++++++++
>> >>>  drivers/remoteproc/remoteproc_internal.h   |   2 +-
>> >>>  drivers/remoteproc/st_remoteproc.c         |   2 +-
>> >>>  include/linux/remoteproc.h                 |   4 +-
>> >>>  6 files changed, 167 insertions(+), 59 deletions(-)
>> >>>  create mode 100644 drivers/remoteproc/remoteproc_elf_loader.h
>> >>> 
>> >>> diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
>> >>> index 03c3d2e568b0..2be1147256e0 100644
>> >>> --- a/Documentation/remoteproc.txt
>> >>> +++ b/Documentation/remoteproc.txt
>> >>> @@ -230,7 +230,7 @@ in the used rings.
>> >>>  Binary Firmware Structure
>> >>>  =========================
>> >>>  
>> >>> -At this point remoteproc only supports ELF32 firmware binaries. However,
>> >>> +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
>> >>>  it is quite expected that other platforms/devices which we'd want to
>> >>>  support with this framework will be based on different binary formats.
>> >>>  
>> >>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c
>> >>> b/drivers/remoteproc/remoteproc_elf_loader.c
>> >>> index 606aae166eba..21fd2b2fe5ae 100644
>> >>> --- a/drivers/remoteproc/remoteproc_elf_loader.c
>> >>> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
>> >>> @@ -23,6 +23,7 @@
>> >>>  #include <linux/elf.h>
>> >>>  
>> >>>  #include "remoteproc_internal.h"
>> >>> +#include "remoteproc_elf_loader.h"
>> >>>  
>> >>>  /**
>> >>>   * rproc_elf_sanity_check() - Sanity Check ELF firmware image
>> >>> @@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>> >>> firmware *fw)
>> >>>  {
>> >>>  	const char *name = rproc->firmware;
>> >>>  	struct device *dev = &rproc->dev;
>> >>> +	/*
>> >>> +	 * Elf files are beginning with the same structure. Thus, to simplify
>> >>> +	 * header parsing, we can use the elf32_hdr one for both elf64 and
>> >>> +	 * elf32.
>> >>> +	 */
>> >>>  	struct elf32_hdr *ehdr;
>> >>> +	u32 elf_shdr_size;
>> >>> +	u64 phoff, shoff;
>> >>>  	char class;
>> >>> +	u16 phnum;
>> >>>  
>> >>>  	if (!fw) {
>> >>>  		dev_err(dev, "failed to load %s\n", name);
>> >>> @@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>> >>> firmware *fw)
>> >>>  
>> >>>  	ehdr = (struct elf32_hdr *)fw->data;
>> >>>  
>> >>> -	/* We only support ELF32 at this point */
>> >>> +	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
>> >>> +		dev_err(dev, "Image is corrupted (bad magic)\n");
>> >>> +		return -EINVAL;
>> >>> +	}
>> >>> +
>> >>>  	class = ehdr->e_ident[EI_CLASS];
>> >>> -	if (class != ELFCLASS32) {
>> >>> +	if (class != ELFCLASS32 && class != ELFCLASS64) {
>> >>>  		dev_err(dev, "Unsupported class: %d\n", class);
>> >>>  		return -EINVAL;
>> >>>  	}
>> >>>  
>> >>> +	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
>> >>> +		dev_err(dev, "elf64 header is too small\n");
>> >>> +		return -EINVAL;
>> >>> +	}
>> >>> +
>> >>>  	/* We assume the firmware has the same endianness as the host */
>> >>>  # ifdef __LITTLE_ENDIAN
>> >>>  	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
>> >>> @@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct
>> >>> firmware *fw)
>> >>>  		return -EINVAL;
>> >>>  	}
>> >>>  
>> >>> -	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
>> >>> -		dev_err(dev, "Image is too small\n");
>> >>> -		return -EINVAL;
>> >>> -	}
>> >>> +	phoff = elf_hdr_e_phoff(class, fw->data);
>> >>> +	shoff = elf_hdr_e_shoff(class, fw->data);
>> >>> +	phnum =  elf_hdr_e_phnum(class, fw->data);
>> >>> +	elf_shdr_size = elf_size_of_shdr(class);
>> >>>  
>> >>> -	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
>> >>> -		dev_err(dev, "Image is corrupted (bad magic)\n");
>> >>> +	if (fw->size < shoff + elf_shdr_size) {
>> >>> +		dev_err(dev, "Image is too small\n");
>> >>>  		return -EINVAL;
>> >>>  	}
>> >>>  
>> >>> -	if (ehdr->e_phnum == 0) {
>> >>> +	if (phnum == 0) {
>> >>>  		dev_err(dev, "No loadable segments\n");
>> >>>  		return -EINVAL;
>> >>>  	}
>> >>>  
>> >>> -	if (ehdr->e_phoff > fw->size) {
>> >>> +	if (phoff > fw->size) {
>> >>>  		dev_err(dev, "Firmware size is too small\n");
>> >>>  		return -EINVAL;
>> >>>  	}
>> >>>  
>> >>> +	dev_dbg(dev, "Firmware is an elf%d file\n",
>> >>> +		class == ELFCLASS32 ? 32 : 64);
>> >>> +
>> >>>  	return 0;
>> >>>  }
>> >>>  EXPORT_SYMBOL(rproc_elf_sanity_check);
>> >>> @@ -102,11 +123,9 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
>> >>>   * Note that the boot address is not a configurable property of all remote
>> >>>   * processors. Some will always boot at a specific hard-coded address.
>> >>>   */
>> >>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>> >>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
>> >>>  {
>> >>> -	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
>> >>> -
>> >>> -	return ehdr->e_entry;
>> >>> +	return elf_hdr_e_entry(fw_elf_get_class(fw), fw->data);
>> >>>  }
>> >>>  EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>> >>>  
>> >>> @@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
>> >>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>> >>>  {
>> >>>  	struct device *dev = &rproc->dev;
>> >>> -	struct elf32_hdr *ehdr;
>> >>> -	struct elf32_phdr *phdr;
>> >>> +	const void *ehdr, *phdr;
>> >>>  	int i, ret = 0;
>> >>> +	u16 phnum;
>> >>>  	const u8 *elf_data = fw->data;
>> >>> +	u8 class = fw_elf_get_class(fw);
>> >>> +	u32 elf_phdr_size = elf_size_of_phdr(class);
>> >>>  
>> >>> -	ehdr = (struct elf32_hdr *)elf_data;
>> >>> -	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
>> >>> +	ehdr = elf_data;
>> >>> +	phnum = elf_hdr_e_phnum(class, ehdr);
>> >>> +	phdr = elf_data + elf_hdr_e_phoff(class, ehdr);
>> >>>  
>> >>>  	/* go through the available ELF segments */
>> >>> -	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
>> >>> -		u32 da = phdr->p_paddr;
>> >>> -		u32 memsz = phdr->p_memsz;
>> >>> -		u32 filesz = phdr->p_filesz;
>> >>> -		u32 offset = phdr->p_offset;
>> >>> +	for (i = 0; i < phnum; i++, phdr += elf_phdr_size) {
>> >>> +		u64 da = elf_phdr_p_paddr(class, phdr);
>> >>> +		u64 memsz = elf_phdr_p_memsz(class, phdr);
>> >>> +		u64 filesz = elf_phdr_p_filesz(class, phdr);
>> >>> +		u64 offset = elf_phdr_p_offset(class, phdr);
>> >>> +		u32 type = elf_phdr_p_type(class, phdr);
>> >>>  		void *ptr;
>> >>>  
>> >>> -		if (phdr->p_type != PT_LOAD)
>> >>> +		if (type != PT_LOAD)
>> >>>  			continue;
>> >>>  
>> >>> -		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
>> >>> -			phdr->p_type, da, memsz, filesz);
>> >>> +		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
>> >>> +			type, da, memsz, filesz);
>> >>>  
>> >>>  		if (filesz > memsz) {
>> >>> -			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
>> >>> +			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
>> >>>  				filesz, memsz);
>> >>>  			ret = -EINVAL;
>> >>>  			break;
>> >>>  		}
>> >>>  
>> >>>  		if (offset + filesz > fw->size) {
>> >>> -			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
>> >>> +			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
>> >>>  				offset + filesz, fw->size);
>> >>>  			ret = -EINVAL;
>> >>>  			break;
>> >>> @@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const
>> >>> struct firmware *fw)
>> >>>  		/* grab the kernel address for this device address */
>> >>>  		ptr = rproc_da_to_va(rproc, da, memsz);
>> >>>  		if (!ptr) {
>> >>> -			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
>> >>> +			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
>> >>> +				memsz);
>> >>>  			ret = -EINVAL;
>> >>>  			break;
>> >>>  		}
>> >>>  
>> >>>  		/* put the segment where the remote processor expects it */
>> >>> -		if (phdr->p_filesz)
>> >>> -			memcpy(ptr, elf_data + phdr->p_offset, filesz);
>> >>> +		if (filesz)
>> >>> +			memcpy(ptr, elf_data + offset, filesz);
>> >>>  
>> >>>  		/*
>> >>>  		 * Zero out remaining memory for this segment.
>> >>> @@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const
>> >>> struct firmware *fw)
>> >>>  }
>> >>>  EXPORT_SYMBOL(rproc_elf_load_segments);
>> >>>  
>> >>> -static struct elf32_shdr *
>> >>> -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
>> >>> +static const void *
>> >>> +find_table(struct device *dev, const struct firmware *fw)
>> >>>  {
>> >>> -	struct elf32_shdr *shdr;
>> >>> +	const void *shdr, *name_table_shdr;
>> >>>  	int i;
>> >>>  	const char *name_table;
>> >>>  	struct resource_table *table = NULL;
>> >>> -	const u8 *elf_data = (void *)ehdr;
>> >>> +	const u8 *elf_data = (void *)fw->data;
>> >>> +	u8 class = fw_elf_get_class(fw);
>> >>> +	size_t fw_size = fw->size;
>> >>> +	const void *ehdr = elf_data;
>> >>> +	u16 shnum = elf_hdr_e_shnum(class, ehdr);
>> >>> +	u32 elf_shdr_size = elf_size_of_shdr(class);
>> >>> +	u16 shstrndx = elf_hdr_e_shstrndx(class, ehdr);
>> >>>  
>> >>>  	/* look for the resource table and handle it */
>> >>> -	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
>> >>> -	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
>> >>> -
>> >>> -	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
>> >>> -		u32 size = shdr->sh_size;
>> >>> -		u32 offset = shdr->sh_offset;
>> >>> -
>> >>> -		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
>> >>> +	/* First, get the section header according to the elf class */
>> >>> +	shdr = elf_data + elf_hdr_e_shoff(class, ehdr);
>> >>> +	/* Compute name table section header entry in shdr array */
>> >>> +	name_table_shdr = shdr + (shstrndx * elf_shdr_size);
>> >>> +	/* Finally, compute the name table section address in elf */
>> >>> +	name_table = elf_data + elf_shdr_sh_offset(class, name_table_shdr);
>> >>> +
>> >>> +	for (i = 0; i < shnum; i++, shdr += elf_shdr_size) {
>> >>> +		u64 size = elf_shdr_sh_size(class, shdr);
>> >>> +		u64 offset = elf_shdr_sh_offset(class, shdr);
>> >>> +		u32 name = elf_shdr_sh_name(class, shdr);
>> >>> +
>> >>> +		if (strcmp(name_table + name, ".resource_table"))
>> >>>  			continue;
>> >>>  
>> >>>  		table = (struct resource_table *)(elf_data + offset);
>> >>> @@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr,
>> >>> size_t fw_size)
>> >>>   */
>> >>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
>> >>>  {
>> >>> -	struct elf32_hdr *ehdr;
>> >>> -	struct elf32_shdr *shdr;
>> >>> +	const void *shdr;
>> >>>  	struct device *dev = &rproc->dev;
>> >>>  	struct resource_table *table = NULL;
>> >>>  	const u8 *elf_data = fw->data;
>> >>>  	size_t tablesz;
>> >>> +	u8 class = fw_elf_get_class(fw);
>> >>> +	u64 sh_offset;
>> >>>  
>> >>> -	ehdr = (struct elf32_hdr *)elf_data;
>> >>> -
>> >>> -	shdr = find_table(dev, ehdr, fw->size);
>> >>> +	shdr = find_table(dev, fw);
>> >>>  	if (!shdr)
>> >>>  		return -EINVAL;
>> >>>  
>> >>> -	table = (struct resource_table *)(elf_data + shdr->sh_offset);
>> >>> -	tablesz = shdr->sh_size;
>> >>> +	sh_offset = elf_shdr_sh_offset(class, shdr);
>> >>> +	table = (struct resource_table *)(elf_data + sh_offset);
>> >>> +	tablesz = elf_shdr_sh_size(class, shdr);
>> >>>  
>> >>>  	/*
>> >>>  	 * Create a copy of the resource table. When a virtio device starts
>> >>> @@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
>> >>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>> >>>  						       const struct firmware *fw)
>> >>>  {
>> >>> -	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
>> >>> -	struct elf32_shdr *shdr;
>> >>> +	const void *shdr;
>> >>> +	u64 sh_addr, sh_size;
>> >>> +	u8 class = fw_elf_get_class(fw);
>> >>>  
>> >>> -	shdr = find_table(&rproc->dev, ehdr, fw->size);
>> >>> +	shdr = find_table(&rproc->dev, fw);
>> >>>  	if (!shdr)
>> >>>  		return NULL;
>> >>>  
>> >>> -	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
>> >>> +	sh_addr = elf_shdr_sh_addr(class, shdr);
>> >>> +	sh_size = elf_shdr_sh_size(class, shdr);
>> >>> +
>> >>> +	return rproc_da_to_va(rproc, sh_addr, sh_size);
>> >>>  }
>> >>>  EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
>> >>> diff --git a/drivers/remoteproc/remoteproc_elf_loader.h
>> >>> b/drivers/remoteproc/remoteproc_elf_loader.h
>> >>> new file mode 100644
>> >>> index 000000000000..fac3565734f9
>> >>> --- /dev/null
>> >>> +++ b/drivers/remoteproc/remoteproc_elf_loader.h
>> >>> @@ -0,0 +1,69 @@
>> >>> +/* SPDX-License-Identifier: GPL-2.0 */
>> >>> +/*
>> >>> + * Remote processor elf loader defines
>> >>> + *
>> >>> + * Copyright (C) 2019 Kalray, Inc.
>> >>> + */
>> >>> +
>> >>> +#ifndef REMOTEPROC_ELF_LOADER_H
>> >>> +#define REMOTEPROC_ELF_LOADER_H
>> >>> +
>> >>> +#include <linux/elf.h>
>> >>> +#include <linux/types.h>
>> >>> +
>> >>> +/**
>> >>> + * fw_elf_get_class - Get elf class
>> >>> + * @fw: the ELF firmware image
>> >>> + *
>> >>> + * Note that we use and elf32_hdr to access the class since the start of the
>> >>> + * struct is the same for both elf class
>> >>> + *
>> >>> + * Return: elf class of the firmware
>> >>> + */
>> >>> +static inline u8 fw_elf_get_class(const struct firmware *fw)
>> >>> +{
>> >>> +	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
>> >>> +
>> >>> +	return ehdr->e_ident[EI_CLASS];
>> >>> +}
>> >>> +
>> >>> +#define ELF_GET_FIELD(__s, __field, __type) \
>> >>> +static inline __type elf_##__s##_##__field(u8 class, const void *arg) \
>> >>> +{ \
>> >>> +	if (class == ELFCLASS32) \
>> >>> +		return (__type) ((const struct elf32_##__s *) arg)->__field; \
>> >>> +	else \
>> >>> +		return (__type) ((const struct elf64_##__s *) arg)->__field; \
>> >>> +}
>> >>> +
>> >>> +ELF_GET_FIELD(hdr, e_entry, u64)
>> >>> +ELF_GET_FIELD(hdr, e_phnum, u16)
>> >>> +ELF_GET_FIELD(hdr, e_shnum, u16)
>> >>> +ELF_GET_FIELD(hdr, e_phoff, u64)
>> >>> +ELF_GET_FIELD(hdr, e_shoff, u64)
>> >>> +ELF_GET_FIELD(hdr, e_shstrndx, u16)
>> >>> +
>> >>> +ELF_GET_FIELD(phdr, p_paddr, u64)
>> >>> +ELF_GET_FIELD(phdr, p_filesz, u64)
>> >>> +ELF_GET_FIELD(phdr, p_memsz, u64)
>> >>> +ELF_GET_FIELD(phdr, p_type, u32)
>> >>> +ELF_GET_FIELD(phdr, p_offset, u64)
>> >>> +
>> >>> +ELF_GET_FIELD(shdr, sh_size, u64)
>> >>> +ELF_GET_FIELD(shdr, sh_offset, u64)
>> >>> +ELF_GET_FIELD(shdr, sh_name, u32)
>> >>> +ELF_GET_FIELD(shdr, sh_addr, u64)
>> >>> +
>> >>> +#define ELF_STRUCT_SIZE(__s) \
>> >>> +static inline unsigned long elf_size_of_##__s(u8 class) \
>> >>> +{ \
>> >>> +	if (class == ELFCLASS32)\
>> >>> +		return sizeof(struct elf32_##__s); \
>> >>> +	else \
>> >>> +		return sizeof(struct elf64_##__s); \
>> >>> +}
>> >>> +
>> >>> +ELF_STRUCT_SIZE(shdr)
>> >>> +ELF_STRUCT_SIZE(phdr)
>> >>> +
>> >>> +#endif /* REMOTEPROC_ELF_LOADER_H */
>> >>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>> >>> b/drivers/remoteproc/remoteproc_internal.h
>> >>> index 004867061721..eeb26434220e 100644
>> >>> --- a/drivers/remoteproc/remoteproc_internal.h
>> >>> +++ b/drivers/remoteproc/remoteproc_internal.h
>> >>> @@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
>> >>>  int rproc_trigger_recovery(struct rproc *rproc);
>> >>>  
>> >>>  int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
>> >>> -u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>> >>> +u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
>> >>>  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
>> >>>  int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
>> >>>  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>> >>> diff --git a/drivers/remoteproc/st_remoteproc.c
>> >>> b/drivers/remoteproc/st_remoteproc.c
>> >>> index ee13d23b43a9..a3268d95a50e 100644
>> >>> --- a/drivers/remoteproc/st_remoteproc.c
>> >>> +++ b/drivers/remoteproc/st_remoteproc.c
>> >>> @@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
>> >>>  		}
>> >>>  	}
>> >>>  
>> >>> -	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
>> >>> +	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
>> >>>  
>> >>>  	return 0;
>> >>>  
>> >>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>> >>> index f84bd5fe0211..82cebca9344c 100644
>> >>> --- a/include/linux/remoteproc.h
>> >>> +++ b/include/linux/remoteproc.h
>> >>> @@ -382,7 +382,7 @@ struct rproc_ops {
>> >>>  				struct rproc *rproc, const struct firmware *fw);
>> >>>  	int (*load)(struct rproc *rproc, const struct firmware *fw);
>> >>>  	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
>> >>> -	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>> >>> +	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
>> >>>  };
>> >>>  
>> >>>  /**
>> >>> @@ -498,7 +498,7 @@ struct rproc {
>> >>>  	int num_traces;
>> >>>  	struct list_head carveouts;
>> >>>  	struct list_head mappings;
>> >>> -	u32 bootaddr;
>> >>> +	u64 bootaddr;
>> >> 
>> >> That will cause problems for rproc_coredump()[1] and fixing it properly
>> >> likely means that a 32 or 64 elf should be generated based on the type of image
>> >> that was loaded.  This is also true if ->p_vaddr and ->p_paddr (also in the same
>> >> function) are to be handled properly.
>> >> 
>> >> I'm interested in your opinion on this.
>> > 
>> > Indeed, you are right !
>> > 
>> > I'm "afraid" I will have to fix that !
>> > Most sane thing to do is to dump an elf with the input elf class.
>> > I will make a V4 with a patch for that.
>> > 
>> 
>> Actually, this does not seems directly related to elf loading.
>> The coredump mecanism dumps segment that have been registered
>> using rproc_coredump_add_*_segment and this is not done directly
>> by the elf loader.
> 
> Correct, but it is fair to assume rpoc_coredump_add_*_segment() is called for
> the image that will run on the MCU (otherwiser doing so would be pointless).
> 
>> I'm not 100% sure but the coredump elf format is not tied to
>> any machine (EM_NONE) and as a special type (ET_CORE) so the elf
>> type is probably not relevant adn elf64 would be generic.
> 
> That is true, we could generate an elf64 core dump for both 32 and 64 bit MCU
> image and be done with it.  But that is almost guaranteed to break some user
> space that isn't tailored to deal with an elf64.
> 
>> If some coredump user could speak for that part, that would be
>> nice !
>> 
>> If needed, then we could add a rproc_coredump_set_format() function
>> to specify various parameters (machine, elf type, lsb/msb, etc).
>> 
> 
> For this specific patchset I don't think you need to cover cases where this much
> flexibility is needed (up to now it hasn't been a requiment).
> 
> Keeping track of the type of image being loaded in something like
> rproc::elfclass and use that information to generate the right elf core in
> rproc_coredump() is probably sufficient for the time being.

Ok, let's go this way.

> 
>> Let me know what you think about it.
>> 
>> Clément
>> 
>> > Thanks,
>> > 
>> > Clément
>> > 
>> >> 
>> >> Thanks,
>> >> Mathieu
>> >> 
>> >> [1].
>> >> https://elixir.bootlin.com/linux/latest/source/drivers/remoteproc/remoteproc_core.c#L1600
>> >> 
>> >>>  	struct list_head rvdevs;
>> >>>  	struct list_head subdevs;
>> >>>  	struct idr notifyids;
>> >>> --
> > > >> 2.15.0.276.g89ea799

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 0/5] remoteproc: Add elf64 support
  2020-02-07  7:57             ` Clément Leger
@ 2020-02-10 16:22               ` Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va Clement Leger
                                   ` (5 more replies)
  0 siblings, 6 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-10 16:22 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

This serie add support for elf64 in remoteproc (elf loader, coredump). 
First two patches modifies the type of len argument (in da_to_va) and
boot_addr in order to allow loading elf64 segment with a u64 size
and a u64 entry point.
Next patch introduce a set of macros to access elf64 and elf32
transparently.
Last two patches are the actual modification in the elf loader and
remoteproc coredump support to add elf64 support.

Changes from V3:
 - Adapt coredump to elf64 file format
 - Rename remoteproc_elf_loader.h to remoteproc_elf_helpers.h
 - Update copyright year in remoteproc_elf_helpers.h
 - Rename macros elf_hdr_* to elf_get_hdr_* for coherency with elf_hdr_set_*
 - Split elf64 loader patch in 3:
   - boot_addr u64 change
   - remoteproc_elf_helpers.h creation
   - elf64 loading

Clement Leger (5):
  remoteproc: Use u64 len for da_to_va
  remoteproc: Use u64 type for boot_addr
  remoteproc: Add elf helpers to access elf64 and elf32 fields
  remoteproc: Add elf64 support in elf loader
  remoteproc: Adapt coredump to generate correct elf type

 Documentation/remoteproc.txt                |   2 +-
 drivers/remoteproc/imx_rproc.c              |  11 +-
 drivers/remoteproc/keystone_remoteproc.c    |   4 +-
 drivers/remoteproc/qcom_q6v5_adsp.c         |   2 +-
 drivers/remoteproc/qcom_q6v5_mss.c          |   2 +-
 drivers/remoteproc/qcom_q6v5_pas.c          |   2 +-
 drivers/remoteproc/qcom_q6v5_wcss.c         |   2 +-
 drivers/remoteproc/qcom_wcnss.c             |   2 +-
 drivers/remoteproc/remoteproc_core.c        |  69 +++++++------
 drivers/remoteproc/remoteproc_elf_helpers.h |  95 ++++++++++++++++++
 drivers/remoteproc/remoteproc_elf_loader.c  | 150 ++++++++++++++++++----------
 drivers/remoteproc/remoteproc_internal.h    |   4 +-
 drivers/remoteproc/st_remoteproc.c          |   2 +-
 drivers/remoteproc/st_slim_rproc.c          |   4 +-
 drivers/remoteproc/wkup_m3_rproc.c          |   4 +-
 include/linux/remoteproc.h                  |   7 +-
 16 files changed, 252 insertions(+), 110 deletions(-)
 create mode 100644 drivers/remoteproc/remoteproc_elf_helpers.h

-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
@ 2020-02-10 16:22                 ` Clement Leger
  2020-02-11 15:53                   ` Arnaud POULIQUEN
  2020-02-10 16:22                 ` [PATCH v4 2/5] remoteproc: Use u64 type for boot_addr Clement Leger
                                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 32+ messages in thread
From: Clement Leger @ 2020-02-10 16:22 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

With upcoming changes in elf loader for elf64 support, section size will
be a u64. When used with da_to_va, this will potentially lead to
overflow if using the current "int" type for len argument. Change
da_to_va prototype to use a u64 for len and fix all users of this
function.

Signed-off-by: Clement Leger <cleger@kalray.eu>
---
 drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
 drivers/remoteproc/keystone_remoteproc.c |  4 ++--
 drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
 drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
 drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
 drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
 drivers/remoteproc/qcom_wcnss.c          |  2 +-
 drivers/remoteproc/remoteproc_core.c     |  2 +-
 drivers/remoteproc/remoteproc_internal.h |  2 +-
 drivers/remoteproc/st_slim_rproc.c       |  4 ++--
 drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
 include/linux/remoteproc.h               |  2 +-
 12 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 3e72b6f38d4b..f497f5b49b18 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
 }
 
 static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
-			       int len, u64 *sys)
+			       u64 len, u64 *sys)
 {
 	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
 	int i;
@@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
 		}
 	}
 
-	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
+	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
 		 da, len);
 	return -ENOENT;
 }
 
-static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct imx_rproc *priv = rproc->priv;
 	void *va = NULL;
 	u64 sys;
 	int i;
 
-	if (len <= 0)
+	if (len == 0)
 		return NULL;
 
 	/*
@@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
 		}
 	}
 
-	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
+	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
+		da, len, va);
 
 	return va;
 }
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index 5c4658f00b3d..466093f48814 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct keystone_rproc *ksproc = rproc->priv;
 	void __iomem *va = NULL;
@@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
 	size_t size;
 	int i;
 
-	if (len <= 0)
+	if (len == 0)
 		return NULL;
 
 	for (i = 0; i < ksproc->num_mems; i++) {
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index e953886b2eb7..7518e67a49e5 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 471128a2e723..248febde6fc1 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct q6v5 *qproc = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index db4b3c4bacd7..cf2cd609c90d 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
index f93e1e4a1cc0..3a6b82a16961 100644
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct q6v5_wcss *wcss = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index dc135754bb9c..f893219e45a8 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 307df98347ba..9e6d3c6a60ee 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
  * here the output of the DMA API for the carveouts, which should be more
  * correct.
  */
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct rproc_mem_entry *carveout;
 	void *ptr = NULL;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 493ef9262411..004867061721 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
 void rproc_free_vring(struct rproc_vring *rvring);
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
 
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
+void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
 phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
index 04492fead3c8..fc01cd879b60 100644
--- a/drivers/remoteproc/st_slim_rproc.c
+++ b/drivers/remoteproc/st_slim_rproc.c
@@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct st_slim_rproc *slim_rproc = rproc->priv;
 	void *va = NULL;
@@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
 		}
 	}
 
-	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
+	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
 		da, len, va);
 
 	return va;
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index 3984e585c847..91485b467407 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
 {
 	struct wkup_m3_rproc *wkupm3 = rproc->priv;
 	void *va = NULL;
 	int i;
 	u32 offset;
 
-	if (len <= 0)
+	if (len == 0)
 		return NULL;
 
 	for (i = 0; i < WKUPM3_MEM_MAX; i++) {
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 16ad66683ad0..f84bd5fe0211 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -374,7 +374,7 @@ struct rproc_ops {
 	int (*start)(struct rproc *rproc);
 	int (*stop)(struct rproc *rproc);
 	void (*kick)(struct rproc *rproc, int vqid);
-	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
+	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
 	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
 	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
 			  int offset, int avail);
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 2/5] remoteproc: Use u64 type for boot_addr
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va Clement Leger
@ 2020-02-10 16:22                 ` Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 3/5] remoteproc: Add elf helpers to access elf64 and elf32 fields Clement Leger
                                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-10 16:22 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

elf64 entry is defined as a u64. Since boot_addr is used to store the
elf entry point, change boot_addr type to u64 to support both elf32
and elf64. In the same time, fix users that were using this variable.

Signed-off-by: Clement Leger <cleger@kalray.eu>
---
 drivers/remoteproc/remoteproc_elf_loader.c | 2 +-
 drivers/remoteproc/remoteproc_internal.h   | 2 +-
 drivers/remoteproc/st_remoteproc.c         | 2 +-
 include/linux/remoteproc.h                 | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 606aae166eba..c2a9783cfb9a 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -102,7 +102,7 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
  * Note that the boot address is not a configurable property of all remote
  * processors. Some will always boot at a specific hard-coded address.
  */
-u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
 {
 	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
 
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 004867061721..eeb26434220e 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -55,7 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
-u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
+u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw);
 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index ee13d23b43a9..a3268d95a50e 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -190,7 +190,7 @@ static int st_rproc_start(struct rproc *rproc)
 		}
 	}
 
-	dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr);
+	dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
 
 	return 0;
 
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index f84bd5fe0211..82cebca9344c 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -382,7 +382,7 @@ struct rproc_ops {
 				struct rproc *rproc, const struct firmware *fw);
 	int (*load)(struct rproc *rproc, const struct firmware *fw);
 	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
-	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
+	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
 };
 
 /**
@@ -498,7 +498,7 @@ struct rproc {
 	int num_traces;
 	struct list_head carveouts;
 	struct list_head mappings;
-	u32 bootaddr;
+	u64 bootaddr;
 	struct list_head rvdevs;
 	struct list_head subdevs;
 	struct idr notifyids;
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 3/5] remoteproc: Add elf helpers to access elf64 and elf32 fields
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 2/5] remoteproc: Use u64 type for boot_addr Clement Leger
@ 2020-02-10 16:22                 ` Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 4/5] remoteproc: Add elf64 support in elf loader Clement Leger
                                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-10 16:22 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

elf32 and elf64 mainly differ by their types. In order to avoid
copy/pasting the whole loader code, generate static inline functions
which will access values according to the elf class. It allows to
keep a common loader basis.
In order to accommodate both elf types sizes, the maximum size for a
elf header member is chosen using the maximum value of the field for
both elf class.

Signed-off-by: Clement Leger <cleger@kalray.eu>
---
 drivers/remoteproc/remoteproc_elf_helpers.h | 95 +++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)
 create mode 100644 drivers/remoteproc/remoteproc_elf_helpers.h

diff --git a/drivers/remoteproc/remoteproc_elf_helpers.h b/drivers/remoteproc/remoteproc_elf_helpers.h
new file mode 100644
index 000000000000..a29c17aaedb7
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_elf_helpers.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Remote processor elf helpers defines
+ *
+ * Copyright (C) 2020 Kalray, Inc.
+ */
+
+#ifndef REMOTEPROC_ELF_LOADER_H
+#define REMOTEPROC_ELF_LOADER_H
+
+#include <linux/elf.h>
+#include <linux/types.h>
+
+/**
+ * fw_elf_get_class - Get elf class
+ * @fw: the ELF firmware image
+ *
+ * Note that we use and elf32_hdr to access the class since the start of the
+ * struct is the same for both elf class
+ *
+ * Return: elf class of the firmware
+ */
+static inline u8 fw_elf_get_class(const struct firmware *fw)
+{
+	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
+
+	return ehdr->e_ident[EI_CLASS];
+}
+
+static inline void elf_hdr_init_ident(struct elf32_hdr *hdr, u8 class)
+{
+	memcpy(hdr->e_ident, ELFMAG, SELFMAG);
+	hdr->e_ident[EI_CLASS] = class;
+	hdr->e_ident[EI_DATA] = ELFDATA2LSB;
+	hdr->e_ident[EI_VERSION] = EV_CURRENT;
+	hdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
+}
+
+/* Generate getter and setter for a specific elf struct/field */
+#define ELF_GEN_FIELD_GET_SET(__s, __field, __type) \
+static inline __type elf_##__s##_get_##__field(u8 class, const void *arg) \
+{ \
+	if (class == ELFCLASS32) \
+		return (__type) ((const struct elf32_##__s *) arg)->__field; \
+	else \
+		return (__type) ((const struct elf64_##__s *) arg)->__field; \
+} \
+static inline void elf_##__s##_set_##__field(u8 class, void *arg, __type value) \
+{ \
+	if (class == ELFCLASS32) \
+		((struct elf32_##__s *) arg)->__field = (__type) value; \
+	else \
+		((struct elf64_##__s *) arg)->__field = (__type) value; \
+}
+
+ELF_GEN_FIELD_GET_SET(hdr, e_entry, u64)
+ELF_GEN_FIELD_GET_SET(hdr, e_phnum, u16)
+ELF_GEN_FIELD_GET_SET(hdr, e_shnum, u16)
+ELF_GEN_FIELD_GET_SET(hdr, e_phoff, u64)
+ELF_GEN_FIELD_GET_SET(hdr, e_shoff, u64)
+ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
+ELF_GEN_FIELD_GET_SET(hdr, e_machine, u16)
+ELF_GEN_FIELD_GET_SET(hdr, e_type, u16)
+ELF_GEN_FIELD_GET_SET(hdr, e_version, u32)
+ELF_GEN_FIELD_GET_SET(hdr, e_ehsize, u32)
+ELF_GEN_FIELD_GET_SET(hdr, e_phentsize, u16)
+
+ELF_GEN_FIELD_GET_SET(phdr, p_paddr, u64)
+ELF_GEN_FIELD_GET_SET(phdr, p_vaddr, u64)
+ELF_GEN_FIELD_GET_SET(phdr, p_filesz, u64)
+ELF_GEN_FIELD_GET_SET(phdr, p_memsz, u64)
+ELF_GEN_FIELD_GET_SET(phdr, p_type, u32)
+ELF_GEN_FIELD_GET_SET(phdr, p_offset, u64)
+ELF_GEN_FIELD_GET_SET(phdr, p_flags, u32)
+ELF_GEN_FIELD_GET_SET(phdr, p_align, u64)
+
+ELF_GEN_FIELD_GET_SET(shdr, sh_size, u64)
+ELF_GEN_FIELD_GET_SET(shdr, sh_offset, u64)
+ELF_GEN_FIELD_GET_SET(shdr, sh_name, u32)
+ELF_GEN_FIELD_GET_SET(shdr, sh_addr, u64)
+
+#define ELF_STRUCT_SIZE(__s) \
+static inline unsigned long elf_size_of_##__s(u8 class) \
+{ \
+	if (class == ELFCLASS32)\
+		return sizeof(struct elf32_##__s); \
+	else \
+		return sizeof(struct elf64_##__s); \
+}
+
+ELF_STRUCT_SIZE(shdr)
+ELF_STRUCT_SIZE(phdr)
+ELF_STRUCT_SIZE(hdr)
+
+#endif /* REMOTEPROC_ELF_LOADER_H */
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 4/5] remoteproc: Add elf64 support in elf loader
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
                                   ` (2 preceding siblings ...)
  2020-02-10 16:22                 ` [PATCH v4 3/5] remoteproc: Add elf helpers to access elf64 and elf32 fields Clement Leger
@ 2020-02-10 16:22                 ` Clement Leger
  2020-02-10 16:22                 ` [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type Clement Leger
  2020-02-11 15:57                 ` [PATCH v4 0/5] remoteproc: Add elf64 support Arnaud POULIQUEN
  5 siblings, 0 replies; 32+ messages in thread
From: Clement Leger @ 2020-02-10 16:22 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

In order to support elf64, use macros from remoteproc_elf_helpers.h
to access elf headers depending on elf class.

Signed-off-by: Clement Leger <cleger@kalray.eu>
Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com>
---
 Documentation/remoteproc.txt               |   2 +-
 drivers/remoteproc/remoteproc_elf_loader.c | 145 ++++++++++++++++++-----------
 2 files changed, 93 insertions(+), 54 deletions(-)

diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
index 03c3d2e568b0..2be1147256e0 100644
--- a/Documentation/remoteproc.txt
+++ b/Documentation/remoteproc.txt
@@ -230,7 +230,7 @@ in the used rings.
 Binary Firmware Structure
 =========================
 
-At this point remoteproc only supports ELF32 firmware binaries. However,
+At this point remoteproc supports ELF32 and ELF64 firmware binaries. However,
 it is quite expected that other platforms/devices which we'd want to
 support with this framework will be based on different binary formats.
 
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index c2a9783cfb9a..2ffb02a2ee36 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -23,6 +23,7 @@
 #include <linux/elf.h>
 
 #include "remoteproc_internal.h"
+#include "remoteproc_elf_helpers.h"
 
 /**
  * rproc_elf_sanity_check() - Sanity Check ELF firmware image
@@ -35,8 +36,16 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 {
 	const char *name = rproc->firmware;
 	struct device *dev = &rproc->dev;
+	/*
+	 * Elf files are beginning with the same structure. Thus, to simplify
+	 * header parsing, we can use the elf32_hdr one for both elf64 and
+	 * elf32.
+	 */
 	struct elf32_hdr *ehdr;
+	u32 elf_shdr_get_size;
+	u64 phoff, shoff;
 	char class;
+	u16 phnum;
 
 	if (!fw) {
 		dev_err(dev, "failed to load %s\n", name);
@@ -50,13 +59,22 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 
 	ehdr = (struct elf32_hdr *)fw->data;
 
-	/* We only support ELF32 at this point */
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		dev_err(dev, "Image is corrupted (bad magic)\n");
+		return -EINVAL;
+	}
+
 	class = ehdr->e_ident[EI_CLASS];
-	if (class != ELFCLASS32) {
+	if (class != ELFCLASS32 && class != ELFCLASS64) {
 		dev_err(dev, "Unsupported class: %d\n", class);
 		return -EINVAL;
 	}
 
+	if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) {
+		dev_err(dev, "elf64 header is too small\n");
+		return -EINVAL;
+	}
+
 	/* We assume the firmware has the same endianness as the host */
 # ifdef __LITTLE_ENDIAN
 	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
@@ -67,26 +85,29 @@ int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
 		return -EINVAL;
 	}
 
-	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
-		dev_err(dev, "Image is too small\n");
-		return -EINVAL;
-	}
+	phoff = elf_hdr_get_e_phoff(class, fw->data);
+	shoff = elf_hdr_get_e_shoff(class, fw->data);
+	phnum =  elf_hdr_get_e_phnum(class, fw->data);
+	elf_shdr_get_size = elf_size_of_shdr(class);
 
-	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
-		dev_err(dev, "Image is corrupted (bad magic)\n");
+	if (fw->size < shoff + elf_shdr_get_size) {
+		dev_err(dev, "Image is too small\n");
 		return -EINVAL;
 	}
 
-	if (ehdr->e_phnum == 0) {
+	if (phnum == 0) {
 		dev_err(dev, "No loadable segments\n");
 		return -EINVAL;
 	}
 
-	if (ehdr->e_phoff > fw->size) {
+	if (phoff > fw->size) {
 		dev_err(dev, "Firmware size is too small\n");
 		return -EINVAL;
 	}
 
+	dev_dbg(dev, "Firmware is an elf%d file\n",
+		class == ELFCLASS32 ? 32 : 64);
+
 	return 0;
 }
 EXPORT_SYMBOL(rproc_elf_sanity_check);
@@ -104,9 +125,7 @@ EXPORT_SYMBOL(rproc_elf_sanity_check);
  */
 u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
-
-	return ehdr->e_entry;
+	return elf_hdr_get_e_entry(fw_elf_get_class(fw), fw->data);
 }
 EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 
@@ -137,37 +156,41 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr);
 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = &rproc->dev;
-	struct elf32_hdr *ehdr;
-	struct elf32_phdr *phdr;
+	const void *ehdr, *phdr;
 	int i, ret = 0;
+	u16 phnum;
 	const u8 *elf_data = fw->data;
+	u8 class = fw_elf_get_class(fw);
+	u32 elf_phdr_get_size = elf_size_of_phdr(class);
 
-	ehdr = (struct elf32_hdr *)elf_data;
-	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
+	ehdr = elf_data;
+	phnum = elf_hdr_get_e_phnum(class, ehdr);
+	phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr);
 
 	/* go through the available ELF segments */
-	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
-		u32 da = phdr->p_paddr;
-		u32 memsz = phdr->p_memsz;
-		u32 filesz = phdr->p_filesz;
-		u32 offset = phdr->p_offset;
+	for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) {
+		u64 da = elf_phdr_get_p_paddr(class, phdr);
+		u64 memsz = elf_phdr_get_p_memsz(class, phdr);
+		u64 filesz = elf_phdr_get_p_filesz(class, phdr);
+		u64 offset = elf_phdr_get_p_offset(class, phdr);
+		u32 type = elf_phdr_get_p_type(class, phdr);
 		void *ptr;
 
-		if (phdr->p_type != PT_LOAD)
+		if (type != PT_LOAD)
 			continue;
 
-		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
-			phdr->p_type, da, memsz, filesz);
+		dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
+			type, da, memsz, filesz);
 
 		if (filesz > memsz) {
-			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
+			dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
 				filesz, memsz);
 			ret = -EINVAL;
 			break;
 		}
 
 		if (offset + filesz > fw->size) {
-			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
+			dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
 				offset + filesz, fw->size);
 			ret = -EINVAL;
 			break;
@@ -176,14 +199,15 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		/* grab the kernel address for this device address */
 		ptr = rproc_da_to_va(rproc, da, memsz);
 		if (!ptr) {
-			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
+			dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
+				memsz);
 			ret = -EINVAL;
 			break;
 		}
 
 		/* put the segment where the remote processor expects it */
-		if (phdr->p_filesz)
-			memcpy(ptr, elf_data + phdr->p_offset, filesz);
+		if (filesz)
+			memcpy(ptr, elf_data + offset, filesz);
 
 		/*
 		 * Zero out remaining memory for this segment.
@@ -200,24 +224,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 }
 EXPORT_SYMBOL(rproc_elf_load_segments);
 
-static struct elf32_shdr *
-find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
+static const void *
+find_table(struct device *dev, const struct firmware *fw)
 {
-	struct elf32_shdr *shdr;
+	const void *shdr, *name_table_shdr;
 	int i;
 	const char *name_table;
 	struct resource_table *table = NULL;
-	const u8 *elf_data = (void *)ehdr;
+	const u8 *elf_data = (void *)fw->data;
+	u8 class = fw_elf_get_class(fw);
+	size_t fw_size = fw->size;
+	const void *ehdr = elf_data;
+	u16 shnum = elf_hdr_get_e_shnum(class, ehdr);
+	u32 elf_shdr_get_size = elf_size_of_shdr(class);
+	u16 shstrndx = elf_hdr_get_e_shstrndx(class, ehdr);
 
 	/* look for the resource table and handle it */
-	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
-	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
-
-	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
-		u32 size = shdr->sh_size;
-		u32 offset = shdr->sh_offset;
-
-		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
+	/* First, get the section header according to the elf class */
+	shdr = elf_data + elf_hdr_get_e_shoff(class, ehdr);
+	/* Compute name table section header entry in shdr array */
+	name_table_shdr = shdr + (shstrndx * elf_shdr_get_size);
+	/* Finally, compute the name table section address in elf */
+	name_table = elf_data + elf_shdr_get_sh_offset(class, name_table_shdr);
+
+	for (i = 0; i < shnum; i++, shdr += elf_shdr_get_size) {
+		u64 size = elf_shdr_get_sh_size(class, shdr);
+		u64 offset = elf_shdr_get_sh_offset(class, shdr);
+		u32 name = elf_shdr_get_sh_name(class, shdr);
+
+		if (strcmp(name_table + name, ".resource_table"))
 			continue;
 
 		table = (struct resource_table *)(elf_data + offset);
@@ -270,21 +305,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
  */
 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr;
-	struct elf32_shdr *shdr;
+	const void *shdr;
 	struct device *dev = &rproc->dev;
 	struct resource_table *table = NULL;
 	const u8 *elf_data = fw->data;
 	size_t tablesz;
+	u8 class = fw_elf_get_class(fw);
+	u64 sh_offset;
 
-	ehdr = (struct elf32_hdr *)elf_data;
-
-	shdr = find_table(dev, ehdr, fw->size);
+	shdr = find_table(dev, fw);
 	if (!shdr)
 		return -EINVAL;
 
-	table = (struct resource_table *)(elf_data + shdr->sh_offset);
-	tablesz = shdr->sh_size;
+	sh_offset = elf_shdr_get_sh_offset(class, shdr);
+	table = (struct resource_table *)(elf_data + sh_offset);
+	tablesz = elf_shdr_get_sh_size(class, shdr);
 
 	/*
 	 * Create a copy of the resource table. When a virtio device starts
@@ -317,13 +352,17 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table);
 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
 						       const struct firmware *fw)
 {
-	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
-	struct elf32_shdr *shdr;
+	const void *shdr;
+	u64 sh_addr, sh_size;
+	u8 class = fw_elf_get_class(fw);
 
-	shdr = find_table(&rproc->dev, ehdr, fw->size);
+	shdr = find_table(&rproc->dev, fw);
 	if (!shdr)
 		return NULL;
 
-	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
+	sh_addr = elf_shdr_get_sh_addr(class, shdr);
+	sh_size = elf_shdr_get_sh_size(class, shdr);
+
+	return rproc_da_to_va(rproc, sh_addr, sh_size);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
                                   ` (3 preceding siblings ...)
  2020-02-10 16:22                 ` [PATCH v4 4/5] remoteproc: Add elf64 support in elf loader Clement Leger
@ 2020-02-10 16:22                 ` Clement Leger
  2020-02-11 23:11                   ` Mathieu Poirier
  2020-02-11 15:57                 ` [PATCH v4 0/5] remoteproc: Add elf64 support Arnaud POULIQUEN
  5 siblings, 1 reply; 32+ messages in thread
From: Clement Leger @ 2020-02-10 16:22 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Arnaud Pouliquen, Loic PALLARDY,
	s-anna, Mathieu Poirier, Clement Leger

Now that remoteproc can load an elf64, coredump elf class should be
the same as the loaded elf class. In order to do that, add a
elf_class field to rproc with default values. If an elf is loaded
successfully, these fields will be updated with the loaded elf class.
Then, the coredump core code has been modified to use the generic elf
macro in order to create an elf file with correct class.

Signed-off-by: Clement Leger <cleger@kalray.eu>
---
 drivers/remoteproc/remoteproc_core.c       | 67 ++++++++++++++++--------------
 drivers/remoteproc/remoteproc_elf_loader.c |  3 ++
 include/linux/remoteproc.h                 |  1 +
 3 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 9e6d3c6a60ee..ce70656ae150 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -38,6 +38,7 @@
 #include <linux/platform_device.h>
 
 #include "remoteproc_internal.h"
+#include "remoteproc_elf_helpers.h"
 
 #define HIGH_BITS_MASK 0xFFFFFFFF00000000ULL
 
@@ -1564,20 +1565,21 @@ EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
 static void rproc_coredump(struct rproc *rproc)
 {
 	struct rproc_dump_segment *segment;
-	struct elf32_phdr *phdr;
-	struct elf32_hdr *ehdr;
+	void *phdr;
+	void *ehdr;
 	size_t data_size;
 	size_t offset;
 	void *data;
 	void *ptr;
+	u8 class = rproc->elf_class;
 	int phnum = 0;
 
 	if (list_empty(&rproc->dump_segments))
 		return;
 
-	data_size = sizeof(*ehdr);
+	data_size = elf_size_of_hdr(class);
 	list_for_each_entry(segment, &rproc->dump_segments, node) {
-		data_size += sizeof(*phdr) + segment->size;
+		data_size += elf_size_of_phdr(class) + segment->size;
 
 		phnum++;
 	}
@@ -1588,33 +1590,33 @@ static void rproc_coredump(struct rproc *rproc)
 
 	ehdr = data;
 
-	memset(ehdr, 0, sizeof(*ehdr));
-	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
-	ehdr->e_ident[EI_CLASS] = ELFCLASS32;
-	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
-	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
-	ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
-	ehdr->e_type = ET_CORE;
-	ehdr->e_machine = EM_NONE;
-	ehdr->e_version = EV_CURRENT;
-	ehdr->e_entry = rproc->bootaddr;
-	ehdr->e_phoff = sizeof(*ehdr);
-	ehdr->e_ehsize = sizeof(*ehdr);
-	ehdr->e_phentsize = sizeof(*phdr);
-	ehdr->e_phnum = phnum;
-
-	phdr = data + ehdr->e_phoff;
-	offset = ehdr->e_phoff + sizeof(*phdr) * ehdr->e_phnum;
+	memset(ehdr, 0, elf_size_of_hdr(class));
+	/* e_ident field is common for both elf32 and elf64 */
+	elf_hdr_init_ident(ehdr, class);
+
+	elf_hdr_set_e_type(class, ehdr, ET_CORE);
+	elf_hdr_set_e_machine(class, ehdr, EM_NONE);
+	elf_hdr_set_e_version(class, ehdr, EV_CURRENT);
+	elf_hdr_set_e_entry(class, ehdr, rproc->bootaddr);
+	elf_hdr_set_e_phoff(class, ehdr, elf_size_of_hdr(class));
+	elf_hdr_set_e_ehsize(class, ehdr, elf_size_of_hdr(class));
+	elf_hdr_set_e_phentsize(class, ehdr, elf_size_of_phdr(class));
+	elf_hdr_set_e_phnum(class, ehdr, phnum);
+
+	phdr = data + elf_hdr_get_e_phoff(class, ehdr);
+	offset = elf_hdr_get_e_phoff(class, ehdr);
+	offset += elf_size_of_phdr(class) * elf_hdr_get_e_phnum(class, ehdr);
+
 	list_for_each_entry(segment, &rproc->dump_segments, node) {
-		memset(phdr, 0, sizeof(*phdr));
-		phdr->p_type = PT_LOAD;
-		phdr->p_offset = offset;
-		phdr->p_vaddr = segment->da;
-		phdr->p_paddr = segment->da;
-		phdr->p_filesz = segment->size;
-		phdr->p_memsz = segment->size;
-		phdr->p_flags = PF_R | PF_W | PF_X;
-		phdr->p_align = 0;
+		memset(phdr, 0, elf_size_of_phdr(class));
+		elf_phdr_set_p_type(class, phdr, PT_LOAD);
+		elf_phdr_set_p_offset(class, phdr, offset);
+		elf_phdr_set_p_vaddr(class, phdr, segment->da);
+		elf_phdr_set_p_paddr(class, phdr, segment->da);
+		elf_phdr_set_p_filesz(class, phdr, segment->size);
+		elf_phdr_set_p_memsz(class, phdr, segment->size);
+		elf_phdr_set_p_flags(class, phdr, PF_R | PF_W | PF_X);
+		elf_phdr_set_p_align(class, phdr, 0);
 
 		if (segment->dump) {
 			segment->dump(rproc, segment, data + offset);
@@ -1630,8 +1632,8 @@ static void rproc_coredump(struct rproc *rproc)
 			}
 		}
 
-		offset += phdr->p_filesz;
-		phdr++;
+		offset += elf_phdr_get_p_filesz(class, phdr);
+		phdr += elf_size_of_phdr(class);
 	}
 
 	dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL);
@@ -2029,6 +2031,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
 	rproc->name = name;
 	rproc->priv = &rproc[1];
 	rproc->auto_boot = true;
+	rproc->elf_class = ELFCLASS32;
 
 	device_initialize(&rproc->dev);
 	rproc->dev.parent = dev;
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 2ffb02a2ee36..07712a541ea6 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -220,6 +220,9 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 			memset(ptr + filesz, 0, memsz - filesz);
 	}
 
+	if (ret == 0)
+		rproc->elf_class = class;
+
 	return ret;
 }
 EXPORT_SYMBOL(rproc_elf_load_segments);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 82cebca9344c..113e356ce56a 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -514,6 +514,7 @@ struct rproc {
 	bool auto_boot;
 	struct list_head dump_segments;
 	int nb_vdev;
+	int elf_class;
 };
 
 /**
-- 
2.15.0.276.g89ea799


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-10 16:22                 ` [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va Clement Leger
@ 2020-02-11 15:53                   ` Arnaud POULIQUEN
  2020-02-11 16:39                     ` Clément Leger
  0 siblings, 1 reply; 32+ messages in thread
From: Arnaud POULIQUEN @ 2020-02-11 15:53 UTC (permalink / raw)
  To: Clement Leger, Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet,
	Shawn Guo, Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna,
	Mathieu Poirier



On 2/10/20 5:22 PM, Clement Leger wrote:
> With upcoming changes in elf loader for elf64 support, section size will
> be a u64. When used with da_to_va, this will potentially lead to
> overflow if using the current "int" type for len argument. Change
> da_to_va prototype to use a u64 for len and fix all users of this
> function.
> 
> Signed-off-by: Clement Leger <cleger@kalray.eu>
> ---
>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
>  drivers/remoteproc/remoteproc_core.c     |  2 +-
>  drivers/remoteproc/remoteproc_internal.h |  2 +-
>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
>  include/linux/remoteproc.h               |  2 +-
>  12 files changed, 20 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 3e72b6f38d4b..f497f5b49b18 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
>  }
>  
>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
> -			       int len, u64 *sys)
> +			       u64 len, u64 *sys)
>  {
>  	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
>  	int i;
> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>  		}
>  	}
>  
> -	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
> +	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
>  		 da, len);
>  	return -ENOENT;
>  }
>  
> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct imx_rproc *priv = rproc->priv;
>  	void *va = NULL;
>  	u64 sys;
>  	int i;
>  
> -	if (len <= 0)
> +	if (len == 0)
>  		return NULL;
>  
>  	/*
> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>  		}
>  	}
>  
> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
> +		da, len, va);
>  
>  	return va;
>  }
> diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
> index 5c4658f00b3d..466093f48814 100644
> --- a/drivers/remoteproc/keystone_remoteproc.c
> +++ b/drivers/remoteproc/keystone_remoteproc.c
> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
>   * can be used either by the remoteproc core for loading (when using kernel
>   * remoteproc loader), or by any rpmsg bus drivers.
>   */
> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct keystone_rproc *ksproc = rproc->priv;
>  	void __iomem *va = NULL;
> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>  	size_t size;
>  	int i;
>  
> -	if (len <= 0)
> +	if (len == 0)
>  		return NULL;
>  
>  	for (i = 0; i < ksproc->num_mems; i++) {
> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
> index e953886b2eb7..7518e67a49e5 100644
> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
> index 471128a2e723..248febde6fc1 100644
> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct q6v5 *qproc = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index db4b3c4bacd7..cf2cd609c90d 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
> index f93e1e4a1cc0..3a6b82a16961 100644
> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct q6v5_wcss *wcss = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> index dc135754bb9c..f893219e45a8 100644
> --- a/drivers/remoteproc/qcom_wcnss.c
> +++ b/drivers/remoteproc/qcom_wcnss.c
> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 307df98347ba..9e6d3c6a60ee 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>   * here the output of the DMA API for the carveouts, which should be more
>   * correct.
>   */
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)

This function is exported, don't see any update in consequence...
references:
https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
For instance the function rproc_trace_read use it. it quite strange that my gcc does not warns for the cast but i suppose that some could.
An indirect consequence is that the len field in rproc_mem_entry struct should probably been updated to u64 to be aligned.

I'm still wondering about the use of size_t instead,which seems more rational from my window.
So i you or Mathieu remember it was decided to use u64, please could remind me the arguments?
As an alternative a check should be added for 32 bits processors to ensure that the size is not higher than 
its address range capability...  

Regards
Arnaud  
 
>  {
>  	struct rproc_mem_entry *carveout;
>  	void *ptr = NULL;
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index 493ef9262411..004867061721 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>  void rproc_free_vring(struct rproc_vring *rvring);
>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>  
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>  int rproc_trigger_recovery(struct rproc *rproc);
>  
> diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
> index 04492fead3c8..fc01cd879b60 100644
> --- a/drivers/remoteproc/st_slim_rproc.c
> +++ b/drivers/remoteproc/st_slim_rproc.c
> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>  	void *va = NULL;
> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>  		}
>  	}
>  
> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
>  		da, len, va);
>  
>  	return va;
> diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
> index 3984e585c847..91485b467407 100644
> --- a/drivers/remoteproc/wkup_m3_rproc.c
> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>  {
>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>  	void *va = NULL;
>  	int i;
>  	u32 offset;
>  
> -	if (len <= 0)
> +	if (len == 0)
>  		return NULL;
>  
>  	for (i = 0; i < WKUPM3_MEM_MAX; i++) {
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index 16ad66683ad0..f84bd5fe0211 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -374,7 +374,7 @@ struct rproc_ops {
>  	int (*start)(struct rproc *rproc);
>  	int (*stop)(struct rproc *rproc);
>  	void (*kick)(struct rproc *rproc, int vqid);
> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>  			  int offset, int avail);
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 0/5] remoteproc: Add elf64 support
  2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
                                   ` (4 preceding siblings ...)
  2020-02-10 16:22                 ` [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type Clement Leger
@ 2020-02-11 15:57                 ` Arnaud POULIQUEN
  2020-02-11 23:12                   ` Mathieu Poirier
  5 siblings, 1 reply; 32+ messages in thread
From: Arnaud POULIQUEN @ 2020-02-11 15:57 UTC (permalink / raw)
  To: Clement Leger, Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet,
	Shawn Guo, Sascha Hauer, linux-remoteproc
  Cc: Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna,
	Mathieu Poirier

Hi Clement,

I tested the series on the stm32 platform for remote proc firmwre load: no regression found.
I do not test the da_to_va feature as not implemented on stm32 platform.

Regards,
Arnaud



On 2/10/20 5:22 PM, Clement Leger wrote:
> This serie add support for elf64 in remoteproc (elf loader, coredump). 
> First two patches modifies the type of len argument (in da_to_va) and
> boot_addr in order to allow loading elf64 segment with a u64 size
> and a u64 entry point.
> Next patch introduce a set of macros to access elf64 and elf32
> transparently.
> Last two patches are the actual modification in the elf loader and
> remoteproc coredump support to add elf64 support.
> 
> Changes from V3:
>  - Adapt coredump to elf64 file format
>  - Rename remoteproc_elf_loader.h to remoteproc_elf_helpers.h
>  - Update copyright year in remoteproc_elf_helpers.h
>  - Rename macros elf_hdr_* to elf_get_hdr_* for coherency with elf_hdr_set_*
>  - Split elf64 loader patch in 3:
>    - boot_addr u64 change
>    - remoteproc_elf_helpers.h creation
>    - elf64 loading
> 
> Clement Leger (5):
>   remoteproc: Use u64 len for da_to_va
>   remoteproc: Use u64 type for boot_addr
>   remoteproc: Add elf helpers to access elf64 and elf32 fields
>   remoteproc: Add elf64 support in elf loader
>   remoteproc: Adapt coredump to generate correct elf type
> 
>  Documentation/remoteproc.txt                |   2 +-
>  drivers/remoteproc/imx_rproc.c              |  11 +-
>  drivers/remoteproc/keystone_remoteproc.c    |   4 +-
>  drivers/remoteproc/qcom_q6v5_adsp.c         |   2 +-
>  drivers/remoteproc/qcom_q6v5_mss.c          |   2 +-
>  drivers/remoteproc/qcom_q6v5_pas.c          |   2 +-
>  drivers/remoteproc/qcom_q6v5_wcss.c         |   2 +-
>  drivers/remoteproc/qcom_wcnss.c             |   2 +-
>  drivers/remoteproc/remoteproc_core.c        |  69 +++++++------
>  drivers/remoteproc/remoteproc_elf_helpers.h |  95 ++++++++++++++++++
>  drivers/remoteproc/remoteproc_elf_loader.c  | 150 ++++++++++++++++++----------
>  drivers/remoteproc/remoteproc_internal.h    |   4 +-
>  drivers/remoteproc/st_remoteproc.c          |   2 +-
>  drivers/remoteproc/st_slim_rproc.c          |   4 +-
>  drivers/remoteproc/wkup_m3_rproc.c          |   4 +-
>  include/linux/remoteproc.h                  |   7 +-
>  16 files changed, 252 insertions(+), 110 deletions(-)
>  create mode 100644 drivers/remoteproc/remoteproc_elf_helpers.h
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-11 15:53                   ` Arnaud POULIQUEN
@ 2020-02-11 16:39                     ` Clément Leger
  2020-02-11 17:24                       ` Arnaud POULIQUEN
  2020-02-11 22:37                       ` Mathieu Poirier
  0 siblings, 2 replies; 32+ messages in thread
From: Clément Leger @ 2020-02-11 16:39 UTC (permalink / raw)
  To: Arnaud Pouliquen
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Loic PALLARDY, s-anna, Mathieu Poirier

Hi Arnaud,

----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:

> On 2/10/20 5:22 PM, Clement Leger wrote:
>> With upcoming changes in elf loader for elf64 support, section size will
>> be a u64. When used with da_to_va, this will potentially lead to
>> overflow if using the current "int" type for len argument. Change
>> da_to_va prototype to use a u64 for len and fix all users of this
>> function.
>> 
>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>> ---
>>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
>>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
>>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
>>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
>>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
>>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
>>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
>>  drivers/remoteproc/remoteproc_core.c     |  2 +-
>>  drivers/remoteproc/remoteproc_internal.h |  2 +-
>>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
>>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
>>  include/linux/remoteproc.h               |  2 +-
>>  12 files changed, 20 insertions(+), 19 deletions(-)
>> 
>> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> index 3e72b6f38d4b..f497f5b49b18 100644
>> --- a/drivers/remoteproc/imx_rproc.c
>> +++ b/drivers/remoteproc/imx_rproc.c
>> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
>>  }
>>  
>>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>> -			       int len, u64 *sys)
>> +			       u64 len, u64 *sys)
>>  {
>>  	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
>>  	int i;
>> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
>> da,
>>  		}
>>  	}
>>  
>> -	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
>> +	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
>>  		 da, len);
>>  	return -ENOENT;
>>  }
>>  
>> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct imx_rproc *priv = rproc->priv;
>>  	void *va = NULL;
>>  	u64 sys;
>>  	int i;
>>  
>> -	if (len <= 0)
>> +	if (len == 0)
>>  		return NULL;
>>  
>>  	/*
>> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
>> int len)
>>  		}
>>  	}
>>  
>> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
>> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
>> +		da, len, va);
>>  
>>  	return va;
>>  }
>> diff --git a/drivers/remoteproc/keystone_remoteproc.c
>> b/drivers/remoteproc/keystone_remoteproc.c
>> index 5c4658f00b3d..466093f48814 100644
>> --- a/drivers/remoteproc/keystone_remoteproc.c
>> +++ b/drivers/remoteproc/keystone_remoteproc.c
>> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
>> vqid)
>>   * can be used either by the remoteproc core for loading (when using kernel
>>   * remoteproc loader), or by any rpmsg bus drivers.
>>   */
>> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct keystone_rproc *ksproc = rproc->priv;
>>  	void __iomem *va = NULL;
>> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
>> u64 da, int len)
>>  	size_t size;
>>  	int i;
>>  
>> -	if (len <= 0)
>> +	if (len == 0)
>>  		return NULL;
>>  
>>  	for (i = 0; i < ksproc->num_mems; i++) {
>> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
>> b/drivers/remoteproc/qcom_q6v5_adsp.c
>> index e953886b2eb7..7518e67a49e5 100644
>> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
>> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
>> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>>  	return ret;
>>  }
>>  
>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
>> b/drivers/remoteproc/qcom_q6v5_mss.c
>> index 471128a2e723..248febde6fc1 100644
>> --- a/drivers/remoteproc/qcom_q6v5_mss.c
>> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
>> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct q6v5 *qproc = rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
>> b/drivers/remoteproc/qcom_q6v5_pas.c
>> index db4b3c4bacd7..cf2cd609c90d 100644
>> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
>> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>>  	return ret;
>>  }
>>  
>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
>> b/drivers/remoteproc/qcom_q6v5_wcss.c
>> index f93e1e4a1cc0..3a6b82a16961 100644
>> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
>> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
>> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct q6v5_wcss *wcss = rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
>> index dc135754bb9c..f893219e45a8 100644
>> --- a/drivers/remoteproc/qcom_wcnss.c
>> +++ b/drivers/remoteproc/qcom_wcnss.c
>> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>>  	return ret;
>>  }
>>  
>> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>>  	int offset;
>> diff --git a/drivers/remoteproc/remoteproc_core.c
>> b/drivers/remoteproc/remoteproc_core.c
>> index 307df98347ba..9e6d3c6a60ee 100644
>> --- a/drivers/remoteproc/remoteproc_core.c
>> +++ b/drivers/remoteproc/remoteproc_core.c
>> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>>   * here the output of the DMA API for the carveouts, which should be more
>>   * correct.
>>   */
>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> 
> This function is exported, don't see any update in consequence...
> references:
> https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
> For instance the function rproc_trace_read use it. it quite strange that my gcc
> does not warns for the cast but i suppose that some could.

Agreed, even if len should never have been a signed type since it can't be
negative. I will try to fix all callers.

> An indirect consequence is that the len field in rproc_mem_entry struct should
> probably been updated to u64 to be aligned.

Ok, I will do that once we settle on the type of len.

> 
> I'm still wondering about the use of size_t instead,which seems more rational
> from my window.
> So i you or Mathieu remember it was decided to use u64, please could remind me
> the arguments?

I tried to find the notes of a meeting we had for OpenAMP but I did not found
them. Anyway, the argument was coming from Tomas or someone else, (I can't
remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
In that case, the size_t type could fail due to being only 32bits on the host
CPU but larger than 4G.

However, I can't say if it's a real usecase or not... All I can say is
that keeping it open is probably better if one day somebody comes with such
architecture.

> As an alternative a check should be added for 32 bits processors to ensure that
> the size is not higher than
> its address range capability...

Agreed.
I was even thinking about a mecanism for remoteproc drivers to declare the type
of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
Or should it be supported by overriding .sanity_check in drivers  to reject
elf64 for instance ?

Since elf is a "specific format" and that rproc can support other formats,
I did not want to add a specific elf_sanity_check field to rproc ops.

Regards,

Clément

> 
> Regards
> Arnaud
> 
>>  {
>>  	struct rproc_mem_entry *carveout;
>>  	void *ptr = NULL;
>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>> b/drivers/remoteproc/remoteproc_internal.h
>> index 493ef9262411..004867061721 100644
>> --- a/drivers/remoteproc/remoteproc_internal.h
>> +++ b/drivers/remoteproc/remoteproc_internal.h
>> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>>  void rproc_free_vring(struct rproc_vring *rvring);
>>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>>  
>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>>  int rproc_trigger_recovery(struct rproc *rproc);
>>  
>> diff --git a/drivers/remoteproc/st_slim_rproc.c
>> b/drivers/remoteproc/st_slim_rproc.c
>> index 04492fead3c8..fc01cd879b60 100644
>> --- a/drivers/remoteproc/st_slim_rproc.c
>> +++ b/drivers/remoteproc/st_slim_rproc.c
>> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>>  	void *va = NULL;
>> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
>> da, int len)
>>  		}
>>  	}
>>  
>> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
>> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
>>  		da, len, va);
>>  
>>  	return va;
>> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
>> b/drivers/remoteproc/wkup_m3_rproc.c
>> index 3984e585c847..91485b467407 100644
>> --- a/drivers/remoteproc/wkup_m3_rproc.c
>> +++ b/drivers/remoteproc/wkup_m3_rproc.c
>> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>>  	return 0;
>>  }
>>  
>> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>  {
>>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>>  	void *va = NULL;
>>  	int i;
>>  	u32 offset;
>>  
>> -	if (len <= 0)
>> +	if (len == 0)
>>  		return NULL;
>>  
>>  	for (i = 0; i < WKUPM3_MEM_MAX; i++) {
>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>> index 16ad66683ad0..f84bd5fe0211 100644
>> --- a/include/linux/remoteproc.h
>> +++ b/include/linux/remoteproc.h
>> @@ -374,7 +374,7 @@ struct rproc_ops {
>>  	int (*start)(struct rproc *rproc);
>>  	int (*stop)(struct rproc *rproc);
>>  	void (*kick)(struct rproc *rproc, int vqid);
>> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
>> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>>  			  int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-11 16:39                     ` Clément Leger
@ 2020-02-11 17:24                       ` Arnaud POULIQUEN
  2020-02-11 22:37                       ` Mathieu Poirier
  1 sibling, 0 replies; 32+ messages in thread
From: Arnaud POULIQUEN @ 2020-02-11 17:24 UTC (permalink / raw)
  To: Clément Leger
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Loic PALLARDY, s-anna, Mathieu Poirier



On 2/11/20 5:39 PM, Clément Leger wrote:
> Hi Arnaud,
> 
> ----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
> 
>> On 2/10/20 5:22 PM, Clement Leger wrote:
>>> With upcoming changes in elf loader for elf64 support, section size will
>>> be a u64. When used with da_to_va, this will potentially lead to
>>> overflow if using the current "int" type for len argument. Change
>>> da_to_va prototype to use a u64 for len and fix all users of this
>>> function.
>>>
>>> Signed-off-by: Clement Leger <cleger@kalray.eu>
>>> ---
>>>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
>>>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
>>>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
>>>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
>>>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
>>>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
>>>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
>>>  drivers/remoteproc/remoteproc_core.c     |  2 +-
>>>  drivers/remoteproc/remoteproc_internal.h |  2 +-
>>>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
>>>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
>>>  include/linux/remoteproc.h               |  2 +-
>>>  12 files changed, 20 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>>> index 3e72b6f38d4b..f497f5b49b18 100644
>>> --- a/drivers/remoteproc/imx_rproc.c
>>> +++ b/drivers/remoteproc/imx_rproc.c
>>> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
>>>  }
>>>  
>>>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>>> -			       int len, u64 *sys)
>>> +			       u64 len, u64 *sys)
>>>  {
>>>  	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
>>>  	int i;
>>> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
>>> da,
>>>  		}
>>>  	}
>>>  
>>> -	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
>>> +	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
>>>  		 da, len);
>>>  	return -ENOENT;
>>>  }
>>>  
>>> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct imx_rproc *priv = rproc->priv;
>>>  	void *va = NULL;
>>>  	u64 sys;
>>>  	int i;
>>>  
>>> -	if (len <= 0)
>>> +	if (len == 0)
>>>  		return NULL;
>>>  
>>>  	/*
>>> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
>>> int len)
>>>  		}
>>>  	}
>>>  
>>> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
>>> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
>>> +		da, len, va);
>>>  
>>>  	return va;
>>>  }
>>> diff --git a/drivers/remoteproc/keystone_remoteproc.c
>>> b/drivers/remoteproc/keystone_remoteproc.c
>>> index 5c4658f00b3d..466093f48814 100644
>>> --- a/drivers/remoteproc/keystone_remoteproc.c
>>> +++ b/drivers/remoteproc/keystone_remoteproc.c
>>> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
>>> vqid)
>>>   * can be used either by the remoteproc core for loading (when using kernel
>>>   * remoteproc loader), or by any rpmsg bus drivers.
>>>   */
>>> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct keystone_rproc *ksproc = rproc->priv;
>>>  	void __iomem *va = NULL;
>>> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
>>> u64 da, int len)
>>>  	size_t size;
>>>  	int i;
>>>  
>>> -	if (len <= 0)
>>> +	if (len == 0)
>>>  		return NULL;
>>>  
>>>  	for (i = 0; i < ksproc->num_mems; i++) {
>>> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
>>> b/drivers/remoteproc/qcom_q6v5_adsp.c
>>> index e953886b2eb7..7518e67a49e5 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
>>> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>>>  	return ret;
>>>  }
>>>  
>>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
>>> b/drivers/remoteproc/qcom_q6v5_mss.c
>>> index 471128a2e723..248febde6fc1 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_mss.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
>>> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct q6v5 *qproc = rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
>>> b/drivers/remoteproc/qcom_q6v5_pas.c
>>> index db4b3c4bacd7..cf2cd609c90d 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
>>> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>>>  	return ret;
>>>  }
>>>  
>>> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
>>> b/drivers/remoteproc/qcom_q6v5_wcss.c
>>> index f93e1e4a1cc0..3a6b82a16961 100644
>>> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
>>> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
>>> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct q6v5_wcss *wcss = rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
>>> index dc135754bb9c..f893219e45a8 100644
>>> --- a/drivers/remoteproc/qcom_wcnss.c
>>> +++ b/drivers/remoteproc/qcom_wcnss.c
>>> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>>>  	return ret;
>>>  }
>>>  
>>> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>>>  	int offset;
>>> diff --git a/drivers/remoteproc/remoteproc_core.c
>>> b/drivers/remoteproc/remoteproc_core.c
>>> index 307df98347ba..9e6d3c6a60ee 100644
>>> --- a/drivers/remoteproc/remoteproc_core.c
>>> +++ b/drivers/remoteproc/remoteproc_core.c
>>> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>>>   * here the output of the DMA API for the carveouts, which should be more
>>>   * correct.
>>>   */
>>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>
>> This function is exported, don't see any update in consequence...
>> references:
>> https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
>> For instance the function rproc_trace_read use it. it quite strange that my gcc
>> does not warns for the cast but i suppose that some could.
> 
> Agreed, even if len should never have been a signed type since it can't be
> negative. I will try to fix all callers.
> 
>> An indirect consequence is that the len field in rproc_mem_entry struct should
>> probably been updated to u64 to be aligned.
> 
> Ok, I will do that once we settle on the type of len.
> 
>>
>> I'm still wondering about the use of size_t instead,which seems more rational
>> from my window.
>> So i you or Mathieu remember it was decided to use u64, please could remind me
>> the arguments?
> 
> I tried to find the notes of a meeting we had for OpenAMP but I did not found
> them. Anyway, the argument was coming from Tomas or someone else, (I can't
> remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
> In that case, the size_t type could fail due to being only 32bits on the host
> CPU but larger than 4G.
> 
> However, I can't say if it's a real usecase or not... All I can say is
> that keeping it open is probably better if one day somebody comes with such
> architecture.
> 
>> As an alternative a check should be added for 32 bits processors to ensure that
>> the size is not higher than
>> its address range capability...
> 
> Agreed.
> I was even thinking about a mecanism for remoteproc drivers to declare the type
> of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
> Or should it be supported by overriding .sanity_check in drivers  to reject
> elf64 for instance ?
> 
> Since elf is a "specific format" and that rproc can support other formats,
> I did not want to add a specific elf_sanity_check field to rproc ops.
Agree, platform driver as to check the format it can support, elf, bin, properitay format....
To check the size, the da_to_va ops seems a good candidate as called for loaded segments and memories.
So ok to delegate the check to the platform driver.

Regards
Arnaud

> 
> Regards,
> 
> Clément
> 
>>
>> Regards
>> Arnaud
>>
>>>  {
>>>  	struct rproc_mem_entry *carveout;
>>>  	void *ptr = NULL;
>>> diff --git a/drivers/remoteproc/remoteproc_internal.h
>>> b/drivers/remoteproc/remoteproc_internal.h
>>> index 493ef9262411..004867061721 100644
>>> --- a/drivers/remoteproc/remoteproc_internal.h
>>> +++ b/drivers/remoteproc/remoteproc_internal.h
>>> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>>>  void rproc_free_vring(struct rproc_vring *rvring);
>>>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>>>  
>>> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
>>> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>>>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>>>  int rproc_trigger_recovery(struct rproc *rproc);
>>>  
>>> diff --git a/drivers/remoteproc/st_slim_rproc.c
>>> b/drivers/remoteproc/st_slim_rproc.c
>>> index 04492fead3c8..fc01cd879b60 100644
>>> --- a/drivers/remoteproc/st_slim_rproc.c
>>> +++ b/drivers/remoteproc/st_slim_rproc.c
>>> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>>>  	void *va = NULL;
>>> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
>>> da, int len)
>>>  		}
>>>  	}
>>>  
>>> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
>>> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
>>>  		da, len, va);
>>>  
>>>  	return va;
>>> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
>>> b/drivers/remoteproc/wkup_m3_rproc.c
>>> index 3984e585c847..91485b467407 100644
>>> --- a/drivers/remoteproc/wkup_m3_rproc.c
>>> +++ b/drivers/remoteproc/wkup_m3_rproc.c
>>> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>>>  	return 0;
>>>  }
>>>  
>>> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>>> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>>>  {
>>>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>>>  	void *va = NULL;
>>>  	int i;
>>>  	u32 offset;
>>>  
>>> -	if (len <= 0)
>>> +	if (len == 0)
>>>  		return NULL;
>>>  
>>>  	for (i = 0; i < WKUPM3_MEM_MAX; i++) {
>>> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>>> index 16ad66683ad0..f84bd5fe0211 100644
>>> --- a/include/linux/remoteproc.h
>>> +++ b/include/linux/remoteproc.h
>>> @@ -374,7 +374,7 @@ struct rproc_ops {
>>>  	int (*start)(struct rproc *rproc);
>>>  	int (*stop)(struct rproc *rproc);
>>>  	void (*kick)(struct rproc *rproc, int vqid);
>>> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
>>> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>>>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>>>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
>>>  			  int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-11 16:39                     ` Clément Leger
  2020-02-11 17:24                       ` Arnaud POULIQUEN
@ 2020-02-11 22:37                       ` Mathieu Poirier
  2020-02-12 10:37                         ` Clément Leger
  1 sibling, 1 reply; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-11 22:37 UTC (permalink / raw)
  To: Clément Leger
  Cc: Arnaud Pouliquen, Ohad Ben-Cohen, Bjorn Andersson,
	Jonathan Corbet, Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna

On Tue, Feb 11, 2020 at 05:39:21PM +0100, Clément Leger wrote:
> Hi Arnaud,
> 
> ----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
> 
> > On 2/10/20 5:22 PM, Clement Leger wrote:
> >> With upcoming changes in elf loader for elf64 support, section size will
> >> be a u64. When used with da_to_va, this will potentially lead to
> >> overflow if using the current "int" type for len argument. Change
> >> da_to_va prototype to use a u64 for len and fix all users of this
> >> function.
> >> 
> >> Signed-off-by: Clement Leger <cleger@kalray.eu>
> >> ---
> >>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
> >>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
> >>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
> >>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
> >>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
> >>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
> >>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
> >>  drivers/remoteproc/remoteproc_core.c     |  2 +-
> >>  drivers/remoteproc/remoteproc_internal.h |  2 +-
> >>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
> >>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
> >>  include/linux/remoteproc.h               |  2 +-
> >>  12 files changed, 20 insertions(+), 19 deletions(-)
> >> 
> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> >> index 3e72b6f38d4b..f497f5b49b18 100644
> >> --- a/drivers/remoteproc/imx_rproc.c
> >> +++ b/drivers/remoteproc/imx_rproc.c
> >> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
> >>  }
> >>  
> >>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
> >> -			       int len, u64 *sys)
> >> +			       u64 len, u64 *sys)
> >>  {
> >>  	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
> >>  	int i;
> >> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
> >> da,
> >>  		}
> >>  	}
> >>  
> >> -	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
> >> +	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
> >>  		 da, len);
> >>  	return -ENOENT;
> >>  }
> >>  
> >> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct imx_rproc *priv = rproc->priv;
> >>  	void *va = NULL;
> >>  	u64 sys;
> >>  	int i;
> >>  
> >> -	if (len <= 0)
> >> +	if (len == 0)
> >>  		return NULL;
> >>  
> >>  	/*
> >> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
> >> int len)
> >>  		}
> >>  	}
> >>  
> >> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
> >> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
> >> +		da, len, va);
> >>  
> >>  	return va;
> >>  }
> >> diff --git a/drivers/remoteproc/keystone_remoteproc.c
> >> b/drivers/remoteproc/keystone_remoteproc.c
> >> index 5c4658f00b3d..466093f48814 100644
> >> --- a/drivers/remoteproc/keystone_remoteproc.c
> >> +++ b/drivers/remoteproc/keystone_remoteproc.c
> >> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
> >> vqid)
> >>   * can be used either by the remoteproc core for loading (when using kernel
> >>   * remoteproc loader), or by any rpmsg bus drivers.
> >>   */
> >> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct keystone_rproc *ksproc = rproc->priv;
> >>  	void __iomem *va = NULL;
> >> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
> >> u64 da, int len)
> >>  	size_t size;
> >>  	int i;
> >>  
> >> -	if (len <= 0)
> >> +	if (len == 0)
> >>  		return NULL;
> >>  
> >>  	for (i = 0; i < ksproc->num_mems; i++) {
> >> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
> >> b/drivers/remoteproc/qcom_q6v5_adsp.c
> >> index e953886b2eb7..7518e67a49e5 100644
> >> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> >> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> >> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
> >>  	return ret;
> >>  }
> >>  
> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
> >>  	int offset;
> >> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
> >> b/drivers/remoteproc/qcom_q6v5_mss.c
> >> index 471128a2e723..248febde6fc1 100644
> >> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> >> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> >> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
> >>  	return 0;
> >>  }
> >>  
> >> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct q6v5 *qproc = rproc->priv;
> >>  	int offset;
> >> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
> >> b/drivers/remoteproc/qcom_q6v5_pas.c
> >> index db4b3c4bacd7..cf2cd609c90d 100644
> >> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> >> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> >> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
> >>  	return ret;
> >>  }
> >>  
> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
> >>  	int offset;
> >> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
> >> b/drivers/remoteproc/qcom_q6v5_wcss.c
> >> index f93e1e4a1cc0..3a6b82a16961 100644
> >> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> >> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> >> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
> >>  	return 0;
> >>  }
> >>  
> >> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct q6v5_wcss *wcss = rproc->priv;
> >>  	int offset;
> >> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> >> index dc135754bb9c..f893219e45a8 100644
> >> --- a/drivers/remoteproc/qcom_wcnss.c
> >> +++ b/drivers/remoteproc/qcom_wcnss.c
> >> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
> >>  	return ret;
> >>  }
> >>  
> >> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
> >>  	int offset;
> >> diff --git a/drivers/remoteproc/remoteproc_core.c
> >> b/drivers/remoteproc/remoteproc_core.c
> >> index 307df98347ba..9e6d3c6a60ee 100644
> >> --- a/drivers/remoteproc/remoteproc_core.c
> >> +++ b/drivers/remoteproc/remoteproc_core.c
> >> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
> >>   * here the output of the DMA API for the carveouts, which should be more
> >>   * correct.
> >>   */
> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> > 
> > This function is exported, don't see any update in consequence...
> > references:
> > https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
> > For instance the function rproc_trace_read use it. it quite strange that my gcc
> > does not warns for the cast but i suppose that some could.
> 
> Agreed, even if len should never have been a signed type since it can't be
> negative. I will try to fix all callers.
> 
> > An indirect consequence is that the len field in rproc_mem_entry struct should
> > probably been updated to u64 to be aligned.
> 
> Ok, I will do that once we settle on the type of len.
> 
> > 
> > I'm still wondering about the use of size_t instead,which seems more rational
> > from my window.
> > So i you or Mathieu remember it was decided to use u64, please could remind me
> > the arguments?
> 
> I tried to find the notes of a meeting we had for OpenAMP but I did not found
> them. Anyway, the argument was coming from Tomas or someone else, (I can't
> remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
> In that case, the size_t type could fail due to being only 32bits on the host
> CPU but larger than 4G.
> 
> However, I can't say if it's a real usecase or not... All I can say is
> that keeping it open is probably better if one day somebody comes with such
> architecture.

In order to support a 32bit AP with a 64bit MCU we'd also have to deal with all
the dma_attr_t in the structure we use.

Also something that became very clear to me while thinking about this patchset
is that supporting elf64 does __not__ mean we support 64bit MCU.  As long as
the addresses conveyed by the elf64 image fit within 32 bits we are fine.
Supporting 64bit MCUs is a completely different topic, one that will demand
serious refactoring. 

So moving from "int len" to "u64 len" doesn't give us much.  It doesn't hurt to
do it but if @len ever becomes bigger than 31 bits we'll have other problems to
deal with. 

> 
> > As an alternative a check should be added for 32 bits processors to ensure that
> > the size is not higher than
> > its address range capability...
> 
> Agreed.
> I was even thinking about a mecanism for remoteproc drivers to declare the type
> of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
> Or should it be supported by overriding .sanity_check in drivers  to reject
> elf64 for instance ?
> 
> Since elf is a "specific format" and that rproc can support other formats,
> I did not want to add a specific elf_sanity_check field to rproc ops.
> 
> Regards,
> 
> Clément
> 
> > 
> > Regards
> > Arnaud
> > 
> >>  {
> >>  	struct rproc_mem_entry *carveout;
> >>  	void *ptr = NULL;
> >> diff --git a/drivers/remoteproc/remoteproc_internal.h
> >> b/drivers/remoteproc/remoteproc_internal.h
> >> index 493ef9262411..004867061721 100644
> >> --- a/drivers/remoteproc/remoteproc_internal.h
> >> +++ b/drivers/remoteproc/remoteproc_internal.h
> >> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
> >>  void rproc_free_vring(struct rproc_vring *rvring);
> >>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
> >>  
> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
> >>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
> >>  int rproc_trigger_recovery(struct rproc *rproc);
> >>  
> >> diff --git a/drivers/remoteproc/st_slim_rproc.c
> >> b/drivers/remoteproc/st_slim_rproc.c
> >> index 04492fead3c8..fc01cd879b60 100644
> >> --- a/drivers/remoteproc/st_slim_rproc.c
> >> +++ b/drivers/remoteproc/st_slim_rproc.c
> >> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
> >>  	return 0;
> >>  }
> >>  
> >> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct st_slim_rproc *slim_rproc = rproc->priv;
> >>  	void *va = NULL;
> >> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
> >> da, int len)
> >>  		}
> >>  	}
> >>  
> >> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
> >> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
> >>  		da, len, va);
> >>  
> >>  	return va;
> >> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
> >> b/drivers/remoteproc/wkup_m3_rproc.c
> >> index 3984e585c847..91485b467407 100644
> >> --- a/drivers/remoteproc/wkup_m3_rproc.c
> >> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> >> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
> >>  	return 0;
> >>  }
> >>  
> >> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >>  {
> >>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
> >>  	void *va = NULL;
> >>  	int i;
> >>  	u32 offset;
> >>  
> >> -	if (len <= 0)
> >> +	if (len == 0)
> >>  		return NULL;
> >>  
> >>  	for (i = 0; i < WKUPM3_MEM_MAX; i++) {
> >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> >> index 16ad66683ad0..f84bd5fe0211 100644
> >> --- a/include/linux/remoteproc.h
> >> +++ b/include/linux/remoteproc.h
> >> @@ -374,7 +374,7 @@ struct rproc_ops {
> >>  	int (*start)(struct rproc *rproc);
> >>  	int (*stop)(struct rproc *rproc);
> >>  	void (*kick)(struct rproc *rproc, int vqid);
> >> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
> >> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
> >>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
> >>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
> >>  			  int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type
  2020-02-10 16:22                 ` [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type Clement Leger
@ 2020-02-11 23:11                   ` Mathieu Poirier
  0 siblings, 0 replies; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-11 23:11 UTC (permalink / raw)
  To: Clement Leger
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet, Shawn Guo,
	Sascha Hauer, linux-remoteproc, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Andy Gross, Patrice Chotard,
	linux-doc, linux-kernel, linux-arm-kernel, linux-arm-msm,
	Arnaud Pouliquen, Loic PALLARDY, s-anna

On Mon, Feb 10, 2020 at 05:22:09PM +0100, Clement Leger wrote:
> Now that remoteproc can load an elf64, coredump elf class should be
> the same as the loaded elf class. In order to do that, add a
> elf_class field to rproc with default values. If an elf is loaded
> successfully, these fields will be updated with the loaded elf class.
> Then, the coredump core code has been modified to use the generic elf
> macro in order to create an elf file with correct class.
> 
> Signed-off-by: Clement Leger <cleger@kalray.eu>
> ---
>  drivers/remoteproc/remoteproc_core.c       | 67 ++++++++++++++++--------------
>  drivers/remoteproc/remoteproc_elf_loader.c |  3 ++
>  include/linux/remoteproc.h                 |  1 +
>  3 files changed, 39 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 9e6d3c6a60ee..ce70656ae150 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -38,6 +38,7 @@
>  #include <linux/platform_device.h>
>  
>  #include "remoteproc_internal.h"
> +#include "remoteproc_elf_helpers.h"
>  
>  #define HIGH_BITS_MASK 0xFFFFFFFF00000000ULL
>  
> @@ -1564,20 +1565,21 @@ EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
>  static void rproc_coredump(struct rproc *rproc)
>  {
>  	struct rproc_dump_segment *segment;
> -	struct elf32_phdr *phdr;
> -	struct elf32_hdr *ehdr;
> +	void *phdr;
> +	void *ehdr;
>  	size_t data_size;
>  	size_t offset;
>  	void *data;
>  	void *ptr;
> +	u8 class = rproc->elf_class;
>  	int phnum = 0;
>  
>  	if (list_empty(&rproc->dump_segments))
>  		return;
>  
> -	data_size = sizeof(*ehdr);
> +	data_size = elf_size_of_hdr(class);
>  	list_for_each_entry(segment, &rproc->dump_segments, node) {
> -		data_size += sizeof(*phdr) + segment->size;
> +		data_size += elf_size_of_phdr(class) + segment->size;
>  
>  		phnum++;
>  	}
> @@ -1588,33 +1590,33 @@ static void rproc_coredump(struct rproc *rproc)
>  
>  	ehdr = data;
>  
> -	memset(ehdr, 0, sizeof(*ehdr));
> -	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
> -	ehdr->e_ident[EI_CLASS] = ELFCLASS32;
> -	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
> -	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
> -	ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
> -	ehdr->e_type = ET_CORE;
> -	ehdr->e_machine = EM_NONE;
> -	ehdr->e_version = EV_CURRENT;
> -	ehdr->e_entry = rproc->bootaddr;
> -	ehdr->e_phoff = sizeof(*ehdr);
> -	ehdr->e_ehsize = sizeof(*ehdr);
> -	ehdr->e_phentsize = sizeof(*phdr);
> -	ehdr->e_phnum = phnum;
> -
> -	phdr = data + ehdr->e_phoff;
> -	offset = ehdr->e_phoff + sizeof(*phdr) * ehdr->e_phnum;
> +	memset(ehdr, 0, elf_size_of_hdr(class));
> +	/* e_ident field is common for both elf32 and elf64 */
> +	elf_hdr_init_ident(ehdr, class);
> +
> +	elf_hdr_set_e_type(class, ehdr, ET_CORE);
> +	elf_hdr_set_e_machine(class, ehdr, EM_NONE);
> +	elf_hdr_set_e_version(class, ehdr, EV_CURRENT);
> +	elf_hdr_set_e_entry(class, ehdr, rproc->bootaddr);
> +	elf_hdr_set_e_phoff(class, ehdr, elf_size_of_hdr(class));
> +	elf_hdr_set_e_ehsize(class, ehdr, elf_size_of_hdr(class));
> +	elf_hdr_set_e_phentsize(class, ehdr, elf_size_of_phdr(class));
> +	elf_hdr_set_e_phnum(class, ehdr, phnum);
> +
> +	phdr = data + elf_hdr_get_e_phoff(class, ehdr);
> +	offset = elf_hdr_get_e_phoff(class, ehdr);
> +	offset += elf_size_of_phdr(class) * elf_hdr_get_e_phnum(class, ehdr);
> +
>  	list_for_each_entry(segment, &rproc->dump_segments, node) {
> -		memset(phdr, 0, sizeof(*phdr));
> -		phdr->p_type = PT_LOAD;
> -		phdr->p_offset = offset;
> -		phdr->p_vaddr = segment->da;
> -		phdr->p_paddr = segment->da;
> -		phdr->p_filesz = segment->size;
> -		phdr->p_memsz = segment->size;
> -		phdr->p_flags = PF_R | PF_W | PF_X;
> -		phdr->p_align = 0;
> +		memset(phdr, 0, elf_size_of_phdr(class));
> +		elf_phdr_set_p_type(class, phdr, PT_LOAD);
> +		elf_phdr_set_p_offset(class, phdr, offset);
> +		elf_phdr_set_p_vaddr(class, phdr, segment->da);
> +		elf_phdr_set_p_paddr(class, phdr, segment->da);
> +		elf_phdr_set_p_filesz(class, phdr, segment->size);
> +		elf_phdr_set_p_memsz(class, phdr, segment->size);
> +		elf_phdr_set_p_flags(class, phdr, PF_R | PF_W | PF_X);
> +		elf_phdr_set_p_align(class, phdr, 0);
>  
>  		if (segment->dump) {
>  			segment->dump(rproc, segment, data + offset);
> @@ -1630,8 +1632,8 @@ static void rproc_coredump(struct rproc *rproc)
>  			}
>  		}
>  
> -		offset += phdr->p_filesz;
> -		phdr++;
> +		offset += elf_phdr_get_p_filesz(class, phdr);
> +		phdr += elf_size_of_phdr(class);
>  	}
>  
>  	dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL);
> @@ -2029,6 +2031,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
>  	rproc->name = name;
>  	rproc->priv = &rproc[1];
>  	rproc->auto_boot = true;
> +	rproc->elf_class = ELFCLASS32;

I suppose this is as good a place as any.

>  
>  	device_initialize(&rproc->dev);
>  	rproc->dev.parent = dev;
> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
> index 2ffb02a2ee36..07712a541ea6 100644
> --- a/drivers/remoteproc/remoteproc_elf_loader.c
> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
> @@ -220,6 +220,9 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  			memset(ptr + filesz, 0, memsz - filesz);
>  	}
>  
> +	if (ret == 0)
> +		rproc->elf_class = class;
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL(rproc_elf_load_segments);
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index 82cebca9344c..113e356ce56a 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -514,6 +514,7 @@ struct rproc {
>  	bool auto_boot;
>  	struct list_head dump_segments;
>  	int nb_vdev;
> +	int elf_class;

Type 'int'?  I expected 'u8' as it is in the specification and in
rproc_elf_load_segments().

Thanks,
Mathieu


>  };
>  
>  /**
> -- 
> 2.15.0.276.g89ea799
> 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 0/5] remoteproc: Add elf64 support
  2020-02-11 15:57                 ` [PATCH v4 0/5] remoteproc: Add elf64 support Arnaud POULIQUEN
@ 2020-02-11 23:12                   ` Mathieu Poirier
  2020-02-12  8:15                     ` Arnaud POULIQUEN
  0 siblings, 1 reply; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-11 23:12 UTC (permalink / raw)
  To: Arnaud POULIQUEN
  Cc: Clement Leger, Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet,
	Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna

On Tue, Feb 11, 2020 at 04:57:18PM +0100, Arnaud POULIQUEN wrote:
> Hi Clement,
> 
> I tested the series on the stm32 platform for remote proc firmwre load: no regression found.
> I do not test the da_to_va feature as not implemented on stm32 platform.

It would be very interesting if you could test the coredump, that would give us
a lot more confidence in the implementation.

Thanks,
Mathieu

> 
> Regards,
> Arnaud
> 
> 
> 
> On 2/10/20 5:22 PM, Clement Leger wrote:
> > This serie add support for elf64 in remoteproc (elf loader, coredump). 
> > First two patches modifies the type of len argument (in da_to_va) and
> > boot_addr in order to allow loading elf64 segment with a u64 size
> > and a u64 entry point.
> > Next patch introduce a set of macros to access elf64 and elf32
> > transparently.
> > Last two patches are the actual modification in the elf loader and
> > remoteproc coredump support to add elf64 support.
> > 
> > Changes from V3:
> >  - Adapt coredump to elf64 file format
> >  - Rename remoteproc_elf_loader.h to remoteproc_elf_helpers.h
> >  - Update copyright year in remoteproc_elf_helpers.h
> >  - Rename macros elf_hdr_* to elf_get_hdr_* for coherency with elf_hdr_set_*
> >  - Split elf64 loader patch in 3:
> >    - boot_addr u64 change
> >    - remoteproc_elf_helpers.h creation
> >    - elf64 loading
> > 
> > Clement Leger (5):
> >   remoteproc: Use u64 len for da_to_va
> >   remoteproc: Use u64 type for boot_addr
> >   remoteproc: Add elf helpers to access elf64 and elf32 fields
> >   remoteproc: Add elf64 support in elf loader
> >   remoteproc: Adapt coredump to generate correct elf type
> > 
> >  Documentation/remoteproc.txt                |   2 +-
> >  drivers/remoteproc/imx_rproc.c              |  11 +-
> >  drivers/remoteproc/keystone_remoteproc.c    |   4 +-
> >  drivers/remoteproc/qcom_q6v5_adsp.c         |   2 +-
> >  drivers/remoteproc/qcom_q6v5_mss.c          |   2 +-
> >  drivers/remoteproc/qcom_q6v5_pas.c          |   2 +-
> >  drivers/remoteproc/qcom_q6v5_wcss.c         |   2 +-
> >  drivers/remoteproc/qcom_wcnss.c             |   2 +-
> >  drivers/remoteproc/remoteproc_core.c        |  69 +++++++------
> >  drivers/remoteproc/remoteproc_elf_helpers.h |  95 ++++++++++++++++++
> >  drivers/remoteproc/remoteproc_elf_loader.c  | 150 ++++++++++++++++++----------
> >  drivers/remoteproc/remoteproc_internal.h    |   4 +-
> >  drivers/remoteproc/st_remoteproc.c          |   2 +-
> >  drivers/remoteproc/st_slim_rproc.c          |   4 +-
> >  drivers/remoteproc/wkup_m3_rproc.c          |   4 +-
> >  include/linux/remoteproc.h                  |   7 +-
> >  16 files changed, 252 insertions(+), 110 deletions(-)
> >  create mode 100644 drivers/remoteproc/remoteproc_elf_helpers.h
> > 

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 0/5] remoteproc: Add elf64 support
  2020-02-11 23:12                   ` Mathieu Poirier
@ 2020-02-12  8:15                     ` Arnaud POULIQUEN
  0 siblings, 0 replies; 32+ messages in thread
From: Arnaud POULIQUEN @ 2020-02-12  8:15 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Clement Leger, Ohad Ben-Cohen, Bjorn Andersson, Jonathan Corbet,
	Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna



On 2/12/20 12:12 AM, Mathieu Poirier wrote:
> On Tue, Feb 11, 2020 at 04:57:18PM +0100, Arnaud POULIQUEN wrote:
>> Hi Clement,
>>
>> I tested the series on the stm32 platform for remote proc firmwre load: no regression found.
>> I do not test the da_to_va feature as not implemented on stm32 platform.
> 
> It would be very interesting if you could test the coredump, that would give us
> a lot more confidence in the implementation.
I also tested the coredump generation. LGTM

> 
> Thanks,
> Mathieu
> 
>>
>> Regards,
>> Arnaud
>>
>>
>>
>> On 2/10/20 5:22 PM, Clement Leger wrote:
>>> This serie add support for elf64 in remoteproc (elf loader, coredump). 
>>> First two patches modifies the type of len argument (in da_to_va) and
>>> boot_addr in order to allow loading elf64 segment with a u64 size
>>> and a u64 entry point.
>>> Next patch introduce a set of macros to access elf64 and elf32
>>> transparently.
>>> Last two patches are the actual modification in the elf loader and
>>> remoteproc coredump support to add elf64 support.
>>>
>>> Changes from V3:
>>>  - Adapt coredump to elf64 file format
>>>  - Rename remoteproc_elf_loader.h to remoteproc_elf_helpers.h
>>>  - Update copyright year in remoteproc_elf_helpers.h
>>>  - Rename macros elf_hdr_* to elf_get_hdr_* for coherency with elf_hdr_set_*
>>>  - Split elf64 loader patch in 3:
>>>    - boot_addr u64 change
>>>    - remoteproc_elf_helpers.h creation
>>>    - elf64 loading
>>>
>>> Clement Leger (5):
>>>   remoteproc: Use u64 len for da_to_va
>>>   remoteproc: Use u64 type for boot_addr
>>>   remoteproc: Add elf helpers to access elf64 and elf32 fields
>>>   remoteproc: Add elf64 support in elf loader
>>>   remoteproc: Adapt coredump to generate correct elf type
>>>
>>>  Documentation/remoteproc.txt                |   2 +-
>>>  drivers/remoteproc/imx_rproc.c              |  11 +-
>>>  drivers/remoteproc/keystone_remoteproc.c    |   4 +-
>>>  drivers/remoteproc/qcom_q6v5_adsp.c         |   2 +-
>>>  drivers/remoteproc/qcom_q6v5_mss.c          |   2 +-
>>>  drivers/remoteproc/qcom_q6v5_pas.c          |   2 +-
>>>  drivers/remoteproc/qcom_q6v5_wcss.c         |   2 +-
>>>  drivers/remoteproc/qcom_wcnss.c             |   2 +-
>>>  drivers/remoteproc/remoteproc_core.c        |  69 +++++++------
>>>  drivers/remoteproc/remoteproc_elf_helpers.h |  95 ++++++++++++++++++
>>>  drivers/remoteproc/remoteproc_elf_loader.c  | 150 ++++++++++++++++++----------
>>>  drivers/remoteproc/remoteproc_internal.h    |   4 +-
>>>  drivers/remoteproc/st_remoteproc.c          |   2 +-
>>>  drivers/remoteproc/st_slim_rproc.c          |   4 +-
>>>  drivers/remoteproc/wkup_m3_rproc.c          |   4 +-
>>>  include/linux/remoteproc.h                  |   7 +-
>>>  16 files changed, 252 insertions(+), 110 deletions(-)
>>>  create mode 100644 drivers/remoteproc/remoteproc_elf_helpers.h
>>>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-11 22:37                       ` Mathieu Poirier
@ 2020-02-12 10:37                         ` Clément Leger
  2020-02-12 21:59                           ` Mathieu Poirier
  0 siblings, 1 reply; 32+ messages in thread
From: Clément Leger @ 2020-02-12 10:37 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Arnaud Pouliquen, Ohad Ben-Cohen, Bjorn Andersson,
	Jonathan Corbet, Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna

Hi Mathieu,

----- On 11 Feb, 2020, at 23:37, Mathieu Poirier mathieu.poirier@linaro.org wrote:

> On Tue, Feb 11, 2020 at 05:39:21PM +0100, Clément Leger wrote:
>> Hi Arnaud,
>> 
>> ----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
>> 
>> > On 2/10/20 5:22 PM, Clement Leger wrote:
>> >> With upcoming changes in elf loader for elf64 support, section size will
>> >> be a u64. When used with da_to_va, this will potentially lead to
>> >> overflow if using the current "int" type for len argument. Change
>> >> da_to_va prototype to use a u64 for len and fix all users of this
>> >> function.
>> >> 
>> >> Signed-off-by: Clement Leger <cleger@kalray.eu>
>> >> ---
>> >>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
>> >>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
>> >>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
>> >>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
>> >>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
>> >>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
>> >>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
>> >>  drivers/remoteproc/remoteproc_core.c     |  2 +-
>> >>  drivers/remoteproc/remoteproc_internal.h |  2 +-
>> >>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
>> >>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
>> >>  include/linux/remoteproc.h               |  2 +-
>> >>  12 files changed, 20 insertions(+), 19 deletions(-)
>> >> 
>> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> >> index 3e72b6f38d4b..f497f5b49b18 100644
>> >> --- a/drivers/remoteproc/imx_rproc.c
>> >> +++ b/drivers/remoteproc/imx_rproc.c
>> >> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
>> >>  }
>> >>  
>> >>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>> >> -			       int len, u64 *sys)
>> >> +			       u64 len, u64 *sys)
>> >>  {
>> >>  	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
>> >>  	int i;
>> >> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
>> >> da,
>> >>  		}
>> >>  	}
>> >>  
>> >> -	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
>> >> +	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
>> >>  		 da, len);
>> >>  	return -ENOENT;
>> >>  }
>> >>  
>> >> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct imx_rproc *priv = rproc->priv;
>> >>  	void *va = NULL;
>> >>  	u64 sys;
>> >>  	int i;
>> >>  
>> >> -	if (len <= 0)
>> >> +	if (len == 0)
>> >>  		return NULL;
>> >>  
>> >>  	/*
>> >> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
>> >> int len)
>> >>  		}
>> >>  	}
>> >>  
>> >> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
>> >> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
>> >> +		da, len, va);
>> >>  
>> >>  	return va;
>> >>  }
>> >> diff --git a/drivers/remoteproc/keystone_remoteproc.c
>> >> b/drivers/remoteproc/keystone_remoteproc.c
>> >> index 5c4658f00b3d..466093f48814 100644
>> >> --- a/drivers/remoteproc/keystone_remoteproc.c
>> >> +++ b/drivers/remoteproc/keystone_remoteproc.c
>> >> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
>> >> vqid)
>> >>   * can be used either by the remoteproc core for loading (when using kernel
>> >>   * remoteproc loader), or by any rpmsg bus drivers.
>> >>   */
>> >> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct keystone_rproc *ksproc = rproc->priv;
>> >>  	void __iomem *va = NULL;
>> >> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
>> >> u64 da, int len)
>> >>  	size_t size;
>> >>  	int i;
>> >>  
>> >> -	if (len <= 0)
>> >> +	if (len == 0)
>> >>  		return NULL;
>> >>  
>> >>  	for (i = 0; i < ksproc->num_mems; i++) {
>> >> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> b/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> index e953886b2eb7..7518e67a49e5 100644
>> >> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>> >>  	return ret;
>> >>  }
>> >>  
>> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>> >>  	int offset;
>> >> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
>> >> b/drivers/remoteproc/qcom_q6v5_mss.c
>> >> index 471128a2e723..248febde6fc1 100644
>> >> --- a/drivers/remoteproc/qcom_q6v5_mss.c
>> >> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
>> >> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>> >>  	return 0;
>> >>  }
>> >>  
>> >> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct q6v5 *qproc = rproc->priv;
>> >>  	int offset;
>> >> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
>> >> b/drivers/remoteproc/qcom_q6v5_pas.c
>> >> index db4b3c4bacd7..cf2cd609c90d 100644
>> >> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>> >> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
>> >> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>> >>  	return ret;
>> >>  }
>> >>  
>> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>> >>  	int offset;
>> >> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> b/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> index f93e1e4a1cc0..3a6b82a16961 100644
>> >> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>> >>  	return 0;
>> >>  }
>> >>  
>> >> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct q6v5_wcss *wcss = rproc->priv;
>> >>  	int offset;
>> >> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
>> >> index dc135754bb9c..f893219e45a8 100644
>> >> --- a/drivers/remoteproc/qcom_wcnss.c
>> >> +++ b/drivers/remoteproc/qcom_wcnss.c
>> >> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>> >>  	return ret;
>> >>  }
>> >>  
>> >> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>> >>  	int offset;
>> >> diff --git a/drivers/remoteproc/remoteproc_core.c
>> >> b/drivers/remoteproc/remoteproc_core.c
>> >> index 307df98347ba..9e6d3c6a60ee 100644
>> >> --- a/drivers/remoteproc/remoteproc_core.c
>> >> +++ b/drivers/remoteproc/remoteproc_core.c
>> >> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>> >>   * here the output of the DMA API for the carveouts, which should be more
>> >>   * correct.
>> >>   */
>> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> > 
>> > This function is exported, don't see any update in consequence...
>> > references:
>> > https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
>> > For instance the function rproc_trace_read use it. it quite strange that my gcc
>> > does not warns for the cast but i suppose that some could.
>> 
>> Agreed, even if len should never have been a signed type since it can't be
>> negative. I will try to fix all callers.
>> 
>> > An indirect consequence is that the len field in rproc_mem_entry struct should
>> > probably been updated to u64 to be aligned.
>> 
>> Ok, I will do that once we settle on the type of len.
>> 
>> > 
>> > I'm still wondering about the use of size_t instead,which seems more rational
>> > from my window.
>> > So i you or Mathieu remember it was decided to use u64, please could remind me
>> > the arguments?
>> 
>> I tried to find the notes of a meeting we had for OpenAMP but I did not found
>> them. Anyway, the argument was coming from Tomas or someone else, (I can't
>> remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
>> In that case, the size_t type could fail due to being only 32bits on the host
>> CPU but larger than 4G.
>> 
>> However, I can't say if it's a real usecase or not... All I can say is
>> that keeping it open is probably better if one day somebody comes with such
>> architecture.
> 
> In order to support a 32bit AP with a 64bit MCU we'd also have to deal with all
> the dma_attr_t in the structure we use.

Totally ok with that... 

> 
> Also something that became very clear to me while thinking about this patchset
> is that supporting elf64 does __not__ mean we support 64bit MCU.  As long as
> the addresses conveyed by the elf64 image fit within 32 bits we are fine.
> Supporting 64bit MCUs is a completely different topic, one that will demand
> serious refactoring.

Exactly, an elf64 can potentially contain an executable fitting in 32 bits.

> 
> So moving from "int len" to "u64 len" doesn't give us much.  It doesn't hurt to
> do it but if @len ever becomes bigger than 31 bits we'll have other problems to
> deal with.

Agreed, so what would be your recommendation reagrding the type of len ?
I'm ok with Arnaud statement too and using a size_t is probably more
"type-safe" than a u64. At least it adds some information.

Thanks,

Clément

> 
>> 
>> > As an alternative a check should be added for 32 bits processors to ensure that
>> > the size is not higher than
>> > its address range capability...
>> 
>> Agreed.
>> I was even thinking about a mecanism for remoteproc drivers to declare the type
>> of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
>> Or should it be supported by overriding .sanity_check in drivers  to reject
>> elf64 for instance ?
>> 
>> Since elf is a "specific format" and that rproc can support other formats,
>> I did not want to add a specific elf_sanity_check field to rproc ops.
>> 
>> Regards,
>> 
>> Clément
>> 
>> > 
>> > Regards
>> > Arnaud
>> > 
>> >>  {
>> >>  	struct rproc_mem_entry *carveout;
>> >>  	void *ptr = NULL;
>> >> diff --git a/drivers/remoteproc/remoteproc_internal.h
>> >> b/drivers/remoteproc/remoteproc_internal.h
>> >> index 493ef9262411..004867061721 100644
>> >> --- a/drivers/remoteproc/remoteproc_internal.h
>> >> +++ b/drivers/remoteproc/remoteproc_internal.h
>> >> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>> >>  void rproc_free_vring(struct rproc_vring *rvring);
>> >>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>> >>  
>> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
>> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>> >>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>> >>  int rproc_trigger_recovery(struct rproc *rproc);
>> >>  
>> >> diff --git a/drivers/remoteproc/st_slim_rproc.c
>> >> b/drivers/remoteproc/st_slim_rproc.c
>> >> index 04492fead3c8..fc01cd879b60 100644
>> >> --- a/drivers/remoteproc/st_slim_rproc.c
>> >> +++ b/drivers/remoteproc/st_slim_rproc.c
>> >> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>> >>  	return 0;
>> >>  }
>> >>  
>> >> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>> >>  	void *va = NULL;
>> >> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
>> >> da, int len)
>> >>  		}
>> >>  	}
>> >>  
>> >> -	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
>> >> +	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
>> >>  		da, len, va);
>> >>  
>> >>  	return va;
>> >> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
>> >> b/drivers/remoteproc/wkup_m3_rproc.c
>> >> index 3984e585c847..91485b467407 100644
>> >> --- a/drivers/remoteproc/wkup_m3_rproc.c
>> >> +++ b/drivers/remoteproc/wkup_m3_rproc.c
>> >> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>> >>  	return 0;
>> >>  }
>> >>  
>> >> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >>  {
>> >>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>> >>  	void *va = NULL;
>> >>  	int i;
>> >>  	u32 offset;
>> >>  
>> >> -	if (len <= 0)
>> >> +	if (len == 0)
>> >>  		return NULL;
>> >>  
>> >>  	for (i = 0; i < WKUPM3_MEM_MAX; i++) {
>> >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>> >> index 16ad66683ad0..f84bd5fe0211 100644
>> >> --- a/include/linux/remoteproc.h
>> >> +++ b/include/linux/remoteproc.h
>> >> @@ -374,7 +374,7 @@ struct rproc_ops {
>> >>  	int (*start)(struct rproc *rproc);
>> >>  	int (*stop)(struct rproc *rproc);
>> >>  	void (*kick)(struct rproc *rproc, int vqid);
>> >> -	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
>> >> +	void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>> >>  	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>> >>  	int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
> > >>  			  int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-12 10:37                         ` Clément Leger
@ 2020-02-12 21:59                           ` Mathieu Poirier
  2020-02-18 10:10                             ` Clément Leger
  0 siblings, 1 reply; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-12 21:59 UTC (permalink / raw)
  To: Clément Leger
  Cc: Arnaud Pouliquen, Ohad Ben-Cohen, Bjorn Andersson,
	Jonathan Corbet, Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna

On Wed, 12 Feb 2020 at 03:37, Clément Leger <cleger@kalray.eu> wrote:
>
> Hi Mathieu,
>
> ----- On 11 Feb, 2020, at 23:37, Mathieu Poirier mathieu.poirier@linaro.org wrote:
>
> > On Tue, Feb 11, 2020 at 05:39:21PM +0100, Clément Leger wrote:
> >> Hi Arnaud,
> >>
> >> ----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
> >>
> >> > On 2/10/20 5:22 PM, Clement Leger wrote:
> >> >> With upcoming changes in elf loader for elf64 support, section size will
> >> >> be a u64. When used with da_to_va, this will potentially lead to
> >> >> overflow if using the current "int" type for len argument. Change
> >> >> da_to_va prototype to use a u64 for len and fix all users of this
> >> >> function.
> >> >>
> >> >> Signed-off-by: Clement Leger <cleger@kalray.eu>
> >> >> ---
> >> >>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
> >> >>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
> >> >>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
> >> >>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
> >> >>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
> >> >>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
> >> >>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
> >> >>  drivers/remoteproc/remoteproc_core.c     |  2 +-
> >> >>  drivers/remoteproc/remoteproc_internal.h |  2 +-
> >> >>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
> >> >>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
> >> >>  include/linux/remoteproc.h               |  2 +-
> >> >>  12 files changed, 20 insertions(+), 19 deletions(-)
> >> >>
> >> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> >> >> index 3e72b6f38d4b..f497f5b49b18 100644
> >> >> --- a/drivers/remoteproc/imx_rproc.c
> >> >> +++ b/drivers/remoteproc/imx_rproc.c
> >> >> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
> >> >>  }
> >> >>
> >> >>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
> >> >> -                        int len, u64 *sys)
> >> >> +                        u64 len, u64 *sys)
> >> >>  {
> >> >>   const struct imx_rproc_dcfg *dcfg = priv->dcfg;
> >> >>   int i;
> >> >> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
> >> >> da,
> >> >>           }
> >> >>   }
> >> >>
> >> >> - dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
> >> >> + dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
> >> >>            da, len);
> >> >>   return -ENOENT;
> >> >>  }
> >> >>
> >> >> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct imx_rproc *priv = rproc->priv;
> >> >>   void *va = NULL;
> >> >>   u64 sys;
> >> >>   int i;
> >> >>
> >> >> - if (len <= 0)
> >> >> + if (len == 0)
> >> >>           return NULL;
> >> >>
> >> >>   /*
> >> >> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
> >> >> int len)
> >> >>           }
> >> >>   }
> >> >>
> >> >> - dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
> >> >> + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
> >> >> +         da, len, va);
> >> >>
> >> >>   return va;
> >> >>  }
> >> >> diff --git a/drivers/remoteproc/keystone_remoteproc.c
> >> >> b/drivers/remoteproc/keystone_remoteproc.c
> >> >> index 5c4658f00b3d..466093f48814 100644
> >> >> --- a/drivers/remoteproc/keystone_remoteproc.c
> >> >> +++ b/drivers/remoteproc/keystone_remoteproc.c
> >> >> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
> >> >> vqid)
> >> >>   * can be used either by the remoteproc core for loading (when using kernel
> >> >>   * remoteproc loader), or by any rpmsg bus drivers.
> >> >>   */
> >> >> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct keystone_rproc *ksproc = rproc->priv;
> >> >>   void __iomem *va = NULL;
> >> >> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
> >> >> u64 da, int len)
> >> >>   size_t size;
> >> >>   int i;
> >> >>
> >> >> - if (len <= 0)
> >> >> + if (len == 0)
> >> >>           return NULL;
> >> >>
> >> >>   for (i = 0; i < ksproc->num_mems; i++) {
> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> b/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> index e953886b2eb7..7518e67a49e5 100644
> >> >> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
> >> >>   return ret;
> >> >>  }
> >> >>
> >> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
> >> >>   int offset;
> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> b/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> index 471128a2e723..248febde6fc1 100644
> >> >> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
> >> >>   return 0;
> >> >>  }
> >> >>
> >> >> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct q6v5 *qproc = rproc->priv;
> >> >>   int offset;
> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> b/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> index db4b3c4bacd7..cf2cd609c90d 100644
> >> >> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
> >> >>   return ret;
> >> >>  }
> >> >>
> >> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
> >> >>   int offset;
> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> b/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> index f93e1e4a1cc0..3a6b82a16961 100644
> >> >> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
> >> >>   return 0;
> >> >>  }
> >> >>
> >> >> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct q6v5_wcss *wcss = rproc->priv;
> >> >>   int offset;
> >> >> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> >> >> index dc135754bb9c..f893219e45a8 100644
> >> >> --- a/drivers/remoteproc/qcom_wcnss.c
> >> >> +++ b/drivers/remoteproc/qcom_wcnss.c
> >> >> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
> >> >>   return ret;
> >> >>  }
> >> >>
> >> >> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
> >> >>   int offset;
> >> >> diff --git a/drivers/remoteproc/remoteproc_core.c
> >> >> b/drivers/remoteproc/remoteproc_core.c
> >> >> index 307df98347ba..9e6d3c6a60ee 100644
> >> >> --- a/drivers/remoteproc/remoteproc_core.c
> >> >> +++ b/drivers/remoteproc/remoteproc_core.c
> >> >> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
> >> >>   * here the output of the DMA API for the carveouts, which should be more
> >> >>   * correct.
> >> >>   */
> >> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >
> >> > This function is exported, don't see any update in consequence...
> >> > references:
> >> > https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
> >> > For instance the function rproc_trace_read use it. it quite strange that my gcc
> >> > does not warns for the cast but i suppose that some could.
> >>
> >> Agreed, even if len should never have been a signed type since it can't be
> >> negative. I will try to fix all callers.
> >>
> >> > An indirect consequence is that the len field in rproc_mem_entry struct should
> >> > probably been updated to u64 to be aligned.
> >>
> >> Ok, I will do that once we settle on the type of len.
> >>
> >> >
> >> > I'm still wondering about the use of size_t instead,which seems more rational
> >> > from my window.
> >> > So i you or Mathieu remember it was decided to use u64, please could remind me
> >> > the arguments?
> >>
> >> I tried to find the notes of a meeting we had for OpenAMP but I did not found
> >> them. Anyway, the argument was coming from Tomas or someone else, (I can't
> >> remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
> >> In that case, the size_t type could fail due to being only 32bits on the host
> >> CPU but larger than 4G.
> >>
> >> However, I can't say if it's a real usecase or not... All I can say is
> >> that keeping it open is probably better if one day somebody comes with such
> >> architecture.
> >
> > In order to support a 32bit AP with a 64bit MCU we'd also have to deal with all
> > the dma_attr_t in the structure we use.
>
> Totally ok with that...
>
> >
> > Also something that became very clear to me while thinking about this patchset
> > is that supporting elf64 does __not__ mean we support 64bit MCU.  As long as
> > the addresses conveyed by the elf64 image fit within 32 bits we are fine.
> > Supporting 64bit MCUs is a completely different topic, one that will demand
> > serious refactoring.
>
> Exactly, an elf64 can potentially contain an executable fitting in 32 bits.
>
> >
> > So moving from "int len" to "u64 len" doesn't give us much.  It doesn't hurt to
> > do it but if @len ever becomes bigger than 31 bits we'll have other problems to
> > deal with.
>
> Agreed, so what would be your recommendation reagrding the type of len ?
> I'm ok with Arnaud statement too and using a size_t is probably more
> "type-safe" than a u64. At least it adds some information.

If @len becomes big enough that it doesn't fit in 31bit then it is
very likely that things will break even before we get to call
rproc_da_to_va().  Fixing it here is possible but will introduce a
fair amount of ripple effect that we probably don't want to deal with
right now.

Other people might feel more opinionated on this but as far as I'm
concerned, I would keep it as it is and fix it for real when the time
comes to add support for 64bit MCUs.

>
> Thanks,
>
> Clément
>
> >
> >>
> >> > As an alternative a check should be added for 32 bits processors to ensure that
> >> > the size is not higher than
> >> > its address range capability...
> >>
> >> Agreed.
> >> I was even thinking about a mecanism for remoteproc drivers to declare the type
> >> of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
> >> Or should it be supported by overriding .sanity_check in drivers  to reject
> >> elf64 for instance ?
> >>
> >> Since elf is a "specific format" and that rproc can support other formats,
> >> I did not want to add a specific elf_sanity_check field to rproc ops.
> >>
> >> Regards,
> >>
> >> Clément
> >>
> >> >
> >> > Regards
> >> > Arnaud
> >> >
> >> >>  {
> >> >>   struct rproc_mem_entry *carveout;
> >> >>   void *ptr = NULL;
> >> >> diff --git a/drivers/remoteproc/remoteproc_internal.h
> >> >> b/drivers/remoteproc/remoteproc_internal.h
> >> >> index 493ef9262411..004867061721 100644
> >> >> --- a/drivers/remoteproc/remoteproc_internal.h
> >> >> +++ b/drivers/remoteproc/remoteproc_internal.h
> >> >> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
> >> >>  void rproc_free_vring(struct rproc_vring *rvring);
> >> >>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
> >> >>
> >> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
> >> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
> >> >>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
> >> >>  int rproc_trigger_recovery(struct rproc *rproc);
> >> >>
> >> >> diff --git a/drivers/remoteproc/st_slim_rproc.c
> >> >> b/drivers/remoteproc/st_slim_rproc.c
> >> >> index 04492fead3c8..fc01cd879b60 100644
> >> >> --- a/drivers/remoteproc/st_slim_rproc.c
> >> >> +++ b/drivers/remoteproc/st_slim_rproc.c
> >> >> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
> >> >>   return 0;
> >> >>  }
> >> >>
> >> >> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct st_slim_rproc *slim_rproc = rproc->priv;
> >> >>   void *va = NULL;
> >> >> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
> >> >> da, int len)
> >> >>           }
> >> >>   }
> >> >>
> >> >> - dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
> >> >> + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
> >> >>           da, len, va);
> >> >>
> >> >>   return va;
> >> >> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
> >> >> b/drivers/remoteproc/wkup_m3_rproc.c
> >> >> index 3984e585c847..91485b467407 100644
> >> >> --- a/drivers/remoteproc/wkup_m3_rproc.c
> >> >> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> >> >> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
> >> >>   return 0;
> >> >>  }
> >> >>
> >> >> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >>  {
> >> >>   struct wkup_m3_rproc *wkupm3 = rproc->priv;
> >> >>   void *va = NULL;
> >> >>   int i;
> >> >>   u32 offset;
> >> >>
> >> >> - if (len <= 0)
> >> >> + if (len == 0)
> >> >>           return NULL;
> >> >>
> >> >>   for (i = 0; i < WKUPM3_MEM_MAX; i++) {
> >> >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> >> >> index 16ad66683ad0..f84bd5fe0211 100644
> >> >> --- a/include/linux/remoteproc.h
> >> >> +++ b/include/linux/remoteproc.h
> >> >> @@ -374,7 +374,7 @@ struct rproc_ops {
> >> >>   int (*start)(struct rproc *rproc);
> >> >>   int (*stop)(struct rproc *rproc);
> >> >>   void (*kick)(struct rproc *rproc, int vqid);
> >> >> - void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
> >> >> + void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
> >> >>   int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
> >> >>   int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
> > > >>                            int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-12 21:59                           ` Mathieu Poirier
@ 2020-02-18 10:10                             ` Clément Leger
  2020-02-18 17:01                               ` Mathieu Poirier
  0 siblings, 1 reply; 32+ messages in thread
From: Clément Leger @ 2020-02-18 10:10 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Arnaud Pouliquen, Ohad Ben-Cohen, Bjorn Andersson,
	Jonathan Corbet, Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna

Hi Mathieu,

----- On 12 Feb, 2020, at 22:59, Mathieu Poirier mathieu.poirier@linaro.org wrote:

> On Wed, 12 Feb 2020 at 03:37, Clément Leger <cleger@kalray.eu> wrote:
>>
>> Hi Mathieu,
>>
>> ----- On 11 Feb, 2020, at 23:37, Mathieu Poirier mathieu.poirier@linaro.org
>> wrote:
>>
>> > On Tue, Feb 11, 2020 at 05:39:21PM +0100, Clément Leger wrote:
>> >> Hi Arnaud,
>> >>
>> >> ----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
>> >>
>> >> > On 2/10/20 5:22 PM, Clement Leger wrote:
>> >> >> With upcoming changes in elf loader for elf64 support, section size will
>> >> >> be a u64. When used with da_to_va, this will potentially lead to
>> >> >> overflow if using the current "int" type for len argument. Change
>> >> >> da_to_va prototype to use a u64 for len and fix all users of this
>> >> >> function.
>> >> >>
>> >> >> Signed-off-by: Clement Leger <cleger@kalray.eu>
>> >> >> ---
>> >> >>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
>> >> >>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
>> >> >>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
>> >> >>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
>> >> >>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
>> >> >>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
>> >> >>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
>> >> >>  drivers/remoteproc/remoteproc_core.c     |  2 +-
>> >> >>  drivers/remoteproc/remoteproc_internal.h |  2 +-
>> >> >>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
>> >> >>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
>> >> >>  include/linux/remoteproc.h               |  2 +-
>> >> >>  12 files changed, 20 insertions(+), 19 deletions(-)
>> >> >>
>> >> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
>> >> >> index 3e72b6f38d4b..f497f5b49b18 100644
>> >> >> --- a/drivers/remoteproc/imx_rproc.c
>> >> >> +++ b/drivers/remoteproc/imx_rproc.c
>> >> >> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
>> >> >>  }
>> >> >>
>> >> >>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>> >> >> -                        int len, u64 *sys)
>> >> >> +                        u64 len, u64 *sys)
>> >> >>  {
>> >> >>   const struct imx_rproc_dcfg *dcfg = priv->dcfg;
>> >> >>   int i;
>> >> >> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
>> >> >> da,
>> >> >>           }
>> >> >>   }
>> >> >>
>> >> >> - dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
>> >> >> + dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
>> >> >>            da, len);
>> >> >>   return -ENOENT;
>> >> >>  }
>> >> >>
>> >> >> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct imx_rproc *priv = rproc->priv;
>> >> >>   void *va = NULL;
>> >> >>   u64 sys;
>> >> >>   int i;
>> >> >>
>> >> >> - if (len <= 0)
>> >> >> + if (len == 0)
>> >> >>           return NULL;
>> >> >>
>> >> >>   /*
>> >> >> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
>> >> >> int len)
>> >> >>           }
>> >> >>   }
>> >> >>
>> >> >> - dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
>> >> >> + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
>> >> >> +         da, len, va);
>> >> >>
>> >> >>   return va;
>> >> >>  }
>> >> >> diff --git a/drivers/remoteproc/keystone_remoteproc.c
>> >> >> b/drivers/remoteproc/keystone_remoteproc.c
>> >> >> index 5c4658f00b3d..466093f48814 100644
>> >> >> --- a/drivers/remoteproc/keystone_remoteproc.c
>> >> >> +++ b/drivers/remoteproc/keystone_remoteproc.c
>> >> >> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
>> >> >> vqid)
>> >> >>   * can be used either by the remoteproc core for loading (when using kernel
>> >> >>   * remoteproc loader), or by any rpmsg bus drivers.
>> >> >>   */
>> >> >> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct keystone_rproc *ksproc = rproc->priv;
>> >> >>   void __iomem *va = NULL;
>> >> >> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
>> >> >> u64 da, int len)
>> >> >>   size_t size;
>> >> >>   int i;
>> >> >>
>> >> >> - if (len <= 0)
>> >> >> + if (len == 0)
>> >> >>           return NULL;
>> >> >>
>> >> >>   for (i = 0; i < ksproc->num_mems; i++) {
>> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> >> b/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> >> index e953886b2eb7..7518e67a49e5 100644
>> >> >> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> >> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
>> >> >> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
>> >> >>   return ret;
>> >> >>  }
>> >> >>
>> >> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>> >> >>   int offset;
>> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
>> >> >> b/drivers/remoteproc/qcom_q6v5_mss.c
>> >> >> index 471128a2e723..248febde6fc1 100644
>> >> >> --- a/drivers/remoteproc/qcom_q6v5_mss.c
>> >> >> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
>> >> >> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
>> >> >>   return 0;
>> >> >>  }
>> >> >>
>> >> >> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct q6v5 *qproc = rproc->priv;
>> >> >>   int offset;
>> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
>> >> >> b/drivers/remoteproc/qcom_q6v5_pas.c
>> >> >> index db4b3c4bacd7..cf2cd609c90d 100644
>> >> >> --- a/drivers/remoteproc/qcom_q6v5_pas.c
>> >> >> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
>> >> >> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
>> >> >>   return ret;
>> >> >>  }
>> >> >>
>> >> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>> >> >>   int offset;
>> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> >> b/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> >> index f93e1e4a1cc0..3a6b82a16961 100644
>> >> >> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> >> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
>> >> >> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>> >> >>   return 0;
>> >> >>  }
>> >> >>
>> >> >> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct q6v5_wcss *wcss = rproc->priv;
>> >> >>   int offset;
>> >> >> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
>> >> >> index dc135754bb9c..f893219e45a8 100644
>> >> >> --- a/drivers/remoteproc/qcom_wcnss.c
>> >> >> +++ b/drivers/remoteproc/qcom_wcnss.c
>> >> >> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
>> >> >>   return ret;
>> >> >>  }
>> >> >>
>> >> >> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>> >> >>   int offset;
>> >> >> diff --git a/drivers/remoteproc/remoteproc_core.c
>> >> >> b/drivers/remoteproc/remoteproc_core.c
>> >> >> index 307df98347ba..9e6d3c6a60ee 100644
>> >> >> --- a/drivers/remoteproc/remoteproc_core.c
>> >> >> +++ b/drivers/remoteproc/remoteproc_core.c
>> >> >> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>> >> >>   * here the output of the DMA API for the carveouts, which should be more
>> >> >>   * correct.
>> >> >>   */
>> >> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >
>> >> > This function is exported, don't see any update in consequence...
>> >> > references:
>> >> > https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
>> >> > For instance the function rproc_trace_read use it. it quite strange that my gcc
>> >> > does not warns for the cast but i suppose that some could.
>> >>
>> >> Agreed, even if len should never have been a signed type since it can't be
>> >> negative. I will try to fix all callers.
>> >>
>> >> > An indirect consequence is that the len field in rproc_mem_entry struct should
>> >> > probably been updated to u64 to be aligned.
>> >>
>> >> Ok, I will do that once we settle on the type of len.
>> >>
>> >> >
>> >> > I'm still wondering about the use of size_t instead,which seems more rational
>> >> > from my window.
>> >> > So i you or Mathieu remember it was decided to use u64, please could remind me
>> >> > the arguments?
>> >>
>> >> I tried to find the notes of a meeting we had for OpenAMP but I did not found
>> >> them. Anyway, the argument was coming from Tomas or someone else, (I can't
>> >> remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
>> >> In that case, the size_t type could fail due to being only 32bits on the host
>> >> CPU but larger than 4G.
>> >>
>> >> However, I can't say if it's a real usecase or not... All I can say is
>> >> that keeping it open is probably better if one day somebody comes with such
>> >> architecture.
>> >
>> > In order to support a 32bit AP with a 64bit MCU we'd also have to deal with all
>> > the dma_attr_t in the structure we use.
>>
>> Totally ok with that...
>>
>> >
>> > Also something that became very clear to me while thinking about this patchset
>> > is that supporting elf64 does __not__ mean we support 64bit MCU.  As long as
>> > the addresses conveyed by the elf64 image fit within 32 bits we are fine.
>> > Supporting 64bit MCUs is a completely different topic, one that will demand
>> > serious refactoring.
>>
>> Exactly, an elf64 can potentially contain an executable fitting in 32 bits.
>>
>> >
>> > So moving from "int len" to "u64 len" doesn't give us much.  It doesn't hurt to
>> > do it but if @len ever becomes bigger than 31 bits we'll have other problems to
>> > deal with.
>>
>> Agreed, so what would be your recommendation reagrding the type of len ?
>> I'm ok with Arnaud statement too and using a size_t is probably more
>> "type-safe" than a u64. At least it adds some information.
> 
> If @len becomes big enough that it doesn't fit in 31bit then it is
> very likely that things will break even before we get to call
> rproc_da_to_va().  Fixing it here is possible but will introduce a
> fair amount of ripple effect that we probably don't want to deal with
> right now.

I did the modification using u64 and tried to follow various code path.
Some end up in dma_alloc_coherent which uses a size_t member. Since
these might be called by rproc with a u64 len, I would be more
inclined to use a size_t. I can probably also add a check in elf loader
which verifies that if sizeof(size_t) < sizeof(u64), then the len must
fit in 32bits. This seems more clean IMHO.

Clément.

> 
> Other people might feel more opinionated on this but as far as I'm
> concerned, I would keep it as it is and fix it for real when the time
> comes to add support for 64bit MCUs.
> 
>>
>> Thanks,
>>
>> Clément
>>
>> >
>> >>
>> >> > As an alternative a check should be added for 32 bits processors to ensure that
>> >> > the size is not higher than
>> >> > its address range capability...
>> >>
>> >> Agreed.
>> >> I was even thinking about a mecanism for remoteproc drivers to declare the type
>> >> of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
>> >> Or should it be supported by overriding .sanity_check in drivers  to reject
>> >> elf64 for instance ?
>> >>
>> >> Since elf is a "specific format" and that rproc can support other formats,
>> >> I did not want to add a specific elf_sanity_check field to rproc ops.
>> >>
>> >> Regards,
>> >>
>> >> Clément
>> >>
>> >> >
>> >> > Regards
>> >> > Arnaud
>> >> >
>> >> >>  {
>> >> >>   struct rproc_mem_entry *carveout;
>> >> >>   void *ptr = NULL;
>> >> >> diff --git a/drivers/remoteproc/remoteproc_internal.h
>> >> >> b/drivers/remoteproc/remoteproc_internal.h
>> >> >> index 493ef9262411..004867061721 100644
>> >> >> --- a/drivers/remoteproc/remoteproc_internal.h
>> >> >> +++ b/drivers/remoteproc/remoteproc_internal.h
>> >> >> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
>> >> >>  void rproc_free_vring(struct rproc_vring *rvring);
>> >> >>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>> >> >>
>> >> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
>> >> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
>> >> >>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>> >> >>  int rproc_trigger_recovery(struct rproc *rproc);
>> >> >>
>> >> >> diff --git a/drivers/remoteproc/st_slim_rproc.c
>> >> >> b/drivers/remoteproc/st_slim_rproc.c
>> >> >> index 04492fead3c8..fc01cd879b60 100644
>> >> >> --- a/drivers/remoteproc/st_slim_rproc.c
>> >> >> +++ b/drivers/remoteproc/st_slim_rproc.c
>> >> >> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>> >> >>   return 0;
>> >> >>  }
>> >> >>
>> >> >> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct st_slim_rproc *slim_rproc = rproc->priv;
>> >> >>   void *va = NULL;
>> >> >> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
>> >> >> da, int len)
>> >> >>           }
>> >> >>   }
>> >> >>
>> >> >> - dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
>> >> >> + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
>> >> >>           da, len, va);
>> >> >>
>> >> >>   return va;
>> >> >> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
>> >> >> b/drivers/remoteproc/wkup_m3_rproc.c
>> >> >> index 3984e585c847..91485b467407 100644
>> >> >> --- a/drivers/remoteproc/wkup_m3_rproc.c
>> >> >> +++ b/drivers/remoteproc/wkup_m3_rproc.c
>> >> >> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>> >> >>   return 0;
>> >> >>  }
>> >> >>
>> >> >> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
>> >> >> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
>> >> >>  {
>> >> >>   struct wkup_m3_rproc *wkupm3 = rproc->priv;
>> >> >>   void *va = NULL;
>> >> >>   int i;
>> >> >>   u32 offset;
>> >> >>
>> >> >> - if (len <= 0)
>> >> >> + if (len == 0)
>> >> >>           return NULL;
>> >> >>
>> >> >>   for (i = 0; i < WKUPM3_MEM_MAX; i++) {
>> >> >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>> >> >> index 16ad66683ad0..f84bd5fe0211 100644
>> >> >> --- a/include/linux/remoteproc.h
>> >> >> +++ b/include/linux/remoteproc.h
>> >> >> @@ -374,7 +374,7 @@ struct rproc_ops {
>> >> >>   int (*start)(struct rproc *rproc);
>> >> >>   int (*stop)(struct rproc *rproc);
>> >> >>   void (*kick)(struct rproc *rproc, int vqid);
>> >> >> - void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
>> >> >> + void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
>> >> >>   int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
>> >> >>   int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
> > > > >>                            int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va
  2020-02-18 10:10                             ` Clément Leger
@ 2020-02-18 17:01                               ` Mathieu Poirier
  0 siblings, 0 replies; 32+ messages in thread
From: Mathieu Poirier @ 2020-02-18 17:01 UTC (permalink / raw)
  To: Clément Leger
  Cc: Arnaud Pouliquen, Ohad Ben-Cohen, Bjorn Andersson,
	Jonathan Corbet, Shawn Guo, Sascha Hauer, linux-remoteproc,
	Pengutronix Kernel Team, Fabio Estevam, NXP Linux Team,
	Andy Gross, Patrice Chotard, linux-doc, linux-kernel,
	linux-arm-kernel, linux-arm-msm, Loic PALLARDY, s-anna

On Tue, 18 Feb 2020 at 03:10, Clément Leger <cleger@kalrayinc.com> wrote:
>
> Hi Mathieu,
>
> ----- On 12 Feb, 2020, at 22:59, Mathieu Poirier mathieu.poirier@linaro.org wrote:
>
> > On Wed, 12 Feb 2020 at 03:37, Clément Leger <cleger@kalray.eu> wrote:
> >>
> >> Hi Mathieu,
> >>
> >> ----- On 11 Feb, 2020, at 23:37, Mathieu Poirier mathieu.poirier@linaro.org
> >> wrote:
> >>
> >> > On Tue, Feb 11, 2020 at 05:39:21PM +0100, Clément Leger wrote:
> >> >> Hi Arnaud,
> >> >>
> >> >> ----- On 11 Feb, 2020, at 16:53, Arnaud Pouliquen arnaud.pouliquen@st.com wrote:
> >> >>
> >> >> > On 2/10/20 5:22 PM, Clement Leger wrote:
> >> >> >> With upcoming changes in elf loader for elf64 support, section size will
> >> >> >> be a u64. When used with da_to_va, this will potentially lead to
> >> >> >> overflow if using the current "int" type for len argument. Change
> >> >> >> da_to_va prototype to use a u64 for len and fix all users of this
> >> >> >> function.
> >> >> >>
> >> >> >> Signed-off-by: Clement Leger <cleger@kalray.eu>
> >> >> >> ---
> >> >> >>  drivers/remoteproc/imx_rproc.c           | 11 ++++++-----
> >> >> >>  drivers/remoteproc/keystone_remoteproc.c |  4 ++--
> >> >> >>  drivers/remoteproc/qcom_q6v5_adsp.c      |  2 +-
> >> >> >>  drivers/remoteproc/qcom_q6v5_mss.c       |  2 +-
> >> >> >>  drivers/remoteproc/qcom_q6v5_pas.c       |  2 +-
> >> >> >>  drivers/remoteproc/qcom_q6v5_wcss.c      |  2 +-
> >> >> >>  drivers/remoteproc/qcom_wcnss.c          |  2 +-
> >> >> >>  drivers/remoteproc/remoteproc_core.c     |  2 +-
> >> >> >>  drivers/remoteproc/remoteproc_internal.h |  2 +-
> >> >> >>  drivers/remoteproc/st_slim_rproc.c       |  4 ++--
> >> >> >>  drivers/remoteproc/wkup_m3_rproc.c       |  4 ++--
> >> >> >>  include/linux/remoteproc.h               |  2 +-
> >> >> >>  12 files changed, 20 insertions(+), 19 deletions(-)
> >> >> >>
> >> >> >> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> >> >> >> index 3e72b6f38d4b..f497f5b49b18 100644
> >> >> >> --- a/drivers/remoteproc/imx_rproc.c
> >> >> >> +++ b/drivers/remoteproc/imx_rproc.c
> >> >> >> @@ -186,7 +186,7 @@ static int imx_rproc_stop(struct rproc *rproc)
> >> >> >>  }
> >> >> >>
> >> >> >>  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
> >> >> >> -                        int len, u64 *sys)
> >> >> >> +                        u64 len, u64 *sys)
> >> >> >>  {
> >> >> >>   const struct imx_rproc_dcfg *dcfg = priv->dcfg;
> >> >> >>   int i;
> >> >> >> @@ -203,19 +203,19 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64
> >> >> >> da,
> >> >> >>           }
> >> >> >>   }
> >> >> >>
> >> >> >> - dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
> >> >> >> + dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%llx\n",
> >> >> >>            da, len);
> >> >> >>   return -ENOENT;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct imx_rproc *priv = rproc->priv;
> >> >> >>   void *va = NULL;
> >> >> >>   u64 sys;
> >> >> >>   int i;
> >> >> >>
> >> >> >> - if (len <= 0)
> >> >> >> + if (len == 0)
> >> >> >>           return NULL;
> >> >> >>
> >> >> >>   /*
> >> >> >> @@ -235,7 +235,8 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da,
> >> >> >> int len)
> >> >> >>           }
> >> >> >>   }
> >> >> >>
> >> >> >> - dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%p\n", da, len, va);
> >> >> >> + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%p\n",
> >> >> >> +         da, len, va);
> >> >> >>
> >> >> >>   return va;
> >> >> >>  }
> >> >> >> diff --git a/drivers/remoteproc/keystone_remoteproc.c
> >> >> >> b/drivers/remoteproc/keystone_remoteproc.c
> >> >> >> index 5c4658f00b3d..466093f48814 100644
> >> >> >> --- a/drivers/remoteproc/keystone_remoteproc.c
> >> >> >> +++ b/drivers/remoteproc/keystone_remoteproc.c
> >> >> >> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int
> >> >> >> vqid)
> >> >> >>   * can be used either by the remoteproc core for loading (when using kernel
> >> >> >>   * remoteproc loader), or by any rpmsg bus drivers.
> >> >> >>   */
> >> >> >> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct keystone_rproc *ksproc = rproc->priv;
> >> >> >>   void __iomem *va = NULL;
> >> >> >> @@ -255,7 +255,7 @@ static void *keystone_rproc_da_to_va(struct rproc *rproc,
> >> >> >> u64 da, int len)
> >> >> >>   size_t size;
> >> >> >>   int i;
> >> >> >>
> >> >> >> - if (len <= 0)
> >> >> >> + if (len == 0)
> >> >> >>           return NULL;
> >> >> >>
> >> >> >>   for (i = 0; i < ksproc->num_mems; i++) {
> >> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> >> b/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> >> index e953886b2eb7..7518e67a49e5 100644
> >> >> >> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> >> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> >> >> >> @@ -270,7 +270,7 @@ static int adsp_stop(struct rproc *rproc)
> >> >> >>   return ret;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
> >> >> >>   int offset;
> >> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> >> b/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> >> index 471128a2e723..248febde6fc1 100644
> >> >> >> --- a/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> >> +++ b/drivers/remoteproc/qcom_q6v5_mss.c
> >> >> >> @@ -1148,7 +1148,7 @@ static int q6v5_stop(struct rproc *rproc)
> >> >> >>   return 0;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *q6v5_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct q6v5 *qproc = rproc->priv;
> >> >> >>   int offset;
> >> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> >> b/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> >> index db4b3c4bacd7..cf2cd609c90d 100644
> >> >> >> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> >> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> >> >> >> @@ -159,7 +159,7 @@ static int adsp_stop(struct rproc *rproc)
> >> >> >>   return ret;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
> >> >> >>   int offset;
> >> >> >> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> >> b/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> >> index f93e1e4a1cc0..3a6b82a16961 100644
> >> >> >> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> >> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> >> >> >> @@ -406,7 +406,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
> >> >> >>   return 0;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct q6v5_wcss *wcss = rproc->priv;
> >> >> >>   int offset;
> >> >> >> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> >> >> >> index dc135754bb9c..f893219e45a8 100644
> >> >> >> --- a/drivers/remoteproc/qcom_wcnss.c
> >> >> >> +++ b/drivers/remoteproc/qcom_wcnss.c
> >> >> >> @@ -287,7 +287,7 @@ static int wcnss_stop(struct rproc *rproc)
> >> >> >>   return ret;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
> >> >> >>   int offset;
> >> >> >> diff --git a/drivers/remoteproc/remoteproc_core.c
> >> >> >> b/drivers/remoteproc/remoteproc_core.c
> >> >> >> index 307df98347ba..9e6d3c6a60ee 100644
> >> >> >> --- a/drivers/remoteproc/remoteproc_core.c
> >> >> >> +++ b/drivers/remoteproc/remoteproc_core.c
> >> >> >> @@ -185,7 +185,7 @@ EXPORT_SYMBOL(rproc_va_to_pa);
> >> >> >>   * here the output of the DMA API for the carveouts, which should be more
> >> >> >>   * correct.
> >> >> >>   */
> >> >> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >
> >> >> > This function is exported, don't see any update in consequence...
> >> >> > references:
> >> >> > https://elixir.bootlin.com/linux/v5.6-rc1/ident/rproc_da_to_va
> >> >> > For instance the function rproc_trace_read use it. it quite strange that my gcc
> >> >> > does not warns for the cast but i suppose that some could.
> >> >>
> >> >> Agreed, even if len should never have been a signed type since it can't be
> >> >> negative. I will try to fix all callers.
> >> >>
> >> >> > An indirect consequence is that the len field in rproc_mem_entry struct should
> >> >> > probably been updated to u64 to be aligned.
> >> >>
> >> >> Ok, I will do that once we settle on the type of len.
> >> >>
> >> >> >
> >> >> > I'm still wondering about the use of size_t instead,which seems more rational
> >> >> > from my window.
> >> >> > So i you or Mathieu remember it was decided to use u64, please could remind me
> >> >> > the arguments?
> >> >>
> >> >> I tried to find the notes of a meeting we had for OpenAMP but I did not found
> >> >> them. Anyway, the argument was coming from Tomas or someone else, (I can't
> >> >> remember) talking about a 32 bits CPU executing code on a 64 bits accelerator.
> >> >> In that case, the size_t type could fail due to being only 32bits on the host
> >> >> CPU but larger than 4G.
> >> >>
> >> >> However, I can't say if it's a real usecase or not... All I can say is
> >> >> that keeping it open is probably better if one day somebody comes with such
> >> >> architecture.
> >> >
> >> > In order to support a 32bit AP with a 64bit MCU we'd also have to deal with all
> >> > the dma_attr_t in the structure we use.
> >>
> >> Totally ok with that...
> >>
> >> >
> >> > Also something that became very clear to me while thinking about this patchset
> >> > is that supporting elf64 does __not__ mean we support 64bit MCU.  As long as
> >> > the addresses conveyed by the elf64 image fit within 32 bits we are fine.
> >> > Supporting 64bit MCUs is a completely different topic, one that will demand
> >> > serious refactoring.
> >>
> >> Exactly, an elf64 can potentially contain an executable fitting in 32 bits.
> >>
> >> >
> >> > So moving from "int len" to "u64 len" doesn't give us much.  It doesn't hurt to
> >> > do it but if @len ever becomes bigger than 31 bits we'll have other problems to
> >> > deal with.
> >>
> >> Agreed, so what would be your recommendation reagrding the type of len ?
> >> I'm ok with Arnaud statement too and using a size_t is probably more
> >> "type-safe" than a u64. At least it adds some information.
> >
> > If @len becomes big enough that it doesn't fit in 31bit then it is
> > very likely that things will break even before we get to call
> > rproc_da_to_va().  Fixing it here is possible but will introduce a
> > fair amount of ripple effect that we probably don't want to deal with
> > right now.
>
> I did the modification using u64 and tried to follow various code path.
> Some end up in dma_alloc_coherent which uses a size_t member. Since
> these might be called by rproc with a u64 len, I would be more
> inclined to use a size_t. I can probably also add a check in elf loader
> which verifies that if sizeof(size_t) < sizeof(u64), then the len must
> fit in 32bits. This seems more clean IMHO.
>

I'm all good with that.

> Clément.
>
> >
> > Other people might feel more opinionated on this but as far as I'm
> > concerned, I would keep it as it is and fix it for real when the time
> > comes to add support for 64bit MCUs.
> >
> >>
> >> Thanks,
> >>
> >> Clément
> >>
> >> >
> >> >>
> >> >> > As an alternative a check should be added for 32 bits processors to ensure that
> >> >> > the size is not higher than
> >> >> > its address range capability...
> >> >>
> >> >> Agreed.
> >> >> I was even thinking about a mecanism for remoteproc drivers to declare the type
> >> >> of supported elfs files (such as EM_*, ELFCLASS* and other needed thing).
> >> >> Or should it be supported by overriding .sanity_check in drivers  to reject
> >> >> elf64 for instance ?
> >> >>
> >> >> Since elf is a "specific format" and that rproc can support other formats,
> >> >> I did not want to add a specific elf_sanity_check field to rproc ops.
> >> >>
> >> >> Regards,
> >> >>
> >> >> Clément
> >> >>
> >> >> >
> >> >> > Regards
> >> >> > Arnaud
> >> >> >
> >> >> >>  {
> >> >> >>   struct rproc_mem_entry *carveout;
> >> >> >>   void *ptr = NULL;
> >> >> >> diff --git a/drivers/remoteproc/remoteproc_internal.h
> >> >> >> b/drivers/remoteproc/remoteproc_internal.h
> >> >> >> index 493ef9262411..004867061721 100644
> >> >> >> --- a/drivers/remoteproc/remoteproc_internal.h
> >> >> >> +++ b/drivers/remoteproc/remoteproc_internal.h
> >> >> >> @@ -50,7 +50,7 @@ void rproc_exit_sysfs(void);
> >> >> >>  void rproc_free_vring(struct rproc_vring *rvring);
> >> >> >>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
> >> >> >>
> >> >> >> -void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
> >> >> >> +void *rproc_da_to_va(struct rproc *rproc, u64 da, u64 len);
> >> >> >>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
> >> >> >>  int rproc_trigger_recovery(struct rproc *rproc);
> >> >> >>
> >> >> >> diff --git a/drivers/remoteproc/st_slim_rproc.c
> >> >> >> b/drivers/remoteproc/st_slim_rproc.c
> >> >> >> index 04492fead3c8..fc01cd879b60 100644
> >> >> >> --- a/drivers/remoteproc/st_slim_rproc.c
> >> >> >> +++ b/drivers/remoteproc/st_slim_rproc.c
> >> >> >> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
> >> >> >>   return 0;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct st_slim_rproc *slim_rproc = rproc->priv;
> >> >> >>   void *va = NULL;
> >> >> >> @@ -191,7 +191,7 @@ static void *slim_rproc_da_to_va(struct rproc *rproc, u64
> >> >> >> da, int len)
> >> >> >>           }
> >> >> >>   }
> >> >> >>
> >> >> >> - dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%x va = 0x%pK\n",
> >> >> >> + dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%llx va = 0x%pK\n",
> >> >> >>           da, len, va);
> >> >> >>
> >> >> >>   return va;
> >> >> >> diff --git a/drivers/remoteproc/wkup_m3_rproc.c
> >> >> >> b/drivers/remoteproc/wkup_m3_rproc.c
> >> >> >> index 3984e585c847..91485b467407 100644
> >> >> >> --- a/drivers/remoteproc/wkup_m3_rproc.c
> >> >> >> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> >> >> >> @@ -80,14 +80,14 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
> >> >> >>   return 0;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> >> >> >> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, u64 len)
> >> >> >>  {
> >> >> >>   struct wkup_m3_rproc *wkupm3 = rproc->priv;
> >> >> >>   void *va = NULL;
> >> >> >>   int i;
> >> >> >>   u32 offset;
> >> >> >>
> >> >> >> - if (len <= 0)
> >> >> >> + if (len == 0)
> >> >> >>           return NULL;
> >> >> >>
> >> >> >>   for (i = 0; i < WKUPM3_MEM_MAX; i++) {
> >> >> >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> >> >> >> index 16ad66683ad0..f84bd5fe0211 100644
> >> >> >> --- a/include/linux/remoteproc.h
> >> >> >> +++ b/include/linux/remoteproc.h
> >> >> >> @@ -374,7 +374,7 @@ struct rproc_ops {
> >> >> >>   int (*start)(struct rproc *rproc);
> >> >> >>   int (*stop)(struct rproc *rproc);
> >> >> >>   void (*kick)(struct rproc *rproc, int vqid);
> >> >> >> - void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
> >> >> >> + void * (*da_to_va)(struct rproc *rproc, u64 da, u64 len);
> >> >> >>   int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
> >> >> >>   int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
> > > > > >>                            int offset, int avail);

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, back to index

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20200129163013.GA16538@xps15>
2020-02-04 14:33 ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
2020-02-04 14:33   ` [PATCH v2 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
2020-02-04 16:27   ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Arnaud POULIQUEN
2020-02-04 17:10     ` Clément Leger
2020-02-04 17:42       ` Arnaud POULIQUEN
2020-02-04 17:44 ` [PATCH v3 0/2] remoteproc: Add elf64 support to elf loader Clement Leger
2020-02-04 17:44   ` [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va Clement Leger
2020-02-05 21:06     ` Mathieu Poirier
2020-02-04 17:44   ` [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader Clement Leger
2020-02-05 22:49     ` Mathieu Poirier
2020-02-06  8:37       ` Clément Leger
2020-02-06 15:05         ` Clément Leger
2020-02-06 17:48           ` Mathieu Poirier
2020-02-07  7:57             ` Clément Leger
2020-02-10 16:22               ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger
2020-02-10 16:22                 ` [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va Clement Leger
2020-02-11 15:53                   ` Arnaud POULIQUEN
2020-02-11 16:39                     ` Clément Leger
2020-02-11 17:24                       ` Arnaud POULIQUEN
2020-02-11 22:37                       ` Mathieu Poirier
2020-02-12 10:37                         ` Clément Leger
2020-02-12 21:59                           ` Mathieu Poirier
2020-02-18 10:10                             ` Clément Leger
2020-02-18 17:01                               ` Mathieu Poirier
2020-02-10 16:22                 ` [PATCH v4 2/5] remoteproc: Use u64 type for boot_addr Clement Leger
2020-02-10 16:22                 ` [PATCH v4 3/5] remoteproc: Add elf helpers to access elf64 and elf32 fields Clement Leger
2020-02-10 16:22                 ` [PATCH v4 4/5] remoteproc: Add elf64 support in elf loader Clement Leger
2020-02-10 16:22                 ` [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type Clement Leger
2020-02-11 23:11                   ` Mathieu Poirier
2020-02-11 15:57                 ` [PATCH v4 0/5] remoteproc: Add elf64 support Arnaud POULIQUEN
2020-02-11 23:12                   ` Mathieu Poirier
2020-02-12  8:15                     ` Arnaud POULIQUEN

Linux-Doc Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-doc/0 linux-doc/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-doc linux-doc/ https://lore.kernel.org/linux-doc \
		linux-doc@vger.kernel.org
	public-inbox-index linux-doc

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-doc


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git