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: <20230929-jakub-os-90-trim-v1-1-a3af0c08f812@cloudflare.com>
Date:   Fri, 29 Sep 2023 22:46:03 +0200
From:   Jakub Sitnicki <jakub@...udflare.com>
To:     virtualization@...ts.linux-foundation.org
Cc:     "Michael S. Tsirkin" <mst@...hat.com>,
        Jason Wang <jasowang@...hat.com>,
        Xuan Zhuo <xuanzhuo@...ux.alibaba.com>,
        linux-kernel@...r.kernel.org, kernel-team@...udflare.com
Subject: [PATCH 1/2] virtio-mmio: Parse a range of IRQ numbers passed on the command line

virtio-mmio devices in theory can use multiple interrupts. However, the
existing virtio-mmio command line configuration format does not provide a
way to express it.

Extend the configuration format so that the user can specify an IRQ
range. This prepares ground for registering multiple IRQs per device.

Because we need to stay backward compatible with VMMs which don't yet use
the new format, fall back to the old one if we fail to find an IRQ range in
the passed parameters.

Signed-off-by: Jakub Sitnicki <jakub@...udflare.com>
---
 drivers/virtio/virtio_mmio.c | 77 ++++++++++++++++++++++++++++++--------------
 1 file changed, 52 insertions(+), 25 deletions(-)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 97760f611295..06a587b23542 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -39,11 +39,12 @@
  * 3. Kernel module (or command line) parameter. Can be used more than once -
  *    one device will be created for each one. Syntax:
  *
- *		[virtio_mmio.]device=<size>@<baseaddr>:<irq>[:<id>]
+ *		[virtio_mmio.]device=<size>@<baseaddr>:<irq>[-<irq last>][:<id>]
  *    where:
  *		<size>     := size (can use standard suffixes like K, M or G)
  *		<baseaddr> := physical base address
- *		<irq>      := interrupt number (as passed to request_irq())
+ *		<irq>      := first interrupt number (as passed to request_irq())
+ *		<irq last> := (optional) last interrupt number
  *		<id>       := (optional) platform device id
  *    eg.:
  *		virtio_mmio.device=0x100@...00b0000:48 \
@@ -712,36 +713,38 @@ static int vm_cmdline_set(const char *device,
 		const struct kernel_param *kp)
 {
 	int err;
-	struct resource resources[2] = {};
 	char *str;
 	long long base, size;
-	unsigned int irq;
+	unsigned int irq, irq_last;
 	int processed, consumed = 0;
 	struct platform_device *pdev;
+	struct resource *resources, *res;
+	size_t num_resources;
 
 	/* Consume "size" part of the command line parameter */
 	size = memparse(device, &str);
 
-	/* Get "@<base>:<irq>[:<id>]" chunks */
-	processed = sscanf(str, "@%lli:%u%n:%d%n",
-			&base, &irq, &consumed,
-			&vm_cmdline_id, &consumed);
+	/* Get "@<base>:<irq>-<irq last>[:<id>]" chunks */
+	processed = sscanf(str, "@%lli:%u-%u%n:%d%n",
+			   &base, &irq, &irq_last, &consumed,
+			   &vm_cmdline_id, &consumed);
+	/* Fall back to "@<base>:<irq>[:<id>]" */
+	if (processed < 3) {
+		processed = sscanf(str, "@%lli:%u%n:%d%n",
+				   &base, &irq, &consumed,
+				   &vm_cmdline_id, &consumed);
+		irq_last = irq;
+	}
 
 	/*
 	 * sscanf() must process at least 2 chunks; also there
 	 * must be no extra characters after the last chunk, so
 	 * str[consumed] must be '\0'
 	 */
-	if (processed < 2 || str[consumed] || irq == 0)
+	if (processed < 2 || str[consumed] ||
+	    irq == 0 || irq_last == 0 || irq > irq_last)
 		return -EINVAL;
 
-	resources[0].flags = IORESOURCE_MEM;
-	resources[0].start = base;
-	resources[0].end = base + size - 1;
-
-	resources[1].flags = IORESOURCE_IRQ;
-	resources[1].start = resources[1].end = irq;
-
 	if (!vm_cmdline_parent_registered) {
 		err = device_register(&vm_cmdline_parent);
 		if (err) {
@@ -752,16 +755,34 @@ static int vm_cmdline_set(const char *device,
 		vm_cmdline_parent_registered = 1;
 	}
 
-	pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n",
-		       vm_cmdline_id,
-		       (unsigned long long)resources[0].start,
-		       (unsigned long long)resources[0].end,
-		       (int)resources[1].start);
+	num_resources = 1; /* mem */
+	num_resources += irq_last - irq + 1;
+	resources = devm_kcalloc(&vm_cmdline_parent, num_resources,
+				 sizeof(*resources), GFP_KERNEL);
+	if (!resources)
+		return -ENOMEM;
+
+	resources[0].flags = IORESOURCE_MEM;
+	resources[0].start = base;
+	resources[0].end = base + size - 1;
+
+	for (res = &resources[1]; irq <= irq_last; irq++, res++) {
+		res->flags = IORESOURCE_IRQ;
+		res->start = irq;
+		res->end = irq;
+	}
+
+	pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQs %u-%u.\n",
+		vm_cmdline_id,
+		(unsigned long long)resources[0].start,
+		(unsigned long long)resources[0].end,
+		irq, irq_last);
 
 	pdev = platform_device_register_resndata(&vm_cmdline_parent,
 			"virtio-mmio", vm_cmdline_id++,
-			resources, ARRAY_SIZE(resources), NULL, 0);
+			resources, num_resources, NULL, 0);
 
+	devm_kfree(&vm_cmdline_parent, resources);
 	return PTR_ERR_OR_ZERO(pdev);
 }
 
@@ -770,12 +791,18 @@ static int vm_cmdline_get_device(struct device *dev, void *data)
 	char *buffer = data;
 	unsigned int len = strlen(buffer);
 	struct platform_device *pdev = to_platform_device(dev);
+	size_t nres = pdev->num_resources;
+	bool irq_range = nres > 2;
 
-	snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@...llx:%llu:%d\n",
+	len += snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@...llx:%llu",
 			pdev->resource[0].end - pdev->resource[0].start + 1ULL,
 			(unsigned long long)pdev->resource[0].start,
-			(unsigned long long)pdev->resource[1].start,
-			pdev->id);
+			(unsigned long long)pdev->resource[1].start);
+	if (irq_range)
+		len += snprintf(buffer + len, PAGE_SIZE - len, "-%llu",
+				(unsigned long long)pdev->resource[nres - 1].start);
+	snprintf(buffer + len, PAGE_SIZE - len, ":%d\n", pdev->id);
+
 	return 0;
 }
 

-- 
2.41.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ