* [PATCH v2 4/6] mshv: limit SynIC management to MSHV-owned resources
From: Jork Loeser @ 2026-04-03 19:06 UTC (permalink / raw)
To: linux-hyperv
Cc: x86, K . Y . Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui,
Long Li, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, H . Peter Anvin, Arnd Bergmann, Michael Kelley,
linux-kernel, linux-arch, Jork Loeser
In-Reply-To: <20260403190613.47026-1-jloeser@linux.microsoft.com>
The SynIC is shared between VMBus and MSHV. VMBus owns the message
page (SIMP), event flags page (SIEFP), global enable (SCONTROL),
and SINT2. MSHV adds SINT0, SINT5, and the event ring page (SIRBP).
Currently mshv_synic_init() redundantly enables SIMP, SIEFP, and
SCONTROL that VMBus already configured, and mshv_synic_cleanup()
disables all of them. This is wrong because MSHV can be torn down
while VMBus is still active. In particular, a kexec reboot notifier
tears down MSHV first. Disabling SCONTROL, SIMP, and SIEFP out
from under VMBus causes its later cleanup to write SynIC MSRs while
SynIC is disabled, which the hypervisor does not tolerate.
Restrict MSHV to managing only the resources it owns:
- SINT0, SINT5: mask on cleanup, unmask on init
- SIRBP: enable/disable as before
- SIMP, SIEFP, SCONTROL: leave to VMBus when it is active (L1VH
and nested root partition); on a non-nested root partition VMBus
doesn't run, so MSHV must enable/disable them
Signed-off-by: Jork Loeser <jloeser@linux.microsoft.com>
---
drivers/hv/mshv_synic.c | 142 ++++++++++++++++++++++++++--------------
1 file changed, 94 insertions(+), 48 deletions(-)
diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
index f8b0337cdc82..7d273766bdb5 100644
--- a/drivers/hv/mshv_synic.c
+++ b/drivers/hv/mshv_synic.c
@@ -454,46 +454,72 @@ int mshv_synic_init(unsigned int cpu)
#ifdef HYPERVISOR_CALLBACK_VECTOR
union hv_synic_sint sint;
#endif
- union hv_synic_scontrol sctrl;
struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_synic_event_flags_page **event_flags_page =
&spages->synic_event_flags_page;
struct hv_synic_event_ring_page **event_ring_page =
&spages->synic_event_ring_page;
+ /* VMBus runs on L1VH and nested root; it owns SIMP/SIEFP/SCONTROL */
+ bool vmbus_active = !hv_root_partition() || hv_nested;
- /* Setup the Synic's message page */
+ /*
+ * Map the SYNIC message page. When VMBus is not active the
+ * hypervisor pre-provisions the SIMP GPA but may not set
+ * simp_enabled — enable it here.
+ */
simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
- simp.simp_enabled = true;
+ if (!vmbus_active) {
+ simp.simp_enabled = true;
+ hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
+ }
*msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
HV_HYP_PAGE_SIZE,
MEMREMAP_WB);
if (!(*msg_page))
- return -EFAULT;
+ goto cleanup_simp;
- hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
-
- /* Setup the Synic's event flags page */
+ /*
+ * Map the event flags page. Same as SIMP: enable when
+ * VMBus is not active, already enabled by VMBus otherwise.
+ */
siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
- siefp.siefp_enabled = true;
+ if (!vmbus_active) {
+ siefp.siefp_enabled = true;
+ hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
+ }
*event_flags_page = memremap(siefp.base_siefp_gpa << PAGE_SHIFT,
PAGE_SIZE, MEMREMAP_WB);
if (!(*event_flags_page))
- goto cleanup;
-
- hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
+ goto cleanup_siefp;
/* Setup the Synic's event ring page */
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
- sirbp.sirbp_enabled = true;
- *event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
- PAGE_SIZE, MEMREMAP_WB);
- if (!(*event_ring_page))
- goto cleanup;
+ if (hv_root_partition()) {
+ *event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
+ PAGE_SIZE, MEMREMAP_WB);
+ if (!(*event_ring_page))
+ goto cleanup_siefp;
+ } else {
+ /*
+ * On L1VH the hypervisor does not provide a SIRBP page.
+ * Allocate one and program its GPA into the MSR.
+ */
+ *event_ring_page = (struct hv_synic_event_ring_page *)
+ get_zeroed_page(GFP_KERNEL);
+
+ if (!(*event_ring_page))
+ goto cleanup_siefp;
+
+ sirbp.base_sirbp_gpa = virt_to_phys(*event_ring_page)
+ >> PAGE_SHIFT;
+ }
+
+ sirbp.sirbp_enabled = true;
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
#ifdef HYPERVISOR_CALLBACK_VECTOR
@@ -515,28 +541,30 @@ int mshv_synic_init(unsigned int cpu)
sint.as_uint64);
#endif
- /* Enable global synic bit */
- sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
- sctrl.enable = 1;
- hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
+ /* When VMBus is active it already enabled SCONTROL. */
+ if (!vmbus_active) {
+ union hv_synic_scontrol sctrl;
+
+ sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
+ sctrl.enable = 1;
+ hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
+ }
return 0;
-cleanup:
- if (*event_ring_page) {
- sirbp.sirbp_enabled = false;
- hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
- memunmap(*event_ring_page);
- }
- if (*event_flags_page) {
+cleanup_siefp:
+ if (*event_flags_page)
+ memunmap(*event_flags_page);
+ if (!vmbus_active) {
siefp.siefp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
- memunmap(*event_flags_page);
}
- if (*msg_page) {
+cleanup_simp:
+ if (*msg_page)
+ memunmap(*msg_page);
+ if (!vmbus_active) {
simp.simp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
- memunmap(*msg_page);
}
return -EFAULT;
@@ -545,16 +573,15 @@ int mshv_synic_init(unsigned int cpu)
int mshv_synic_cleanup(unsigned int cpu)
{
union hv_synic_sint sint;
- union hv_synic_simp simp;
- union hv_synic_siefp siefp;
union hv_synic_sirbp sirbp;
- union hv_synic_scontrol sctrl;
struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_synic_event_flags_page **event_flags_page =
&spages->synic_event_flags_page;
struct hv_synic_event_ring_page **event_ring_page =
&spages->synic_event_ring_page;
+ /* VMBus runs on L1VH and nested root; it owns SIMP/SIEFP/SCONTROL */
+ bool vmbus_active = !hv_root_partition() || hv_nested;
/* Disable the interrupt */
sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX);
@@ -568,28 +595,47 @@ int mshv_synic_cleanup(unsigned int cpu)
hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
sint.as_uint64);
- /* Disable Synic's event ring page */
+ /* Disable SYNIC event ring page owned by MSHV */
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
sirbp.sirbp_enabled = false;
- hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
- memunmap(*event_ring_page);
- /* Disable Synic's event flags page */
- siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
- siefp.siefp_enabled = false;
- hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
+ if (hv_root_partition()) {
+ hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
+ memunmap(*event_ring_page);
+ } else {
+ sirbp.base_sirbp_gpa = 0;
+ hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
+ free_page((unsigned long)*event_ring_page);
+ }
+
+ /*
+ * Release our mappings of the message and event flags pages.
+ * When VMBus is not active, we enabled SIMP/SIEFP — disable
+ * them. Otherwise VMBus owns the MSRs — leave them.
+ */
memunmap(*event_flags_page);
+ if (!vmbus_active) {
+ union hv_synic_simp simp;
+ union hv_synic_siefp siefp;
- /* Disable Synic's message page */
- simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
- simp.simp_enabled = false;
- hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
+ siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
+ siefp.siefp_enabled = false;
+ hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
+
+ simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
+ simp.simp_enabled = false;
+ hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
+ }
memunmap(*msg_page);
- /* Disable global synic bit */
- sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
- sctrl.enable = 0;
- hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
+ /* When VMBus is active it owns SCONTROL — leave it. */
+ if (!vmbus_active) {
+ union hv_synic_scontrol sctrl;
+
+ sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
+ sctrl.enable = 0;
+ hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
+ }
return 0;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2 5/6] mshv: clean up SynIC state on kexec for L1VH
From: Jork Loeser @ 2026-04-03 19:06 UTC (permalink / raw)
To: linux-hyperv
Cc: x86, K . Y . Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui,
Long Li, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, H . Peter Anvin, Arnd Bergmann, Michael Kelley,
linux-kernel, linux-arch, Jork Loeser
In-Reply-To: <20260403190613.47026-1-jloeser@linux.microsoft.com>
Register the mshv reboot notifier for all parent partitions, not just
root. Previously the notifier was gated on hv_root_partition(), so on
L1VH (where hv_root_partition() is false) SINT0, SINT5, and SIRBP were
never cleaned up before kexec. The kexec'd kernel then inherited stale
unmasked SINTs and an enabled SIRBP pointing to freed memory.
The L1VH SIRBP also needs special handling: unlike the root partition
where the hypervisor provides the SIRBP page, L1VH must allocate its
own page and program the GPA into the MSR. Add this allocation to
mshv_synic_init() and the corresponding free to mshv_synic_cleanup().
Remove the unnecessary mshv_root_partition_init/exit wrappers and
register the reboot notifier directly in mshv_parent_partition_init().
Make mshv_reboot_nb static since it no longer needs external linkage.
Signed-off-by: Jork Loeser <jloeser@linux.microsoft.com>
---
drivers/hv/mshv_root_main.c | 21 ++++-----------------
1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index e6509c980763..281f530b68a9 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -2256,20 +2256,10 @@ static int mshv_reboot_notify(struct notifier_block *nb,
return 0;
}
-struct notifier_block mshv_reboot_nb = {
+static struct notifier_block mshv_reboot_nb = {
.notifier_call = mshv_reboot_notify,
};
-static void mshv_root_partition_exit(void)
-{
- unregister_reboot_notifier(&mshv_reboot_nb);
-}
-
-static int __init mshv_root_partition_init(struct device *dev)
-{
- return register_reboot_notifier(&mshv_reboot_nb);
-}
-
static int __init mshv_init_vmm_caps(struct device *dev)
{
int ret;
@@ -2339,8 +2329,7 @@ static int __init mshv_parent_partition_init(void)
if (ret)
goto remove_cpu_state;
- if (hv_root_partition())
- ret = mshv_root_partition_init(dev);
+ ret = register_reboot_notifier(&mshv_reboot_nb);
if (ret)
goto remove_cpu_state;
@@ -2368,8 +2357,7 @@ static int __init mshv_parent_partition_init(void)
deinit_root_scheduler:
root_scheduler_deinit();
exit_partition:
- if (hv_root_partition())
- mshv_root_partition_exit();
+ unregister_reboot_notifier(&mshv_reboot_nb);
remove_cpu_state:
cpuhp_remove_state(mshv_cpuhp_online);
free_synic_pages:
@@ -2387,8 +2375,7 @@ static void __exit mshv_parent_partition_exit(void)
misc_deregister(&mshv_dev);
mshv_irqfd_wq_cleanup();
root_scheduler_deinit();
- if (hv_root_partition())
- mshv_root_partition_exit();
+ unregister_reboot_notifier(&mshv_reboot_nb);
cpuhp_remove_state(mshv_cpuhp_online);
free_percpu(mshv_root.synic_pages);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2 6/6] mshv: unmap debugfs stats pages on kexec
From: Jork Loeser @ 2026-04-03 19:06 UTC (permalink / raw)
To: linux-hyperv
Cc: x86, K . Y . Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui,
Long Li, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, H . Peter Anvin, Arnd Bergmann, Michael Kelley,
linux-kernel, linux-arch, Jork Loeser
In-Reply-To: <20260403190613.47026-1-jloeser@linux.microsoft.com>
On L1VH, debugfs stats pages are overlay pages: the kernel allocates
them and registers the GPAs with the hypervisor via
HVCALL_MAP_STATS_PAGE2. These overlay mappings persist in the
hypervisor across kexec. If the kexec'd kernel reuses those physical
pages, the hypervisor's overlay semantics cause a machine check
exception.
Fix this by calling mshv_debugfs_exit() from the reboot notifier,
which issues HVCALL_UNMAP_STATS_PAGE for each mapped stats page before
kexec. This releases the overlay bindings so the physical pages can be
safely reused. Guard mshv_debugfs_exit() against being called when
init failed.
Signed-off-by: Jork Loeser <jloeser@linux.microsoft.com>
---
drivers/hv/mshv_debugfs.c | 7 ++++++-
drivers/hv/mshv_root_main.c | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/mshv_debugfs.c b/drivers/hv/mshv_debugfs.c
index ebf2549eb44d..f9a4499cf8f3 100644
--- a/drivers/hv/mshv_debugfs.c
+++ b/drivers/hv/mshv_debugfs.c
@@ -676,8 +676,10 @@ int __init mshv_debugfs_init(void)
mshv_debugfs = debugfs_create_dir("mshv", NULL);
if (IS_ERR(mshv_debugfs)) {
+ err = PTR_ERR(mshv_debugfs);
+ mshv_debugfs = NULL;
pr_err("%s: failed to create debugfs directory\n", __func__);
- return PTR_ERR(mshv_debugfs);
+ return err;
}
if (hv_root_partition()) {
@@ -712,6 +714,9 @@ int __init mshv_debugfs_init(void)
void mshv_debugfs_exit(void)
{
+ if (!mshv_debugfs)
+ return;
+
mshv_debugfs_parent_partition_remove();
if (hv_root_partition()) {
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 281f530b68a9..7038fd830646 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -2252,6 +2252,7 @@ root_scheduler_deinit(void)
static int mshv_reboot_notify(struct notifier_block *nb,
unsigned long code, void *unused)
{
+ mshv_debugfs_exit();
cpuhp_remove_state(mshv_cpuhp_online);
return 0;
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 4/6] mshv: limit SynIC management to MSHV-owned resources
From: Jork Loeser @ 2026-04-03 19:19 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: linux-hyperv, x86, K . Y . Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H . Peter Anvin, Arnd Bergmann,
Roman Kisel, Michael Kelley, linux-kernel, linux-arch
In-Reply-To: <20260403-natural-fuzzy-kakapo-f5cbab@anirudhrb>
On Fri, 3 Apr 2026, Anirudh Rayabharam wrote:
> Actually, I believe VMBus does run on a nested root partition. Doesn't
> it? That would then be another case to handle in this patch.
Good catch, v2 series is out.
Best,
Jork
^ permalink raw reply
* RE: [PATCH 1/2] hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation
From: Michael Kelley @ 2026-04-04 1:22 UTC (permalink / raw)
To: Sebastian Andrzej Siewior, linux-hyperv@vger.kernel.org,
linux-rt-devel@lists.linux.dev
Cc: K. Y. Srinivasan, Dexuan Cui, Haiyang Zhang, Jan Kiszka, Long Li,
Wei Liu
In-Reply-To: <20260401151517.1743555-2-bigeasy@linutronix.de>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Sent: Wednesday, April 1, 2026 8:15 AM
>
Nit: For historical consistency, use "Drivers: hv: vmbus:" as the prefix for the
patch "Subject:" line. Same in Patch 2 of this series.
Also, any reason not to have copied linux-kernel@vger.kernel.org? I know this
is pretty much just a Hyper-V thing, but I would have liked to see what the
Sashiko AI did with these two patches. :-)
> lockdep_hardirq_threaded() is supposed to be used within IRQ core code
> and not within drivers. It is not obvious from within the driver, that
> this is the only interrupt service routing and that it is not shared
> handler.
I presume you meant "routine". And what do you mean by "the only interrupt
service routine"? And why is the lack of obviousness relevant here? I don't have
deep expertise in lockdep, but evidently there's some conclusion to reach and it
would have helped me to have it spelled out.
>
> Replace lockdep_hardirq_threaded() with a lockdep annotation limiting
> threaded context on PREEMPT_RT to __vmbus_isr().
Again, I'm not clear what "limiting threaded context" means. But see my
additional comment further down.
>
> Fixes: f8e6343b7a89c ("Drivers: hv: vmbus: Use kthread for vmbus interrupts on PREEMPT_RT")
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> drivers/hv/vmbus_drv.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index bc4fc1951ae1c..e44275370ac2a 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -1407,8 +1407,11 @@ void vmbus_isr(void)
> if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
> vmbus_irqd_wake();
> } else {
> - lockdep_hardirq_threaded();
I see two similar occurrences of LD_WAIT_CONFIG in the kernel:
__kfree_rcu_sheaf() and adjacent to printk_legacy_allow_spinlock_enter().
Both occurrences have a multi-line comment explaining the "why". I'd like
to see a similar comment here so that drive-by readers of the code have
some idea of what's going on. My suggestion is something like this:
vmbus_isr() always runs at hard IRQ level -- the interrupt is not threaded. It
calls __vmbus_isr() here, which may obtain the spinlock_t sched_lock for
a VMBus channel in vmbus_chan_sched(). If CONFIG_PROVE_LOCKING=y,
lockdep complains because obtaining spinlock_t's is not permitted at hard
IRQ level in PREEMPT_RT configurations. However, the PREEMPT_RT path
is handled separately above, so there's actually not a problem. Tell
lockdep that acquiring the spinlock_t is valid by temporarily raising
the wait-type to LD_WAIT_CONFIG using the "fake" lock vmbus_map.
If lockdep is not enabled, the acquire & release of the fake lock are no-ops,
so performance is not impacted.
Please review my suggested text and revise as appropriate, as I'm far
from an expert on any of this. The above is based on what I've learned
just now from a bit of research.
And thanks for jumping in and making all this better ....
Michael
> + static DEFINE_WAIT_OVERRIDE_MAP(vmbus_map, LD_WAIT_CONFIG);
> +
> + lock_map_acquire_try(&vmbus_map);
> __vmbus_isr();
> + lock_map_release(&vmbus_map);
> }
> }
> EXPORT_SYMBOL_FOR_MODULES(vmbus_isr, "mshv_vtl");
> --
> 2.53.0
^ permalink raw reply
* RE: [PATCH 2/2] hv: vmbus: Remove vmbus_irq_initialized
From: Michael Kelley @ 2026-04-04 1:22 UTC (permalink / raw)
To: Sebastian Andrzej Siewior, linux-hyperv@vger.kernel.org,
linux-rt-devel@lists.linux.dev
Cc: K. Y. Srinivasan, Dexuan Cui, Haiyang Zhang, Jan Kiszka, Long Li,
Wei Liu
In-Reply-To: <20260401151517.1743555-3-bigeasy@linutronix.de>
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Sent: Wednesday, April 1, 2026 8:15 AM
>
> vmbus_irq_initialized is only true if the registration of the per-CPU
> threads succeeded. If it failed, the whole registration aborts and the
> vmbus_exit() path is never called.
>
> Remove vmbus_irq_initialized.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
But see comment about the patch Subject prefix from Patch 1 of this series.
> ---
> drivers/hv/vmbus_drv.c | 14 ++++----------
> 1 file changed, 4 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index e44275370ac2a..7417841cd1f70 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -1392,8 +1392,6 @@ static void run_vmbus_irqd(unsigned int cpu)
> __vmbus_isr();
> }
>
> -static bool vmbus_irq_initialized;
> -
> static struct smp_hotplug_thread vmbus_irq_threads = {
> .store = &vmbus_irqd,
> .setup = vmbus_irqd_setup,
> @@ -1513,11 +1511,10 @@ static int vmbus_bus_init(void)
> * the VMbus interrupt handler.
> */
>
> - if (IS_ENABLED(CONFIG_PREEMPT_RT) && !vmbus_irq_initialized) {
> + if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
> ret = smpboot_register_percpu_thread(&vmbus_irq_threads);
> if (ret)
> goto err_kthread;
> - vmbus_irq_initialized = true;
> }
>
> if (vmbus_irq == -1) {
> @@ -1561,10 +1558,8 @@ static int vmbus_bus_init(void)
> else
> free_percpu_irq(vmbus_irq, &vmbus_evt);
> err_setup:
> - if (IS_ENABLED(CONFIG_PREEMPT_RT) && vmbus_irq_initialized) {
> + if (IS_ENABLED(CONFIG_PREEMPT_RT))
> smpboot_unregister_percpu_thread(&vmbus_irq_threads);
> - vmbus_irq_initialized = false;
> - }
> err_kthread:
> bus_unregister(&hv_bus);
> return ret;
> @@ -3033,10 +3028,9 @@ static void __exit vmbus_exit(void)
> hv_remove_vmbus_handler();
> else
> free_percpu_irq(vmbus_irq, &vmbus_evt);
> - if (IS_ENABLED(CONFIG_PREEMPT_RT) && vmbus_irq_initialized) {
> + if (IS_ENABLED(CONFIG_PREEMPT_RT))
> smpboot_unregister_percpu_thread(&vmbus_irq_threads);
> - vmbus_irq_initialized = false;
> - }
> +
> for_each_online_cpu(cpu) {
> struct hv_per_cpu_context *hv_cpu
> = per_cpu_ptr(hv_context.cpu_context, cpu);
> --
> 2.53.0
^ permalink raw reply
* Re: [PATCH] PCI: hv: Fix double ida_free in hv_pci_probe error path
From: Manivannan Sadhasivam @ 2026-04-04 2:42 UTC (permalink / raw)
To: Sahil Chandna
Cc: kys, haiyangz, wei.liu, decui, longli, lpieralisi, kwilczynski,
robh, bhelgaas, dan.j.williams, mhklinux, linux-hyperv, linux-pci,
linux-kernel
In-Reply-To: <20260403120933.466259-1-sahilchandna@linux.microsoft.com>
On Fri, Apr 03, 2026 at 05:09:29AM -0700, Sahil Chandna wrote:
> If hv_pci_probe() fails after storing the domain number in
> hbus->bridge->domain_nr, there is a call to free this domain_nr via
> pci_bus_release_emul_domain_nr(), however, during cleanup, the bridge
> release callback pci_release_host_bridge_dev() also frees the domain_nr
> causing ida_free to be called on same ID twice and triggering following
> warning:
>
> ida_free called for id=28971 which is not allocated.
> WARNING: lib/idr.c:594 at ida_free+0xdf/0x160, CPU#0: kworker/0:2/198
> Call Trace:
> pci_bus_release_emul_domain_nr+0x17/0x20
> pci_release_host_bridge_dev+0x4b/0x60
> device_release+0x3b/0xa0
> kobject_put+0x8e/0x220
> devm_pci_alloc_host_bridge_release+0xe/0x20
> devres_release_all+0x9a/0xd0
> device_unbind_cleanup+0x12/0xa0
> really_probe+0x1c5/0x3f0
> vmbus_add_channel_work+0x135/0x1a0
>
> Fix this by letting pci core handle the free domain_nr and remove
> the explicit free called in pci-hyperv driver.
>
> Fixes: bcce8c74f1ce ("PCI: Enable host bridge emulation for PCI_DOMAINS_GENERIC platforms")
> Signed-off-by: Sahil Chandna <sahilchandna@linux.microsoft.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Wei: I see that you've taken previous hyperv patches. So feel free to take this
one also.
We will be proactive from next release onwards ;)
- Mani
> ---
> drivers/pci/controller/pci-hyperv.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
> index 2c7a406b4ba8..5616ad5d2a8f 100644
> --- a/drivers/pci/controller/pci-hyperv.c
> +++ b/drivers/pci/controller/pci-hyperv.c
> @@ -3778,7 +3778,7 @@ static int hv_pci_probe(struct hv_device *hdev,
> hbus->bridge->domain_nr);
> if (!hbus->wq) {
> ret = -ENOMEM;
> - goto free_dom;
> + goto free_bus;
> }
>
> hdev->channel->next_request_id_callback = vmbus_next_request_id;
> @@ -3874,8 +3874,6 @@ static int hv_pci_probe(struct hv_device *hdev,
> vmbus_close(hdev->channel);
> destroy_wq:
> destroy_workqueue(hbus->wq);
> -free_dom:
> - pci_bus_release_emul_domain_nr(hbus->bridge->domain_nr);
> free_bus:
> kfree(hbus);
> return ret;
> --
> 2.53.0
>
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH] PCI: hv: Fix double ida_free in hv_pci_probe error path
From: Wei Liu @ 2026-04-04 5:19 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: Sahil Chandna, kys, haiyangz, wei.liu, decui, longli, lpieralisi,
kwilczynski, robh, bhelgaas, dan.j.williams, mhklinux,
linux-hyperv, linux-pci, linux-kernel
In-Reply-To: <v7l3vghep7h52f3qyoxdbqzu6un5vhio3njy4u46wjrqzhrrvx@hl5imwzjwocf>
On Sat, Apr 04, 2026 at 08:12:36AM +0530, Manivannan Sadhasivam wrote:
> On Fri, Apr 03, 2026 at 05:09:29AM -0700, Sahil Chandna wrote:
> > If hv_pci_probe() fails after storing the domain number in
> > hbus->bridge->domain_nr, there is a call to free this domain_nr via
> > pci_bus_release_emul_domain_nr(), however, during cleanup, the bridge
> > release callback pci_release_host_bridge_dev() also frees the domain_nr
> > causing ida_free to be called on same ID twice and triggering following
> > warning:
> >
> > ida_free called for id=28971 which is not allocated.
> > WARNING: lib/idr.c:594 at ida_free+0xdf/0x160, CPU#0: kworker/0:2/198
> > Call Trace:
> > pci_bus_release_emul_domain_nr+0x17/0x20
> > pci_release_host_bridge_dev+0x4b/0x60
> > device_release+0x3b/0xa0
> > kobject_put+0x8e/0x220
> > devm_pci_alloc_host_bridge_release+0xe/0x20
> > devres_release_all+0x9a/0xd0
> > device_unbind_cleanup+0x12/0xa0
> > really_probe+0x1c5/0x3f0
> > vmbus_add_channel_work+0x135/0x1a0
> >
> > Fix this by letting pci core handle the free domain_nr and remove
> > the explicit free called in pci-hyperv driver.
> >
> > Fixes: bcce8c74f1ce ("PCI: Enable host bridge emulation for PCI_DOMAINS_GENERIC platforms")
> > Signed-off-by: Sahil Chandna <sahilchandna@linux.microsoft.com>
>
> Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
>
> Wei: I see that you've taken previous hyperv patches. So feel free to take this
> one also.
Sure. I will pick this up.
Wei
^ permalink raw reply
* Re: [PATCH] mshv: Fix infinite fault loop on permission-denied GPA intercepts
From: Wei Liu @ 2026-04-04 5:26 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: Stanislav Kinsburskii, kys, haiyangz, wei.liu, decui, longli,
linux-hyperv, linux-kernel
In-Reply-To: <20260402-rare-heretic-tench-adfc68@anirudhrb>
On Thu, Apr 02, 2026 at 03:44:58PM +0000, Anirudh Rayabharam wrote:
> On Tue, Mar 24, 2026 at 11:57:40PM +0000, Stanislav Kinsburskii wrote:
> > Prevent infinite fault loops when guests access memory regions without
> > proper permissions. Currently, mshv_handle_gpa_intercept() attempts to
> > remap pages for all faults on movable memory regions, regardless of
> > whether the access type is permitted. When a guest writes to a read-only
> > region, the remap succeeds but the region remains read-only, causing
> > immediate re-fault and spinning the vCPU indefinitely.
> >
> > Validate intercept access type against region permissions before
> > attempting remaps. Reject writes to non-writable regions and executes to
> > non-executable regions early, returning false to let the VMM handle the
> > intercept appropriately.
> >
> > This also closes a potential DoS vector where malicious guests could
> > intentionally trigger these fault loops to consume host resources.
> >
> > Fixes: b9a66cd5ccbb ("mshv: Add support for movable memory regions")
> > Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> > ---
> > drivers/hv/mshv_root_main.c | 15 ++++++++++++---
> > include/hyperv/hvgdk_mini.h | 6 ++++++
> > include/hyperv/hvhdk.h | 4 ++--
> > 3 files changed, 20 insertions(+), 5 deletions(-)
>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
>
Applied to hyperv-fixes.
^ permalink raw reply
* Re: [PATCH 2/2] Drivers: hv: Move add_interrupt_randomness() to hypervisor callback sysvec
From: Wei Liu @ 2026-04-04 6:11 UTC (permalink / raw)
To: mhklinux
Cc: kys, haiyangz, wei.liu, decui, longli, tglx, mingo, bp,
dave.hansen, hpa, maz, bigeasy, x86, linux-kernel, linux-hyperv
In-Reply-To: <20260402202400.1707-3-mhklkml@zohomail.com>
On Thu, Apr 02, 2026 at 01:24:00PM -0700, Michael Kelley wrote:
> From: Michael Kelley <mhklinux@outlook.com>
>
> The Hyper-V ISRs, for normal guests and when running in the
> hypervisor root patition, are calling add_interrupt_randomness() as a
> primary source of entropy. The call is currently in the ISRs as a common
> place to handle both x86/x64 and arm64. On x86/x64, hypervisor interrupts
> come through a custom sysvec entry, and do not go through a generic
> interrupt handler. On arm64, hypervisor interrupts come through an
> emulated GICv3. GICv3 uses the generic handler handle_percpu_devid_irq(),
> which does not do add_interrupt_randomness() -- unlike its counterpart
> handle_percpu_irq(). But handle_percpu_devid_irq() is now updated to do
> the add_interrupt_randomness(). So add_interrupt_randomness() is now
> needed only in Hyper-V's x86/x64 custom sysvec path.
>
> Move add_interrupt_randomness() from the Hyper-V ISRs into the Hyper-V
> x86/x64 custom sysvec path, matching the existing STIMER0 sysvec path.
> With this change, add_interrupt_randomness() is no longer called from any
> device drivers, which is appropriate.
>
> Signed-off-by: Michael Kelley <mhklinux@outlook.com>
Acked-by: Wei Liu <wei.liu@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next 0/4] net: mana: Fix probe/remove error path bugs
From: Mohsin Bashir @ 2026-04-04 6:28 UTC (permalink / raw)
To: Erni Sri Satya Vennela, kys, haiyangz, wei.liu, decui, longli,
andrew+netdev, davem, edumazet, kuba, pabeni, ssengar, dipayanroy,
gargaditya, shirazsaleem, kees, kotaranov, leon, shacharr,
stephen, linux-hyperv, netdev, linux-kernel
In-Reply-To: <20260403070948.9225-1-ernis@linux.microsoft.com>
On 4/3/26 12:09 AM, Erni Sri Satya Vennela wrote:
> Fix four pre-existing bugs in mana_probe()/mana_remove() error handling
> that can cause warnings on uninitialized work structs, masked errors,
> and resource leaks when early probe steps fail.
>
> Patches 1-2 move work struct initialization (link_change_work and
> gf_stats_work) to before any error path that could trigger
> mana_remove(), preventing WARN_ON in __flush_work() or debug object
> warnings when sync cancellation runs on uninitialized work structs.
>
> Patch 3 prevents add_adev() from overwriting a port probe error,
> which could leave the driver in a broken state with NULL ports while
> reporting success.
>
> Patch 4 changes 'goto out' to 'break' in mana_remove()'s port loop
> so that mana_destroy_eq() is always reached, preventing EQ leaks when
> a NULL port is encountered.
>
> Erni Sri Satya Vennela (4):
> net: mana: Init link_change_work before potential error paths in probe
> net: mana: Init gf_stats_work before potential error paths in probe
> net: mana: Don't overwrite port probe error with add_adev result
> net: mana: Fix EQ leak in mana_remove on NULL port
>
> drivers/net/ethernet/microsoft/mana/mana_en.c | 28 +++++++++----------
> 1 file changed, 14 insertions(+), 14 deletions(-)
>
I believe mana is already in the mainline so fixes go to the net tree?
^ permalink raw reply
* Re: [PATCH] mshv: Add tracepoint for GPA intercept handling
From: Wei Liu @ 2026-04-04 6:41 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: Stanislav Kinsburskii, kys, haiyangz, wei.liu, decui, longli,
linux-hyperv, linux-kernel
In-Reply-To: <20260402-sarcastic-rottweiler-of-criticism-8330ae@anirudhrb>
On Thu, Apr 02, 2026 at 03:45:58PM +0000, Anirudh Rayabharam wrote:
> On Tue, Mar 24, 2026 at 11:59:59PM +0000, Stanislav Kinsburskii wrote:
> > Provide visibility into GPA intercept operations for debugging and
> > performance analysis of Microsoft Hypervisor guest memory management.
> >
> > Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> > ---
> > drivers/hv/mshv_root_main.c | 6 ++++--
> > drivers/hv/mshv_trace.h | 29 +++++++++++++++++++++++++++++
> > 2 files changed, 33 insertions(+), 2 deletions(-)
>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
>
This doesn't apply cleanly to hyperv-next.
Wei
^ permalink raw reply
* Re: [PATCH] mshv: Add tracepoint for GPA intercept handling
From: Wei Liu @ 2026-04-04 6:45 UTC (permalink / raw)
To: Anirudh Rayabharam
Cc: Stanislav Kinsburskii, kys, haiyangz, wei.liu, decui, longli,
linux-hyperv, linux-kernel
In-Reply-To: <20260402-sarcastic-rottweiler-of-criticism-8330ae@anirudhrb>
On Thu, Apr 02, 2026 at 03:45:58PM +0000, Anirudh Rayabharam wrote:
> On Tue, Mar 24, 2026 at 11:59:59PM +0000, Stanislav Kinsburskii wrote:
> > Provide visibility into GPA intercept operations for debugging and
> > performance analysis of Microsoft Hypervisor guest memory management.
> >
> > Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> > ---
> > drivers/hv/mshv_root_main.c | 6 ++++--
> > drivers/hv/mshv_trace.h | 29 +++++++++++++++++++++++++++++
> > 2 files changed, 33 insertions(+), 2 deletions(-)
>
> Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
>
This patch has a dependency on another bug fix. That's not listed
anywhere. In the future, please list the dependency, or post this as
part of a series.
The tracing support is in hyeprv-next. This patch needs to wait.
Wei
^ permalink raw reply
* Re: [PATCH net-next v5 1/3] net: mana: Use pci_name() for debugfs directory naming
From: Simon Horman @ 2026-04-04 9:05 UTC (permalink / raw)
To: Erni Sri Satya Vennela
Cc: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
edumazet, kuba, pabeni, kotaranov, shradhagupta, shirazsaleem,
yury.norov, kees, ssengar, dipayanroy, gargaditya, linux-hyperv,
netdev, linux-kernel, linux-rdma
In-Reply-To: <20260402182704.2474739-2-ernis@linux.microsoft.com>
On Thu, Apr 02, 2026 at 11:26:55AM -0700, Erni Sri Satya Vennela wrote:
> Use pci_name(pdev) for the per-device debugfs directory instead of
> hardcoded "0" for PFs and pci_slot_name(pdev->slot) for VFs. The
> previous approach had two issues:
>
> 1. pci_slot_name() dereferences pdev->slot, which can be NULL for VFs
> in environments like generic VFIO passthrough or nested KVM,
> causing a NULL pointer dereference.
>
> 2. Multiple PFs would all use "0", and VFs across different PCI
> domains or buses could share the same slot name, leading to
> -EEXIST errors from debugfs_create_dir().
>
> pci_name(pdev) returns the unique BDF address, is always valid, and
> is unique across the system.
>
> Fixes: 6607c17c6c5e ("net: mana: Enable debugfs files for MANA device")
> Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
Hi Erni,
Possibly the code differs between net and net-next.
But if this is fixing a bug in code present in net - as per the cited
commit - then I think it should be a patch that targets net.
With some strategy for merging that change into net-next
if conflicts are expected.
^ permalink raw reply
* [PATCH v2] Drivers: hv: vmbus: use generic driver_override infrastructure
From: Danilo Krummrich @ 2026-04-04 15:01 UTC (permalink / raw)
To: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki,
Ioana Ciornei, Nipun Gupta, Nikhil Agarwal, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Bjorn Helgaas,
Armin Wolf, Bjorn Andersson, Mathieu Poirier, Vineeth Vijayan,
Peter Oberparleiter, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Harald Freudenberger, Holger Dengler, Mark Brown,
Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Alex Williamson, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, Christophe Leroy (CS GROUP)
Cc: linux-kernel, driver-core, linuxppc-dev, linux-hyperv, linux-pci,
platform-driver-x86, linux-arm-msm, linux-remoteproc, linux-s390,
linux-spi, virtualization, kvm, xen-devel, linux-arm-kernel,
Danilo Krummrich, Michael Kelley, Gui-Dong Han
In-Reply-To: <BN7PR02MB414825D0532A1DFE16F3B671D449A@BN7PR02MB4148.namprd02.prod.outlook.com>
When a driver is probed through __driver_attach(), the bus' match()
callback is called without the device lock held, thus accessing the
driver_override field without a lock, which can cause a UAF.
Fix this by using the driver-core driver_override infrastructure taking
care of proper locking internally.
Note that calling match() from __driver_attach() without the device lock
held is intentional. [1]
Tested-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1]
Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789
Fixes: d765edbb301c ("vmbus: add driver_override support")
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
Changes in v2:
- Change patch subject and comments according to Michael's suggestion.
---
drivers/hv/vmbus_drv.c | 43 ++++++++++--------------------------------
include/linux/hyperv.h | 5 -----
2 files changed, 10 insertions(+), 38 deletions(-)
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index bc4fc1951ae1..ba7326ec6add 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -541,34 +541,6 @@ static ssize_t device_show(struct device *dev,
}
static DEVICE_ATTR_RO(device);
-static ssize_t driver_override_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct hv_device *hv_dev = device_to_hv_device(dev);
- int ret;
-
- ret = driver_set_override(dev, &hv_dev->driver_override, buf, count);
- if (ret)
- return ret;
-
- return count;
-}
-
-static ssize_t driver_override_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct hv_device *hv_dev = device_to_hv_device(dev);
- ssize_t len;
-
- device_lock(dev);
- len = sysfs_emit(buf, "%s\n", hv_dev->driver_override);
- device_unlock(dev);
-
- return len;
-}
-static DEVICE_ATTR_RW(driver_override);
-
/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
static struct attribute *vmbus_dev_attrs[] = {
&dev_attr_id.attr,
@@ -599,7 +571,6 @@ static struct attribute *vmbus_dev_attrs[] = {
&dev_attr_channel_vp_mapping.attr,
&dev_attr_vendor.attr,
&dev_attr_device.attr,
- &dev_attr_driver_override.attr,
NULL,
};
@@ -711,9 +682,11 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(const struct hv_driver *
{
const guid_t *guid = &dev->dev_type;
const struct hv_vmbus_device_id *id;
+ int ret;
- /* When driver_override is set, only bind to the matching driver */
- if (dev->driver_override && strcmp(dev->driver_override, drv->name))
+ /* If a driver override is set, only bind to the matching driver */
+ ret = device_match_driver_override(&dev->device, &drv->driver);
+ if (ret == 0)
return NULL;
/* Look at the dynamic ids first, before the static ones */
@@ -721,8 +694,11 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(const struct hv_driver *
if (!id)
id = hv_vmbus_dev_match(drv->id_table, guid);
- /* driver_override will always match, send a dummy id */
- if (!id && dev->driver_override)
+ /*
+ * If there's a matching driver override, this function should succeed,
+ * thus return a dummy device ID if no matching ID is found.
+ */
+ if (!id && ret > 0)
id = &vmbus_device_null;
return id;
@@ -1024,6 +1000,7 @@ static const struct dev_pm_ops vmbus_pm = {
/* The one and only one */
static const struct bus_type hv_bus = {
.name = "vmbus",
+ .driver_override = true,
.match = vmbus_match,
.shutdown = vmbus_shutdown,
.remove = vmbus_remove,
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index dfc516c1c719..bf689d07d750 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1272,11 +1272,6 @@ struct hv_device {
u16 device_id;
struct device device;
- /*
- * Driver name to force a match. Do not set directly, because core
- * frees it. Use driver_set_override() to set or clear it.
- */
- const char *driver_override;
struct vmbus_channel *channel;
struct kset *channels_kset;
--
2.53.0
^ permalink raw reply related
* Re: (subset) [PATCH 00/12] treewide: Convert buses to use generic driver_override
From: Danilo Krummrich @ 2026-04-04 15:07 UTC (permalink / raw)
To: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki,
Ioana Ciornei, Nipun Gupta, Nikhil Agarwal, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Bjorn Helgaas,
Armin Wolf, Bjorn Andersson, Mathieu Poirier, Vineeth Vijayan,
Peter Oberparleiter, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Harald Freudenberger, Holger Dengler, Mark Brown,
Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Alex Williamson, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, Christophe Leroy (CS GROUP)
Cc: linux-kernel, driver-core, linuxppc-dev, linux-hyperv, linux-pci,
platform-driver-x86, linux-arm-msm, linux-remoteproc, linux-s390,
linux-spi, virtualization, kvm, xen-devel, linux-arm-kernel,
Danilo Krummrich
In-Reply-To: <20260324005919.2408620-1-dakr@kernel.org>
On Tue Mar 24, 2026 at 1:59 AM CET, Danilo Krummrich wrote:
> Danilo Krummrich (12):
> PCI: use generic driver_override infrastructure
> platform/wmi: use generic driver_override infrastructure
> vdpa: use generic driver_override infrastructure
> s390/cio: use generic driver_override infrastructure
> s390/ap: use generic driver_override infrastructure
Applied to driver-core-testing, thanks!
> amba: use generic driver_override infrastructure
> cdx: use generic driver_override infrastructure
> hv: vmbus: use generic driver_override infrastructure
> rpmsg: use generic driver_override infrastructure
I have not picked these up, as they have not received ACKs from the
corresponding subsystem maintainers so far.
> bus: fsl-mc: use generic driver_override infrastructure
> spi: use generic driver_override infrastructure
These have already been picked up via the respective subsystem trees -- thanks!
Thanks,
Danilo
^ permalink raw reply
* Re: [PATCH 02/12] bus: fsl-mc: use generic driver_override infrastructure
From: Christophe Leroy (CS GROUP) @ 2026-04-04 16:56 UTC (permalink / raw)
To: Ioana Ciornei, Danilo Krummrich
Cc: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki, Nipun Gupta,
Nikhil Agarwal, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Bjorn Helgaas, Armin Wolf, Bjorn Andersson,
Mathieu Poirier, Vineeth Vijayan, Peter Oberparleiter,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Christian Borntraeger, Sven Schnelle, Harald Freudenberger,
Holger Dengler, Mark Brown, Michael S. Tsirkin, Jason Wang,
Xuan Zhuo, Eugenio Pérez, Alex Williamson,
Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
linux-kernel, driver-core, linuxppc-dev, linux-hyperv, linux-pci,
platform-driver-x86, linux-arm-msm, linux-remoteproc, linux-s390,
linux-spi, virtualization, kvm, xen-devel, linux-arm-kernel,
Gui-Dong Han
In-Reply-To: <4c5e9bad-82f0-4714-99c2-8ccd79a45043@kernel.org>
Le 28/03/2026 à 13:10, Christophe Leroy (CS GROUP) a écrit :
>
>
> Le 25/03/2026 à 13:01, Ioana Ciornei a écrit :
>> On Tue, Mar 24, 2026 at 01:59:06AM +0100, Danilo Krummrich wrote:
>>> When a driver is probed through __driver_attach(), the bus' match()
>>> callback is called without the device lock held, thus accessing the
>>> driver_override field without a lock, which can cause a UAF.
>>>
>>> Fix this by using the driver-core driver_override infrastructure taking
>>> care of proper locking internally.
>>>
>>> Note that calling match() from __driver_attach() without the device lock
>>> held is intentional. [1]
>>>
>>> Link: https://eur01.safelinks.protection.outlook.com/?
>>> url=https%3A%2F%2Flore.kernel.org%2Fdriver-
>>> core%2FDGRGTIRHA62X.3RY09D9SOK77P%40kernel.org%2F&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7C4b9262ddecdd4ce29f9808de8a66485e%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C639100369055903282%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=%2BRfjlUkq7oWV%2F0v2S2B%2BEuxCY%2FLRQv6qHiEWiupd6kc%3D&reserved=0 [1]
>>> Reported-by: Gui-Dong Han <hanguidong02@gmail.com>
>>> Closes: https://eur01.safelinks.protection.outlook.com/?
>>> url=https%3A%2F%2Fbugzilla.kernel.org%2Fshow_bug.cgi%3Fid%3D220789&data=05%7C02%7Cchristophe.leroy%40csgroup.eu%7C4b9262ddecdd4ce29f9808de8a66485e%7C8b87af7d86474dc78df45f69a2011bb5%7C0%7C0%7C639100369055936232%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=XL1K1ICiygOZnlvDUbQFe192KnLsBQms0HFNGCuyz%2Fw%3D&reserved=0
>>> Fixes: 1f86a00c1159 ("bus/fsl-mc: add support for 'driver_override'
>>> in the mc-bus")
>>> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
>>
>> Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com>
>> Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
>>
>
>
> Applied, thanks
Have to drop it for now, build fails:
CALL scripts/checksyscalls.sh
CC drivers/bus/fsl-mc/fsl-mc-bus.o
drivers/bus/fsl-mc/fsl-mc-bus.c: In function 'fsl_mc_bus_match':
drivers/bus/fsl-mc/fsl-mc-bus.c:92:15: error: implicit declaration of
function 'device_match_driver_override'
[-Werror=implicit-function-declaration]
92 | ret = device_match_driver_override(dev, drv);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/bus/fsl-mc/fsl-mc-bus.c: At top level:
drivers/bus/fsl-mc/fsl-mc-bus.c:321:10: error: 'const struct bus_type'
has no member named 'driver_override'
321 | .driver_override = true,
| ^~~~~~~~~~~~~~~
drivers/bus/fsl-mc/fsl-mc-bus.c:321:28: warning: initialization of
'const char *' from 'int' makes pointer from integer without a cast
[-Wint-conversion]
321 | .driver_override = true,
| ^~~~
drivers/bus/fsl-mc/fsl-mc-bus.c:321:28: note: (near initialization for
'fsl_mc_bus_type.dev_name')
cc1: some warnings being treated as errors
make[5]: *** [scripts/Makefile.build:289:
drivers/bus/fsl-mc/fsl-mc-bus.o] Error 1
make[4]: *** [scripts/Makefile.build:546: drivers/bus/fsl-mc] Error 2
make[3]: *** [scripts/Makefile.build:546: drivers/bus] Error 2
make[2]: *** [scripts/Makefile.build:546: drivers] Error 2
make[1]: *** [/home/chleroy/linux-powerpc/Makefile:2101: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2
Christophe
^ permalink raw reply
* Re: (subset) [PATCH 00/12] treewide: Convert buses to use generic driver_override
From: Christophe Leroy (CS GROUP) @ 2026-04-04 16:58 UTC (permalink / raw)
To: Danilo Krummrich, Russell King, Greg Kroah-Hartman,
Rafael J. Wysocki, Ioana Ciornei, Nipun Gupta, Nikhil Agarwal,
K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Bjorn Helgaas, Armin Wolf, Bjorn Andersson, Mathieu Poirier,
Vineeth Vijayan, Peter Oberparleiter, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Harald Freudenberger, Holger Dengler, Mark Brown,
Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Alex Williamson, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, Christophe Leroy (CS GROUP)
Cc: linux-kernel, driver-core, linuxppc-dev, linux-hyperv, linux-pci,
platform-driver-x86, linux-arm-msm, linux-remoteproc, linux-s390,
linux-spi, virtualization, kvm, xen-devel, linux-arm-kernel
In-Reply-To: <DHKGQN6D0ANO.2QYY3JTM5435O@kernel.org>
Le 04/04/2026 à 17:07, Danilo Krummrich a écrit :
> On Tue Mar 24, 2026 at 1:59 AM CET, Danilo Krummrich wrote:
>> Danilo Krummrich (12):
>> PCI: use generic driver_override infrastructure
>> platform/wmi: use generic driver_override infrastructure
>> vdpa: use generic driver_override infrastructure
>> s390/cio: use generic driver_override infrastructure
>> s390/ap: use generic driver_override infrastructure
>
> Applied to driver-core-testing, thanks!
>
>> amba: use generic driver_override infrastructure
>> cdx: use generic driver_override infrastructure
>> hv: vmbus: use generic driver_override infrastructure
>> rpmsg: use generic driver_override infrastructure
>
> I have not picked these up, as they have not received ACKs from the
> corresponding subsystem maintainers so far.
>
>> bus: fsl-mc: use generic driver_override infrastructure
I droped it from soc_fsl tree, some dependency must be missing.
Feal free to take it if you can, it is acked-by Ioana.
>> spi: use generic driver_override infrastructure
>
> These have already been picked up via the respective subsystem trees -- thanks!
>
> Thanks,
> Danilo
^ permalink raw reply
* Re: (subset) [PATCH 00/12] treewide: Convert buses to use generic driver_override
From: Danilo Krummrich @ 2026-04-04 17:04 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki,
Ioana Ciornei, Nipun Gupta, Nikhil Agarwal, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Bjorn Helgaas,
Armin Wolf, Bjorn Andersson, Mathieu Poirier, Vineeth Vijayan,
Peter Oberparleiter, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Harald Freudenberger, Holger Dengler, Mark Brown,
Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Alex Williamson, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, linux-kernel, driver-core, linuxppc-dev,
linux-hyperv, linux-pci, platform-driver-x86, linux-arm-msm,
linux-remoteproc, linux-s390, linux-spi, virtualization, kvm,
xen-devel, linux-arm-kernel
In-Reply-To: <76355cb5-0b5d-4a29-9702-8d020a79f4c0@kernel.org>
On Sat Apr 4, 2026 at 6:58 PM CEST, Christophe Leroy (CS GROUP) wrote:
>
>
> Le 04/04/2026 à 17:07, Danilo Krummrich a écrit :
>> On Tue Mar 24, 2026 at 1:59 AM CET, Danilo Krummrich wrote:
>>> Danilo Krummrich (12):
>>> PCI: use generic driver_override infrastructure
>>> platform/wmi: use generic driver_override infrastructure
>>> vdpa: use generic driver_override infrastructure
>>> s390/cio: use generic driver_override infrastructure
>>> s390/ap: use generic driver_override infrastructure
>>
>> Applied to driver-core-testing, thanks!
>>
>>> amba: use generic driver_override infrastructure
>>> cdx: use generic driver_override infrastructure
>>> hv: vmbus: use generic driver_override infrastructure
>>> rpmsg: use generic driver_override infrastructure
>>
>> I have not picked these up, as they have not received ACKs from the
>> corresponding subsystem maintainers so far.
>>
>>> bus: fsl-mc: use generic driver_override infrastructure
>
> I droped it from soc_fsl tree, some dependency must be missing.
>
> Feal free to take it if you can, it is acked-by Ioana.
It is based on v7.0-rc5; if you want I can pick it up.
>>> spi: use generic driver_override infrastructure
>>
>> These have already been picked up via the respective subsystem trees -- thanks!
>>
>> Thanks,
>> Danilo
^ permalink raw reply
* Re: (subset) [PATCH 00/12] treewide: Convert buses to use generic driver_override
From: Christophe Leroy (CS GROUP) @ 2026-04-04 17:09 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki,
Ioana Ciornei, Nipun Gupta, Nikhil Agarwal, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Bjorn Helgaas,
Armin Wolf, Bjorn Andersson, Mathieu Poirier, Vineeth Vijayan,
Peter Oberparleiter, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Harald Freudenberger, Holger Dengler, Mark Brown,
Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Alex Williamson, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, linux-kernel, driver-core, linuxppc-dev,
linux-hyperv, linux-pci, platform-driver-x86, linux-arm-msm,
linux-remoteproc, linux-s390, linux-spi, virtualization, kvm,
xen-devel, linux-arm-kernel
In-Reply-To: <DHKJ7VWI1CHO.3ETHUGQVPFFDE@kernel.org>
Le 04/04/2026 à 19:04, Danilo Krummrich a écrit :
> On Sat Apr 4, 2026 at 6:58 PM CEST, Christophe Leroy (CS GROUP) wrote:
>>
>>
>> Le 04/04/2026 à 17:07, Danilo Krummrich a écrit :
>>> On Tue Mar 24, 2026 at 1:59 AM CET, Danilo Krummrich wrote:
>>>> Danilo Krummrich (12):
>>>> PCI: use generic driver_override infrastructure
>>>> platform/wmi: use generic driver_override infrastructure
>>>> vdpa: use generic driver_override infrastructure
>>>> s390/cio: use generic driver_override infrastructure
>>>> s390/ap: use generic driver_override infrastructure
>>>
>>> Applied to driver-core-testing, thanks!
>>>
>>>> amba: use generic driver_override infrastructure
>>>> cdx: use generic driver_override infrastructure
>>>> hv: vmbus: use generic driver_override infrastructure
>>>> rpmsg: use generic driver_override infrastructure
>>>
>>> I have not picked these up, as they have not received ACKs from the
>>> corresponding subsystem maintainers so far.
>>>
>>>> bus: fsl-mc: use generic driver_override infrastructure
>>
>> I droped it from soc_fsl tree, some dependency must be missing.
>>
>> Feal free to take it if you can, it is acked-by Ioana.
>
> It is based on v7.0-rc5; if you want I can pick it up.
Yes please pick it up as my tree is based on rc1.
Thanks
Christophe
>
>>>> spi: use generic driver_override infrastructure
>>>
>>> These have already been picked up via the respective subsystem trees -- thanks!
>>>
>>> Thanks,
>>> Danilo
>
^ permalink raw reply
* Re: (subset) [PATCH 00/12] treewide: Convert buses to use generic driver_override
From: Danilo Krummrich @ 2026-04-04 19:20 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Russell King, Greg Kroah-Hartman, Rafael J. Wysocki,
Ioana Ciornei, Nipun Gupta, Nikhil Agarwal, K. Y. Srinivasan,
Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Bjorn Helgaas,
Armin Wolf, Bjorn Andersson, Mathieu Poirier, Vineeth Vijayan,
Peter Oberparleiter, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Harald Freudenberger, Holger Dengler, Mark Brown,
Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Alex Williamson, Juergen Gross, Stefano Stabellini,
Oleksandr Tyshchenko, linux-kernel, driver-core, linuxppc-dev,
linux-hyperv, linux-pci, platform-driver-x86, linux-arm-msm,
linux-remoteproc, linux-s390, linux-spi, virtualization, kvm,
xen-devel, linux-arm-kernel
In-Reply-To: <a8c85884-e2ba-4a3a-a660-9715f0de2704@kernel.org>
On Sat Apr 4, 2026 at 7:09 PM CEST, Christophe Leroy (CS GROUP) wrote:
> Yes please pick it up as my tree is based on rc1.
Applied the patch to driver-core-testing, thanks!
^ permalink raw reply
* Re: [PATCH net-next,v4] net: mana: Force full-page RX buffers via ethtool private flag
From: Dipayaan Roy @ 2026-04-05 3:14 UTC (permalink / raw)
To: Jakub Kicinski
Cc: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
pabeni, leon, longli, kotaranov, horms, shradhagupta, ssengar,
ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, leitao, kees, dipayanroy
In-Reply-To: <20260330154755.6a8c73a6@kernel.org>
On Mon, Mar 30, 2026 at 03:47:55PM -0700, Jakub Kicinski wrote:
> On Mon, 30 Mar 2026 14:01:54 -0700 Dipayaan Roy wrote:
> > On some ARM64 platforms with 4K PAGE_SIZE, page_pool fragment
> > allocation in the RX refill path can cause 15-20% throughput
> > regression under high connection counts (>16 TCP streams).
>
> Did you investigate what makes such a difference exactly?
> As I said I suspect there are some improvements we could
> make in the page pool fragmentation logic that could yield
> similar wins without bothering the user.
>
I collected the perf numbers, shared the analysis below.
> > Add an ethtool private flag "full-page-rx" that allows the user to
> > force one RX buffer per page, bypassing the page_pool fragment path.
> > This restores line-rate(180+ Gbps) performance on affected platforms.
> >
> > Usage:
> > ethtool --set-priv-flags eth0 full-page-rx on
> >
> > There is no behavioral change by default. The flag must be explicitly
> > enabled by the user or udev rule.
> >
> > The existing single-buffer-per-page logic for XDP and jumbo frames is
> > consolidated into a new helper mana_use_single_rxbuf_per_page().
>
> ethtool -g rx-buf-len could also fit the bill but I guess this is more
> of a hack / workaround than legit config so no strong preference.
>
ok, want to stay with private flag.
> > -static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
> > +static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
> > {
> > - struct mana_port_context *apc = netdev_priv(ndev);
> > unsigned int num_queues = apc->num_queues;
> > int i, j;
> >
> > - if (stringset != ETH_SS_STATS)
> > - return;
> > for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++)
> > - ethtool_puts(&data, mana_eth_stats[i].name);
> > + ethtool_puts(data, mana_eth_stats[i].name);
> >
> > for (i = 0; i < ARRAY_SIZE(mana_hc_stats); i++)
> > - ethtool_puts(&data, mana_hc_stats[i].name);
> > + ethtool_puts(data, mana_hc_stats[i].name);
> >
> > for (i = 0; i < ARRAY_SIZE(mana_phy_stats); i++)
> > - ethtool_puts(&data, mana_phy_stats[i].name);
> > + ethtool_puts(data, mana_phy_stats[i].name);
> >
> > for (i = 0; i < num_queues; i++) {
> > - ethtool_sprintf(&data, "rx_%d_packets", i);
> > - ethtool_sprintf(&data, "rx_%d_bytes", i);
> > - ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
> > - ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
> > - ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
> > - ethtool_sprintf(&data, "rx_%d_pkt_len0_err", i);
> > + ethtool_sprintf(data, "rx_%d_packets", i);
>
> Please factor out the noisy, no-op prep work into a separate patch for
> ease of review
Ack, will split it out in 2 separate patches in v5.
> --
> pw-bot: cr
Hi Jakub,
I did some perf analysis on the ARM64 platform for which we want to
have this work around of full page rx buffers:
test: ntttcp with 48 tcp connections
perf: perf record -ag --call-graph dwarf -C 0-33 -- sleep 32
Page pool overhead summary:
(framgment based rx buff vs full page rx buff on the same ARM64
platform)
Function Fragment Full-page Delta
─---------------------------- ─------- --------- -----
napi_pp_put_page 3.93% 0.85% +3.08%
page_pool_alloc_frag_netmem 1.93% — +1.93%
Total page_pool overhead 5.86% 0.85% +5.01%
In fragment mode, napi_pp_put_page performs an atomic decrement of
the shared page refcount on every packet free. This single operation
accounts for ~3% more CPU than in full-page mode, where the page is
sole-owned and the atomic is skipped entirely. Additionally,
page_pool_alloc_frag_netmem adds ~2% overhead on the allocation
path for fragments.
Further annotation of the hot page pool functions in fragment mode
shows:
napi_pp_put_page:
0.09 : ffff80008117c240: b ffff80008117c268
<napi_pp_put_page+0x68>
: 64 ATOMIC64_FETCH_OP( , al, op, asm_op,
"memory")
:
: 66 ATOMIC64_FETCH_OPS(andnot, ldclr)
: 67 ATOMIC64_FETCH_OPS(or, ldset)
: 68 ATOMIC64_FETCH_OPS(xor, ldeor)
: 69 ATOMIC64_FETCH_OPS(add, ldadd)
0.00 : ffff80008117c244: mov x3, #0xffffffffffffffff
// #-1
0.08 : ffff80008117c248: add x0, x2, #0x28
0.06 : ffff80008117c24c: ldaddal x3, x3, [x0]
: 73 }
:
: 75 ATOMIC64_OP_ADD_SUB_RETURN(_relaxed)
: 76 ATOMIC64_OP_ADD_SUB_RETURN(_acquire)
: 77 ATOMIC64_OP_ADD_SUB_RETURN(_release)
: 78 ATOMIC64_OP_ADD_SUB_RETURN( )
88.09 : ffff80008117c250: sub x3, x3, #0x1
:
: 81 return 0;
: 82 }
88% of this function's cycles stall on the sub that depends on
ldaddal.
page_pool_alloc_frag_netmem:
: 151 ATOMIC64_FETCH_OPS(add, ldadd)
0.00 : ffff8000811fd40c: add x1, x21, #0x28
0.14 : ffff8000811fd410: ldaddal x0, x1, [x1]
: 154 }
:
: 156 ATOMIC64_OP_ADD_SUB_RETURN(_relaxed)
: 157 ATOMIC64_OP_ADD_SUB_RETURN(_acquire)
: 158 ATOMIC64_OP_ADD_SUB_RETURN(_release)
: 159 ATOMIC64_OP_ADD_SUB_RETURN( )
75.09 : ffff8000811fd414: add x0, x0, x1
: 161 WARN_ON(ret < 0);
0.16 : ffff8000811fd418: cmp x0, #0x0
0.00 : ffff8000811fd41c: b.lt ffff8000811fd394
<page_pool_alloc_frag_netmem+0xb4> // b.tstop
75% of this function's cycles stall on the same pattern.
Full comparison (top functions, >0.5%):
Fragment mode: Full-page mode:
------------- --------------
15.88% __wake_up_sync_key 13.66% __wake_up_sync_key
9.66% default_idle_call 10.41% default_idle_call
8.38% handle_softirqs 8.89% handle_softirqs
3.93% napi_pp_put_page ← 0.85% napi_pp_put_page
3.18% tcp_gro_receive 3.43% tcp_gro_receive
1.93% page_pool_alloc_frag ← —
— 1.14%
page_pool_recycle_in_cache
— 1.06%
page_pool_put_unrefed_netmem
0.93% napi_build_skb 1.24% napi_build_skb
0.56% __build_skb_around 1.46% __build_skb_around
In full page rx buffers mode 'napi_pp_put_page' took just 0.85% on
the same ARM64 platform.
Comparing with another platform(x86):
To confirm this behaviour is specific to this ARM64 platform, I
collected the same data on a x86 Vm (Intel, 192 vCPUs, same MANA NIC 200Gbps)
Here both full page rx buff mode and fragment modes rx buffs achieves identical
~182 Gbps on x86.
x86 fragment mode: x86 full-page mode:
─----------------- ─------------------
61.69% pv_native_safe_halt 50.91% pv_native_safe_halt
4.17% _raw_spin_unlock_irqrestore 6.19%
_raw_spin_unlock_irqrestore
3.95% handle_softirqs 4.02% handle_softirqs
2.51% _copy_to_iter 2.53% _copy_to_iter
0.60% napi_pp_put_page — napi_pp_put_page (<0.5%)
On x86, napi_pp_put_page is only 0.60% in fragment mode (vs 3.93%
on the ARM64 platform data shared earlier).
Note: I did not had a different arm64 platform available to run and compare
it with.
From the above data, seems to be an issue specific to this ARM64
platform.
Regards
^ permalink raw reply
* [PATCH net-next v5 0/2] net: mana: add ethtool private flag for full-page RX buffers
From: Dipayaan Roy @ 2026-04-05 3:42 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees
On some ARM64 platforms with 4K PAGE_SIZE, utilizing page_pool
fragments for allocation in the RX refill path (~2kB buffer per fragment)
causes 15-20% throughput regression under high connection counts
(>16 TCP streams at 180+ Gbps). Using full-page buffers on these
platforms shows no regression and restores line-rate performance.
This behavior is observed on a single platform; other platforms
perform better with page_pool fragments, indicating this is not a
page_pool issue but platform-specific.
This series adds an ethtool private flag "full-page-rx" to let the
user opt in to one RX buffer per page:
ethtool --set-priv-flags eth0 full-page-rx on
There is no behavioral change by default. The flag can be persisted
via udev rule for affected platforms.
Changes in v5:
- Split prep refactor into separate patch (patch 1/2)
Changes in v4:
- Dropping the smbios string parsing and add ethtool priv flag
to reconfigure the queues with full page rx buffers.
Changes in v3:
- changed u8* to char*
Changes in v2:
- separate reading string index and the string, remove inline.
Dipayaan Roy (2):
net: mana: refactor mana_get_strings() and mana_get_sset_count() to
use switch
net: mana: force full-page RX buffers via ethtool private flag
drivers/net/ethernet/microsoft/mana/mana_en.c | 22 ++-
.../ethernet/microsoft/mana/mana_ethtool.c | 164 ++++++++++++++----
include/net/mana/mana.h | 8 +
3 files changed, 163 insertions(+), 31 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH net-next v5 1/2] net: mana: refactor mana_get_strings() and mana_get_sset_count() to use switch
From: Dipayaan Roy @ 2026-04-05 3:44 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees
Refactor mana_get_strings() and mana_get_sset_count() from if/else to
switch statements in preparation for adding ethtool private flags
support which requires handling ETH_SS_PRIV_FLAGS.
No functional change.
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
.../ethernet/microsoft/mana/mana_ethtool.c | 75 ++++++++++++-------
1 file changed, 46 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 6a4b42fe0944..a28ca461c135 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -138,53 +138,70 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
struct mana_port_context *apc = netdev_priv(ndev);
unsigned int num_queues = apc->num_queues;
- if (stringset != ETH_SS_STATS)
+ switch (stringset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(mana_eth_stats) +
+ ARRAY_SIZE(mana_phy_stats) +
+ ARRAY_SIZE(mana_hc_stats) +
+ num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+ default:
return -EINVAL;
-
- return ARRAY_SIZE(mana_eth_stats) + ARRAY_SIZE(mana_phy_stats) + ARRAY_SIZE(mana_hc_stats) +
- num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+ }
}
-static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
{
- struct mana_port_context *apc = netdev_priv(ndev);
unsigned int num_queues = apc->num_queues;
int i, j;
- if (stringset != ETH_SS_STATS)
- return;
for (i = 0; i < ARRAY_SIZE(mana_eth_stats); i++)
- ethtool_puts(&data, mana_eth_stats[i].name);
+ ethtool_puts(data, mana_eth_stats[i].name);
for (i = 0; i < ARRAY_SIZE(mana_hc_stats); i++)
- ethtool_puts(&data, mana_hc_stats[i].name);
+ ethtool_puts(data, mana_hc_stats[i].name);
for (i = 0; i < ARRAY_SIZE(mana_phy_stats); i++)
- ethtool_puts(&data, mana_phy_stats[i].name);
+ ethtool_puts(data, mana_phy_stats[i].name);
for (i = 0; i < num_queues; i++) {
- ethtool_sprintf(&data, "rx_%d_packets", i);
- ethtool_sprintf(&data, "rx_%d_bytes", i);
- ethtool_sprintf(&data, "rx_%d_xdp_drop", i);
- ethtool_sprintf(&data, "rx_%d_xdp_tx", i);
- ethtool_sprintf(&data, "rx_%d_xdp_redirect", i);
- ethtool_sprintf(&data, "rx_%d_pkt_len0_err", i);
+ ethtool_sprintf(data, "rx_%d_packets", i);
+ ethtool_sprintf(data, "rx_%d_bytes", i);
+ ethtool_sprintf(data, "rx_%d_xdp_drop", i);
+ ethtool_sprintf(data, "rx_%d_xdp_tx", i);
+ ethtool_sprintf(data, "rx_%d_xdp_redirect", i);
+ ethtool_sprintf(data, "rx_%d_pkt_len0_err", i);
for (j = 0; j < MANA_RXCOMP_OOB_NUM_PPI - 1; j++)
- ethtool_sprintf(&data, "rx_%d_coalesced_cqe_%d", i, j + 2);
+ ethtool_sprintf(data,
+ "rx_%d_coalesced_cqe_%d",
+ i,
+ j + 2);
}
for (i = 0; i < num_queues; i++) {
- ethtool_sprintf(&data, "tx_%d_packets", i);
- ethtool_sprintf(&data, "tx_%d_bytes", i);
- ethtool_sprintf(&data, "tx_%d_xdp_xmit", i);
- ethtool_sprintf(&data, "tx_%d_tso_packets", i);
- ethtool_sprintf(&data, "tx_%d_tso_bytes", i);
- ethtool_sprintf(&data, "tx_%d_tso_inner_packets", i);
- ethtool_sprintf(&data, "tx_%d_tso_inner_bytes", i);
- ethtool_sprintf(&data, "tx_%d_long_pkt_fmt", i);
- ethtool_sprintf(&data, "tx_%d_short_pkt_fmt", i);
- ethtool_sprintf(&data, "tx_%d_csum_partial", i);
- ethtool_sprintf(&data, "tx_%d_mana_map_err", i);
+ ethtool_sprintf(data, "tx_%d_packets", i);
+ ethtool_sprintf(data, "tx_%d_bytes", i);
+ ethtool_sprintf(data, "tx_%d_xdp_xmit", i);
+ ethtool_sprintf(data, "tx_%d_tso_packets", i);
+ ethtool_sprintf(data, "tx_%d_tso_bytes", i);
+ ethtool_sprintf(data, "tx_%d_tso_inner_packets", i);
+ ethtool_sprintf(data, "tx_%d_tso_inner_bytes", i);
+ ethtool_sprintf(data, "tx_%d_long_pkt_fmt", i);
+ ethtool_sprintf(data, "tx_%d_short_pkt_fmt", i);
+ ethtool_sprintf(data, "tx_%d_csum_partial", i);
+ ethtool_sprintf(data, "tx_%d_mana_map_err", i);
+ }
+}
+
+static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ mana_get_strings_stats(apc, &data);
+ break;
+ default:
+ break;
}
}
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v5 2/2] net: mana: force full-page RX buffers via ethtool private flag
From: Dipayaan Roy @ 2026-04-05 3:47 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees
On some ARM64 platforms with 4K PAGE_SIZE, page_pool fragment
allocation in the RX refill path can cause 15-20% throughput
regression under high connection counts (>16 TCP streams).
Add an ethtool private flag "full-page-rx" that allows the user to
force one RX buffer per page, bypassing the page_pool fragment path.
This restores line-rate (180+ Gbps) performance on affected platforms.
Usage:
ethtool --set-priv-flags ethx full-page-rx on
There is no behavioral change by default. The flag must be explicitly
enabled by the user or udev rule.
The existing single-buffer-per-page logic for XDP and jumbo frames is
consolidated into a new helper mana_use_single_rxbuf_per_page() which
is now the single decision point for both the automatic and
user-controlled paths.
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 22 ++++-
.../ethernet/microsoft/mana/mana_ethtool.c | 89 +++++++++++++++++++
include/net/mana/mana.h | 8 ++
3 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 49c65cc1697c..59a1626c2be1 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -744,6 +744,25 @@ static void *mana_get_rxbuf_pre(struct mana_rxq *rxq, dma_addr_t *da)
return va;
}
+static bool
+mana_use_single_rxbuf_per_page(struct mana_port_context *apc, u32 mtu)
+{
+ /* On some platforms with 4K PAGE_SIZE, page_pool fragment allocation
+ * in the RX refill path (~2kB buffer) can cause significant throughput
+ * regression under high connection counts. Allow user to force one RX
+ * buffer per page via ethtool private flag to bypass the fragment
+ * path.
+ */
+ if (apc->priv_flags & BIT(MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF))
+ return true;
+
+ /* For xdp and jumbo frames make sure only one packet fits per page. */
+ if (mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 || mana_xdp_get(apc))
+ return true;
+
+ return false;
+}
+
/* Get RX buffer's data size, alloc size, XDP headroom based on MTU */
static void mana_get_rxbuf_cfg(struct mana_port_context *apc,
int mtu, u32 *datasize, u32 *alloc_size,
@@ -754,8 +773,7 @@ static void mana_get_rxbuf_cfg(struct mana_port_context *apc,
/* Calculate datasize first (consistent across all cases) */
*datasize = mtu + ETH_HLEN;
- /* For xdp and jumbo frames make sure only one packet fits per page */
- if (mtu + MANA_RXBUF_PAD > PAGE_SIZE / 2 || mana_xdp_get(apc)) {
+ if (mana_use_single_rxbuf_per_page(apc, mtu)) {
if (mana_xdp_get(apc)) {
*headroom = XDP_PACKET_HEADROOM;
*alloc_size = PAGE_SIZE;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index a28ca461c135..0547c903f613 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -133,6 +133,10 @@ static const struct mana_stats_desc mana_phy_stats[] = {
{ "hc_tc7_tx_pause_phy", offsetof(struct mana_ethtool_phy_stats, tx_pause_tc7_phy) },
};
+static const char mana_priv_flags[MANA_PRIV_FLAG_MAX][ETH_GSTRING_LEN] = {
+ [MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF] = "full-page-rx"
+};
+
static int mana_get_sset_count(struct net_device *ndev, int stringset)
{
struct mana_port_context *apc = netdev_priv(ndev);
@@ -144,6 +148,10 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
ARRAY_SIZE(mana_phy_stats) +
ARRAY_SIZE(mana_hc_stats) +
num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+
+ case ETH_SS_PRIV_FLAGS:
+ return MANA_PRIV_FLAG_MAX;
+
default:
return -EINVAL;
}
@@ -192,6 +200,14 @@ static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
}
}
+static void mana_get_strings_priv_flags(u8 **data)
+{
+ int i;
+
+ for (i = 0; i < MANA_PRIV_FLAG_MAX; i++)
+ ethtool_puts(data, mana_priv_flags[i]);
+}
+
static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct mana_port_context *apc = netdev_priv(ndev);
@@ -200,6 +216,9 @@ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
case ETH_SS_STATS:
mana_get_strings_stats(apc, &data);
break;
+ case ETH_SS_PRIV_FLAGS:
+ mana_get_strings_priv_flags(&data);
+ break;
default:
break;
}
@@ -590,6 +609,74 @@ static int mana_get_link_ksettings(struct net_device *ndev,
return 0;
}
+static u32 mana_get_priv_flags(struct net_device *ndev)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+
+ return apc->priv_flags;
+}
+
+static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags)
+{
+ struct mana_port_context *apc = netdev_priv(ndev);
+ u32 changed = apc->priv_flags ^ priv_flags;
+ u32 old_priv_flags = apc->priv_flags;
+ bool schedule_port_reset = false;
+ int err = 0;
+
+ if (!changed)
+ return 0;
+
+ /* Reject unknown bits */
+ if (priv_flags & ~GENMASK(MANA_PRIV_FLAG_MAX - 1, 0))
+ return -EINVAL;
+
+ if (changed & BIT(MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF)) {
+ apc->priv_flags = priv_flags;
+
+ if (!apc->port_is_up) {
+ /* Port is down, flag updated to apply on next up
+ * so just return.
+ */
+ return 0;
+ }
+
+ /* Pre-allocate buffers to prevent failure in mana_attach
+ * later
+ */
+ err = mana_pre_alloc_rxbufs(apc, ndev->mtu, apc->num_queues);
+ if (err) {
+ netdev_err(ndev,
+ "Insufficient memory for new allocations\n");
+ apc->priv_flags = old_priv_flags;
+ return err;
+ }
+
+ err = mana_detach(ndev, false);
+ if (err) {
+ netdev_err(ndev, "mana_detach failed: %d\n", err);
+ apc->priv_flags = old_priv_flags;
+ goto out;
+ }
+
+ err = mana_attach(ndev);
+ if (err) {
+ netdev_err(ndev, "mana_attach failed: %d\n", err);
+ apc->priv_flags = old_priv_flags;
+ schedule_port_reset = true;
+ }
+ }
+
+out:
+ mana_pre_dealloc_rxbufs(apc);
+
+ if (err && schedule_port_reset)
+ queue_work(apc->ac->per_port_queue_reset_wq,
+ &apc->queue_reset_work);
+
+ return err;
+}
+
const struct ethtool_ops mana_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES,
.get_ethtool_stats = mana_get_ethtool_stats,
@@ -608,4 +695,6 @@ const struct ethtool_ops mana_ethtool_ops = {
.set_ringparam = mana_set_ringparam,
.get_link_ksettings = mana_get_link_ksettings,
.get_link = ethtool_op_get_link,
+ .get_priv_flags = mana_get_priv_flags,
+ .set_priv_flags = mana_set_priv_flags,
};
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 3336688fed5e..fd87e3d6c1f4 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -30,6 +30,12 @@ enum TRI_STATE {
TRI_STATE_TRUE = 1
};
+/* MANA ethtool private flag bit positions */
+enum mana_priv_flag_bits {
+ MANA_PRIV_FLAG_USE_FULL_PAGE_RXBUF = 0,
+ MANA_PRIV_FLAG_MAX,
+};
+
/* Number of entries for hardware indirection table must be in power of 2 */
#define MANA_INDIRECT_TABLE_MAX_SIZE 512
#define MANA_INDIRECT_TABLE_DEF_SIZE 64
@@ -531,6 +537,8 @@ struct mana_port_context {
u32 rxbpre_headroom;
u32 rxbpre_frag_count;
+ u32 priv_flags;
+
struct bpf_prog *bpf_prog;
/* Create num_queues EQs, SQs, SQ-CQs, RQs and RQ-CQs, respectively. */
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox