* [PATCH] hyperv: move vmbus_root_device outside of the VMBus driver
@ 2026-05-20 15:49 Hamza Mahfooz
2026-05-20 17:28 ` Jork Loeser
0 siblings, 1 reply; 2+ messages in thread
From: Hamza Mahfooz @ 2026-05-20 15:49 UTC (permalink / raw)
To: linux-hyperv
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Stanislav Kinsburskii, Anirudh Rayabharam (Microsoft),
Jork Loeser, Michael Kelley, Hamza Mahfooz, Arnd Bergmann
Conceptually, we shouldn't have to build the VMBus driver to answer the
question "does VMBus exist?" So, move vmbus_root_device and the
functions that access it directly to hyperv.h. Also, introduce
hv_set_vmbus_root_device() to allow vmbus_drv to set the root device.
Reported-by: Arnd Bergmann <arnd@arndb.de>
Closes: https://lore.kernel.org/r/20260520074044.923728-1-arnd@kernel.org/
Fixes: f1a9e67c1138 ("mshv: limit SynIC management to MSHV-owned resources")
Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
---
drivers/hv/vmbus_drv.c | 27 ++++++---------------------
include/linux/hyperv.h | 18 ++++++++++++++++--
2 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 71f1b4d52f7f..b26e6b42fa49 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -47,9 +47,6 @@ struct vmbus_dynid {
struct hv_vmbus_device_id id;
};
-/* VMBus Root Device */
-static struct device *vmbus_root_device;
-
static int hyperv_cpuhp_online;
static DEFINE_PER_CPU(long, vmbus_evt);
@@ -95,18 +92,6 @@ static struct resource *fb_mmio;
static struct resource *hyperv_mmio;
static DEFINE_MUTEX(hyperv_mmio_lock);
-struct device *hv_get_vmbus_root_device(void)
-{
- return vmbus_root_device;
-}
-EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
-
-bool hv_vmbus_exists(void)
-{
- return vmbus_root_device != NULL;
-}
-EXPORT_SYMBOL_GPL(hv_vmbus_exists);
-
static u8 channel_monitor_group(const struct vmbus_channel *channel)
{
return (u8)channel->offermsg.monitorid / 32;
@@ -903,7 +888,7 @@ static int vmbus_dma_configure(struct device *child_device)
* On x86/x64 coherence is assumed and these calls have no effect.
*/
hv_setup_dma_ops(child_device,
- device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
+ device_get_dma_attr(hv_get_vmbus_root_device()) == DEV_DMA_COHERENT);
return 0;
}
@@ -2172,7 +2157,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
&child_device_obj->channel->offermsg.offer.if_instance);
child_device_obj->device.bus = &hv_bus;
- child_device_obj->device.parent = vmbus_root_device;
+ child_device_obj->device.parent = hv_get_vmbus_root_device();
child_device_obj->device.release = vmbus_device_release;
child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
@@ -2561,7 +2546,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
struct acpi_device *ancestor;
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
- vmbus_root_device = &device->dev;
+ hv_set_vmbus_root_device(&device->dev);
/*
* Older versions of Hyper-V for ARM64 fail to include the _CCA
@@ -2648,7 +2633,7 @@ static int vmbus_device_add(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
int ret;
- vmbus_root_device = &pdev->dev;
+ hv_set_vmbus_root_device(&pdev->dev);
ret = of_range_parser_init(&parser, np);
if (ret)
@@ -2969,7 +2954,7 @@ static int __init hv_acpi_init(void)
if (ret)
return ret;
- if (!vmbus_root_device) {
+ if (!hv_vmbus_exists()) {
ret = -ENODEV;
goto cleanup;
}
@@ -3000,7 +2985,7 @@ static int __init hv_acpi_init(void)
cleanup:
platform_driver_unregister(&vmbus_platform_driver);
- vmbus_root_device = NULL;
+ hv_set_vmbus_root_device(NULL);
return ret;
}
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 5459e776ec17..3e8ea7d9653c 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1302,9 +1302,23 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
return dev_get_drvdata(&dev->device);
}
-struct device *hv_get_vmbus_root_device(void);
+/* Do *not* use this outside of hyperv.h */
+static struct device *__vmbus_root_device __read_mostly;
-bool hv_vmbus_exists(void);
+static inline void hv_set_vmbus_root_device(struct device *dev)
+{
+ __vmbus_root_device = dev;
+}
+
+static inline struct device *hv_get_vmbus_root_device(void)
+{
+ return __vmbus_root_device;
+}
+
+static inline bool hv_vmbus_exists(void)
+{
+ return hv_get_vmbus_root_device();
+}
struct hv_ring_buffer_debug_info {
u32 current_interrupt_mask;
--
2.54.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] hyperv: move vmbus_root_device outside of the VMBus driver
2026-05-20 15:49 [PATCH] hyperv: move vmbus_root_device outside of the VMBus driver Hamza Mahfooz
@ 2026-05-20 17:28 ` Jork Loeser
0 siblings, 0 replies; 2+ messages in thread
From: Jork Loeser @ 2026-05-20 17:28 UTC (permalink / raw)
To: Hamza Mahfooz
Cc: linux-hyperv, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Stanislav Kinsburskii,
Anirudh Rayabharam (Microsoft), Michael Kelley, Arnd Bergmann
On Wed, 20 May 2026, Hamza Mahfooz wrote:
> Conceptually, we shouldn't have to build the VMBus driver to answer the
> question "does VMBus exist?" So, move vmbus_root_device and the
> functions that access it directly to hyperv.h. Also, introduce
> hv_set_vmbus_root_device() to allow vmbus_drv to set the root device.
>
> Reported-by: Arnd Bergmann <arnd@arndb.de>
> Closes: https://lore.kernel.org/r/20260520074044.923728-1-arnd@kernel.org/
> Fixes: f1a9e67c1138 ("mshv: limit SynIC management to MSHV-owned resources")
> Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
> ---
> drivers/hv/vmbus_drv.c | 27 ++++++---------------------
> include/linux/hyperv.h | 18 ++++++++++++++++--
> 2 files changed, 22 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 71f1b4d52f7f..b26e6b42fa49 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -47,9 +47,6 @@ struct vmbus_dynid {
> struct hv_vmbus_device_id id;
> };
>
> -/* VMBus Root Device */
> -static struct device *vmbus_root_device;
> -
> static int hyperv_cpuhp_online;
>
> static DEFINE_PER_CPU(long, vmbus_evt);
> @@ -95,18 +92,6 @@ static struct resource *fb_mmio;
> static struct resource *hyperv_mmio;
> static DEFINE_MUTEX(hyperv_mmio_lock);
>
> -struct device *hv_get_vmbus_root_device(void)
> -{
> - return vmbus_root_device;
> -}
> -EXPORT_SYMBOL_GPL(hv_get_vmbus_root_device);
> -
> -bool hv_vmbus_exists(void)
> -{
> - return vmbus_root_device != NULL;
> -}
> -EXPORT_SYMBOL_GPL(hv_vmbus_exists);
> -
> static u8 channel_monitor_group(const struct vmbus_channel *channel)
> {
> return (u8)channel->offermsg.monitorid / 32;
> @@ -903,7 +888,7 @@ static int vmbus_dma_configure(struct device *child_device)
> * On x86/x64 coherence is assumed and these calls have no effect.
> */
> hv_setup_dma_ops(child_device,
> - device_get_dma_attr(vmbus_root_device) == DEV_DMA_COHERENT);
> + device_get_dma_attr(hv_get_vmbus_root_device()) == DEV_DMA_COHERENT);
> return 0;
> }
>
> @@ -2172,7 +2157,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
> &child_device_obj->channel->offermsg.offer.if_instance);
>
> child_device_obj->device.bus = &hv_bus;
> - child_device_obj->device.parent = vmbus_root_device;
> + child_device_obj->device.parent = hv_get_vmbus_root_device();
> child_device_obj->device.release = vmbus_device_release;
>
> child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
> @@ -2561,7 +2546,7 @@ static int vmbus_acpi_add(struct platform_device *pdev)
> struct acpi_device *ancestor;
> struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
>
> - vmbus_root_device = &device->dev;
> + hv_set_vmbus_root_device(&device->dev);
>
> /*
> * Older versions of Hyper-V for ARM64 fail to include the _CCA
> @@ -2648,7 +2633,7 @@ static int vmbus_device_add(struct platform_device *pdev)
> struct device_node *np = pdev->dev.of_node;
> int ret;
>
> - vmbus_root_device = &pdev->dev;
> + hv_set_vmbus_root_device(&pdev->dev);
>
> ret = of_range_parser_init(&parser, np);
> if (ret)
> @@ -2969,7 +2954,7 @@ static int __init hv_acpi_init(void)
> if (ret)
> return ret;
>
> - if (!vmbus_root_device) {
> + if (!hv_vmbus_exists()) {
> ret = -ENODEV;
> goto cleanup;
> }
> @@ -3000,7 +2985,7 @@ static int __init hv_acpi_init(void)
>
> cleanup:
> platform_driver_unregister(&vmbus_platform_driver);
> - vmbus_root_device = NULL;
> + hv_set_vmbus_root_device(NULL);
> return ret;
> }
>
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index 5459e776ec17..3e8ea7d9653c 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -1302,9 +1302,23 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
> return dev_get_drvdata(&dev->device);
> }
>
> -struct device *hv_get_vmbus_root_device(void);
> +/* Do *not* use this outside of hyperv.h */
> +static struct device *__vmbus_root_device __read_mostly;
>
> -bool hv_vmbus_exists(void);
> +static inline void hv_set_vmbus_root_device(struct device *dev)
> +{
> + __vmbus_root_device = dev;
> +}
> +
> +static inline struct device *hv_get_vmbus_root_device(void)
> +{
> + return __vmbus_root_device;
> +}
> +
> +static inline bool hv_vmbus_exists(void)
> +{
> + return hv_get_vmbus_root_device();
> +}
>
> struct hv_ring_buffer_debug_info {
> u32 current_interrupt_mask;
> --
> 2.54.0
>
Thank you Hamza. Yes, one could do this. It still does not solve the
problem of loading MSHV-root first, then VMBUS. The entire
hv_vmbus_exists() test is a workaround that mostly works, but shouldn't be
there in the first place. What really needs to happen is a SYNIC driver so
components can load in arbitrary orders if compiled as modules. Which in
turn is outside of my original goal to fix L1VH's kexec. The SYNIC
abstraction needs to come no later than the root/nested capability.
Best,
Jork
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-05-20 17:28 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-20 15:49 [PATCH] hyperv: move vmbus_root_device outside of the VMBus driver Hamza Mahfooz
2026-05-20 17:28 ` Jork Loeser
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox