mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support
@ 2017-09-19 11:58 marcandre.lureau
  2017-09-19 11:58 ` [PATCH v2 1/4] fw_cfg: add DMA register marcandre.lureau
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: marcandre.lureau @ 2017-09-19 11:58 UTC (permalink / raw)
  To: linux-kernel; +Cc: somlo, qemu-devel, mst, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Hi,

This series brings DMA operations support to the fw_cfg kernel module
and provide "etc/vmcoreinfo" support.

At the current iteration of "[Qemu-devel] [PATCH v6 0/7] KASLR kernel
dump support" patch series, a "etc/vmcoreinfo" entry is added with
qemu -device vmcoreinfo, where the guest during boot or later, can
write the addr/size location of a ELF note to be appended in the qemu
dump.

v2:
- use platform device for dma mapping
- add etc/vmcoreinfo patch
- some code cleanups

Marc-André Lureau (4):
  fw_cfg: add DMA register
  fw_cfg: do DMA read operation
  fw_cfg: write vmcoreinfo details
  RFC: fw_cfg: add DMA write operation in sysfs

 drivers/firmware/qemu_fw_cfg.c | 284 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 254 insertions(+), 30 deletions(-)

-- 
2.14.1.146.gd35faa819

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

* [PATCH v2 1/4] fw_cfg: add DMA register
  2017-09-19 11:58 [PATCH v2 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support marcandre.lureau
@ 2017-09-19 11:58 ` marcandre.lureau
  2017-09-22 11:05   ` kbuild test robot
  2017-09-22 11:45   ` kbuild test robot
  2017-09-19 11:58 ` [PATCH v2 2/4] fw_cfg: do DMA read operation marcandre.lureau
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 10+ messages in thread
From: marcandre.lureau @ 2017-09-19 11:58 UTC (permalink / raw)
  To: linux-kernel; +Cc: somlo, qemu-devel, mst, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Add an optional <dma_off> kernel module (or command line) parameter
using the following syntax:

      [fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]
 or
      [fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]

and initializes the register address using given or default offset.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 drivers/firmware/qemu_fw_cfg.c | 53 ++++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 0e2011636fbb..614037703530 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -10,20 +10,21 @@
  * and select subsets of aarch64), a Device Tree node (on arm), or using
  * a kernel module (or command line) parameter with the following syntax:
  *
- *      [fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>]
+ *      [fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]
  * or
- *      [fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>]
+ *      [fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]
  *
  * where:
  *      <size>     := size of ioport or mmio range
  *      <base>     := physical base address of ioport or mmio range
  *      <ctrl_off> := (optional) offset of control register
  *      <data_off> := (optional) offset of data register
+ *      <dma_off> := (optional) offset of dma register
  *
  * e.g.:
- *      fw_cfg.ioport=2@0x510:0:1		(the default on x86)
+ *      fw_cfg.ioport=2@0x510:0:1:4		(the default on x86)
  * or
- *      fw_cfg.mmio=0xA@0x9020000:8:0		(the default on arm)
+ *      fw_cfg.mmio=0xA@0x9020000:8:0:16	(the default on arm)
  */
 
 #include <linux/module.h>
@@ -63,6 +64,7 @@ static resource_size_t fw_cfg_p_size;
 static void __iomem *fw_cfg_dev_base;
 static void __iomem *fw_cfg_reg_ctrl;
 static void __iomem *fw_cfg_reg_data;
+static void __iomem *fw_cfg_reg_dma;
 
 /* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */
 static DEFINE_MUTEX(fw_cfg_dev_lock);
@@ -118,12 +120,14 @@ static void fw_cfg_io_cleanup(void)
 # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64))
 #  define FW_CFG_CTRL_OFF 0x08
 #  define FW_CFG_DATA_OFF 0x00
+#  define FW_CFG_DMA_OFF 0x10
 # elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x02
 # elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x01
+#  define FW_CFG_DMA_OFF 0x04
 # else
 #  error "QEMU FW_CFG not available on this architecture!"
 # endif
@@ -133,7 +137,7 @@ static void fw_cfg_io_cleanup(void)
 static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 {
 	char sig[FW_CFG_SIG_SIZE];
-	struct resource *range, *ctrl, *data;
+	struct resource *range, *ctrl, *data, *dma;
 
 	/* acquire i/o range details */
 	fw_cfg_is_mmio = false;
@@ -170,6 +174,7 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 	/* were custom register offsets provided (e.g. on the command line)? */
 	ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl");
 	data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data");
+	dma = platform_get_resource_byname(pdev, IORESOURCE_REG, "dma");
 	if (ctrl && data) {
 		fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start;
 		fw_cfg_reg_data = fw_cfg_dev_base + data->start;
@@ -179,6 +184,13 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 		fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF;
 	}
 
+	if (dma)
+		fw_cfg_reg_dma = fw_cfg_dev_base + dma->start;
+#ifdef FW_CFG_DMA_OFF
+	else
+		fw_cfg_reg_dma = fw_cfg_dev_base + FW_CFG_DMA_OFF;
+#endif
+
 	/* verify fw_cfg device signature */
 	fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE);
 	if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
@@ -628,6 +640,7 @@ static struct platform_device *fw_cfg_cmdline_dev;
 /* use special scanf/printf modifier for phys_addr_t, resource_size_t */
 #define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \
 			 ":%" __PHYS_ADDR_PREFIX "i" \
+			 ":%" __PHYS_ADDR_PREFIX "i%n" \
 			 ":%" __PHYS_ADDR_PREFIX "i%n"
 
 #define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \
@@ -637,12 +650,15 @@ static struct platform_device *fw_cfg_cmdline_dev;
 			 ":%" __PHYS_ADDR_PREFIX "u" \
 			 ":%" __PHYS_ADDR_PREFIX "u"
 
+#define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \
+			 ":%" __PHYS_ADDR_PREFIX "u"
+
 static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
 {
-	struct resource res[3] = {};
+	struct resource res[4] = {};
 	char *str;
 	phys_addr_t base;
-	resource_size_t size, ctrl_off, data_off;
+	resource_size_t size, ctrl_off, data_off, dma_off;
 	int processed, consumed = 0;
 
 	/* only one fw_cfg device can exist system-wide, so if one
@@ -658,19 +674,20 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
 	/* consume "<size>" portion of command line argument */
 	size = memparse(arg, &str);
 
-	/* get "@<base>[:<ctrl_off>:<data_off>]" chunks */
+	/* get "@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]" chunks */
 	processed = sscanf(str, PH_ADDR_SCAN_FMT,
 			   &base, &consumed,
-			   &ctrl_off, &data_off, &consumed);
+			   &ctrl_off, &data_off, &consumed,
+			   &dma_off, &consumed);
 
-	/* sscanf() must process precisely 1 or 3 chunks:
+	/* sscanf() must process precisely 1, 3 or 4 chunks:
 	 * <base> is mandatory, optionally followed by <ctrl_off>
-	 * and <data_off>;
+	 * and <data_off>, and <dma_off>;
 	 * there must be no extra characters after the last chunk,
 	 * so str[consumed] must be '\0'.
 	 */
 	if (str[consumed] ||
-	    (processed != 1 && processed != 3))
+	    (processed != 1 && processed != 3 && process != 4))
 		return -EINVAL;
 
 	res[0].start = base;
@@ -687,6 +704,11 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
 		res[2].start = data_off;
 		res[2].flags = IORESOURCE_REG;
 	}
+	if (processed > 3) {
+		res[3].name = "dma";
+		res[3].start = dma_off;
+		res[3].flags = IORESOURCE_REG;
+	}
 
 	/* "processed" happens to nicely match the number of resources
 	 * we need to pass in to this platform device.
@@ -721,6 +743,13 @@ static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)
 				fw_cfg_cmdline_dev->resource[0].start,
 				fw_cfg_cmdline_dev->resource[1].start,
 				fw_cfg_cmdline_dev->resource[2].start);
+	case 4:
+		return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_4_FMT,
+				resource_size(&fw_cfg_cmdline_dev->resource[0]),
+				fw_cfg_cmdline_dev->resource[0].start,
+				fw_cfg_cmdline_dev->resource[1].start,
+				fw_cfg_cmdline_dev->resource[2].start,
+				fw_cfg_cmdline_dev->resource[3].start);
 	}
 
 	/* Should never get here */
-- 
2.14.1.146.gd35faa819

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

* [PATCH v2 2/4] fw_cfg: do DMA read operation
  2017-09-19 11:58 [PATCH v2 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support marcandre.lureau
  2017-09-19 11:58 ` [PATCH v2 1/4] fw_cfg: add DMA register marcandre.lureau
@ 2017-09-19 11:58 ` marcandre.lureau
  2017-09-22 11:25   ` kbuild test robot
  2017-09-19 11:58 ` [PATCH v2 3/4] fw_cfg: write vmcoreinfo details marcandre.lureau
  2017-09-19 11:58 ` [PATCH v2 4/4] RFC: fw_cfg: add DMA write operation in sysfs marcandre.lureau
  3 siblings, 1 reply; 10+ messages in thread
From: marcandre.lureau @ 2017-09-19 11:58 UTC (permalink / raw)
  To: linux-kernel; +Cc: somlo, qemu-devel, mst, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Modify fw_cfg_read_blob() to use DMA if the device supports it.
Return errors, because the operation may fail.

This is a proof-of-concept patch with some FIXME. It uses yield() to
wait for the memory to be cleared. Help on how to improve this is
welcome.

We may also want to switch all the *buf addresses to use only
kmalloc'ed buffer (instead of using stack/image addresses with
dma=false).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 drivers/firmware/qemu_fw_cfg.c | 132 +++++++++++++++++++++++++++++++++++------
 1 file changed, 115 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 614037703530..a0e24fdf3ae5 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/dma-mapping.h>
 
 MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>");
 MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
@@ -43,12 +44,25 @@ MODULE_LICENSE("GPL");
 #define FW_CFG_ID         0x01
 #define FW_CFG_FILE_DIR   0x19
 
+#define FW_CFG_VERSION_DMA     0x02
+#define FW_CFG_DMA_CTL_ERROR   0x01
+#define FW_CFG_DMA_CTL_READ    0x02
+#define FW_CFG_DMA_CTL_SKIP    0x04
+#define FW_CFG_DMA_CTL_SELECT  0x08
+#define FW_CFG_DMA_CTL_WRITE   0x10
+
 /* size in bytes of fw_cfg signature */
 #define FW_CFG_SIG_SIZE 4
 
 /* fw_cfg "file name" is up to 56 characters (including terminating nul) */
 #define FW_CFG_MAX_FILE_PATH 56
 
+/* platform device for dma mapping */
+static struct device *dev;
+
+/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
+static u32 fw_cfg_rev;
+
 /* fw_cfg file directory entry type */
 struct fw_cfg_file {
 	u32 size;
@@ -57,6 +71,12 @@ struct fw_cfg_file {
 	char name[FW_CFG_MAX_FILE_PATH];
 };
 
+struct fw_cfg_dma {
+	u32 control;
+	u32 length;
+	u64 address;
+} __packed;
+
 /* fw_cfg device i/o register addresses */
 static bool fw_cfg_is_mmio;
 static phys_addr_t fw_cfg_p_base;
@@ -75,12 +95,73 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
 	return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key);
 }
 
+static inline bool fw_cfg_dma_enabled(void)
+{
+	return fw_cfg_rev & FW_CFG_VERSION_DMA && fw_cfg_reg_dma;
+}
+
+static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)
+{
+	dma_addr_t dma_addr = 0;
+	struct fw_cfg_dma *d;
+	dma_addr_t dma;
+	ssize_t ret = length;
+	enum dma_data_direction dir =
+		(control & FW_CFG_DMA_CTL_READ ? DMA_FROM_DEVICE : 0);
+
+	if (address && length) {
+		dma_addr = dma_map_single(dev, address, length, dir);
+		if (dma_mapping_error(NULL, dma_addr)) {
+			WARN(1, "%s: failed to map address\n", __func__);
+			return -EFAULT;
+		}
+	}
+
+	d = kmalloc(sizeof(*d), GFP_KERNEL | GFP_DMA);
+	if (!d) {
+		ret = -ENOMEM;
+		goto end;
+	}
+
+	dma = dma_map_single(dev, d, sizeof(*d), DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(NULL, dma)) {
+		WARN(1, "%s: failed to map fw_cfg_dma\n", __func__);
+		ret = -EFAULT;
+		goto end;
+	}
+
+	*d = (struct fw_cfg_dma) {
+		.address = cpu_to_be64(dma_addr),
+		.length = cpu_to_be32(length),
+		.control = cpu_to_be32(control)
+	};
+
+	iowrite32be(dma >> 32, fw_cfg_reg_dma);
+	iowrite32be(dma, fw_cfg_reg_dma + 4);
+	while (be32_to_cpu(d->control) & ~FW_CFG_DMA_CTL_ERROR)
+		yield(); /* FIXME: wait_event? */
+
+	if (be32_to_cpu(d->control) & FW_CFG_DMA_CTL_ERROR)
+		ret = -EIO;
+
+	dma_unmap_single(dev, dma, sizeof(*d), DMA_BIDIRECTIONAL);
+
+end:
+	kfree(d);
+	if (dma_addr)
+		dma_unmap_single(dev, dma_addr, length, dir);
+
+	return ret;
+}
+
 /* read chunk of given fw_cfg blob (caller responsible for sanity-check) */
-static inline void fw_cfg_read_blob(u16 key,
-				    void *buf, loff_t pos, size_t count)
+static ssize_t fw_cfg_read_blob(u16 key,
+				void *buf, loff_t pos, size_t count,
+				bool dma)
 {
 	u32 glk = -1U;
 	acpi_status status;
+	ssize_t ret = count;
 
 	/* If we have ACPI, ensure mutual exclusion against any potential
 	 * device access by the firmware, e.g. via AML methods:
@@ -90,17 +171,36 @@ static inline void fw_cfg_read_blob(u16 key,
 		/* Should never get here */
 		WARN(1, "fw_cfg_read_blob: Failed to lock ACPI!\n");
 		memset(buf, 0, count);
-		return;
+		return -EBUSY;
 	}
 
 	mutex_lock(&fw_cfg_dev_lock);
-	iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
-	while (pos-- > 0)
-		ioread8(fw_cfg_reg_data);
-	ioread8_rep(fw_cfg_reg_data, buf, count);
+	if (dma && fw_cfg_dma_enabled()) {
+		if (pos == 0) {
+			ret = fw_cfg_dma_transfer(buf, count, key << 16
+						  | FW_CFG_DMA_CTL_SELECT
+						  | FW_CFG_DMA_CTL_READ);
+		} else {
+			iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
+			ret = fw_cfg_dma_transfer(0, pos, FW_CFG_DMA_CTL_SKIP);
+			if (ret < 0)
+				goto end;
+			ret = fw_cfg_dma_transfer(buf, count,
+						  FW_CFG_DMA_CTL_READ);
+		}
+	} else {
+		iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
+		while (pos-- > 0)
+			ioread8(fw_cfg_reg_data);
+		ioread8_rep(fw_cfg_reg_data, buf, count);
+	}
+
+end:
 	mutex_unlock(&fw_cfg_dev_lock);
 
 	acpi_release_global_lock(glk);
+
+	return ret;
 }
 
 /* clean up fw_cfg device i/o */
@@ -192,7 +292,7 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 #endif
 
 	/* verify fw_cfg device signature */
-	fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE);
+	fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE, false);
 	if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
 		fw_cfg_io_cleanup();
 		return -ENODEV;
@@ -201,9 +301,6 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 	return 0;
 }
 
-/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
-static u32 fw_cfg_rev;
-
 static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf)
 {
 	return sprintf(buf, "%u\n", fw_cfg_rev);
@@ -351,8 +448,7 @@ static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj,
 	if (count > entry->f.size - pos)
 		count = entry->f.size - pos;
 
-	fw_cfg_read_blob(entry->f.select, buf, pos, count);
-	return count;
+	return fw_cfg_read_blob(entry->f.select, buf, pos, count, true);
 }
 
 static struct bin_attribute fw_cfg_sysfs_attr_raw = {
@@ -505,7 +601,7 @@ static int fw_cfg_register_dir_entries(void)
 	struct fw_cfg_file *dir;
 	size_t dir_size;
 
-	fw_cfg_read_blob(FW_CFG_FILE_DIR, &count, 0, sizeof(count));
+	fw_cfg_read_blob(FW_CFG_FILE_DIR, &count, 0, sizeof(count), false);
 	count = be32_to_cpu(count);
 	dir_size = count * sizeof(struct fw_cfg_file);
 
@@ -513,7 +609,7 @@ static int fw_cfg_register_dir_entries(void)
 	if (!dir)
 		return -ENOMEM;
 
-	fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(count), dir_size);
+	fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(count), dir_size, true);
 
 	for (i = 0; i < count; i++) {
 		dir[i].size = be32_to_cpu(dir[i].size);
@@ -544,9 +640,10 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev)
 	 * one fw_cfg device exist system-wide, so if one was already found
 	 * earlier, we might as well stop here.
 	 */
-	if (fw_cfg_sel_ko)
+	if (dev)
 		return -EBUSY;
 
+	dev = &pdev->dev;
 	/* create by_key and by_name subdirs of /sys/firmware/qemu_fw_cfg/ */
 	err = -ENOMEM;
 	fw_cfg_sel_ko = kobject_create_and_add("by_key", fw_cfg_top_ko);
@@ -562,7 +659,7 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev)
 		goto err_probe;
 
 	/* get revision number, add matching top-level attribute */
-	fw_cfg_read_blob(FW_CFG_ID, &fw_cfg_rev, 0, sizeof(fw_cfg_rev));
+	fw_cfg_read_blob(FW_CFG_ID, &fw_cfg_rev, 0, sizeof(fw_cfg_rev), false);
 	fw_cfg_rev = le32_to_cpu(fw_cfg_rev);
 	err = sysfs_create_file(fw_cfg_top_ko, &fw_cfg_rev_attr.attr);
 	if (err)
@@ -587,6 +684,7 @@ static int fw_cfg_sysfs_probe(struct platform_device *pdev)
 err_name:
 	fw_cfg_kobj_cleanup(fw_cfg_sel_ko);
 err_sel:
+	dev = NULL;
 	return err;
 }
 
-- 
2.14.1.146.gd35faa819

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

* [PATCH v2 3/4] fw_cfg: write vmcoreinfo details
  2017-09-19 11:58 [PATCH v2 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support marcandre.lureau
  2017-09-19 11:58 ` [PATCH v2 1/4] fw_cfg: add DMA register marcandre.lureau
  2017-09-19 11:58 ` [PATCH v2 2/4] fw_cfg: do DMA read operation marcandre.lureau
@ 2017-09-19 11:58 ` marcandre.lureau
  2017-09-22 18:01   ` kbuild test robot
  2017-09-22 20:38   ` kbuild test robot
  2017-09-19 11:58 ` [PATCH v2 4/4] RFC: fw_cfg: add DMA write operation in sysfs marcandre.lureau
  3 siblings, 2 replies; 10+ messages in thread
From: marcandre.lureau @ 2017-09-19 11:58 UTC (permalink / raw)
  To: linux-kernel; +Cc: somlo, qemu-devel, mst, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

If the "etc/vmcoreinfo" file is present, write the addr/size of the
vmcoreinfo ELF note.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 drivers/firmware/qemu_fw_cfg.c | 80 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index a0e24fdf3ae5..26152bfc7805 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/dma-mapping.h>
+#include <linux/crash_core.h>
 
 MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>");
 MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
@@ -57,6 +58,8 @@ MODULE_LICENSE("GPL");
 /* fw_cfg "file name" is up to 56 characters (including terminating nul) */
 #define FW_CFG_MAX_FILE_PATH 56
 
+#define VMCOREINFO_FORMAT_ELF 0x1
+
 /* platform device for dma mapping */
 static struct device *dev;
 
@@ -107,7 +110,8 @@ static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)
 	dma_addr_t dma;
 	ssize_t ret = length;
 	enum dma_data_direction dir =
-		(control & FW_CFG_DMA_CTL_READ ? DMA_FROM_DEVICE : 0);
+		(control & FW_CFG_DMA_CTL_READ ? DMA_FROM_DEVICE : 0) |
+		(control & FW_CFG_DMA_CTL_WRITE ? DMA_TO_DEVICE : 0);
 
 	if (address && length) {
 		dma_addr = dma_map_single(dev, address, length, dir);
@@ -203,6 +207,46 @@ static ssize_t fw_cfg_read_blob(u16 key,
 	return ret;
 }
 
+/* write chunk of given fw_cfg blob (caller responsible for sanity-check) */
+static ssize_t fw_cfg_write_blob(u16 key,
+				 void *buf, loff_t pos, size_t count)
+{
+	u32 glk = -1U;
+	acpi_status status;
+	ssize_t ret = count;
+
+	/* If we have ACPI, ensure mutual exclusion against any potential
+	 * device access by the firmware, e.g. via AML methods:
+	 */
+	status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);
+	if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {
+		/* Should never get here */
+		WARN(1, "%s: Failed to lock ACPI!\n", __func__);
+		memset(buf, 0, count);
+		return -EBUSY;
+	}
+
+	mutex_lock(&fw_cfg_dev_lock);
+	if (pos == 0) {
+		ret = fw_cfg_dma_transfer(buf, count, key << 16
+					  | FW_CFG_DMA_CTL_SELECT
+					  | FW_CFG_DMA_CTL_WRITE);
+	} else {
+		iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
+		ret = fw_cfg_dma_transfer(0, pos, FW_CFG_DMA_CTL_SKIP);
+		if (ret < 0)
+			goto end;
+		ret = fw_cfg_dma_transfer(buf, count, FW_CFG_DMA_CTL_WRITE);
+	}
+
+end:
+	mutex_unlock(&fw_cfg_dev_lock);
+
+	acpi_release_global_lock(glk);
+
+	return ret;
+}
+
 /* clean up fw_cfg device i/o */
 static void fw_cfg_io_cleanup(void)
 {
@@ -321,6 +365,35 @@ struct fw_cfg_sysfs_entry {
 	struct list_head list;
 };
 
+static ssize_t write_vmcoreinfo(const struct fw_cfg_file *f)
+{
+	struct vmci {
+		__le16 host_format;
+		__le16 guest_format;
+		__le32 size;
+		__le64 paddr;
+	} __packed;
+	struct vmci *data;
+	ssize_t ret;
+
+	data = kmalloc(sizeof(struct vmci), GFP_KERNEL | GFP_DMA);
+	if (!data)
+		return -ENOMEM;
+
+	/* spare ourself reading host format support for now since we
+	 * don't know what else to format - host may ignore ours
+	 */
+	*data = (struct vmci) {
+		.guest_format = cpu_to_le16(VMCOREINFO_FORMAT_ELF),
+		.size = cpu_to_le32(VMCOREINFO_NOTE_SIZE),
+		.paddr = cpu_to_le64(paddr_vmcoreinfo_note())
+	};
+	ret = fw_cfg_write_blob(f->select, data, 0, sizeof(struct vmci));
+
+	kfree(data);
+	return ret;
+}
+
 /* get fw_cfg_sysfs_entry from kobject member */
 static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj)
 {
@@ -560,6 +633,11 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
 	int err;
 	struct fw_cfg_sysfs_entry *entry;
 
+	if (strcmp(f->name, "etc/vmcoreinfo") == 0) {
+		if (write_vmcoreinfo(f) < 0)
+			pr_warn("fw_cfg: failed to write vmcoreinfo");
+	}
+
 	/* allocate new entry */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-- 
2.14.1.146.gd35faa819

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

* [PATCH v2 4/4] RFC: fw_cfg: add DMA write operation in sysfs
  2017-09-19 11:58 [PATCH v2 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support marcandre.lureau
                   ` (2 preceding siblings ...)
  2017-09-19 11:58 ` [PATCH v2 3/4] fw_cfg: write vmcoreinfo details marcandre.lureau
@ 2017-09-19 11:58 ` marcandre.lureau
  3 siblings, 0 replies; 10+ messages in thread
From: marcandre.lureau @ 2017-09-19 11:58 UTC (permalink / raw)
  To: linux-kernel; +Cc: somlo, qemu-devel, mst, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Since qemu 2.9, DMA write operations are allowed. However, usage of this
interface from kernel or user-space is strongly discouraged by the
maintainers. This patch is meant for experimentations for now.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 drivers/firmware/qemu_fw_cfg.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 26152bfc7805..1ca3382e98df 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -524,9 +524,28 @@ static ssize_t fw_cfg_sysfs_read_raw(struct file *filp, struct kobject *kobj,
 	return fw_cfg_read_blob(entry->f.select, buf, pos, count, true);
 }
 
+static ssize_t fw_cfg_sysfs_write_raw(struct file *filp, struct kobject *kobj,
+				      struct bin_attribute *bin_attr,
+				      char *buf, loff_t pos, size_t count)
+{
+	struct fw_cfg_sysfs_entry *entry = to_entry(kobj);
+
+	if (!fw_cfg_dma_enabled())
+		return -ENOTSUPP;
+
+	if (pos > entry->f.size)
+		return -EINVAL;
+
+	if (count > entry->f.size - pos)
+		count = entry->f.size - pos;
+
+	return fw_cfg_write_blob(entry->f.select, buf, pos, count);
+}
+
 static struct bin_attribute fw_cfg_sysfs_attr_raw = {
-	.attr = { .name = "raw", .mode = S_IRUSR },
+	.attr = { .name = "raw", .mode = S_IRUSR | S_IWUSR },
 	.read = fw_cfg_sysfs_read_raw,
+	.write = fw_cfg_sysfs_write_raw,
 };
 
 /*
-- 
2.14.1.146.gd35faa819

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

* Re: [PATCH v2 1/4] fw_cfg: add DMA register
  2017-09-19 11:58 ` [PATCH v2 1/4] fw_cfg: add DMA register marcandre.lureau
@ 2017-09-22 11:05   ` kbuild test robot
  2017-09-22 11:45   ` kbuild test robot
  1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-09-22 11:05 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: kbuild-all, linux-kernel, somlo, qemu-devel, mst, Marc-André Lureau

[-- Attachment #1: Type: text/plain, Size: 4265 bytes --]

Hi Marc-André,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/marcandre-lureau-redhat-com/fw_cfg-add-DMA-operations-etc-vmcoreinfo-support/20170922-182716
config: i386-randconfig-x009-201738 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set':
>> drivers/firmware/qemu_fw_cfg.c:690:43: error: 'process' undeclared (first use in this function)
         (processed != 1 && processed != 3 && process != 4))
                                              ^~~~~~~
   drivers/firmware/qemu_fw_cfg.c:690:43: note: each undeclared identifier is reported only once for each function it appears in

vim +/process +690 drivers/firmware/qemu_fw_cfg.c

   639	
   640	/* use special scanf/printf modifier for phys_addr_t, resource_size_t */
   641	#define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \
   642				 ":%" __PHYS_ADDR_PREFIX "i" \
   643				 ":%" __PHYS_ADDR_PREFIX "i%n" \
   644				 ":%" __PHYS_ADDR_PREFIX "i%n"
   645	
   646	#define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \
   647				 "0x%" __PHYS_ADDR_PREFIX "x"
   648	
   649	#define PH_ADDR_PR_3_FMT PH_ADDR_PR_1_FMT \
   650				 ":%" __PHYS_ADDR_PREFIX "u" \
   651				 ":%" __PHYS_ADDR_PREFIX "u"
   652	
   653	#define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \
   654				 ":%" __PHYS_ADDR_PREFIX "u"
   655	
   656	static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
   657	{
   658		struct resource res[4] = {};
   659		char *str;
   660		phys_addr_t base;
   661		resource_size_t size, ctrl_off, data_off, dma_off;
   662		int processed, consumed = 0;
   663	
   664		/* only one fw_cfg device can exist system-wide, so if one
   665		 * was processed on the command line already, we might as
   666		 * well stop here.
   667		 */
   668		if (fw_cfg_cmdline_dev) {
   669			/* avoid leaking previously registered device */
   670			platform_device_unregister(fw_cfg_cmdline_dev);
   671			return -EINVAL;
   672		}
   673	
   674		/* consume "<size>" portion of command line argument */
   675		size = memparse(arg, &str);
   676	
   677		/* get "@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]" chunks */
   678		processed = sscanf(str, PH_ADDR_SCAN_FMT,
   679				   &base, &consumed,
   680				   &ctrl_off, &data_off, &consumed,
   681				   &dma_off, &consumed);
   682	
   683		/* sscanf() must process precisely 1, 3 or 4 chunks:
   684		 * <base> is mandatory, optionally followed by <ctrl_off>
   685		 * and <data_off>, and <dma_off>;
   686		 * there must be no extra characters after the last chunk,
   687		 * so str[consumed] must be '\0'.
   688		 */
   689		if (str[consumed] ||
 > 690		    (processed != 1 && processed != 3 && process != 4))
   691			return -EINVAL;
   692	
   693		res[0].start = base;
   694		res[0].end = base + size - 1;
   695		res[0].flags = !strcmp(kp->name, "mmio") ? IORESOURCE_MEM :
   696							   IORESOURCE_IO;
   697	
   698		/* insert register offsets, if provided */
   699		if (processed > 1) {
   700			res[1].name = "ctrl";
   701			res[1].start = ctrl_off;
   702			res[1].flags = IORESOURCE_REG;
   703			res[2].name = "data";
   704			res[2].start = data_off;
   705			res[2].flags = IORESOURCE_REG;
   706		}
   707		if (processed > 3) {
   708			res[3].name = "dma";
   709			res[3].start = dma_off;
   710			res[3].flags = IORESOURCE_REG;
   711		}
   712	
   713		/* "processed" happens to nicely match the number of resources
   714		 * we need to pass in to this platform device.
   715		 */
   716		fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg",
   717						PLATFORM_DEVID_NONE, res, processed);
   718		if (IS_ERR(fw_cfg_cmdline_dev))
   719			return PTR_ERR(fw_cfg_cmdline_dev);
   720	
   721		return 0;
   722	}
   723	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 25956 bytes --]

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

* Re: [PATCH v2 2/4] fw_cfg: do DMA read operation
  2017-09-19 11:58 ` [PATCH v2 2/4] fw_cfg: do DMA read operation marcandre.lureau
@ 2017-09-22 11:25   ` kbuild test robot
  0 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-09-22 11:25 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: kbuild-all, linux-kernel, somlo, qemu-devel, mst, Marc-André Lureau

[-- Attachment #1: Type: text/plain, Size: 7688 bytes --]

Hi Marc-André,

[auto build test WARNING on linus/master]
[also build test WARNING on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/marcandre-lureau-redhat-com/fw_cfg-add-DMA-operations-etc-vmcoreinfo-support/20170922-182716
config: i386-randconfig-x000-201738 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers//firmware/qemu_fw_cfg.c: In function 'fw_cfg_dma_transfer':
>> drivers//firmware/qemu_fw_cfg.c:139:18: warning: right shift count >= width of type [-Wshift-count-overflow]
     iowrite32be(dma >> 32, fw_cfg_reg_dma);
                     ^~
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/module.h:9,
                    from drivers//firmware/qemu_fw_cfg.c:30:
   drivers//firmware/qemu_fw_cfg.c: At top level:
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'strcpy' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:421:2: note: in expansion of macro 'if'
     if (p_size == (size_t)-1 && q_size == (size_t)-1)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:411:2: note: in expansion of macro 'if'
     if (p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:409:2: note: in expansion of macro 'if'
     if (__builtin_constant_p(size) && p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:400:2: note: in expansion of macro 'if'
     if (p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:398:2: note: in expansion of macro 'if'
     if (__builtin_constant_p(size) && p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:389:2: note: in expansion of macro 'if'
     if (p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:387:2: note: in expansion of macro 'if'
     if (__builtin_constant_p(size) && p_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:379:2: note: in expansion of macro 'if'
     if (p_size < size || q_size < size)
     ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:376:3: note: in expansion of macro 'if'
      if (q_size < size)
      ^~
   include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static
       ______f = {     \
       ^
   include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if'
    #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
                          ^~~~~~~~~~
   include/linux/string.h:374:3: note: in expansion of macro 'if'
      if (p_size < size)

vim +139 drivers//firmware/qemu_fw_cfg.c

   102	
   103	static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)
   104	{
   105		dma_addr_t dma_addr = 0;
   106		struct fw_cfg_dma *d;
   107		dma_addr_t dma;
   108		ssize_t ret = length;
   109		enum dma_data_direction dir =
   110			(control & FW_CFG_DMA_CTL_READ ? DMA_FROM_DEVICE : 0);
   111	
   112		if (address && length) {
   113			dma_addr = dma_map_single(dev, address, length, dir);
   114			if (dma_mapping_error(NULL, dma_addr)) {
   115				WARN(1, "%s: failed to map address\n", __func__);
   116				return -EFAULT;
   117			}
   118		}
   119	
   120		d = kmalloc(sizeof(*d), GFP_KERNEL | GFP_DMA);
   121		if (!d) {
   122			ret = -ENOMEM;
   123			goto end;
   124		}
   125	
   126		dma = dma_map_single(dev, d, sizeof(*d), DMA_BIDIRECTIONAL);
   127		if (dma_mapping_error(NULL, dma)) {
   128			WARN(1, "%s: failed to map fw_cfg_dma\n", __func__);
   129			ret = -EFAULT;
   130			goto end;
   131		}
   132	
   133		*d = (struct fw_cfg_dma) {
   134			.address = cpu_to_be64(dma_addr),
   135			.length = cpu_to_be32(length),
   136			.control = cpu_to_be32(control)
   137		};
   138	
 > 139		iowrite32be(dma >> 32, fw_cfg_reg_dma);
   140		iowrite32be(dma, fw_cfg_reg_dma + 4);
   141		while (be32_to_cpu(d->control) & ~FW_CFG_DMA_CTL_ERROR)
   142			yield(); /* FIXME: wait_event? */
   143	
   144		if (be32_to_cpu(d->control) & FW_CFG_DMA_CTL_ERROR)
   145			ret = -EIO;
   146	
   147		dma_unmap_single(dev, dma, sizeof(*d), DMA_BIDIRECTIONAL);
   148	
   149	end:
   150		kfree(d);
   151		if (dma_addr)
   152			dma_unmap_single(dev, dma_addr, length, dir);
   153	
   154		return ret;
   155	}
   156	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29438 bytes --]

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

* Re: [PATCH v2 1/4] fw_cfg: add DMA register
  2017-09-19 11:58 ` [PATCH v2 1/4] fw_cfg: add DMA register marcandre.lureau
  2017-09-22 11:05   ` kbuild test robot
@ 2017-09-22 11:45   ` kbuild test robot
  1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-09-22 11:45 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: kbuild-all, linux-kernel, somlo, qemu-devel, mst, Marc-André Lureau

[-- Attachment #1: Type: text/plain, Size: 8786 bytes --]

Hi Marc-André,

[auto build test WARNING on linus/master]
[also build test WARNING on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/marcandre-lureau-redhat-com/fw_cfg-add-DMA-operations-etc-vmcoreinfo-support/20170922-182716
config: i386-randconfig-x075-201738 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/module.h:9,
                    from drivers//firmware/qemu_fw_cfg.c:30:
   drivers//firmware/qemu_fw_cfg.c: In function 'fw_cfg_cmdline_set':
   drivers//firmware/qemu_fw_cfg.c:690:43: error: 'process' undeclared (first use in this function)
         (processed != 1 && processed != 3 && process != 4))
                                              ^
   include/linux/compiler.h:156:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
>> drivers//firmware/qemu_fw_cfg.c:689:2: note: in expansion of macro 'if'
     if (str[consumed] ||
     ^~
   drivers//firmware/qemu_fw_cfg.c:690:43: note: each undeclared identifier is reported only once for each function it appears in
         (processed != 1 && processed != 3 && process != 4))
                                              ^
   include/linux/compiler.h:156:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
>> drivers//firmware/qemu_fw_cfg.c:689:2: note: in expansion of macro 'if'
     if (str[consumed] ||
     ^~

vim +/if +689 drivers//firmware/qemu_fw_cfg.c

75f3e8e4 Gabriel Somlo     2016-01-28  639  
75f3e8e4 Gabriel Somlo     2016-01-28  640  /* use special scanf/printf modifier for phys_addr_t, resource_size_t */
75f3e8e4 Gabriel Somlo     2016-01-28  641  #define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \
75f3e8e4 Gabriel Somlo     2016-01-28  642  			 ":%" __PHYS_ADDR_PREFIX "i" \
46ebd6f8 Marc-André Lureau 2017-09-19  643  			 ":%" __PHYS_ADDR_PREFIX "i%n" \
75f3e8e4 Gabriel Somlo     2016-01-28  644  			 ":%" __PHYS_ADDR_PREFIX "i%n"
75f3e8e4 Gabriel Somlo     2016-01-28  645  
75f3e8e4 Gabriel Somlo     2016-01-28  646  #define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \
75f3e8e4 Gabriel Somlo     2016-01-28  647  			 "0x%" __PHYS_ADDR_PREFIX "x"
75f3e8e4 Gabriel Somlo     2016-01-28  648  
75f3e8e4 Gabriel Somlo     2016-01-28  649  #define PH_ADDR_PR_3_FMT PH_ADDR_PR_1_FMT \
75f3e8e4 Gabriel Somlo     2016-01-28  650  			 ":%" __PHYS_ADDR_PREFIX "u" \
75f3e8e4 Gabriel Somlo     2016-01-28  651  			 ":%" __PHYS_ADDR_PREFIX "u"
75f3e8e4 Gabriel Somlo     2016-01-28  652  
46ebd6f8 Marc-André Lureau 2017-09-19  653  #define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \
46ebd6f8 Marc-André Lureau 2017-09-19  654  			 ":%" __PHYS_ADDR_PREFIX "u"
46ebd6f8 Marc-André Lureau 2017-09-19  655  
75f3e8e4 Gabriel Somlo     2016-01-28  656  static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
75f3e8e4 Gabriel Somlo     2016-01-28  657  {
46ebd6f8 Marc-André Lureau 2017-09-19  658  	struct resource res[4] = {};
75f3e8e4 Gabriel Somlo     2016-01-28  659  	char *str;
75f3e8e4 Gabriel Somlo     2016-01-28  660  	phys_addr_t base;
46ebd6f8 Marc-André Lureau 2017-09-19  661  	resource_size_t size, ctrl_off, data_off, dma_off;
75f3e8e4 Gabriel Somlo     2016-01-28  662  	int processed, consumed = 0;
75f3e8e4 Gabriel Somlo     2016-01-28  663  
75f3e8e4 Gabriel Somlo     2016-01-28  664  	/* only one fw_cfg device can exist system-wide, so if one
75f3e8e4 Gabriel Somlo     2016-01-28  665  	 * was processed on the command line already, we might as
75f3e8e4 Gabriel Somlo     2016-01-28  666  	 * well stop here.
75f3e8e4 Gabriel Somlo     2016-01-28  667  	 */
75f3e8e4 Gabriel Somlo     2016-01-28  668  	if (fw_cfg_cmdline_dev) {
75f3e8e4 Gabriel Somlo     2016-01-28  669  		/* avoid leaking previously registered device */
75f3e8e4 Gabriel Somlo     2016-01-28  670  		platform_device_unregister(fw_cfg_cmdline_dev);
75f3e8e4 Gabriel Somlo     2016-01-28  671  		return -EINVAL;
75f3e8e4 Gabriel Somlo     2016-01-28  672  	}
75f3e8e4 Gabriel Somlo     2016-01-28  673  
75f3e8e4 Gabriel Somlo     2016-01-28  674  	/* consume "<size>" portion of command line argument */
75f3e8e4 Gabriel Somlo     2016-01-28  675  	size = memparse(arg, &str);
75f3e8e4 Gabriel Somlo     2016-01-28  676  
46ebd6f8 Marc-André Lureau 2017-09-19  677  	/* get "@<base>[:<ctrl_off>:<data_off>[:<dma_off>]]" chunks */
75f3e8e4 Gabriel Somlo     2016-01-28  678  	processed = sscanf(str, PH_ADDR_SCAN_FMT,
75f3e8e4 Gabriel Somlo     2016-01-28  679  			   &base, &consumed,
46ebd6f8 Marc-André Lureau 2017-09-19  680  			   &ctrl_off, &data_off, &consumed,
46ebd6f8 Marc-André Lureau 2017-09-19  681  			   &dma_off, &consumed);
75f3e8e4 Gabriel Somlo     2016-01-28  682  
46ebd6f8 Marc-André Lureau 2017-09-19  683  	/* sscanf() must process precisely 1, 3 or 4 chunks:
75f3e8e4 Gabriel Somlo     2016-01-28  684  	 * <base> is mandatory, optionally followed by <ctrl_off>
46ebd6f8 Marc-André Lureau 2017-09-19  685  	 * and <data_off>, and <dma_off>;
75f3e8e4 Gabriel Somlo     2016-01-28  686  	 * there must be no extra characters after the last chunk,
75f3e8e4 Gabriel Somlo     2016-01-28  687  	 * so str[consumed] must be '\0'.
75f3e8e4 Gabriel Somlo     2016-01-28  688  	 */
75f3e8e4 Gabriel Somlo     2016-01-28 @689  	if (str[consumed] ||
46ebd6f8 Marc-André Lureau 2017-09-19  690  	    (processed != 1 && processed != 3 && process != 4))
75f3e8e4 Gabriel Somlo     2016-01-28  691  		return -EINVAL;
75f3e8e4 Gabriel Somlo     2016-01-28  692  
75f3e8e4 Gabriel Somlo     2016-01-28  693  	res[0].start = base;
75f3e8e4 Gabriel Somlo     2016-01-28  694  	res[0].end = base + size - 1;
75f3e8e4 Gabriel Somlo     2016-01-28  695  	res[0].flags = !strcmp(kp->name, "mmio") ? IORESOURCE_MEM :
75f3e8e4 Gabriel Somlo     2016-01-28  696  						   IORESOURCE_IO;
75f3e8e4 Gabriel Somlo     2016-01-28  697  
75f3e8e4 Gabriel Somlo     2016-01-28  698  	/* insert register offsets, if provided */
75f3e8e4 Gabriel Somlo     2016-01-28  699  	if (processed > 1) {
75f3e8e4 Gabriel Somlo     2016-01-28  700  		res[1].name = "ctrl";
75f3e8e4 Gabriel Somlo     2016-01-28  701  		res[1].start = ctrl_off;
75f3e8e4 Gabriel Somlo     2016-01-28  702  		res[1].flags = IORESOURCE_REG;
75f3e8e4 Gabriel Somlo     2016-01-28  703  		res[2].name = "data";
75f3e8e4 Gabriel Somlo     2016-01-28  704  		res[2].start = data_off;
75f3e8e4 Gabriel Somlo     2016-01-28  705  		res[2].flags = IORESOURCE_REG;
75f3e8e4 Gabriel Somlo     2016-01-28  706  	}
46ebd6f8 Marc-André Lureau 2017-09-19  707  	if (processed > 3) {
46ebd6f8 Marc-André Lureau 2017-09-19  708  		res[3].name = "dma";
46ebd6f8 Marc-André Lureau 2017-09-19  709  		res[3].start = dma_off;
46ebd6f8 Marc-André Lureau 2017-09-19  710  		res[3].flags = IORESOURCE_REG;
46ebd6f8 Marc-André Lureau 2017-09-19  711  	}
75f3e8e4 Gabriel Somlo     2016-01-28  712  
75f3e8e4 Gabriel Somlo     2016-01-28  713  	/* "processed" happens to nicely match the number of resources
75f3e8e4 Gabriel Somlo     2016-01-28  714  	 * we need to pass in to this platform device.
75f3e8e4 Gabriel Somlo     2016-01-28  715  	 */
75f3e8e4 Gabriel Somlo     2016-01-28  716  	fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg",
75f3e8e4 Gabriel Somlo     2016-01-28  717  					PLATFORM_DEVID_NONE, res, processed);
75f3e8e4 Gabriel Somlo     2016-01-28  718  	if (IS_ERR(fw_cfg_cmdline_dev))
75f3e8e4 Gabriel Somlo     2016-01-28  719  		return PTR_ERR(fw_cfg_cmdline_dev);
75f3e8e4 Gabriel Somlo     2016-01-28  720  
75f3e8e4 Gabriel Somlo     2016-01-28  721  	return 0;
75f3e8e4 Gabriel Somlo     2016-01-28  722  }
75f3e8e4 Gabriel Somlo     2016-01-28  723  

:::::: The code at line 689 was first introduced by commit
:::::: 75f3e8e47f381074801d0034874d20c638d9e3d9 firmware: introduce sysfs driver for QEMU's fw_cfg device

:::::: TO: Gabriel Somlo <somlo@cmu.edu>
:::::: CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26389 bytes --]

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

* Re: [PATCH v2 3/4] fw_cfg: write vmcoreinfo details
  2017-09-19 11:58 ` [PATCH v2 3/4] fw_cfg: write vmcoreinfo details marcandre.lureau
@ 2017-09-22 18:01   ` kbuild test robot
  2017-09-22 20:38   ` kbuild test robot
  1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-09-22 18:01 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: kbuild-all, linux-kernel, somlo, qemu-devel, mst, Marc-André Lureau

[-- Attachment #1: Type: text/plain, Size: 897 bytes --]

Hi Marc-André,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/marcandre-lureau-redhat-com/fw_cfg-add-DMA-operations-etc-vmcoreinfo-support/20170922-182716
config: i386-randconfig-c0-09222256 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/firmware/qemu_fw_cfg.o: In function `fw_cfg_register_dir_entries':
>> qemu_fw_cfg.c:(.text+0x8af): undefined reference to `paddr_vmcoreinfo_note'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31641 bytes --]

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

* Re: [PATCH v2 3/4] fw_cfg: write vmcoreinfo details
  2017-09-19 11:58 ` [PATCH v2 3/4] fw_cfg: write vmcoreinfo details marcandre.lureau
  2017-09-22 18:01   ` kbuild test robot
@ 2017-09-22 20:38   ` kbuild test robot
  1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-09-22 20:38 UTC (permalink / raw)
  To: marcandre.lureau
  Cc: kbuild-all, linux-kernel, somlo, qemu-devel, mst, Marc-André Lureau

[-- Attachment #1: Type: text/plain, Size: 831 bytes --]

Hi Marc-André,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.14-rc1 next-20170922]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/marcandre-lureau-redhat-com/fw_cfg-add-DMA-operations-etc-vmcoreinfo-support/20170922-182716
config: x86_64-randconfig-ws0-09230003 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

>> ERROR: "paddr_vmcoreinfo_note" [drivers/firmware/qemu_fw_cfg.ko] undefined!

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28137 bytes --]

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

end of thread, other threads:[~2017-09-22 20:39 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-19 11:58 [PATCH v2 0/4] fw_cfg: add DMA operations & etc/vmcoreinfo support marcandre.lureau
2017-09-19 11:58 ` [PATCH v2 1/4] fw_cfg: add DMA register marcandre.lureau
2017-09-22 11:05   ` kbuild test robot
2017-09-22 11:45   ` kbuild test robot
2017-09-19 11:58 ` [PATCH v2 2/4] fw_cfg: do DMA read operation marcandre.lureau
2017-09-22 11:25   ` kbuild test robot
2017-09-19 11:58 ` [PATCH v2 3/4] fw_cfg: write vmcoreinfo details marcandre.lureau
2017-09-22 18:01   ` kbuild test robot
2017-09-22 20:38   ` kbuild test robot
2017-09-19 11:58 ` [PATCH v2 4/4] RFC: fw_cfg: add DMA write operation in sysfs marcandre.lureau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®