Linux virtualization list
 help / color / mirror / Atom feed
* Re: [RFC PATCH] virtio-mmio: add xenbus probing
From: Jürgen Groß @ 2026-04-29 15:35 UTC (permalink / raw)
  To: Val Packett, Michael S. Tsirkin, Jason Wang, Xuan Zhuo,
	Eugenio Pérez
  Cc: Marek Marczykowski-Górecki, Viresh Kumar, xen-devel,
	linux-kernel, virtualization
In-Reply-To: <20260429141339.74472-1-val@invisiblethingslab.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 9134 bytes --]

Some minor details from the Xen side of things:

On 29.04.26 15:52, Val Packett wrote:
> The experimental virtio-mmio support for Xen was initially developed
> on aarch64, so device trees were used to configure the mmio devices,
> with arbitrary vGIC interrupts used by the hypervisor. On x86_64
> however, the only reasonable way to interrupt the guest is over Xen
> event channels, which can only be acquired by children of xenbus,

More exact: interdomain event channels need to be connected to a xenbus
device. But you are needing those, so for your use case the above statement
is correct.

> the virtual bus driven by Xen's configuration database, XenStore.
> It is also a more convenient and "Xen-ish" way to provision devices.
> 
> Implement a xenbus client for virtio-mmio which negotiates an
> event channel and provides it as a platform IRQ to the
> virtio-mmio driver.
> 
> 
> Signed-off-by: Val Packett <val@invisiblethingslab.com>
> ---
> 
> Hi,
> 
> I've been working on porting virtio-mmio support from Arm to x86_64,
> with the goal of running vhost-user-gpu to power Wayland/GPU integration
> for Qubes OS. (I'm aware of various proposals for alternative virtio
> transports but virtio-mmio seems to be the only one that *is* upstream
> already and just Works..) Setting up virtio-mmio through xenbus, initially
> motivated just by event channels being the only real way to get interrupts
> working on HVM, turned out to generally be quite pleasant and nice :)
> 
> I'd like to get some early feedback for this patch, particularly
> the general stuff:
> 
> * is this whole thing acceptable in general?
> * should it be extracted into a different file?
> * (from the Xen side) any input on the xenstore keys, what goes where?

You should add some documentation in the Xen source tree regarding the
Xenstore keys (see docs/misc/xenstore-paths.pandoc there).

> * anything else to keep in mind?
> 
> It does seem simple enough, so hopefully this can be done?
> 
> The corresponding userspace-side WIP is available at:
> https://github.com/QubesOS/xen-vhost-frontend
> 
> And the required DMOP for firing the evtchn events will be sent
> to xen-devel shortly as well.
> 
> Thanks,
> ~val
> 
> ---
>   drivers/virtio/Kconfig       |   7 ++
>   drivers/virtio/virtio_mmio.c | 177 ++++++++++++++++++++++++++++++++++-
>   2 files changed, 183 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
> index ce5bc0d9ea28..56bc2b10526b 100644
> --- a/drivers/virtio/Kconfig
> +++ b/drivers/virtio/Kconfig
> @@ -171,6 +171,13 @@ config VIRTIO_MMIO_CMDLINE_DEVICES
>   
>   	 If unsure, say 'N'.
>   
> +config VIRTIO_MMIO_XENBUS
> +	bool "Memory mapped virtio devices parameter parsing"
> +	depends on VIRTIO_MMIO && XEN
> +	select XEN_XENBUS_FRONTEND
> +	help
> +	 Allow virtio-mmio devices instantiation for Xen guests via xenbus.
> +
>   config VIRTIO_DMA_SHARED_BUFFER
>   	tristate
>   	depends on DMA_SHARED_BUFFER
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index 595c2274fbb5..32295284bdbf 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -70,6 +70,11 @@
>   #include <uapi/linux/virtio_mmio.h>
>   #include <linux/virtio_ring.h>
>   
> +#ifdef CONFIG_VIRTIO_MMIO_XENBUS
> +#include <xen/xen.h>
> +#include <xen/xenbus.h>
> +#include <xen/events.h>
> +#endif
>   
>   
>   /* The alignment to use between consumer and producer parts of vring.
> @@ -810,13 +815,183 @@ static struct platform_driver virtio_mmio_driver = {
>   	},
>   };
>   
> +#ifdef CONFIG_VIRTIO_MMIO_XENBUS
> +struct virtio_mmio_xen_info {
> +	struct resource resources[2];
> +	unsigned int evtchn;
> +	struct platform_device *pdev;
> +};
> +
> +static int virtio_mmio_xen_probe(struct xenbus_device *dev,
> +			const struct xenbus_device_id *id)
> +{
> +	int err;
> +	long long base, size;
> +	char *mem;
> +	struct virtio_mmio_xen_info *info;
> +	struct xenbus_transaction xbt;
> +
> +	/* TODO: allocate an unused address here and pass it to the host instead */

Indeed.

> +	err = xenbus_scanf(XBT_NIL, dev->otherend, "base", "0x%llx",
> +			   &base);
> +	if (err < 0) {
> +		xenbus_dev_fatal(dev, err, "reading base");
> +		return -EINVAL;
> +	}
> +
> +	mem = xenbus_read(XBT_NIL, dev->otherend, "size", NULL);
> +	if (XENBUS_IS_ERR_READ(mem))
> +		return PTR_ERR(mem);
> +	size = memparse(mem, NULL);
> +	kfree(mem);
> +
> +	info = kzalloc_obj(*info);
> +	if (!info) {
> +		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
> +		return -ENOMEM;
> +	}
> +
> +	info->resources[0].flags = IORESOURCE_MEM;
> +	info->resources[0].start = base;
> +	info->resources[0].end = base + size - 1;
> +
> +	err = xenbus_alloc_evtchn(dev, &info->evtchn);
> +	if (err) {
> +		xenbus_dev_fatal(dev, err, "xenbus_alloc_evtchn");
> +		goto error_info;
> +	}
> +
> +	err = bind_evtchn_to_irq(info->evtchn);
> +	if (err <= 0) {
> +		xenbus_dev_fatal(dev, err, "bind_evtchn_to_irq");
> +		goto error_evtchan;
> +	}
> +
> +	info->resources[1].flags = IORESOURCE_IRQ;
> +	info->resources[1].start = info->resources[1].end = err;
> +
> +again:
> +	err = xenbus_transaction_start(&xbt);

No need to use a Xenstore transaction here. The written node(s) are
regarded to be valid only after calling xenbus_switch_state() to set
the frontend state to XenbusStateInitialised.

> +	if (err) {
> +		xenbus_dev_fatal(dev, err, "starting transaction");
> +		goto error_irq;
> +	}
> +
> +	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
> +			    info->evtchn);

With allocation of the base address you'd want to write it to another node,
of course.

> +	if (err) {
> +		xenbus_transaction_end(xbt, 1);
> +		xenbus_dev_fatal(dev, err, "%s", "writing event-channel");
> +		goto error_irq;
> +	}
> +
> +	err = xenbus_transaction_end(xbt, 0);
> +	if (err) {
> +		if (err == -EAGAIN)
> +			goto again;
> +		xenbus_dev_fatal(dev, err, "completing transaction");
> +		goto error_irq;
> +	}
> +
> +	dev_set_drvdata(&dev->dev, info);
> +	xenbus_switch_state(dev, XenbusStateInitialised);
> +	return 0;
> +
> +error_irq:
> +	unbind_from_irqhandler(info->resources[1].start, info);
> +error_evtchan:
> +	xenbus_free_evtchn(dev, info->evtchn);
> +error_info:
> +	kfree(info);
> +
> +	return err;
> +}
> +
> +static void virtio_mmio_xen_backend_changed(struct xenbus_device *dev,
> +				   enum xenbus_state backend_state)
> +{
> +	struct virtio_mmio_xen_info *info = dev_get_drvdata(&dev->dev);
> +
> +	switch (backend_state) {
> +	case XenbusStateInitialising:
> +	case XenbusStateInitWait:
> +	case XenbusStateInitialised:
> +	case XenbusStateReconfiguring:
> +	case XenbusStateReconfigured:
> +	case XenbusStateUnknown:
> +		break;
> +
> +	case XenbusStateConnected:
> +		if (dev->state != XenbusStateInitialised) {
> +			dev_warn(&dev->dev, "state %d on connect", dev->state);
> +			break;
> +		}
> +		info->pdev = platform_device_register_resndata(&dev->dev,
> +				"virtio-mmio", PLATFORM_DEVID_AUTO,
> +				info->resources, ARRAY_SIZE(info->resources), NULL, 0);
> +		xenbus_switch_state(dev, XenbusStateConnected);
> +		break;
> +
> +	case XenbusStateClosed:
> +		if (dev->state == XenbusStateClosed)
> +			break;
> +		fallthrough;	/* Missed the backend's Closing state. */
> +	case XenbusStateClosing:
> +		platform_device_unregister(info->pdev);
> +		xenbus_switch_state(dev, XenbusStateClosed);
> +		break;
> +
> +	default:
> +		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
> +				 backend_state);
> +		break;
> +	}
> +}
> +
> +static void virtio_mmio_xen_remove(struct xenbus_device *dev)
> +{
> +	struct virtio_mmio_xen_info *info = dev_get_drvdata(&dev->dev);
> +
> +	kfree(info);
> +	dev_set_drvdata(&dev->dev, NULL);
> +}
> +
> +static const struct xenbus_device_id virtio_mmio_xen_ids[] = {
> +	{ "virtio" },

Please use "virtio-mmio" here, as I could imagine "virtio-pci" devices, too.


Juergen

> +	{ "" },
> +};
> +
> +static struct xenbus_driver virtio_mmio_xen_driver = {
> +	.ids			= virtio_mmio_xen_ids,
> +	.probe			= virtio_mmio_xen_probe,
> +	.otherend_changed	= virtio_mmio_xen_backend_changed,
> +	.remove			= virtio_mmio_xen_remove,
> +};
> +#endif
> +
>   static int __init virtio_mmio_init(void)
>   {
> -	return platform_driver_register(&virtio_mmio_driver);
> +	int ret;
> +
> +	ret = platform_driver_register(&virtio_mmio_driver);
> +	if (ret)
> +		return ret;
> +
> +#ifdef CONFIG_VIRTIO_MMIO_XENBUS
> +	if (xen_domain())
> +		ret = xenbus_register_frontend(&virtio_mmio_xen_driver);
> +#endif
> +
> +	return ret;
>   }
>   
>   static void __exit virtio_mmio_exit(void)
>   {
> +#ifdef CONFIG_VIRTIO_MMIO_XENBUS
> +	if (xen_domain())
> +		xenbus_unregister_driver(&virtio_mmio_xen_driver);
> +#endif
> +
>   	platform_driver_unregister(&virtio_mmio_driver);
>   	vm_unregister_cmdline_devices();
>   }


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply

* [PATCH v2 0/8] x86/msr: Consolidate native/paravirt MSR functions
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen

Changes from v1:
 - Remove "raw_" names. Just use "paravirt_" in the generic code.

I'm thinking I'll just apply this in the coming days if nobody
screams too loudly.

--

This is old cruft, but it appears that having two copies of these
MSR functions is enabling warnings to creep in[1].

I know there's also been some work to pare down the XXL code, but
it's obviously not merged yet and this is a good baby step.

Create helpers that both paravirt and native can use in common code
and remove the paravirt implementations of the helpers. This reduces
the amount of logic that is duplicated in the paravirt code.

The wonky thing about this solution is that it has the common code
always make literal "paravirt_" calls, even when paravirt is not in
use for MSRs. In that case, the calls just go directly to the
"native_" functions via #defines.

Conceptually:
 -   native: The bare-metal implementation. Might not be usable under
	     paravirt XXL.
 - paravirt: Call the native version directly if paravirt is compiled
 	     out. Call into paravirt ops when available, which might
	     ultimately call a native implementation.

1. https://lore.kernel.org/all/20260319152210.210854-1-aldocontelk@gmail.com/

 msr.h      |  124 +++++++++++++++++++++++++++++++------------------------------
 paravirt.h |   44 ---------------------
 2 files changed, 65 insertions(+), 103 deletions(-)

^ permalink raw reply

* [PATCH v2 1/8] x86/msr: Use paravirt "calls" in common code
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

Currently, the paravirt and native code define a common set of MSR
functions. But, some of the code is duplicated between the two. For
instance, the packing and unpacking of the 64-bit MSR value into two
32-bit values is done in both.

Prepare to consolidate the two copies. Have common code use the
paravirt_{rd,wr}msr*() naming and short-circuit the paravirt
infrastructure with the preprocessor to do paravirt=>native without
any paravirt overhead.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h |   21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff -puN arch/x86/include/asm/msr.h~raw_msr_names arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~raw_msr_names	2026-04-01 14:32:55.572415984 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:55.575416096 -0700
@@ -173,6 +173,13 @@ static inline u64 native_read_pmc(int co
 #include <asm/paravirt.h>
 #else
 #include <linux/errno.h>
+
+/* Short-circuit the paravirt MSR infrastructure when it is disabled: */
+#define paravirt_read_msr	native_read_msr
+#define paravirt_read_msr_safe	native_read_msr_safe
+#define paravirt_write_msr	native_write_msr
+#define paravirt_write_msr_safe	native_write_msr_safe
+
 /*
  * Access to machine-specific registers (available on 586 and better only)
  * Note: the rd* operations modify the parameters directly (without using
@@ -181,35 +188,35 @@ static inline u64 native_read_pmc(int co
 
 #define rdmsr(msr, low, high)					\
 do {								\
-	u64 __val = native_read_msr((msr));			\
+	u64 __val = paravirt_read_msr((msr));			\
 	(void)((low) = (u32)__val);				\
 	(void)((high) = (u32)(__val >> 32));			\
 } while (0)
 
 static inline void wrmsr(u32 msr, u32 low, u32 high)
 {
-	native_write_msr(msr, (u64)high << 32 | low);
+	paravirt_write_msr(msr, (u64)high << 32 | low);
 }
 
 #define rdmsrq(msr, val)			\
-	((val) = native_read_msr((msr)))
+	((val) = paravirt_read_msr((msr)))
 
 static inline void wrmsrq(u32 msr, u64 val)
 {
-	native_write_msr(msr, val);
+	paravirt_write_msr(msr, val);
 }
 
 /* wrmsr with exception handling */
 static inline int wrmsrq_safe(u32 msr, u64 val)
 {
-	return native_write_msr_safe(msr, val);
+	return paravirt_write_msr_safe(msr, val);
 }
 
 /* rdmsr with exception handling */
 #define rdmsr_safe(msr, low, high)				\
 ({								\
 	u64 __val;						\
-	int __err = native_read_msr_safe((msr), &__val);	\
+	int __err = paravirt_read_msr_safe((msr), &__val);		\
 	(*low) = (u32)__val;					\
 	(*high) = (u32)(__val >> 32);				\
 	__err;							\
@@ -217,7 +224,7 @@ static inline int wrmsrq_safe(u32 msr, u
 
 static inline int rdmsrq_safe(u32 msr, u64 *p)
 {
-	return native_read_msr_safe(msr, p);
+	return paravirt_read_msr_safe(msr, p);
 }
 
 static __always_inline u64 rdpmc(int counter)
_

^ permalink raw reply

* [PATCH v2 2/8] x86/msr: Consolidate rdmsr() definitions
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

The paravirt and native code define very similar rdmsr()
implementations. Move the non-paravirt one out to common code where
both the "native" and "paravirt" implementations can use it.

Remove the now duplicate paravirt rdmsr().

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h      |   17 ++++++++++-------
 b/arch/x86/include/asm/paravirt.h |    7 -------
 2 files changed, 10 insertions(+), 14 deletions(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-2 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-2	2026-04-01 14:32:56.105435948 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:56.112436210 -0700
@@ -186,13 +186,6 @@ static inline u64 native_read_pmc(int co
  * pointer indirection), this allows gcc to optimize better
  */
 
-#define rdmsr(msr, low, high)					\
-do {								\
-	u64 __val = paravirt_read_msr((msr));			\
-	(void)((low) = (u32)__val);				\
-	(void)((high) = (u32)(__val >> 32));			\
-} while (0)
-
 static inline void wrmsr(u32 msr, u32 low, u32 high)
 {
 	paravirt_write_msr(msr, (u64)high << 32 | low);
@@ -234,6 +227,16 @@ static __always_inline u64 rdpmc(int cou
 
 #endif	/* !CONFIG_PARAVIRT_XXL */
 
+/*
+ * Common paravirt and native helpers:
+ */
+#define rdmsr(msr, low, high)					\
+do {								\
+	u64 __val = paravirt_read_msr((msr));			\
+	(void)((low) = (u32)__val);				\
+	(void)((high) = (u32)(__val >> 32));			\
+} while (0)
+
 /* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */
 #define ASM_WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6)
 
diff -puN arch/x86/include/asm/paravirt.h~rdmsr-dups-2 arch/x86/include/asm/paravirt.h
--- a/arch/x86/include/asm/paravirt.h~rdmsr-dups-2	2026-04-01 14:32:56.109436097 -0700
+++ b/arch/x86/include/asm/paravirt.h	2026-04-01 14:32:56.112436210 -0700
@@ -161,13 +161,6 @@ static inline int paravirt_write_msr_saf
 	return PVOP_CALL2(int, pv_ops, cpu.write_msr_safe, msr, val);
 }
 
-#define rdmsr(msr, val1, val2)			\
-do {						\
-	u64 _l = paravirt_read_msr(msr);	\
-	val1 = (u32)_l;				\
-	val2 = _l >> 32;			\
-} while (0)
-
 static __always_inline void wrmsr(u32 msr, u32 low, u32 high)
 {
 	paravirt_write_msr(msr, (u64)high << 32 | low);
_

^ permalink raw reply

* [PATCH v2 3/8] x86/msr: Consolidate rdmsr_safe() implementations
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

Move the existing "native" rdmsr_safe() implementation out to common
code. Consolidate the two rdmsr_safe() implementations down to one
by removing the paravirt.h version.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h      |   20 ++++++++++----------
 b/arch/x86/include/asm/paravirt.h |   10 ----------
 2 files changed, 10 insertions(+), 20 deletions(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-4 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-4	2026-04-01 14:32:56.670457110 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:56.676457335 -0700
@@ -205,16 +205,6 @@ static inline int wrmsrq_safe(u32 msr, u
 	return paravirt_write_msr_safe(msr, val);
 }
 
-/* rdmsr with exception handling */
-#define rdmsr_safe(msr, low, high)				\
-({								\
-	u64 __val;						\
-	int __err = paravirt_read_msr_safe((msr), &__val);		\
-	(*low) = (u32)__val;					\
-	(*high) = (u32)(__val >> 32);				\
-	__err;							\
-})
-
 static inline int rdmsrq_safe(u32 msr, u64 *p)
 {
 	return paravirt_read_msr_safe(msr, p);
@@ -237,6 +227,16 @@ do {								\
 	(void)((high) = (u32)(__val >> 32));			\
 } while (0)
 
+/* rdmsr with exception handling */
+#define rdmsr_safe(msr, low, high)				\
+({								\
+	u64 __val;						\
+	int __err = paravirt_read_msr_safe((msr), &__val);		\
+	(*low) = (u32)__val;					\
+	(*high) = (u32)(__val >> 32);				\
+	__err;							\
+})
+
 /* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */
 #define ASM_WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6)
 
diff -puN arch/x86/include/asm/paravirt.h~rdmsr-dups-4 arch/x86/include/asm/paravirt.h
--- a/arch/x86/include/asm/paravirt.h~rdmsr-dups-4	2026-04-01 14:32:56.673457222 -0700
+++ b/arch/x86/include/asm/paravirt.h	2026-04-01 14:32:56.676457335 -0700
@@ -181,16 +181,6 @@ static inline int wrmsrq_safe(u32 msr, u
 	return paravirt_write_msr_safe(msr, val);
 }
 
-/* rdmsr with exception handling */
-#define rdmsr_safe(msr, a, b)				\
-({							\
-	u64 _l;						\
-	int _err = paravirt_read_msr_safe((msr), &_l);	\
-	(*a) = (u32)_l;					\
-	(*b) = (u32)(_l >> 32);				\
-	_err;						\
-})
-
 static __always_inline int rdmsrq_safe(u32 msr, u64 *p)
 {
 	return paravirt_read_msr_safe(msr, p);
_

^ permalink raw reply

* [PATCH v2 4/8] x86/msr: Consolidate rdmsrq() implementations
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

Consolidate the two rdmsrq() implementations down to one.

The paravirt.h implementation was probably better, but just stick
with the native one here for consistency.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h      |    6 +++---
 b/arch/x86/include/asm/paravirt.h |    5 -----
 2 files changed, 3 insertions(+), 8 deletions(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-5 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-5	2026-04-01 14:32:57.236478310 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:57.242478534 -0700
@@ -191,9 +191,6 @@ static inline void wrmsr(u32 msr, u32 lo
 	paravirt_write_msr(msr, (u64)high << 32 | low);
 }
 
-#define rdmsrq(msr, val)			\
-	((val) = paravirt_read_msr((msr)))
-
 static inline void wrmsrq(u32 msr, u64 val)
 {
 	paravirt_write_msr(msr, val);
@@ -237,6 +234,9 @@ do {								\
 	__err;							\
 })
 
+#define rdmsrq(msr, val)			\
+	((val) = paravirt_read_msr((msr)))
+
 /* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */
 #define ASM_WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6)
 
diff -puN arch/x86/include/asm/paravirt.h~rdmsr-dups-5 arch/x86/include/asm/paravirt.h
--- a/arch/x86/include/asm/paravirt.h~rdmsr-dups-5	2026-04-01 14:32:57.239478422 -0700
+++ b/arch/x86/include/asm/paravirt.h	2026-04-01 14:32:57.242478534 -0700
@@ -166,11 +166,6 @@ static __always_inline void wrmsr(u32 ms
 	paravirt_write_msr(msr, (u64)high << 32 | low);
 }
 
-#define rdmsrq(msr, val)			\
-do {						\
-	val = paravirt_read_msr(msr);		\
-} while (0)
-
 static inline void wrmsrq(u32 msr, u64 val)
 {
 	paravirt_write_msr(msr, val);
_

^ permalink raw reply

* [PATCH v2 5/8] x86/msr: Consolidate {rd,wr}msr[q]_safe() implementations
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

These should be very familiar by now. Move the native implementations
of the "safe" MSR functions out to common code and zap the paravirt.h
version. Do four at once now because these are quite straightforward.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h      |   42 +++++++++++++++++++-------------------
 b/arch/x86/include/asm/paravirt.h |   20 ------------------
 2 files changed, 21 insertions(+), 41 deletions(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-6 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-6	2026-04-01 14:32:57.802499509 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:57.809499772 -0700
@@ -186,27 +186,6 @@ static inline u64 native_read_pmc(int co
  * pointer indirection), this allows gcc to optimize better
  */
 
-static inline void wrmsr(u32 msr, u32 low, u32 high)
-{
-	paravirt_write_msr(msr, (u64)high << 32 | low);
-}
-
-static inline void wrmsrq(u32 msr, u64 val)
-{
-	paravirt_write_msr(msr, val);
-}
-
-/* wrmsr with exception handling */
-static inline int wrmsrq_safe(u32 msr, u64 val)
-{
-	return paravirt_write_msr_safe(msr, val);
-}
-
-static inline int rdmsrq_safe(u32 msr, u64 *p)
-{
-	return paravirt_read_msr_safe(msr, p);
-}
-
 static __always_inline u64 rdpmc(int counter)
 {
 	return native_read_pmc(counter);
@@ -237,6 +216,27 @@ do {								\
 #define rdmsrq(msr, val)			\
 	((val) = paravirt_read_msr((msr)))
 
+static inline int rdmsrq_safe(u32 msr, u64 *p)
+{
+	return paravirt_read_msr_safe(msr, p);
+}
+
+/* wrmsr with exception handling */
+static inline int wrmsrq_safe(u32 msr, u64 val)
+{
+	return paravirt_write_msr_safe(msr, val);
+}
+
+static inline void wrmsr(u32 msr, u32 low, u32 high)
+{
+	paravirt_write_msr(msr, (u64)high << 32 | low);
+}
+
+static inline void wrmsrq(u32 msr, u64 val)
+{
+	paravirt_write_msr(msr, val);
+}
+
 /* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */
 #define ASM_WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6)
 
diff -puN arch/x86/include/asm/paravirt.h~rdmsr-dups-6 arch/x86/include/asm/paravirt.h
--- a/arch/x86/include/asm/paravirt.h~rdmsr-dups-6	2026-04-01 14:32:57.806499659 -0700
+++ b/arch/x86/include/asm/paravirt.h	2026-04-01 14:32:57.809499772 -0700
@@ -161,26 +161,6 @@ static inline int paravirt_write_msr_saf
 	return PVOP_CALL2(int, pv_ops, cpu.write_msr_safe, msr, val);
 }
 
-static __always_inline void wrmsr(u32 msr, u32 low, u32 high)
-{
-	paravirt_write_msr(msr, (u64)high << 32 | low);
-}
-
-static inline void wrmsrq(u32 msr, u64 val)
-{
-	paravirt_write_msr(msr, val);
-}
-
-static inline int wrmsrq_safe(u32 msr, u64 val)
-{
-	return paravirt_write_msr_safe(msr, val);
-}
-
-static __always_inline int rdmsrq_safe(u32 msr, u64 *p)
-{
-	return paravirt_read_msr_safe(msr, p);
-}
-
 static __always_inline u64 rdpmc(int counter)
 {
 	return PVOP_CALL1(u64, pv_ops, cpu.read_pmc, counter);
_

^ permalink raw reply

* [PATCH v2 6/8] x86/msr: Consolidate rdpmc() implementations
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

Doing this is debatable. It does not actually remove any code. But,
this makes rdpmc() follow the same pattern as all of the MSR functions
where paravirt.h defines a paravirt_foo() function and then msr.h
uses that function in common code.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h      |   11 ++++++-----
 b/arch/x86/include/asm/paravirt.h |    2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-9 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-9	2026-04-01 14:32:58.366520634 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:58.373520897 -0700
@@ -179,6 +179,7 @@ static inline u64 native_read_pmc(int co
 #define paravirt_read_msr_safe	native_read_msr_safe
 #define paravirt_write_msr	native_write_msr
 #define paravirt_write_msr_safe	native_write_msr_safe
+#define paravirt_read_pmc		native_read_pmc
 
 /*
  * Access to machine-specific registers (available on 586 and better only)
@@ -186,11 +187,6 @@ static inline u64 native_read_pmc(int co
  * pointer indirection), this allows gcc to optimize better
  */
 
-static __always_inline u64 rdpmc(int counter)
-{
-	return native_read_pmc(counter);
-}
-
 #endif	/* !CONFIG_PARAVIRT_XXL */
 
 /*
@@ -237,6 +233,11 @@ static inline void wrmsrq(u32 msr, u64 v
 	paravirt_write_msr(msr, val);
 }
 
+static __always_inline u64 rdpmc(int counter)
+{
+	return paravirt_read_pmc(counter);
+}
+
 /* Instruction opcode for WRMSRNS supported in binutils >= 2.40 */
 #define ASM_WRMSRNS _ASM_BYTES(0x0f,0x01,0xc6)
 
diff -puN arch/x86/include/asm/paravirt.h~rdmsr-dups-9 arch/x86/include/asm/paravirt.h
--- a/arch/x86/include/asm/paravirt.h~rdmsr-dups-9	2026-04-01 14:32:58.370520784 -0700
+++ b/arch/x86/include/asm/paravirt.h	2026-04-01 14:32:58.373520897 -0700
@@ -161,7 +161,7 @@ static inline int paravirt_write_msr_saf
 	return PVOP_CALL2(int, pv_ops, cpu.write_msr_safe, msr, val);
 }
 
-static __always_inline u64 rdpmc(int counter)
+static __always_inline u64 paravirt_read_pmc(int counter)
 {
 	return PVOP_CALL1(u64, pv_ops, cpu.read_pmc, counter);
 }
_

^ permalink raw reply

* [PATCH v2 7/8] x86/msr: Remove old crusty comment
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

I'm not sure any of this makes sense any more. The kernel only
runs on "586 and better". The comment about gcc optimization is
hopefully decades out of date too.

Really, the only reason to keep the wonky semantics where the
parameters get modified is to avoid all the churn to make them sane.
Not gcc. gcc was probably a bad reason, even back in the day because
MSRs are mostly very slow and have always been very slow. A few
extra bytes of register shuffling was probably never measurable.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h |    6 ------
 1 file changed, 6 deletions(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-10 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-10	2026-04-01 14:32:58.971543295 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-01 14:32:58.974543407 -0700
@@ -181,12 +181,6 @@ static inline u64 native_read_pmc(int co
 #define paravirt_write_msr_safe	native_write_msr_safe
 #define paravirt_read_pmc		native_read_pmc
 
-/*
- * Access to machine-specific registers (available on 586 and better only)
- * Note: the rd* operations modify the parameters directly (without using
- * pointer indirection), this allows gcc to optimize better
- */
-
 #endif	/* !CONFIG_PARAVIRT_XXL */
 
 /*
_

^ permalink raw reply

* [PATCH v2 8/8] x86/msr: Remove duplicate #include
From: Dave Hansen @ 2026-04-29 18:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86, Juergen Gross,
	virtualization, Dave Hansen
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


From: Dave Hansen <dave.hansen@linux.intel.com>

errno.h is already included for C code at the top of the header.
Zap the duplicate.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/include/asm/msr.h |    1 -
 1 file changed, 1 deletion(-)

diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-11 arch/x86/include/asm/msr.h
--- a/arch/x86/include/asm/msr.h~rdmsr-dups-11	2026-04-29 11:38:57.838732405 -0700
+++ b/arch/x86/include/asm/msr.h	2026-04-29 11:38:57.841732519 -0700
@@ -172,7 +172,6 @@ static inline u64 native_read_pmc(int co
 #ifdef CONFIG_PARAVIRT_XXL
 #include <asm/paravirt.h>
 #else
-#include <linux/errno.h>
 
 /* Short-circuit the paravirt MSR infrastructure when it is disabled: */
 #define paravirt_read_msr	native_read_msr
_

^ permalink raw reply

* Re: [PATCH v12 00/13] blk: honor isolcpus configuration
From: Florian Bezdeka @ 2026-04-29 21:01 UTC (permalink / raw)
  To: Daniel Wagner
  Cc: Aaron Tomlin, axboe, kbusch, hch, sagi, mst, aacraid,
	James.Bottomley, martin.petersen, liyihang9, kashyap.desai,
	sumit.saxena, shivasharan.srikanteshwara, chandrakanth.patil,
	sathya.prakash, sreekanth.reddy, suganath-prabu.subramani,
	ranjan.kumar, jinpu.wang, tglx, mingo, peterz, juri.lelli,
	vincent.guittot, akpm, maz, ruanjinjie, bigeasy, yphbchou0911,
	wagi, frederic, longman, chenridong, hare, kch, ming.lei,
	tom.leiming, steve, sean, chjohnst, neelx, mproche, nick.lange,
	marco.crivellari, linux-block, linux-kernel, virtualization,
	linux-nvme, linux-scsi, megaraidlinux.pdl, mpi3mr-linuxdrv.pdl,
	MPT-FusionLinux.pdl, Jan Kiszka
In-Reply-To: <2d61b1f7-fc06-4fe1-8a6f-cc3a2f114ae1@flourine.local>

On Tue, 2026-04-28 at 15:08 +0200, Daniel Wagner wrote:
> On Mon, Apr 27, 2026 at 12:55:20PM +0200, Florian Bezdeka wrote:
> > This topic reminds me of a discussion started by Tobias [1] some time
> > ago about IRQ spreading of network drivers. The problem was (and still
> > is) that network drivers ignore any CPU isolation when spreading out
> > device IRQs.
> > 
> > In general we have two different CPU isolation mechanisms:
> >   - The static one, via isolcpus= cmdline parameter
> >   - The dynamic one, via cgroups(v2) cpuset controller
> > 
> > This series is only taking the static "world" into account, right? Are
> > there any plans to honor the CPU isolations configured the dynamic
> > way?
> 
> Dynamic configuration would require every driver to fully support
> reconfiguration during runtime. Only a handful of drivers, such as
> nvme-pci, are currently able to handle this.
> 
> The first task, teaching a wide range of drivers to honor CPU isolation
> at boot time, is already going to be a significant amount of work.
> 
> > It has been a while since the last investigations on my end. Last time I
> > went through the code, the IRQ core was completely decoupled from the
> > dynamic configuration via cgroups. Are there any plans to fix that gap?
> 
> Which use case are you actually aiming to support? While dynamic
> reconfiguration would be ideal, the amount of work to get there is
> significant. I won't be signing up for it.

The use case at hand is a RT enabled platform where the concrete RT
workload is not known at boot time. RT applications are deployed "on-
the-fly", nowadays using the existing container runtimes with some
extended resource management on top.

Applications can request certain resources like isolated CPU cores,
special IRQ affinities, PCI devices to pass through, ...,  so that the
resource management on the system can take care of proper system
configuration.

As you said, this requires that drivers are able to honor the system
configuration during runtime. We already identified IRQ spreading of the
network subsystem to be problematic. And yes, that will need some
efforts to fix that. We are still in phase of searching for similar
problems and a starting point for a discussion. Any input in that
direction is highly appreciated.

^ permalink raw reply

* Re: [PATCH net-next v9 0/4] tun/tap & vhost-net: apply qdisc backpressure on full ptr_ring to reduce TX drops
From: Simon Schippers @ 2026-04-29 21:04 UTC (permalink / raw)
  To: willemdebruijn.kernel, jasowang, andrew+netdev, davem, edumazet,
	kuba, pabeni, mst, eperezma, leiyang, stephen, jon, tim.gebauer,
	netdev, linux-kernel, kvm, virtualization
In-Reply-To: <20260428123859.19578-1-simon.schippers@tu-dortmund.de>

I just saw that the Sashiko AI review found some valid regressions.

I will update and test the patch set accordingly and send a new
version...


^ permalink raw reply

* Re: [PATCH v12 02/13] lib/group_cpus: remove dead !SMP code
From: Aaron Tomlin @ 2026-04-29 23:32 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: axboe, kbusch, hch, sagi, mst, aacraid, James.Bottomley,
	martin.petersen, liyihang9, kashyap.desai, sumit.saxena,
	shivasharan.srikanteshwara, chandrakanth.patil, sathya.prakash,
	sreekanth.reddy, suganath-prabu.subramani, ranjan.kumar,
	jinpu.wang, tglx, mingo, peterz, juri.lelli, vincent.guittot,
	akpm, maz, ruanjinjie, yphbchou0911, wagi, frederic, longman,
	chenridong, hare, kch, ming.lei, tom.leiming, steve, sean,
	chjohnst, neelx, mproche, nick.lange, marco.crivellari,
	linux-block, linux-kernel, virtualization, linux-nvme, linux-scsi,
	megaraidlinux.pdl, mpi3mr-linuxdrv.pdl, MPT-FusionLinux.pdl
In-Reply-To: <20260427152104.WTGAesGs@linutronix.de>

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

On Mon, Apr 27, 2026 at 05:21:04PM +0200, Sebastian Andrzej Siewior wrote:
> On 2026-04-22 14:52:04 [-0400], Aaron Tomlin wrote:
> > From: Daniel Wagner <wagi@kernel.org>
> > 
> > The support for the !SMP configuration has been removed from the core by
> > commit cac5cefbade9 ("sched/smp: Make SMP unconditional").
> > 
> > While one can technically still compile a uniprocessor kernel, the core
> > scheduler now mandates SMP unconditionally, rendering this particular
> > !SMP fallback handling redundant. Therefore, remove the #ifdef CONFIG_SMP
> > guards and the fallback logic.
> > 
> > Signed-off-by: Daniel Wagner <wagi@kernel.org>
> > Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > [atomlin: Updated commit message to clarify !SMP removal context]
> 
> This look unchanged vs previous submission. You could explain why you
> want to remove the !SMP case. It looks like the !SMP makes things
> easier ;) I don't know how much of this gets removed because of !SMP
> code elsewhere.
> 
> The description still does not make sense/ is accurate.

Hi Sebastian,

Yes, the !SMP path does make things "easier" and lighter for actual UP
builds by bypassing the SMP overhead. However, maintaining two separate
code paths and #ifdef guards for this specific logic adds testing and
maintenance burden that we'd prefer to drop.

The reference to the scheduler commit was meant to highlight a
philosophical alignment-trading a slight performance edge on UP builds in
exchange for a single, unified code path without #ifdef clutter.

How about the following:

    The core scheduler recently transitioned to compiling SMP data structures
    unconditionally to reduce code complexity (see commit cac5cefbade9
    "sched/smp: Make SMP unconditional").

    In alignment with this philosophy of reducing dual-path maintenance, this
    patch removes the #ifdef CONFIG_SMP guards and the dedicated !SMP fallback
    logic here.

    While the !SMP path provided a slightly simpler execution flow for
    uniprocessor kernels (avoiding SMP-specific overhead), maintaining these
    separate code paths adds unnecessary complexity and testing burden.
    Removing these guards simplifies the codebase by standardizing entirely on
    the SMP logic, which safely resolves to single-CPU operations on UP
    configurations.


Kind regards,
-- 
Aaron Tomlin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH] hv_sock: fix ARM64 support
From: patchwork-bot+netdevbpf @ 2026-04-30  0:50 UTC (permalink / raw)
  To: Hamza Mahfooz
  Cc: netdev, kys, haiyangz, wei.liu, decui, longli, sgarzare, davem,
	edumazet, kuba, pabeni, horms, mhklinux, himadrispandya,
	linux-hyperv, virtualization, linux-kernel
In-Reply-To: <20260428125339.13963-1-hamzamahfooz@linux.microsoft.com>

Hello:

This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue, 28 Apr 2026 08:53:39 -0400 you wrote:
> VMBUS ring buffers must be page aligned. Therefore, the current value of
> 24K presents a challenge on ARM64 kernels (with 64K pages). So, use
> VMBUS_RING_SIZE() to ensure they are always aligned and large enough to
> hold all of the relevant data.
> 
> Cc: stable@vger.kernel.org
> Fixes: 77ffe33363c0 ("hv_sock: use HV_HYP_PAGE_SIZE for Hyper-V communication")
> Tested-by: Dexuan Cui <decui@microsoft.com>
> Reviewed-by: Dexuan Cui <decui@microsoft.com>
> Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
> 
> [...]

Here is the summary with links:
  - hv_sock: fix ARM64 support
    https://git.kernel.org/netdev/net/c/b31681206e3f

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [RFC PATCH] virtio-mmio: add xenbus probing
From: Val Packett @ 2026-04-30  4:01 UTC (permalink / raw)
  To: Teddy Astie, Michael S. Tsirkin, Jason Wang, Xuan Zhuo,
	Eugenio Pérez
  Cc: Marek Marczykowski-Górecki, Viresh Kumar, xen-devel,
	linux-kernel, virtualization
In-Reply-To: <1777473712.8631fc262581453bbf619ec5b2062170.19dd9b07146000f373@vates.tech>


On 4/29/26 11:41 AM, Teddy Astie wrote:
> Hello,
>
> Le 29/04/2026 à 16:18, Val Packett a écrit :
>> […]
>>
>> I've been working on porting virtio-mmio support from Arm to x86_64,
>> with the goal of running vhost-user-gpu to power Wayland/GPU integration
>> for Qubes OS. (I'm aware of various proposals for alternative virtio
>> transports but virtio-mmio seems to be the only one that *is* upstream
>> already and just Works..) Setting up virtio-mmio through xenbus, initially
>> motivated just by event channels being the only real way to get interrupts
>> working on HVM, turned out to generally be quite pleasant and nice :)
> Is it HVM specific, or can we also make it work for PVH (we can actually
> attach a ioreq server to PVH guests) ?

Sorry, typo, I did mean PVH of course!

I've been testing this with PVH guests + PV dom0, with my PV alloc_ioreq 
fix:
https://lore.kernel.org/all/20251126062124.117425-1-val@invisiblethingslab.com/ 


(Time to resend that one as a non-RFC I guess…)

HVM actually does have legacy ISA interrupts (which are often used with 
virtio-mmio on KVM), funnily enough, and I've tried firing those from a 
DMOP but that silly thing didn't work properly.

>> I'd like to get some early feedback for this patch, particularly
>> the general stuff:
>>
>> * is this whole thing acceptable in general?
>> * should it be extracted into a different file?
>> * (from the Xen side) any input on the xenstore keys, what goes where?
>> * anything else to keep in mind?
>>
>> It does seem simple enough, so hopefully this can be done?
>>
>> The corresponding userspace-side WIP is available at:
>> https://github.com/QubesOS/xen-vhost-frontend
>>
>> And the required DMOP for firing the evtchn events will be sent
>> to xen-devel shortly as well.
> Could that be done through evtchn_send (or its userland counterpart) ?

Actually, yes… The use of DMOPs is only dictated by the current Linux 
privcmd.c code (the irqfds created by the kernel react to events by 
executing HYPERVISOR_dm_op with a stored operation), we can avoid the 
need to modify Xen by simply expanding the privcmd driver to make 
"evtchn fds". Sounds good, will do.

>> [..]
>>
>> diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
>> index ce5bc0d9ea28..56bc2b10526b 100644
>> --- a/drivers/virtio/Kconfig
>> +++ b/drivers/virtio/Kconfig
>> @@ -171,6 +171,13 @@ config VIRTIO_MMIO_CMDLINE_DEVICES
>>    
>>    	 If unsure, say 'N'.
>>    
>> +config VIRTIO_MMIO_XENBUS
>> +	bool "Memory mapped virtio devices parameter parsing"
> that text seems to miss the xenbus aspect
Yep, didn't change that yet, ack
>> [..]
> In some way, we're defining a new "PV driver" which is a virtio-mmio
> one, I guess we can eventually specific some form of protocol that
> backend/frontend would need to follow ?

Right, Jürgen mentioned documenting the keys in the xenstore-paths doc.. 
would the entire "protocol" (keys + state transition logic) fit into that?

The keys are currently derived from the initial Arm prototype which 
wasn't actually using xenbus properly (the guest driver was configured 
by a device tree node, but the ioreq server used xenstore keys, without 
properly transitioning between states).


Thanks,
~val


^ permalink raw reply

* Re: [RFC PATCH] virtio-mmio: add xenbus probing
From: Val Packett @ 2026-04-30  4:04 UTC (permalink / raw)
  To: Jürgen Groß, Michael S. Tsirkin, Jason Wang, Xuan Zhuo,
	Eugenio Pérez
  Cc: Marek Marczykowski-Górecki, Viresh Kumar, xen-devel,
	linux-kernel, virtualization
In-Reply-To: <67632532-8421-4a10-a961-f7c4f05b177b@suse.com>


On 4/29/26 12:35 PM, Jürgen Groß wrote:
> Some minor details from the Xen side of things:
>
> On 29.04.26 15:52, Val Packett wrote:
>> The experimental virtio-mmio support for Xen was initially developed
>> on aarch64, so device trees were used to configure the mmio devices,
>> with arbitrary vGIC interrupts used by the hypervisor. On x86_64
>> however, the only reasonable way to interrupt the guest is over Xen
>> event channels, which can only be acquired by children of xenbus,
>
> More exact: interdomain event channels need to be connected to a xenbus
> device. But you are needing those, so for your use case the above 
> statement
> is correct.
>
>> the virtual bus driven by Xen's configuration database, XenStore.
>> It is also a more convenient and "Xen-ish" way to provision devices.
>>
>> Implement a xenbus client for virtio-mmio which negotiates an
>> event channel and provides it as a platform IRQ to the
>> virtio-mmio driver.
>>
>>
>> Signed-off-by: Val Packett <val@invisiblethingslab.com>
>> ---
>>
>> Hi,
>>
>> I've been working on porting virtio-mmio support from Arm to x86_64,
>> with the goal of running vhost-user-gpu to power Wayland/GPU integration
>> for Qubes OS. (I'm aware of various proposals for alternative virtio
>> transports but virtio-mmio seems to be the only one that *is* upstream
>> already and just Works..) Setting up virtio-mmio through xenbus, 
>> initially
>> motivated just by event channels being the only real way to get 
>> interrupts
>> working on HVM, turned out to generally be quite pleasant and nice :)
>>
>> I'd like to get some early feedback for this patch, particularly
>> the general stuff:
>>
>> * is this whole thing acceptable in general?
>> * should it be extracted into a different file?
>> * (from the Xen side) any input on the xenstore keys, what goes where?
>
> You should add some documentation in the Xen source tree regarding the
> Xenstore keys (see docs/misc/xenstore-paths.pandoc there).
Ack, thanks!
>> […]
>>
>> +again:
>> +    err = xenbus_transaction_start(&xbt);
>
> No need to use a Xenstore transaction here. The written node(s) are
> regarded to be valid only after calling xenbus_switch_state() to set
> the frontend state to XenbusStateInitialised.
Oh, I assumed transactions were required for writing from the kernel to 
work at all…
>> [..]
>>
>> +static const struct xenbus_device_id virtio_mmio_xen_ids[] = {
>> +    { "virtio" },
>
> Please use "virtio-mmio" here, as I could imagine "virtio-pci" 
> devices, too. 

Ack. Would actually also distinguish it from the initial Arm 
proof-of-concept version…


Thanks,
~val


^ permalink raw reply

* [PATCH v2] virtio_console: add timeout to __send_to_port() spin loop
From: Peng Yang @ 2026-04-30  5:51 UTC (permalink / raw)
  To: Amit Shah, Arnd Bergmann, Greg Kroah-Hartman
  Cc: kernel, virtualization, linux-kernel, kernel, Peng Yang

__send_to_port() busy-waits on virtqueue_get_buf() while holding
outvq_lock with IRQs disabled.  If the host stops draining the TX
virtqueue, this loop never terminates.

This was observed during secondary VM boot: virtio_mem plugged memory
in multiple iterations, each emitting dev_info() messages through the
hvc console.  A writev() on the hvc TTY entered __send_to_port() and
stalled in the spin loop.  When the watchdog bark ISR fired on another
CPU, it attempted printk(), which tried to acquire outvq_lock through
the same path and spun indefinitely.  With all CPUs stuck, the watchdog
could not be serviced and triggered a bite.

Add a 200 ms deadline using ktime_get_mono_fast_ns() to bound the spin
loop.  ktime_get_mono_fast_ns() reads the hardware counter directly and
is safe to call with IRQs disabled and spinlocks held.

The 200 ms value is chosen to be well above normal host response latency
(microseconds) to avoid spurious exits, yet well below the watchdog
bark-to-bite window (typically 3 s) so that CPUs can escape the loop
and complete the bark handler before a bite occurs.

To handle the timeout case safely, put_chars() is reworked to allocate
a full struct port_buffer (GFP_ATOMIC) instead of a plain kmalloc'd
data buffer.  This allows reclaim_consumed_buffers() to call free_buf()
on the token returned by virtqueue_get_buf() regardless of whether
__send_to_port() timed out before observing the used-ring update.
Ownership of the buffer is transferred to the virtqueue on success and
reclaimed by reclaim_consumed_buffers(); on virtqueue_add_outbuf()
failure the buffer is freed immediately via free_buf().

Signed-off-by: Peng Yang <peng.yang@oss.qualcomm.com>
---
Changes in v2:
- Rework put_chars() to allocate full struct port_buffer (GFP_ATOMIC)
  so free_buf() can safely reclaim the token on timeout.
- Transfer buffer ownership to virtqueue on success; free immediately
  on virtqueue_add_outbuf() failure.
- Link to v1: https://patch.msgid.link/20260420-add_timeout_to___send_to_port-v1-1-6c32d33bf4f2@oss.qualcomm.com

To: Amit Shah <amit@kernel.org>
To: Arnd Bergmann <arnd@arndb.de>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: kernel@oss.qualcomm.com
Cc: virtualization@lists.linux.dev
Cc: linux-kernel@vger.kernel.org
---
 drivers/char/virtio_console.c | 78 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 64 insertions(+), 14 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 9a33217c68d9..91977d458a72 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/string_choices.h>
+#include <linux/timekeeping.h>
 #include "../tty/hvc/hvc_console.h"
 
 #define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC)
@@ -601,6 +602,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 	int err;
 	unsigned long flags;
 	unsigned int len;
+	u64 deadline;
 
 	out_vq = port->out_vq;
 
@@ -632,10 +634,18 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 	 * buffer and relax the spinning requirement.  The downside is
 	 * we need to kmalloc a GFP_ATOMIC buffer each time the
 	 * console driver writes something out.
+	 *
+	 * To avoid spinning forever if the host stops processing the
+	 * TX virtqueue (e.g. during VM shutdown), a 200ms deadline is
+	 * used to break out of the loop as a fallback.
 	 */
-	while (!virtqueue_get_buf(out_vq, &len)
-		&& !virtqueue_is_broken(out_vq))
+	deadline = ktime_get_mono_fast_ns() + 200ULL * NSEC_PER_MSEC;
+	while (!virtqueue_get_buf(out_vq, &len) &&
+	       !virtqueue_is_broken(out_vq)) {
+		if (ktime_get_mono_fast_ns() >= deadline)
+			break;
 		cpu_relax();
+	}
 done:
 	spin_unlock_irqrestore(&port->outvq_lock, flags);
 
@@ -1097,31 +1107,71 @@ static const struct file_operations port_fops = {
 };
 
 /*
- * The put_chars() callback is pretty straightforward.
+ * The put_chars() callback writes characters to the virtio console port.
  *
- * We turn the characters into a scatter-gather list, add it to the
- * output queue and then kick the Host.  Then we sit here waiting for
- * it to finish: inefficient in theory, but in practice
- * implementations will do it immediately.
+ * We allocate a struct port_buffer (with GFP_ATOMIC) to wrap the data so
+ * that reclaim_consumed_buffers() can safely call free_buf() on the token
+ * returned by virtqueue_get_buf(), even if __send_to_port() timed out
+ * before observing the used-ring update.
+ *
+ * On success, ownership of the buffer is transferred to the virtqueue as
+ * the descriptor token; it will be reclaimed by reclaim_consumed_buffers().
+ * On failure (virtqueue_add_outbuf() error), the buffer was never submitted
+ * and must be freed explicitly here.
  */
 static ssize_t put_chars(u32 vtermno, const u8 *buf, size_t count)
 {
 	struct port *port;
 	struct scatterlist sg[1];
-	void *data;
-	int ret;
+	struct port_buffer *pbuf;
+	ssize_t ret;
+
+	if (!count)
+		return 0;
 
 	port = find_port_by_vtermno(vtermno);
 	if (!port)
 		return -EPIPE;
 
-	data = kmemdup(buf, count, GFP_ATOMIC);
-	if (!data)
+	/*
+	 * Allocate a struct port_buffer with GFP_ATOMIC so that
+	 * reclaim_consumed_buffers() can safely call free_buf() on the token
+	 * returned by virtqueue_get_buf(), whether or not __send_to_port()
+	 * timed out.  alloc_buf() uses GFP_KERNEL internally, so we open-code
+	 * the allocation here.
+	 */
+	pbuf = kmalloc(struct_size(pbuf, sg, 0), GFP_ATOMIC);
+	if (!pbuf)
 		return -ENOMEM;
 
-	sg_init_one(sg, data, count);
-	ret = __send_to_port(port, sg, 1, count, data, false);
-	kfree(data);
+	pbuf->buf = kmalloc(count, GFP_ATOMIC);
+	if (!pbuf->buf) {
+		kfree(pbuf);
+		return -ENOMEM;
+	}
+	pbuf->dev = NULL;
+	pbuf->sgpages = 0;
+	pbuf->len = count;
+	pbuf->offset = 0;
+	pbuf->size = count;
+	memcpy(pbuf->buf, buf, count);
+
+	sg_init_one(sg, pbuf->buf, count);
+	ret = __send_to_port(port, sg, 1, count, pbuf, false);
+
+	/*
+	 * If virtqueue_add_outbuf() failed inside __send_to_port() (ret <= 0),
+	 * the token was never submitted to the virtqueue, so reclaim_consumed_
+	 * buffers() will never see it.  Free pbuf explicitly in that case.
+	 *
+	 * On success (ret > 0), ownership of pbuf has been transferred to the
+	 * virtqueue as the descriptor token.  It will be reclaimed and freed
+	 * by reclaim_consumed_buffers() -> free_buf() when the host marks the
+	 * descriptor as used, even if __send_to_port() timed out before
+	 * observing the used-ring update.  Do NOT free pbuf here in that case.
+	 */
+	if (ret <= 0)
+		free_buf(pbuf, false);
 	return ret;
 }
 

---
base-commit: 97e797263a5e963da3d1e66e743fd518567dfe37
change-id: 20260420-add_timeout_to___send_to_port-104ce7bcf241

Best regards,
--  
Peng Yang <peng.yang@oss.qualcomm.com>


^ permalink raw reply related

* [PATCH] vsock/virtio: fix vsockmon info leak in non-linear tap copy
From: Yiqi Sun @ 2026-04-30  7:11 UTC (permalink / raw)
  To: kvm, virtualization
  Cc: netdev, linux-kernel, stefanha, sgarzare, mst, jasowang, xuanzhuo,
	eperezma, davem, edumazet, kuba, pabeni, horms, Yiqi Sun

vsockmon mirrors packets through virtio_transport_build_skb(), which
builds a new skb and copies the payload into it. For non-linear skbs,
this goes through virtio_transport_copy_nonlinear_skb().

Helper manually initializes a iov_iter, but leaves iov_iter.count unset.
As a result, skb_copy_datagram_iter() sees zero writable bytes
in the destination iterator and copies no payload data.

This becomes an info leak because virtio_transport_build_skb() has
already reserved payload_len bytes in the new skb with skb_put(). The
skb is then returned to the tap path with that payload area still
uninitialized, so userspace reading from a vsockmon device can observe
heap contents and potentially kernel address.

Fix it by initializing iov_iter.count to the number of bytes to copy.

Fixes: 4b0bf10eb077 ("vsock/virtio: non-linear skb handling for tap")
Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
---
 net/vmw_vsock/virtio_transport_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 416d533f493d..6b26ee57ccab 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -152,7 +152,7 @@ static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb,
 	iov_iter.nr_segs = 1;
 
 	to_copy = min_t(size_t, len, skb->len);
-
+	iov_iter.count = to_copy;
 	skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
 			       &iov_iter, to_copy);
 }
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v2 8/8] x86/msr: Remove duplicate #include
From: Jürgen Groß @ 2026-04-30  7:20 UTC (permalink / raw)
  To: Dave Hansen, linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
	virtualization
In-Reply-To: <20260429184530.9FE585E8@davehans-spike.ostc.intel.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 1032 bytes --]

On 29.04.26 20:45, Dave Hansen wrote:
> From: Dave Hansen <dave.hansen@linux.intel.com>
> 
> errno.h is already included for C code at the top of the header.

I'm seeing only asm/errno.h being included.

I don't say linux/errno.h is needed, but the reasoning is not really
convincing.


Juergen

> Zap the duplicate.
> 
> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
> ---
> 
>   b/arch/x86/include/asm/msr.h |    1 -
>   1 file changed, 1 deletion(-)
> 
> diff -puN arch/x86/include/asm/msr.h~rdmsr-dups-11 arch/x86/include/asm/msr.h
> --- a/arch/x86/include/asm/msr.h~rdmsr-dups-11	2026-04-29 11:38:57.838732405 -0700
> +++ b/arch/x86/include/asm/msr.h	2026-04-29 11:38:57.841732519 -0700
> @@ -172,7 +172,6 @@ static inline u64 native_read_pmc(int co
>   #ifdef CONFIG_PARAVIRT_XXL
>   #include <asm/paravirt.h>
>   #else
> -#include <linux/errno.h>
>   
>   /* Short-circuit the paravirt MSR infrastructure when it is disabled: */
>   #define paravirt_read_msr	native_read_msr
> _


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply

* Re: [PATCH v2 0/8] x86/msr: Consolidate native/paravirt MSR functions
From: Jürgen Groß @ 2026-04-30  7:21 UTC (permalink / raw)
  To: Dave Hansen, linux-kernel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
	virtualization
In-Reply-To: <20260429184517.7E078510@davehans-spike.ostc.intel.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 1638 bytes --]

On 29.04.26 20:45, Dave Hansen wrote:
> Changes from v1:
>   - Remove "raw_" names. Just use "paravirt_" in the generic code.
> 
> I'm thinking I'll just apply this in the coming days if nobody
> screams too loudly.
> 
> --
> 
> This is old cruft, but it appears that having two copies of these
> MSR functions is enabling warnings to creep in[1].
> 
> I know there's also been some work to pare down the XXL code, but
> it's obviously not merged yet and this is a good baby step.
> 
> Create helpers that both paravirt and native can use in common code
> and remove the paravirt implementations of the helpers. This reduces
> the amount of logic that is duplicated in the paravirt code.
> 
> The wonky thing about this solution is that it has the common code
> always make literal "paravirt_" calls, even when paravirt is not in
> use for MSRs. In that case, the calls just go directly to the
> "native_" functions via #defines.
> 
> Conceptually:
>   -   native: The bare-metal implementation. Might not be usable under
> 	     paravirt XXL.
>   - paravirt: Call the native version directly if paravirt is compiled
>   	     out. Call into paravirt ops when available, which might
> 	     ultimately call a native implementation.
> 
> 1. https://lore.kernel.org/all/20260319152210.210854-1-aldocontelk@gmail.com/
> 
>   msr.h      |  124 +++++++++++++++++++++++++++++++------------------------------
>   paravirt.h |   44 ---------------------
>   2 files changed, 65 insertions(+), 103 deletions(-)

Apart from the comment for patch 8:

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply

* Re: [RFC PATCH] virtio-mmio: add xenbus probing
From: Val Packett @ 2026-04-30  8:48 UTC (permalink / raw)
  To: Teddy Astie, Michael S. Tsirkin, Jason Wang, Xuan Zhuo,
	Eugenio Pérez
  Cc: Marek Marczykowski-Górecki, Viresh Kumar, xen-devel,
	linux-kernel, virtualization
In-Reply-To: <1777536698.8631fc262581453bbf619ec5b2062170.19ddd7187da000f373@vates.tech>


On 4/30/26 5:11 AM, Teddy Astie wrote:
> Le 30/04/2026 à 06:06, Val Packett a écrit :
>> On 4/29/26 11:41 AM, Teddy Astie wrote:
>>> Hello,
>>>
>>> Le 29/04/2026 à 16:18, Val Packett a écrit :
>>>> […]
>>>>
>>>> I've been working on porting virtio-mmio support from Arm to x86_64,
>>>> with the goal of running vhost-user-gpu to power Wayland/GPU integration
>>>> for Qubes OS. (I'm aware of various proposals for alternative virtio
>>>> transports but virtio-mmio seems to be the only one that *is* upstream
>>>> already and just Works..) Setting up virtio-mmio through xenbus,
>>>> initially
>>>> motivated just by event channels being the only real way to get
>>>> interrupts
>>>> working on HVM, turned out to generally be quite pleasant and nice :)
>>> Is it HVM specific, or can we also make it work for PVH (we can actually
>>> attach a ioreq server to PVH guests) ?
>> Sorry, typo, I did mean PVH of course!
>>
>> I've been testing this with PVH guests + PV dom0, with my PV alloc_ioreq
>> fix:
>> https://lore.kernel.org/all/20251126062124.117425-1-
>> val@invisiblethingslab.com/
>>
>> (Time to resend that one as a non-RFC I guess…)
>>
>> HVM actually does have legacy ISA interrupts (which are often used with
>> virtio-mmio on KVM), funnily enough, and I've tried firing those from a
>> DMOP but that silly thing didn't work properly.
>>
>>>> I'd like to get some early feedback for this patch, particularly
>>>> the general stuff:
>>>>
>>>> * is this whole thing acceptable in general?
>>>> * should it be extracted into a different file?
>>>> * (from the Xen side) any input on the xenstore keys, what goes where?
>>>> * anything else to keep in mind?
>>>>
>>>> It does seem simple enough, so hopefully this can be done?
>>>>
>>>> The corresponding userspace-side WIP is available at:
>>>> https://github.com/QubesOS/xen-vhost-frontend
>>>>
>>>> And the required DMOP for firing the evtchn events will be sent
>>>> to xen-devel shortly as well.
>>> Could that be done through evtchn_send (or its userland counterpart) ?
>> Actually, yes… The use of DMOPs is only dictated by the current Linux
>> privcmd.c code (the irqfds created by the kernel react to events by
>> executing HYPERVISOR_dm_op with a stored operation), we can avoid the
>> need to modify Xen by simply expanding the privcmd driver to make
>> "evtchn fds". Sounds good, will do.
>>
> Given that the event channel used by device models is exposed through
> ioreq.vp_eport ("evtchn for notifications to/from device model"). I
> don't think you need to expand the privcmd interface, and you should be
> able to do this instead :
>
> open /dev/xen/evtchn
> perform IOCTL_EVTCHN_BIND_INTERDOMAIN (for each guest vCPU)
>     with remote_domain=guest_domid, remote_port=ioreq.vp_eport
>
> Then interact with the event channel through IOCTL_EVTCHN_NOTIFY (with
> local port given by IOCTL_EVTCHN_BIND_INTERDOMAIN) and read/write on the
> file descriptor.

So the reason there's currently an ioctl to bind an eventfd to fire a 
stored DMOP is that the whole idea is to (efficiently!) support generic, 
hypervisor-neutral device server implementations via the vhost-user 
protocol.

Now of course, the current implementation isn't *entirely* 
hypervisor-neutral as e.g. the vm-memory Rust crate (inside of the 
"neutral" vhost-user device servers) does need to be built with the 
`xen` feature. But still, that's how it works. What can be made generic 
is generic.

xen-vhost-frontend, which is the thing that integrates these with Xen, 
actually used to handle the interrupts in userspace[1] by firing the 
DMOP itself (which is where I could "just replace that with 
IOCTL_EVTCHN_NOTIFY") but that was offloaded to the kernel with the 
introduction of IOCTL_PRIVCMD_IRQFD[2], similarly to KVM_IRQFD.

Switching back to handling the eventfd in userspace would be a literal 
deoptimization :)

While throwing away the whole generic layer to do a fully integrated 
use-case-specific thing sounds more difficult/tedious than this, and not 
necessarily desirable in general.

[1]: 
https://github.com/vireshk/xen-vhost-frontend/commit/06d59035f8a387c0f600931d09dfaa27b80ede7f
[2]: 
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=f8941e6c4c712948663ec5d7bbb546f1a0f4e3f6

~val


^ permalink raw reply

* [PATCH v3 0/3] vfio/pci: Request resources and map BARs at enable time
From: Matt Evans @ 2026-04-30 10:03 UTC (permalink / raw)
  To: Alex Williamson, Kevin Tian, Jason Gunthorpe, Ankit Agrawal,
	Alistair Popple, Leon Romanovsky, Kees Cook, Shameer Kolothum,
	Yishai Hadas
  Cc: Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
	Zhi Wang, kvm, linux-kernel, virtualization

Hi,

These patches fix a potential race for concurrent calls to
vfio_pci_core_setup_barmap(), and a DMABUF missing check for resource
before the export.  Discussion on a previous series (different,
replaced by this one) is here:

 https://lore.kernel.org/kvm/20260415181423.1008458-1-mattev@meta.com

Responses in that thread indicated there wasn't a strong historical
reason to require the mapping to be performed on-demand at BAR
reference time.  It's much simpler to move this earlier, to
vfio_pci_core_enable(), and that then avoids having to deal with
concurrent requests later.

The first patch requests PCI resources and pci_iomap() of the BARs
from vfio_pci_core_enable(), moving this out of
vfio_pci_core_setup_barmap().

Some callers rely on vfio_pci_core_setup_barmap() for its ioremap()
effect, and other callers use it for its resource-acquiring effect.
The function turns into a cheap error check that both these actions
have occurred and keeps the same error behaviour.

The second patch refactors that function plus the various
vdev->barmap[] accesses into vfio_pci_core_get_iomap() which returns
either a pointer to the mapping or an ERR_PTR() describing why it
doesn't exist.  This is used by callers that need the mapping, but
also by other callers to check that the resource/mapping step was
successful.

NOTE: This removes the EXPORT_SYMBOL_GPL(vfio_pci_core_setup_barmap).
It does not re-add an export for vfio_pci_core_get_iomap() yet.  (I
wanted to check the preference/policy here.)

The third patch adds the resource check to VFIO DMABUF export, which
was previously able to export an unrequested resource.  Although patch
1 at first appears to fix this by requesting resources at enable time,
code using the BAR still needs to check the resource really was
acquired.

=== Changes ===

v3:
 - Remove the separate tracking of the BAR mapping versus the
   acquiring its resource.  Errors from failing iomap vs resource
   reservation are ERR_PTR()-elcoded into barmap[bar].

 - Remove the separate test helper, and add vfio_pci_core_get_iomap().
   This gets the iomap base or is used check for error/failure to
   acquire the resource.  Added comments at call sites explaining
   whether they want to just ensure the resource is reserved versus
   actually use the mapping.

v2:
  https://lore.kernel.org/kvm/20260423182517.2286030-1-mattev@meta.com/

 - Don't fail if resources can't be requested or iomapped, even for
   valid BARs, as this would change the userspace-observable error
   behaviour.  Specifically, if there was an issue with one particular
   BAR which happened to never be used, then userspace would never
   encounter an error for it.  Track iomap and resource-acquisition
   status per BAR.

 - Break out the checks for resource success from those for iomap
   success, in the form of the two new helpers.

 - Third patch to add the check to VFIO DMABUF export, because
   init-time requests can now fail.

v1:
  https://lore.kernel.org/kvm/20260421174143.3883579-1-mattev@meta.com/

Matt Evans (3):
  vfio/pci: Set up bar resources and maps in vfio_pci_core_enable()
  vfio/pci: Replace vfio_pci_core_setup_barmap() with
    vfio_pci_core_get_iomap()
  vfio/pci: Check BAR resources before exporting a DMABUF

 drivers/vfio/pci/nvgrace-gpu/main.c | 17 ++++++-----
 drivers/vfio/pci/vfio_pci_core.c    | 44 +++++++++++++++++++++++++----
 drivers/vfio/pci/vfio_pci_dmabuf.c  |  6 ++--
 drivers/vfio/pci/vfio_pci_rdwr.c    | 42 ++++++---------------------
 drivers/vfio/pci/virtio/legacy_io.c | 13 ++++-----
 include/linux/vfio_pci_core.h       | 19 ++++++++++++-
 6 files changed, 84 insertions(+), 57 deletions(-)

-- 
2.47.3


^ permalink raw reply

* [PATCH v3 2/3] vfio/pci: Replace vfio_pci_core_setup_barmap() with vfio_pci_core_get_iomap()
From: Matt Evans @ 2026-04-30 10:03 UTC (permalink / raw)
  To: Alex Williamson, Kevin Tian, Jason Gunthorpe, Ankit Agrawal,
	Alistair Popple, Leon Romanovsky, Kees Cook, Shameer Kolothum,
	Yishai Hadas
  Cc: Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
	Zhi Wang, kvm, linux-kernel, virtualization
In-Reply-To: <20260430100340.2787446-1-mattev@meta.com>

Since "vfio/pci: Set up barmap in vfio_pci_core_enable()", the
resource request and iomap for the BARs was performed early, and
vfio_pci_core_setup_barmap() just checks those actions succeeded.

Move this logic to a new helper that checks success and returns the
iomap address, replacing the various bare vdev->barmap[] lookups.
This maintains the error behaviour of the previous on-demand
vfio_pci_core_setup_barmap() scheme.

Signed-off-by: Matt Evans <mattev@meta.com>
---
 drivers/vfio/pci/nvgrace-gpu/main.c | 17 +++++++------
 drivers/vfio/pci/vfio_pci_core.c    | 11 ++++-----
 drivers/vfio/pci/vfio_pci_rdwr.c    | 37 +++++++----------------------
 drivers/vfio/pci/virtio/legacy_io.c | 13 +++++-----
 include/linux/vfio_pci_core.h       | 19 ++++++++++++++-
 5 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/drivers/vfio/pci/nvgrace-gpu/main.c b/drivers/vfio/pci/nvgrace-gpu/main.c
index fa056b69f899..2f5ec60c15d9 100644
--- a/drivers/vfio/pci/nvgrace-gpu/main.c
+++ b/drivers/vfio/pci/nvgrace-gpu/main.c
@@ -184,13 +184,11 @@ static int nvgrace_gpu_open_device(struct vfio_device *core_vdev)
 
 	/*
 	 * GPU readiness is checked by reading the BAR0 registers.
-	 *
-	 * ioremap BAR0 to ensure that the BAR0 mapping is present before
-	 * register reads on first fault before establishing any GPU
-	 * memory mapping.
+	 * The BAR map was just set up by vfio_pci_core_enable() and,
+	 * although the readiness check checks validity of the BAR0
+	 * map, assert early that the map was successful:
 	 */
-	ret = vfio_pci_core_setup_barmap(vdev, 0);
-	if (ret)
+	if (IS_ERR(vfio_pci_core_get_iomap(vdev, 0)))
 		goto error_exit;
 
 	if (nvdev->resmem.memlength) {
@@ -265,6 +263,7 @@ static int
 nvgrace_gpu_check_device_ready(struct nvgrace_gpu_pci_core_device *nvdev)
 {
 	struct vfio_pci_core_device *vdev = &nvdev->core_device;
+	void __iomem *io;
 	int ret;
 
 	lockdep_assert_held_read(&vdev->memory_lock);
@@ -275,7 +274,11 @@ nvgrace_gpu_check_device_ready(struct nvgrace_gpu_pci_core_device *nvdev)
 	if (!__vfio_pci_memory_enabled(vdev))
 		return -EIO;
 
-	ret = nvgrace_gpu_wait_device_ready(vdev->barmap[0]);
+	io = vfio_pci_core_get_iomap(vdev, 0);
+	if (IS_ERR(io))
+		return PTR_ERR(io);
+
+	ret = nvgrace_gpu_wait_device_ready(io);
 	if (ret)
 		return ret;
 
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index eab4f2626b39..feaf894ac118 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1760,7 +1760,7 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma
 	struct pci_dev *pdev = vdev->pdev;
 	unsigned int index;
 	u64 phys_len, req_len, pgoff, req_start;
-	int ret;
+	void __iomem *bar_io;
 
 	index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
 
@@ -1794,12 +1794,11 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma
 		return -EINVAL;
 
 	/*
-	 * Even though we don't make use of the barmap for the mmap,
-	 * we need to request the region and the barmap tracks that.
+	 * Ensure the BAR resource region is reserved for use.
 	 */
-	ret = vfio_pci_core_setup_barmap(vdev, index);
-	if (ret)
-		return ret;
+	bar_io = vfio_pci_core_get_iomap(vdev, index);
+	if (IS_ERR(bar_io))
+		return PTR_ERR(bar_io);
 
 	vma->vm_private_data = vdev;
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index f66ad3d96481..7f14dd46de17 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -198,26 +198,6 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
 }
 EXPORT_SYMBOL_GPL(vfio_pci_core_do_io_rw);
 
-int vfio_pci_core_setup_barmap(struct vfio_pci_core_device *vdev, int bar)
-{
-	/*
-	 * The barmap is set up in vfio_pci_core_enable().  Callers
-	 * use this function to check that the BAR resources are
-	 * requested or that the pci_iomap() was done.
-	 */
-	if (bar < 0 || bar >= PCI_STD_NUM_BARS)
-		return -EINVAL;
-
-	/* Did vfio_pci_core_map_bars() set it up yet? */
-	if (!vdev->barmap[bar])
-		return -ENODEV;
-
-	if (IS_ERR(vdev->barmap[bar]))
-		return PTR_ERR(vdev->barmap[bar]);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vfio_pci_core_setup_barmap);
-
 ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
 			size_t count, loff_t *ppos, bool iswrite)
 {
@@ -269,13 +249,11 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
 		 */
 		max_width = VFIO_PCI_IO_WIDTH_4;
 	} else {
-		int ret = vfio_pci_core_setup_barmap(vdev, bar);
-		if (ret) {
-			done = ret;
+		io = vfio_pci_core_get_iomap(vdev, bar);
+		if (IS_ERR(io)) {
+			done = PTR_ERR(io);
 			goto out;
 		}
-
-		io = vdev->barmap[bar];
 	}
 
 	if (bar == vdev->msix_bar) {
@@ -430,6 +408,7 @@ int vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
 	loff_t pos = offset & VFIO_PCI_OFFSET_MASK;
 	int ret, bar = VFIO_PCI_OFFSET_TO_INDEX(offset);
 	struct vfio_pci_ioeventfd *ioeventfd;
+	void __iomem *io;
 
 	/* Only support ioeventfds into BARs */
 	if (bar > VFIO_PCI_BAR5_REGION_INDEX)
@@ -447,9 +426,9 @@ int vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
 	if (count == 8)
 		return -EINVAL;
 
-	ret = vfio_pci_core_setup_barmap(vdev, bar);
-	if (ret)
-		return ret;
+	io = vfio_pci_core_get_iomap(vdev, bar);
+	if (IS_ERR(io))
+		return PTR_ERR(io);
 
 	mutex_lock(&vdev->ioeventfds_lock);
 
@@ -486,7 +465,7 @@ int vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
 	}
 
 	ioeventfd->vdev = vdev;
-	ioeventfd->addr = vdev->barmap[bar] + pos;
+	ioeventfd->addr = io + pos;
 	ioeventfd->data = data;
 	ioeventfd->pos = pos;
 	ioeventfd->bar = bar;
diff --git a/drivers/vfio/pci/virtio/legacy_io.c b/drivers/vfio/pci/virtio/legacy_io.c
index 1ed349a55629..c868b2177310 100644
--- a/drivers/vfio/pci/virtio/legacy_io.c
+++ b/drivers/vfio/pci/virtio/legacy_io.c
@@ -299,19 +299,18 @@ int virtiovf_pci_ioctl_get_region_info(struct vfio_device *core_vdev,
 static int virtiovf_set_notify_addr(struct virtiovf_pci_core_device *virtvdev)
 {
 	struct vfio_pci_core_device *core_device = &virtvdev->core_device;
-	int ret;
+	void __iomem *io;
 
 	/*
 	 * Setup the BAR where the 'notify' exists to be used by vfio as well
 	 * This will let us mmap it only once and use it when needed.
 	 */
-	ret = vfio_pci_core_setup_barmap(core_device,
-					 virtvdev->notify_bar);
-	if (ret)
-		return ret;
+	io = vfio_pci_core_get_iomap(core_device,
+				     virtvdev->notify_bar);
+	if (IS_ERR(io))
+		return PTR_ERR(io);
 
-	virtvdev->notify_addr = core_device->barmap[virtvdev->notify_bar] +
-			virtvdev->notify_offset;
+	virtvdev->notify_addr = io + virtvdev->notify_offset;
 	return 0;
 }
 
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 2ebba746c18f..5598071c5ea3 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -188,7 +188,6 @@ int vfio_pci_core_match_token_uuid(struct vfio_device *core_vdev,
 int vfio_pci_core_enable(struct vfio_pci_core_device *vdev);
 void vfio_pci_core_disable(struct vfio_pci_core_device *vdev);
 void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev);
-int vfio_pci_core_setup_barmap(struct vfio_pci_core_device *vdev, int bar);
 pci_ers_result_t vfio_pci_core_aer_err_detected(struct pci_dev *pdev,
 						pci_channel_state_t state);
 ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
@@ -234,6 +233,24 @@ static inline bool is_aligned_for_order(struct vm_area_struct *vma,
 			   !IS_ALIGNED(pfn, 1 << order)));
 }
 
+/*
+ * Returns a BAR's iomap base, or an ERR_PTR() if, for example, the
+ * BAR isn't valid, its resource wasn't acquired, or its iomap
+ * failed.
+ */
+static inline void __iomem __must_check *
+vfio_pci_core_get_iomap(struct vfio_pci_core_device *vdev, int bar)
+{
+	if (bar < 0 || bar >= PCI_STD_NUM_BARS)
+		return ERR_PTR(-EINVAL);
+
+	/* Did vfio_pci_core_map_bars() set it up yet? */
+	if (!vdev->barmap[bar])
+		return ERR_PTR(-ENODEV);
+
+	return vdev->barmap[bar];
+}
+
 int vfio_pci_dma_buf_iommufd_map(struct dma_buf_attachment *attachment,
 				 struct phys_vec *phys);
 
-- 
2.47.3


^ permalink raw reply related

* [PATCH v3 1/3] vfio/pci: Set up bar resources and maps in vfio_pci_core_enable()
From: Matt Evans @ 2026-04-30 10:03 UTC (permalink / raw)
  To: Alex Williamson, Kevin Tian, Jason Gunthorpe, Ankit Agrawal,
	Alistair Popple, Leon Romanovsky, Kees Cook, Shameer Kolothum,
	Yishai Hadas
  Cc: Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
	Zhi Wang, kvm, linux-kernel, virtualization
In-Reply-To: <20260430100340.2787446-1-mattev@meta.com>

Previously BAR resource requests and the corresponding pci_iomap()
were performed on-demand and without synchronisation, which was racy.
Rather than add synchronisation, it's simplest to address this by
doing both activities from vfio_pci_core_enable().

The resource allocation and/or pci_iomap() can still fail; their
status is tracked and existing calls to vfio_pci_core_setup_barmap()
will fail in a similar way to before.  This keeps the point of failure
as observed by userspace the same, i.e. failures to request/map unused
BARs are benign.

Fixes: 7f5764e179c6 ("vfio: use vfio_pci_core_setup_barmap to map bar in mmap")
Fixes: 0d77ed3589ac0 ("vfio/pci: Pull BAR mapping setup from read-write path")
Signed-off-by: Matt Evans <mattev@meta.com>
---
 drivers/vfio/pci/vfio_pci_core.c | 33 ++++++++++++++++++++++++++++++++
 drivers/vfio/pci/vfio_pci_rdwr.c | 29 ++++++++++++----------------
 2 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 3f8d093aacf8..eab4f2626b39 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -482,6 +482,38 @@ static int vfio_pci_core_runtime_resume(struct device *dev)
 }
 #endif /* CONFIG_PM */
 
+static void vfio_pci_core_map_bars(struct vfio_pci_core_device *vdev)
+{
+	struct pci_dev *pdev = vdev->pdev;
+	int i;
+
+	/*
+	 * Eager-request BAR resources, and iomap.  Soft failures are
+	 * allowed, and consumers must check the barmap before use in
+	 * order to give compatible user-visible behaviour with the
+	 * previous on-demand allocation method.
+	 */
+	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
+		int bar = i + PCI_STD_RESOURCES;
+		void __iomem *io = ERR_PTR(-ENODEV);
+
+		if (pci_resource_len(pdev, i) > 0) {
+			if (pci_request_selected_regions(pdev, 1 << bar, "vfio")) {
+				pci_warn(vdev->pdev, "Failed to reserve region %d\n", bar);
+				io = ERR_PTR(-EBUSY);
+			} else {
+				io = pci_iomap(pdev, bar, 0);
+				if (!io) {
+					pci_warn(vdev->pdev, "Failed to iomap region %d\n",
+						 bar);
+					io = ERR_PTR(-ENOMEM);
+				}
+			}
+		}
+		vdev->barmap[bar] = io;
+	}
+}
+
 /*
  * The pci-driver core runtime PM routines always save the device state
  * before going into suspended state. If the device is going into low power
@@ -568,6 +600,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
 	if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
 		vdev->has_vga = true;
 
+	vfio_pci_core_map_bars(vdev);
 
 	return 0;
 
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index 4251ee03e146..f66ad3d96481 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -200,25 +200,20 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_do_io_rw);
 
 int vfio_pci_core_setup_barmap(struct vfio_pci_core_device *vdev, int bar)
 {
-	struct pci_dev *pdev = vdev->pdev;
-	int ret;
-	void __iomem *io;
-
-	if (vdev->barmap[bar])
-		return 0;
-
-	ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
-	if (ret)
-		return ret;
-
-	io = pci_iomap(pdev, bar, 0);
-	if (!io) {
-		pci_release_selected_regions(pdev, 1 << bar);
-		return -ENOMEM;
-	}
+	/*
+	 * The barmap is set up in vfio_pci_core_enable().  Callers
+	 * use this function to check that the BAR resources are
+	 * requested or that the pci_iomap() was done.
+	 */
+	if (bar < 0 || bar >= PCI_STD_NUM_BARS)
+		return -EINVAL;
 
-	vdev->barmap[bar] = io;
+	/* Did vfio_pci_core_map_bars() set it up yet? */
+	if (!vdev->barmap[bar])
+		return -ENODEV;
 
+	if (IS_ERR(vdev->barmap[bar]))
+		return PTR_ERR(vdev->barmap[bar]);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_pci_core_setup_barmap);
-- 
2.47.3


^ permalink raw reply related

* [PATCH v3 3/3] vfio/pci: Check BAR resources before exporting a DMABUF
From: Matt Evans @ 2026-04-30 10:03 UTC (permalink / raw)
  To: Alex Williamson, Kevin Tian, Jason Gunthorpe, Ankit Agrawal,
	Alistair Popple, Leon Romanovsky, Kees Cook, Shameer Kolothum,
	Yishai Hadas
  Cc: Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
	Zhi Wang, kvm, linux-kernel, virtualization
In-Reply-To: <20260430100340.2787446-1-mattev@meta.com>

A DMABUF exports access to BAR resources and, although they are
requested at startup time, we need to ensure they really were reserved
before exporting.  Otherwise, it's possible to access unreserved
resources through the export.

Add a check to the DMABUF-creation path.

Fixes: 5d74781ebc86c ("vfio/pci: Add dma-buf export support for MMIO regions")
Signed-off-by: Matt Evans <mattev@meta.com>
---
 drivers/vfio/pci/vfio_pci_dmabuf.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
index f87fd32e4a01..3bc7d850e258 100644
--- a/drivers/vfio/pci/vfio_pci_dmabuf.c
+++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
@@ -244,9 +244,11 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
 		return -EINVAL;
 
 	/*
-	 * For PCI the region_index is the BAR number like everything else.
+	 * For PCI the region_index is the BAR number like everything
+	 * else.  Check that PCI resources have been claimed for it.
 	 */
-	if (get_dma_buf.region_index >= VFIO_PCI_ROM_REGION_INDEX)
+	if (get_dma_buf.region_index >= VFIO_PCI_ROM_REGION_INDEX ||
+	    !IS_ERR(vfio_pci_core_get_iomap(vdev, get_dma_buf.region_index)))
 		return -ENODEV;
 
 	dma_ranges = memdup_array_user(&arg->dma_ranges, get_dma_buf.nr_ranges,
-- 
2.47.3


^ permalink raw reply related


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