lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1321533732-22983-1-git-send-email-pawel.moll@arm.com>
Date:	Thu, 17 Nov 2011 12:42:12 +0000
From:	Pawel Moll <pawel.moll@....com>
To:	Rusty Russell <rusty@...tcorp.com.au>,
	linux-kernel@...r.kernel.org,
	virtualization@...ts.linux-foundation.org
Cc:	Sasha Levin <levinsasha928@...il.com>,
	Peter Maydell <peter.maydell@...aro.org>,
	Pawel Moll <pawel.moll@....com>
Subject: [PATCH v2] virtio-mmio: Devices parameter parsing

This patch adds an option to instantiate guest virtio-mmio devices
basing on a kernel command line (or module) parameter, for example:

	virtio_mmio.devices=0x100@...00b0000:48,1K@...001e000:74

Signed-off-by: Pawel Moll <pawel.moll@....com>
---
 drivers/virtio/Kconfig       |   31 +++++++
 drivers/virtio/virtio_mmio.c |  181 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 211 insertions(+), 1 deletions(-)

Hi Rusty,

This version adds the "first_id" parameter I mentioned yesterday,
but still using single charp parameter instead of the _cb version.
And unless you are really (_really_) against it, I'd rather see
this variant.

Cheers!

Paweł

diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 816ed08..00f2c82 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -46,4 +46,35 @@ config VIRTIO_BALLOON
 
  	 If unsure, say N.
 
+config VIRTIO_MMIO_CMDLINE_DEVICES
+	bool "Memory mapped virtio devices parameter parsing"
+	depends on VIRTIO_MMIO
+	---help---
+	 Allow virtio-mmio devices instantiation via the kernel command line
+	 or module parameter. Be aware that using incorrect parameters (base
+	 address in particular) can crash your system - you have been warned.
+
+	 The format for the parameter is as follows:
+
+		[virtio_mmio.]devices=<device>[<delim><device>]
+
+	 where:
+		<device>   := <size>@<baseaddr>:<irq>
+		<delim>    := ',' or ';'
+		<size>     := size (can use standard suffixes like K or M)
+		<baseaddr> := physical base address
+		<irq>      := interrupt number (as passed to request_irq())
+
+	 Example kernel command line parameter:
+
+		virtio_mmio.devices=0x100@...00b0000:48,1K@...001e000:74
+
+	 This will register platform devices virtio_mmio.<id>, where <id>
+	 values are consecutive integer numbers starting from 0 by default.
+	 The first id value can be changed with "first_id" parameter:
+
+	 	[virtio_mmio.]first_id=<id>
+
+	 If unsure, say 'N'.
+
 endmenu
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index acc5e43..05b39c1 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -6,6 +6,55 @@
  * This module allows virtio devices to be used over a virtual, memory mapped
  * platform device.
  *
+ * The guest device(s) may be instantiated in one of three equivalent ways:
+ *
+ * 1. Static platform device in board's code, eg.:
+ *
+ *	static struct platform_device v2m_virtio_device = {
+ *		.name = "virtio-mmio",
+ *		.id = -1,
+ *		.num_resources = 2,
+ *		.resource = (struct resource []) {
+ *			{
+ *				.start = 0x1001e000,
+ *				.end = 0x1001e0ff,
+ *				.flags = IORESOURCE_MEM,
+ *			}, {
+ *				.start = 42 + 32,
+ *				.end = 42 + 32,
+ *				.flags = IORESOURCE_IRQ,
+ *			},
+ *		}
+ *	};
+ *
+ * 2. Device Tree node, eg.:
+ *
+ *		virtio_block@...00 {
+ *			compatible = "virtio,mmio";
+ *			reg = <0x1e000 0x100>;
+ *			interrupts = <42>;
+ *		}
+ *
+ * 3. Kernel module (or command line) parameter:
+ *
+ *		[virtio_mmio.]devices=<device>[<delim><device>]
+ *    where:
+ *		<device>   := <size>@<baseaddr>:<irq>
+ *		<delim>    := ',' or ';'
+ *		<size>     := size (can use standard suffixes like K or M)
+ *		<baseaddr> := physical base address
+ *		<irq>      := interrupt number (as passed to request_irq())
+ *    eg.:
+ *		virtio_mmio.devices=0x100@...00b0000:48,1K@...001e000:74
+ *
+ *    This will register platform devices virtio_mmio.<id>, where <id>
+ *    values are consecutive integer numbers starting from 0 by default.
+ *    The first id value can be changed with "first_id" parameter:
+ *
+ *		[virtio_mmio.]first_id=<id>
+ *
+ *
+ *
  * Registers layout (all 32-bit wide):
  *
  * offset d. name             description
@@ -42,6 +91,8 @@
  * See the COPYING file in the top-level directory.
  */
 
+#define pr_fmt(fmt) "virtio-mmio: " fmt
+
 #include <linux/highmem.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -443,6 +494,130 @@ static int __devexit virtio_mmio_remove(struct platform_device *pdev)
 
 
 
+/* Devices list parameter */
+
+#if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES)
+
+static char *virtio_mmio_cmdline_devices;
+module_param_named(devices, virtio_mmio_cmdline_devices, charp, 0);
+
+static int virtio_mmio_cmdline_id;
+module_param_named(first_id, virtio_mmio_cmdline_id, int, 0);
+
+static struct device virtio_mmio_cmdline_parent = {
+	.init_name = "virtio-mmio-cmdline",
+};
+
+static int virtio_mmio_register_cmdline_devices(void)
+{
+	int err;
+	char *device;
+	char *token = NULL;
+
+	err = device_register(&virtio_mmio_cmdline_parent);
+	if (err) {
+		pr_err("Failed to register %s!\n",
+				virtio_mmio_cmdline_parent.init_name);
+		return err;
+	}
+
+	/* Split colon-or-semicolon-separated devices */
+	while ((device = strsep(&virtio_mmio_cmdline_devices, ",;")) != NULL) {
+		struct resource resources[] = {
+			{
+				.flags = IORESOURCE_IRQ,
+			}, {
+				.flags = IORESOURCE_MEM,
+			}
+		};
+		char *size, *base;
+		unsigned long long val;
+
+		if (!*device)
+			continue;
+
+		kfree(token);
+		token = kstrdup(device, GFP_KERNEL);
+
+		/* Split memory and IRQ resources */
+		base = strsep(&token, ":");
+		if (base == token || !token || !*token) {
+			pr_err("No IRQ in '%s'!\n", device);
+			continue;
+		}
+
+		/* Get IRQ */
+		if (kstrtoull(token, 0, &val) != 0) {
+			pr_err("Wrong IRQ in '%s'!\n", device);
+			continue;
+		}
+		resources[0].start = val;
+		resources[0].end = val;
+
+		/* Split base address and size */
+		size = strsep(&base, "@");
+		if (size == base || !base || !*base) {
+			pr_err("No base in '%s'!\n", device);
+			continue;
+		}
+
+		/* Get base address */
+		if (kstrtoull(base, 0, &val) != 0) {
+			pr_err("Wrong base in '%s'!\n", device);
+			continue;
+		}
+		resources[1].start = val;
+		resources[1].end = val;
+
+		/* Get size */
+		resources[1].end += memparse(size, &token) - 1;
+		if (size == token || *token) {
+			pr_err("Wrong size in '%s'!\n", device);
+			continue;
+		}
+
+		pr_info("Registering device %d at 0x%x-0x%x, IRQ %u.\n",
+				virtio_mmio_cmdline_id, resources[1].start,
+				resources[1].end, resources[0].start);
+
+		platform_device_register_resndata(&virtio_mmio_cmdline_parent,
+				"virtio-mmio", virtio_mmio_cmdline_id++,
+				resources, ARRAY_SIZE(resources), NULL, 0);
+	}
+
+	kfree(token);
+
+	return 0;
+}
+
+static int virtio_mmio_unregister_cmdline_device(struct device *dev,
+		void *data)
+{
+	platform_device_unregister(to_platform_device(dev));
+
+	return 0;
+}
+
+static void virtio_mmio_unregister_cmdline_devices(void)
+{
+	device_for_each_child(&virtio_mmio_cmdline_parent, NULL,
+			virtio_mmio_unregister_cmdline_device);
+	device_unregister(&virtio_mmio_cmdline_parent);
+}
+
+#else
+
+static int virtio_mmio_register_cmdline_devices(void)
+{
+	return 0;
+}
+
+static void virtio_mmio_unregister_cmdline_devices(void)
+{
+}
+
+#endif
+
 /* Platform driver */
 
 static struct of_device_id virtio_mmio_match[] = {
@@ -463,11 +638,15 @@ static struct platform_driver virtio_mmio_driver = {
 
 static int __init virtio_mmio_init(void)
 {
-	return platform_driver_register(&virtio_mmio_driver);
+	int err = virtio_mmio_register_cmdline_devices();
+
+	return err ? err : platform_driver_register(&virtio_mmio_driver);
 }
 
 static void __exit virtio_mmio_exit(void)
 {
+	virtio_mmio_unregister_cmdline_devices();
+
 	platform_driver_unregister(&virtio_mmio_driver);
 }
 
-- 
1.6.3.3


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ