Linux virtualization list
 help / color / mirror / Atom feed
* [PATCH v5 03/51] x86/tsc: Ensure that TSC recalibration doesn't run if TSC frequency is known
From: Sean Christopherson @ 2026-07-01 19:31 UTC (permalink / raw)
  To: Jonathan Corbet, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, Kiryl Shutsemau,
	Rick Edgecombe, Sean Christopherson, K. Y. Srinivasan,
	Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
	Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
	Juergen Gross, Daniel Lezcano, John Stultz
  Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
	Broadcom internal kernel review list, Boris Ostrovsky,
	Stephen Boyd, linux-doc, kvm, linux-kernel, linux-coco,
	linux-hyperv, virtualization, xen-devel, Tom Lendacky,
	Nikunj A Dadhania, David Woodhouse, David Woodhouse,
	Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-1-seanjc@google.com>

When attempting TSC recalibration post-boot, which is only done for ancient
CPUS (P4 and K7) on SMP=n kernels, assert that the TSC frequency isn't
known (explicitly provided by hardware) by way of MSR or CPUID, and bail if
the impossible happens.  In practice, recalibration and TSC_KNOWN_FREQ are
mutually exclusive, as TSC_KNOWN_FREQ will only be set when running on
hardware that was released decades after recalibration was obsoleted, but
but it's hard to see that, especially when looking at just the TSC code.

Note, the WARN can likely be tripped by running in a virtual machine and
concocting an impossible CPU model, e.g. by combining a P4 signature with
CPUID 0x15.  This is working as intended, as such a virtual CPU model is
wildly out-of-spec and is not supported.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kernel/tsc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 4d6a446645c0..4393902c0ddd 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -930,6 +930,9 @@ void recalibrate_cpu_khz(void)
 	if (!boot_cpu_has(X86_FEATURE_TSC))
 		return;
 
+	if (WARN_ON_ONCE(cpu_feature_enabled(X86_FEATURE_TSC_KNOWN_FREQ)))
+		return;
+
 	cpu_khz = x86_platform.calibrate_cpu();
 	tsc_khz = x86_platform.calibrate_tsc();
 	if (tsc_khz == 0)
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related

* [PATCH v5 02/51] x86/apic: Add CONFIG_X86_LOCAL_APIC=n stubs for apic_set_timer_period_{,k}hz()
From: Sean Christopherson @ 2026-07-01 19:31 UTC (permalink / raw)
  To: Jonathan Corbet, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, Kiryl Shutsemau,
	Rick Edgecombe, Sean Christopherson, K. Y. Srinivasan,
	Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
	Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
	Juergen Gross, Daniel Lezcano, John Stultz
  Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
	Broadcom internal kernel review list, Boris Ostrovsky,
	Stephen Boyd, linux-doc, kvm, linux-kernel, linux-coco,
	linux-hyperv, virtualization, xen-devel, Tom Lendacky,
	Nikunj A Dadhania, David Woodhouse, David Woodhouse,
	Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-1-seanjc@google.com>

Add stubs for the apic_set_timer_period_{,k}hz() APIs when the kernel is
built without support for a local APIC, and drop #ifdefs in callers that
don't need to check CONFIG_X86_LOCAL_APIC for other reasons.

No functional change intended.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/include/asm/apic.h  | 2 ++
 arch/x86/kernel/cpu/vmware.c | 2 --
 arch/x86/kernel/tsc.c        | 2 --
 arch/x86/kernel/tsc_msr.c    | 2 --
 4 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index cd84a94688a2..035998555e99 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -189,6 +189,8 @@ static inline void disable_local_APIC(void) { }
 # define setup_boot_APIC_clock x86_init_noop
 # define setup_secondary_APIC_clock x86_init_noop
 static inline void lapic_update_tsc_freq(void) { }
+static inline void apic_set_timer_period_hz(u64 period_hz, const char *source) { }
+static inline void apic_set_timer_period_khz(u64 period_khz, const char *source) { }
 static inline void init_bsp_APIC(void) { }
 static inline void apic_intr_mode_select(void) { }
 static inline void apic_intr_mode_init(void) { }
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 36f779dd311d..13b97265c535 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -422,10 +422,8 @@ static void __init vmware_platform_setup(void)
 		x86_platform.calibrate_tsc = vmware_get_tsc_khz;
 		x86_platform.calibrate_cpu = vmware_get_tsc_khz;
 
-#ifdef CONFIG_X86_LOCAL_APIC
 		/* Skip lapic calibration since we know the bus frequency. */
 		apic_set_timer_period_hz(ecx, "VMware hypervisor");
-#endif
 	} else {
 		pr_warn("Failed to get TSC freq from the hypervisor\n");
 	}
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index f9ecc9256863..4d6a446645c0 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -710,7 +710,6 @@ unsigned long native_calibrate_tsc(void)
 	if (boot_cpu_data.x86_vfm == INTEL_ATOM_GOLDMONT)
 		setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
 
-#ifdef CONFIG_X86_LOCAL_APIC
 	/*
 	 * The local APIC appears to be fed by the core crystal clock
 	 * (which sounds entirely sensible). We can set the global
@@ -718,7 +717,6 @@ unsigned long native_calibrate_tsc(void)
 	 * timer later.
 	 */
 	apic_set_timer_period_khz(crystal_khz, "CPUID 0x15/0x16");
-#endif
 
 	return crystal_khz * ebx_numerator / eax_denominator;
 }
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 7e990871e041..aece062aee7e 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -210,9 +210,7 @@ unsigned long cpu_khz_from_msr(void)
 	if (freq == 0)
 		pr_err("Error MSR_FSB_FREQ index %d is unknown\n", index);
 
-#ifdef CONFIG_X86_LOCAL_APIC
 	apic_set_timer_period_khz(freq, "MSR_FSB_FREQ");
-#endif
 
 	/*
 	 * TSC frequency determined by MSR is always considered "known"
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related

* [PATCH v5 01/51] x86/apic: Provide helpers to set local APIC timer period in hz and khz
From: Sean Christopherson @ 2026-07-01 19:31 UTC (permalink / raw)
  To: Jonathan Corbet, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, Kiryl Shutsemau,
	Rick Edgecombe, Sean Christopherson, K. Y. Srinivasan,
	Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
	Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
	Juergen Gross, Daniel Lezcano, John Stultz
  Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
	Broadcom internal kernel review list, Boris Ostrovsky,
	Stephen Boyd, linux-doc, kvm, linux-kernel, linux-coco,
	linux-hyperv, virtualization, xen-devel, Tom Lendacky,
	Nikunj A Dadhania, David Woodhouse, David Woodhouse,
	Michael Kelley, Thomas Gleixner
In-Reply-To: <20260701193212.749551-1-seanjc@google.com>

Add and use APIs to set the local APIC timer period instead of open coding
the subtle HZ math in a all external callers, and make lapic_timer_period
local to apic.c.  Provide APIs to specify the frequency in both hertz and
kilohertz so that Hyper-V and VMware code aren't forced to lose precision.

Opportunistically use mul_u64_u32_div() to harden against the possibility
that the period in Khz is greater than 4294967, i.e. if the APIC timer runs
at ~4.29 GHz.  As pointed out by Sashiko, 4294968 * 1000 == 0x1_000002c0,
and thus a Khz period of 4294968 would silently overflow the 32-bit
unsigned integer used by most callers.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/include/asm/apic.h    |  3 ++-
 arch/x86/kernel/apic/apic.c    | 12 +++++++++++-
 arch/x86/kernel/cpu/mshyperv.c |  5 +----
 arch/x86/kernel/cpu/vmware.c   |  4 +---
 arch/x86/kernel/jailhouse.c    |  2 +-
 arch/x86/kernel/tsc.c          |  2 +-
 arch/x86/kernel/tsc_msr.c      |  2 +-
 7 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 9cd493d467d4..cd84a94688a2 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -63,7 +63,6 @@ extern int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern bool apic_is_disabled;
-extern unsigned int lapic_timer_period;
 
 extern enum apic_intr_mode_id apic_intr_mode;
 enum apic_intr_mode_id {
@@ -138,6 +137,8 @@ void register_lapic_address(unsigned long address);
 extern void setup_boot_APIC_clock(void);
 extern void setup_secondary_APIC_clock(void);
 extern void lapic_update_tsc_freq(void);
+extern void apic_set_timer_period_hz(u64 period_hz, const char *source);
+extern void apic_set_timer_period_khz(u64 period_khz, const char *source);
 
 #ifdef CONFIG_X86_64
 static inline bool apic_force_enable(unsigned long addr)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index aa1e19979aa8..8d3d930576fd 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -176,7 +176,7 @@ static struct resource lapic_resource = {
 };
 
 /* Measured in ticks per HZ. */
-unsigned int lapic_timer_period = 0;
+static unsigned int lapic_timer_period;
 
 static void apic_pm_activate(void);
 
@@ -796,6 +796,16 @@ bool __init apic_needs_pit(void)
 	return lapic_timer_period == 0;
 }
 
+void apic_set_timer_period_khz(u64 period_khz, const char *source)
+{
+	lapic_timer_period = mul_u64_u32_div(period_khz, 1000, HZ);
+}
+
+void apic_set_timer_period_hz(u64 period_hz, const char *source)
+{
+	lapic_timer_period = div_u64(period_hz, HZ);
+}
+
 static int __init calibrate_APIC_clock(void)
 {
 	struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 185d4f677ec0..87beecec76f0 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -646,10 +646,7 @@ static void __init ms_hyperv_init_platform(void)
 		u64	hv_lapic_frequency;
 
 		rdmsrq(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency);
-		hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ);
-		lapic_timer_period = hv_lapic_frequency;
-		pr_info("Hyper-V: LAPIC Timer Frequency: %#x\n",
-			lapic_timer_period);
+		apic_set_timer_period_hz(hv_lapic_frequency, "Hyper-V hypervisor");
 	}
 
 	register_nmi_handler(NMI_UNKNOWN, hv_nmi_unknown, NMI_FLAG_FIRST,
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 34b73573b108..36f779dd311d 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -424,9 +424,7 @@ static void __init vmware_platform_setup(void)
 
 #ifdef CONFIG_X86_LOCAL_APIC
 		/* Skip lapic calibration since we know the bus frequency. */
-		lapic_timer_period = ecx / HZ;
-		pr_info("Host bus clock speed read from hypervisor : %u Hz\n",
-			ecx);
+		apic_set_timer_period_hz(ecx, "VMware hypervisor");
 #endif
 	} else {
 		pr_warn("Failed to get TSC freq from the hypervisor\n");
diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c
index f58ce9220e0f..f2d4ef89c085 100644
--- a/arch/x86/kernel/jailhouse.c
+++ b/arch/x86/kernel/jailhouse.c
@@ -65,7 +65,7 @@ static void jailhouse_get_wallclock(struct timespec64 *now)
 
 static void __init jailhouse_timer_init(void)
 {
-	lapic_timer_period = setup_data.v1.apic_khz * (1000 / HZ);
+	apic_set_timer_period_khz(setup_data.v1.apic_khz, "Jailhouse hypervisor");
 }
 
 static unsigned long jailhouse_get_tsc(void)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index ce10ae4b298b..f9ecc9256863 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -717,7 +717,7 @@ unsigned long native_calibrate_tsc(void)
 	 * lapic_timer_period here to avoid having to calibrate the APIC
 	 * timer later.
 	 */
-	lapic_timer_period = crystal_khz * 1000 / HZ;
+	apic_set_timer_period_khz(crystal_khz, "CPUID 0x15/0x16");
 #endif
 
 	return crystal_khz * ebx_numerator / eax_denominator;
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 48e6cc1cb017..7e990871e041 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -211,7 +211,7 @@ unsigned long cpu_khz_from_msr(void)
 		pr_err("Error MSR_FSB_FREQ index %d is unknown\n", index);
 
 #ifdef CONFIG_X86_LOCAL_APIC
-	lapic_timer_period = (freq * 1000) / HZ;
+	apic_set_timer_period_khz(freq, "MSR_FSB_FREQ");
 #endif
 
 	/*
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related

* [PATCH v5 00/51] x86: Try to wrangle PV clocks vs. TSC
From: Sean Christopherson @ 2026-07-01 19:31 UTC (permalink / raw)
  To: Jonathan Corbet, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, Kiryl Shutsemau,
	Rick Edgecombe, Sean Christopherson, K. Y. Srinivasan,
	Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Ajay Kaher,
	Alexey Makhalov, Jan Kiszka, Andy Lutomirski, Peter Zijlstra,
	Juergen Gross, Daniel Lezcano, John Stultz
  Cc: Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
	Broadcom internal kernel review list, Boris Ostrovsky,
	Stephen Boyd, linux-doc, kvm, linux-kernel, linux-coco,
	linux-hyperv, virtualization, xen-devel, Tom Lendacky,
	Nikunj A Dadhania, David Woodhouse, David Woodhouse,
	Michael Kelley, Thomas Gleixner

The primary goal of this series to fix flaws with SNP and TDX guests where a
PV clock provided by the untrusted hypervisor is used instead of the secure
TSC that is controlled by trusted firmware.

The secondary goal is modernize running under KVM.  Currently, KVM guests will
use TSC for clocksource, but not sched_clock.  And Linux-as-a-KVM-guest doesn't
support paravirt enumeration of the TSC/APIC frequencies, even though QEMU
provides that information by default.

The tertiary goal is to clean up the PV clock code to deduplicate logic across
hypervisors, and to hopefully make it all easier to maintain going forward.

The quaternary goal is to clean up the TSC calibration code, which was made
stupidly hard to follow by hypervisor code mixing in with the native
calibration routines, instead of being implemented as a pure alternative.

Note, the VMware and Xen changes still probably should get acks from those
maintainers, as my understanding of what they're trying to do may be flawed.

Lots more background on the SNP/TDX motiviation:
https://lore.kernel.org/all/20250106124633.1418972-13-nikunj@amd.com

As before, I deliberately omitted jailhouse-dev@googlegroups.com from the To/Cc,
as those emails bounced on v1, AFAICT nothing has changed.

v5:
 - Use cpu_feature_enabled() instead of boot_cpu_has(). [Boris]
 - WARN if recalibrate_cpu_khz() runs on a system with TSC_KNOWN_FREQ. [Thomas]
 - Opportunistically drop a line break in native_calibrate_tsc(). [Thomas]
 - Rely on callers of cpuid_get_tsc_info() to check the result instead of
   unnecessarily zeroing the structure. [Boris]
 - Ignore tsc_early_khz if the TSC frequency is provided by trusted firmware
   or by the hypervisor. [Thomas, Sashiko]
 - Cache CPUID output in acrn_init_platform() to avoid introducing a transient
   bug where TSC_KNOWN_FREQ could be set even if the ACRN hypervisor didn't
   actually provide the frequency. [Sashiko]
 - Drop kvmclock's useless/dead check_tsc_unstable() call (it occurs before the
   command line parameter is parsed). [Sashiko]
 - Add helpers to set lapic_timer_period, to fix not-so-theoretical overflow
   in the various "khz * 1000 / HZ" patterns. [Sashiko]
 - Drop the "x86/xen: Obtain TSC frequency from CPUID if present" patch as it
   doesn't have any dependencies/conflicts on/with this series, and Sashiko had
   concerns about the assumptions it was making. [Sashiko]
 - Collect reviews. [David] (Kirill's got dropped because the patch he reviewed
   got completely rewritten).


v4:
 - Use x86_init_noop() to skip save/restore on VMware and Xen instead of
   nullifying x86_platform.{save,restore}_sched_clock_state. [Sashiko]
 - Use '0' to indicate "failure" when getting the CPU frequency from CPUID, to
   avoid using an out-param and thus make it all but impossible to
   unintentionally clobber the global cpu_khz (which v3 did). [Sashiko]
 - Rename cpuid_get_cpu_freq() => __cpu_khz_from_cpuid() to capture its
   relationship with cpu_khz_from_cpuid().
 - Compute lapic_timer_period in units of ticks, not Khz. [Sashiko]
 - Kill off x86_platform_ops.calibrate_{cpu,tsc}(), and instead use dedicated
   hooks for hypervisor code, and direct calls for TDX and SNP. [David, loosely]
 - Drop SNP's secure TSC override of _CPU_ calibration, as there's zero
   evidence it's justified or a net positive.
 - Collect reviews/acks. [David, Wei]
 - Decouple getting TSC/APIC frequencies from KVM PV CPUID from kvmclock. [David]
 - Fix an amusing number of Opportunistically misspellings. [David]
 - Set kvm_sched_clock_offset _before_ registering kvmclock as sched_clock,
   and add a comment to guard against future goofs. [Sashiko]
 - Keep "setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE)" in Hyper-V's handling
   of HV_ACCESS_TSC_INVARIANT, as it's technically possible to have a VM
   with HV_ACCESS_TSC_INVARIANT but not HV_ACCESS_FREQUENCY_MSRS.  Though as
   a _very_ nice side effect of using dedicated sequencing for selecting the
   TSC frequency source, this would have naturally happened anyways. [Sashiko]

v3:
 - https://lore.kernel.org/all/20260515191942.1892718-1-seanjc@google.com
 - Collect reviews. [Michael, Thomas]
 - Use Hyper-V reference counter / refcounter instead of Hyper-V timer. [Michael]
 - Use the paravirt CPUID interface first proposed by VMware for KVM's
   "official" mechanism for communicating frequency to KVM-aware guests,
   instead of abusing Intel's CPUID leafs. [David]
 - Deal with paravirt code being moved into asm/timers.h and
   arch/x86/kernel/tsc.c.

v2:
 - https://lore.kernel.org/all/Z8YWttWDtvkyCtdJ@google.com
 - Add struct to hold the TSC CPUID output. [Boris]
 - Don't pointlessly inline the TSC CPUID helpers. [Boris]
 - Fix a variable goof in a helper, hopefully for real this time. [Dan]
 - Collect reviews. [Nikunj]
 - Override the sched_clock save/restore hooks if and only if a PV clock
   is successfully registered.
 - During resome, restore clocksources before reading persistent time.
 - Clean up more warts created by kvmclock.
 - Fix more bugs in kvmclock's suspend/resume handling.
 - Try to harden kvmclock against future bugs.

v1: https://lore.kernel.org/all/20250201021718.699411-1-seanjc@google.com

David Woodhouse (2):
  KVM: x86: Officially define CPUID 0x40000010 as PV Timing Info (TSC
    and Bus)
  x86/kvm: Obtain TSC frequency from PV CPUID if present

Sean Christopherson (49):
  x86/apic: Provide helpers to set local APIC timer period in hz and khz
  x86/apic: Add CONFIG_X86_LOCAL_APIC=n stubs for
    apic_set_timer_period_{,k}hz()
  x86/tsc: Ensure that TSC recalibration doesn't run if TSC frequency is
    known
  x86/tsc: Restrict recalibrate_cpu_khz() export to p4-clockmod and
    powernow-k7
  x86/sev: Mark TSC as reliable when configuring Secure TSC
  x86/sev: Don't override CPU frequency calibration for SNP's Secure TSC
  x86/sev: Move check for SNP Secure TSC support to tsc_early_init()
  x86/sev: Shove SNP's secure/trusted TSC frequency directly into
    "calibration"
  x86/tsc: Add a standalone helper for getting TSC info from CPUID.0x15
  x86/tdx: Force TSC frequency with CPUID-based info provided by the
    TDX-Module
  x86/tsc: Add dedicated hypervisor hooks for getting known TSC/CPU
    frequencies
  x86/acrn: Register TSC/CPU frequency callbacks iff frequency is
    actually in CPUID
  x86/acrn: Mark TSC frequency as known when using ACRN for calibration
  x86/tsc: Consolidate forcing of X86_FEATURE_TSC_KNOWN_FREQ for PV code
  x86/tsc: Kill off x86_platform_ops.calibrate_{cpu,tsc}() hooks
  x86/tsc: Rename pit_hpet_ptimer_calibrate_cpu() =>
    native_calibrate_cpu_late()
  x86/tsc: Fold native_calibrate_cpu() into recalibrate_cpu_khz()
  x86/kvmclock: Rename kvm_get_tsc_khz() to kvmclock_get_tsc_khz()
  x86/kvmclock: Drop dead check on TSC being unstable during
    kvmclock_init()
  x86/kvm: Mark TSC as reliable when it's constant and nonstop
  x86/tsc: Add standalone helper for getting CPU frequency from CPUID
  x86/kvm: Get CPU base frequency from CPUID when it's available
  clocksource: hyper-v: Register sched_clock save/restore iff it's
    necessary
  clocksource: hyper-v: Drop wrappers to sched_clock save/restore
    helpers
  clocksource: hyper-v: Don't save/restore TSC offset when using HV
    sched_clock
  x86/kvmclock: Setup kvmclock for secondary CPUs iff CONFIG_SMP=y
  x86/kvm: Don't disable kvmclock on BSP in syscore_suspend()
  x86/paravirt: Remove unnecessary PARAVIRT=n stub for
    paravirt_set_sched_clock()
  x86/paravirt: Move handling of unstable PV clocks into
    paravirt_set_sched_clock()
  x86/kvmclock: Move sched_clock save/restore helpers up in kvmclock.c
  x86/xen/time: NOP-ify x86_platform's sched_clock save/restore hooks
  x86/vmware: NOP-ify save/restore hooks when using VMware's sched_clock
  x86/tsc: WARN if TSC sched_clock save/restore used with PV sched_clock
  x86/paravirt: Pass sched_clock save/restore helpers during
    registration
  x86/kvmclock: Move kvm_sched_clock_init() down in kvmclock.c
  x86/xen/time: Mark xen_setup_vsyscall_time_info() as __init
  x86/pvclock: Mark setup helpers and related various as
    __init/__ro_after_init
  x86/pvclock: WARN if pvclock's valid_flags are overwritten
  x86/kvmclock: Refactor handling of PVCLOCK_TSC_STABLE_BIT during
    kvmclock_init()
  timekeeping: Resume clocksources before reading persistent clock
  x86/kvmclock: Hook clocksource.suspend/resume when kvmclock isn't
    sched_clock
  x86/kvmclock: WARN if wall clock is read while kvmclock is suspended
  x86/paravirt: Mark __paravirt_set_sched_clock() as __init
  x86/paravirt: Plumb a return code into __paravirt_set_sched_clock()
  x86/paravirt: Don't use a PV sched_clock in CoCo guests with trusted
    TSC
  x86/kvmclock: Use TSC for sched_clock if it's constant and non-stop
  x86/kvmclock: Plumb in AP-online and BSP-resume to kvmlock, for
    documentation
  x86/paravirt: Move using_native_sched_clock() stub into timer.h
  x86/kvm: Get local APIC bus frequency from PV CPUID Timing Info

 .../admin-guide/kernel-parameters.txt         |   5 +
 Documentation/virt/kvm/x86/cpuid.rst          |  12 +
 arch/x86/coco/sev/core.c                      |  21 +-
 arch/x86/coco/tdx/tdx.c                       |  19 +-
 arch/x86/include/asm/acrn.h                   |   5 -
 arch/x86/include/asm/apic.h                   |   5 +-
 arch/x86/include/asm/kvm_para.h               |  12 +-
 arch/x86/include/asm/sev.h                    |   4 +-
 arch/x86/include/asm/tdx.h                    |   2 +
 arch/x86/include/asm/timer.h                  |  15 +-
 arch/x86/include/asm/tsc.h                    |  10 +-
 arch/x86/include/asm/x86_init.h               |   8 +-
 arch/x86/include/uapi/asm/kvm_para.h          |  11 +
 arch/x86/kernel/apic/apic.c                   |  12 +-
 arch/x86/kernel/cpu/acrn.c                    |  14 +-
 arch/x86/kernel/cpu/mshyperv.c                |  70 +-----
 arch/x86/kernel/cpu/vmware.c                  |  19 +-
 arch/x86/kernel/jailhouse.c                   |   9 +-
 arch/x86/kernel/kvm.c                         | 101 ++++++--
 arch/x86/kernel/kvmclock.c                    | 208 +++++++++++------
 arch/x86/kernel/pvclock.c                     |   9 +-
 arch/x86/kernel/tsc.c                         | 218 +++++++++++-------
 arch/x86/kernel/tsc_msr.c                     |   4 +-
 arch/x86/kernel/x86_init.c                    |   2 -
 arch/x86/mm/mem_encrypt_amd.c                 |   3 -
 arch/x86/xen/time.c                           |  14 +-
 drivers/clocksource/hyperv_timer.c            |  38 ++-
 include/clocksource/hyperv_timer.h            |   2 -
 kernel/time/timekeeping.c                     |   9 +-
 29 files changed, 540 insertions(+), 321 deletions(-)


base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply

* Re: [PATCH net 1/2] vsock/virtio: collapse receive queue under memory pressure
From: Bobby Eshleman @ 2026-07-01 16:34 UTC (permalink / raw)
  To: Stefano Garzarella
  Cc: netdev, Jason Wang, Jakub Kicinski, Paolo Abeni,
	Michael S. Tsirkin, kvm, virtualization, Xuan Zhuo, Eric Dumazet,
	Simon Horman, linux-kernel, Stefan Hajnoczi, David S. Miller,
	Eugenio Pérez, stable, Brien Oberstein
In-Reply-To: <20260626134823.206676-2-sgarzare@redhat.com>

On Fri, Jun 26, 2026 at 03:48:22PM +0200, Stefano Garzarella wrote:
> From: Stefano Garzarella <sgarzare@redhat.com>
> 
> When many small packets accumulate in the receive queue, the skb overhead
> can exceed buf_alloc even while the payload is within bounds. This causes
> virtio_transport_inc_rx_pkt() to reject packets, leading to connection
> resets during large transfers under backpressure.
> 
> The issue was reported by Brien, who has a reproducer, but it is also
> easily reproducible with iperf-vsock [1] using a small packet size:
> 
>   iperf3 --vsock -c $CID -l 129
> 
> which fails immediately without this patch but with commit 059b7dbd20a6
> ("vsock/virtio: fix potential unbounded skb queue").
> 
> Inspired by TCP's tcp_collapse() which solves a similar problem, add
> virtio_transport_collapse_rx_queue() that walks the receive queue and
> re-copies data into compact linear skbs to reduce the overhead.
> 
> The collapse is triggered from virtio_transport_recv_enqueue() when
> virtio_transport_inc_rx_pkt() fails. A pre-scan counts the eligible bytes
> to size each allocation precisely, avoiding waste for isolated small
> packets. Partially consumed skbs are kept as-is to preserve
> buf_used/fwd_cnt accounting, EOM-marked skbs to maintain SEQPACKET
> message boundaries, and skbs already larger than the collapse target
> because they already have a good data-to-overhead ratio.
> 
> [1] https://github.com/stefano-garzarella/iperf-vsock
> 
> Fixes: 059b7dbd20a6 ("vsock/virtio: fix potential unbounded skb queue")
> Cc: stable@vger.kernel.org
> Reported-by: Brien Oberstein <brienpub@gmail.com>
> Closes: https://lore.kernel.org/netdev/618701dd023e$063de350$12b9a9f0$@gmail.com/
> Tested-by: Brien Oberstein <brienpub@gmail.com>
> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> ---
>  net/vmw_vsock/virtio_transport_common.c | 148 +++++++++++++++++++++++-
>  1 file changed, 146 insertions(+), 2 deletions(-)
> 
> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> index 09475007165b..304ea424995d 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -420,6 +420,137 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
>  	return ret;
>  }
>  
> +static bool virtio_transport_can_collapse(struct sk_buff *skb,
> +					  unsigned int size)
> +{
> +	/* skbs that are partially consumed, mark a SEQPACKET message boundary,
> +	 * or are already large enough should not be collapsed: they either
> +	 * need special accounting, carry protocol state, or already have a
> +	 * good data-to-overhead ratio.
> +	 */
> +	if (VIRTIO_VSOCK_SKB_CB(skb)->offset)
> +		return false;
> +	if (le32_to_cpu(virtio_vsock_hdr(skb)->flags) & VIRTIO_VSOCK_SEQ_EOM)
> +		return false;
> +	if (skb->len >= size)
> +		return false;
> +	return true;
> +}
> +
> +/* Iterate through the packets in the queue starting from the current skb to
> + * count the number of bytes we can collapse.
> + */
> +static unsigned int
> +virtio_transport_collapse_size(struct sk_buff *skb,
> +			       struct sk_buff_head *queue,
> +			       unsigned int max_size)
> +{
> +	unsigned int target = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
> +
> +	while ((skb = skb_peek_next(skb, queue)) &&
> +	       virtio_transport_can_collapse(skb, max_size)) {
> +		unsigned int len = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
> +
> +		if (len > max_size - target)
> +			return target;
> +
> +		target += len;
> +	}
> +
> +	return target;
> +}
> +
> +/* Called under lock_sock when skb overhead exceeds the budget. */
> +static void virtio_transport_collapse_rx_queue(struct virtio_vsock_sock *vvs)
> +{
> +	/* Use the same linear allocation threshold as virtio_vsock_alloc_skb()
> +	 * to avoid adding pressure on the page allocator.
> +	 */
> +	unsigned int collapse_max = SKB_MAX_ORDER(VIRTIO_VSOCK_SKB_HEADROOM,
> +						  PAGE_ALLOC_COSTLY_ORDER);
> +	struct sk_buff *skb, *next_skb, *new_skb = NULL;
> +	struct sk_buff_head new_queue;
> +
> +	__skb_queue_head_init(&new_queue);
> +
> +	skb_queue_walk_safe(&vvs->rx_queue, skb, next_skb) {
> +		struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
> +		u32 src_off = VIRTIO_VSOCK_SKB_CB(skb)->offset;
> +		u32 src_len = skb->len - src_off;
> +		bool keep = false;
> +
> +		if (!virtio_transport_can_collapse(skb, collapse_max)) {
> +			/* Finalize pending collapsed skb to preserve packet
> +			 * ordering.
> +			 */
> +			if (new_skb) {
> +				__skb_queue_tail(&new_queue, new_skb);
> +				new_skb = NULL;
> +			}
> +			keep = true;
> +			goto next;
> +		}
> +
> +		/* Finalize if this packet won't fit in the remaining tailroom,
> +		 * so we can allocate a right-sized new_skb.
> +		 */
> +		if (new_skb && src_len > skb_tailroom(new_skb)) {
> +			__skb_queue_tail(&new_queue, new_skb);
> +			new_skb = NULL;
> +		}
> +
> +		if (!new_skb) {
> +			unsigned int alloc_size;
> +
> +			alloc_size = virtio_transport_collapse_size(skb, &vvs->rx_queue,
> +								    collapse_max);
> +
> +			/* Only this skb's data is eligible, nothing to merge
> +			 * with. Keep as-is.
> +			 */
> +			if (alloc_size <= src_len) {
> +				keep = true;
> +				goto next;
> +			}
> +
> +			new_skb = virtio_vsock_alloc_linear_skb(alloc_size +
> +					VIRTIO_VSOCK_SKB_HEADROOM, GFP_KERNEL);
> +			if (!new_skb)
> +				goto out;
> +
> +			memcpy(virtio_vsock_hdr(new_skb), hdr,
> +			       sizeof(struct virtio_vsock_hdr));
> +			virtio_vsock_hdr(new_skb)->len = 0;
> +		}
> +
> +		/* Cannot fail since src_off/src_len are within bounds, but if
> +		 * it does, discard new_skb to avoid queuing corrupted data.
> +		 */
> +		if (WARN_ON_ONCE(skb_copy_bits(skb, src_off,
> +					       skb_put(new_skb, src_len),
> +					       src_len))) {
> +			kfree_skb(new_skb);
> +			new_skb = NULL;
> +			goto out;
> +		}
> +
> +		le32_add_cpu(&virtio_vsock_hdr(new_skb)->len, src_len);
> +		virtio_vsock_hdr(new_skb)->flags |= hdr->flags;
> +
> +next:
> +		__skb_unlink(skb, &vvs->rx_queue);
> +		if (keep)
> +			__skb_queue_tail(&new_queue, skb);
> +		else
> +			consume_skb(skb);
> +	}
> +out:
> +	if (new_skb)
> +		__skb_queue_tail(&new_queue, new_skb);
> +
> +	skb_queue_splice(&new_queue, &vvs->rx_queue);

I think the new skbs will also need skb_set_owner_sk_safe(skb, sk)
when adding to rx_queue?

Best,
Bobby

> +}
> +
>  static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
>  					u32 len)
>  {
> @@ -1363,8 +1494,21 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
>  	spin_lock_bh(&vvs->rx_lock);
>  
>  	can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
> -	if (!can_enqueue)
> -		goto out;
> +	if (!can_enqueue) {
> +		/* Try to collapse the receive queue to reduce skb overhead and
> +		 * make room for this packet.
> +		 * Unlock rx_lock since the collapse may sleep or, in any case,
> +		 * take some time to collapse the skbs, but this is safe, since
> +		 * sk_lock is held by caller so no one else can enqueue or
> +		 * dequeue.
> +		 */
> +		spin_unlock_bh(&vvs->rx_lock);
> +		virtio_transport_collapse_rx_queue(vvs);
> +		spin_lock_bh(&vvs->rx_lock);
> +		can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
> +		if (!can_enqueue)
> +			goto out;
> +	}
>  
>  	if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM)
>  		vvs->msg_count++;
> -- 
> 2.54.0
> 
> 

^ permalink raw reply

* Re: [PATCH 12/13] mm/mprotect: convert mprotect code to use vma_flags_t
From: Lance Yang @ 2026-07-01 16:09 UTC (permalink / raw)
  To: ljs
  Cc: akpm, tsbogend, maddy, mpe, maarten.lankhorst, mripard,
	tzimmermann, airlied, simona, l.stach, inki.dae, sw0312.kim,
	kyungmin.park, krzk, peter.griffin, jani.nikula, joonas.lahtinen,
	rodrigo.vivi, tursulin, robin.clark, lumag, lyude, dakr,
	tomi.valkeinen, hjc, heiko, andy.yan, thierry.reding, mperttunen,
	jonathanh, kraxel, dmitry.osipenko, zack.rusin, matthew.brost,
	thomas.hellstrom, oleksandr_andrushchenko, deller, bcrl, viro,
	brauner, muchun.song, osalvador, david, ziy, baolin.wang, liam,
	npache, ryan.roberts, dev.jain, baohua, lance.yang, hughd, vbabka,
	rppt, surenb, mhocko, jannh, pfalcato, kees, perex, tiwai,
	linux-mips, linux-kernel, linuxppc-dev, dri-devel, etnaviv,
	linux-arm-kernel, linux-samsung-soc, intel-gfx, linux-arm-msm,
	freedreno, nouveau, linux-rockchip, linux-tegra, virtualization,
	intel-xe, xen-devel, linux-fbdev, linux-aio, linux-fsdevel,
	linux-mm, linux-sound
In-Reply-To: <7ef626d8a12dc742cfc09d080be5dc09850e873a.1782760670.git.ljs@kernel.org>


On Mon, Jun 29, 2026 at 08:25:35PM +0100, Lorenzo Stoakes wrote:
>Replace use of the legacy vm_flags_t flags with vma_flags_t values
>throughout the mprotect logic.
>
>Note that we retain the legacy vm_flags_t bit shifting code in
>do_mprotect_key(), deferring a vma_flags_t approach to this for the time
>being.
>
>Additionally update comments to reflect the changes to be consistent.
>
>No functional change intended.
>
>Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>---
> mm/mprotect.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
>diff --git a/mm/mprotect.c b/mm/mprotect.c
>index 9cbf932b028c..c9504b2a2525 100644
>--- a/mm/mprotect.c
>+++ b/mm/mprotect.c
>@@ -40,7 +40,7 @@
> 
> static bool maybe_change_pte_writable(struct vm_area_struct *vma, pte_t pte)
> {
>-	if (WARN_ON_ONCE(!(vma->vm_flags & VM_WRITE)))
>+	if (WARN_ON_ONCE(!vma_test(vma, VMA_WRITE_BIT)))
> 		return false;
> 
> 	/* Don't touch entries that are not even readable. */
>@@ -97,7 +97,7 @@ static bool can_change_shared_pte_writable(struct vm_area_struct *vma,
> bool can_change_pte_writable(struct vm_area_struct *vma, unsigned long addr,
> 			     pte_t pte)
> {
>-	if (!(vma->vm_flags & VM_SHARED))
>+	if (!vma_test(vma, VMA_SHARED_BIT))
> 		return can_change_private_pte_writable(vma, addr, pte);
> 
> 	return can_change_shared_pte_writable(vma, pte);
>@@ -194,7 +194,7 @@ static __always_inline void set_write_prot_commit_flush_ptes(struct vm_area_stru
> {
> 	bool set_write;
> 
>-	if (vma->vm_flags & VM_SHARED) {
>+	if (vma_test(vma, VMA_SHARED_BIT)) {
> 		set_write = can_change_shared_pte_writable(vma, ptent);
> 		prot_commit_flush_ptes(vma, addr, ptep, oldpte, ptent, nr_ptes,
> 				       /* idx = */ 0, set_write, tlb);
>@@ -811,8 +811,8 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb,
> 		vm_unacct_memory(nrpages);
> 
> 	/*
>-	 * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major
>-	 * fault on access.
>+	 * Private VMA_LOCKED_BIT VMA becoming writable: trigger COW to avoid
>+	 * major fault on access.
> 	 */
> 	if (vma_flags_test(&new_vma_flags, VMA_WRITE_BIT) &&
> 	    vma_flags_test(&old_vma_flags, VMA_LOCKED_BIT) &&
>@@ -886,7 +886,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> 			goto out;
> 		start = vma->vm_start;
> 		error = -EINVAL;
>-		if (!(vma->vm_flags & VM_GROWSDOWN))
>+		if (!vma_test(vma, VMA_GROWSDOWN_BIT))
> 			goto out;
> 	} else {
> 		if (vma->vm_start > start)
>@@ -894,7 +894,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> 		if (unlikely(grows & PROT_GROWSUP)) {
> 			end = vma->vm_end;
> 			error = -EINVAL;
>-			if (!(vma->vm_flags & VM_GROWSUP))
>+			if (!vma_test(vma, VMA_GROWSUP_BIT))

IIUC, should this be

if (!vma_test_single_mask(vma, VMA_GROWSUP))

instead?

#elif defined(CONFIG_PARISC)
#define VM_GROWSUP	INIT_VM_FLAG(GROWSUP)
...
#ifndef VM_GROWSUP
#define VM_GROWSUP	VM_NONE
...

VM_GROWSUP is only defined as GROWSUP on parisc and becomes VM_NONE
elsewhere. But VMA_GROWSUP_BIT is the raw ARCH_1 bit, which is also used
for other arch-specific VMA flags:

	DECLARE_VMA_BIT_ALIAS(SAO, ARCH_1),		/* Strong Access Ordering (powerpc) */
	DECLARE_VMA_BIT_ALIAS(GROWSUP, ARCH_1),		/* parisc */
	DECLARE_VMA_BIT_ALIAS(SPARC_ADI, ARCH_1),	/* sparc64 */
	DECLARE_VMA_BIT_ALIAS(ARM64_BTI, ARCH_1),	/* arm64 */
	DECLARE_VMA_BIT_ALIAS(ARCH_CLEAR, ARCH_1),	/* sparc64, arm64 */
	DECLARE_VMA_BIT_ALIAS(MAPPED_COPY, ARCH_1),	/* !CONFIG_MMU */

Other vma_test() changes look fine to me: just fixed INIT_VM_FLAG()
masks matching their VMA_*_BIT :)

Cheers, Lance

> 				goto out;
> 		}
> 	}
>@@ -918,7 +918,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> 		}
> 
> 		/* Does the application expect PROT_READ to imply PROT_EXEC */
>-		if (rier && (vma->vm_flags & VM_MAYEXEC))
>+		if (rier && vma_test(vma, VMA_MAYEXEC_BIT))
> 			prot |= PROT_EXEC;
> 
> 		/*
>-- 
>2.54.0
>
>

^ permalink raw reply

* Re: [PATCH] vdpa/mlx5: fix wrong list iterated in add_direct_chain error path
From: Dragos Tatulea @ 2026-07-01 15:02 UTC (permalink / raw)
  To: lirongqing, Michael S . Tsirkin, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Kees Cook, Rosen Penev, Parav Pandit,
	Eli Cohen, virtualization, linux-kernel
In-Reply-To: <20260701113608.1972-1-lirongqing@baidu.com>



On 01.07.26 13:36, lirongqing wrote:
> From: Li RongQing <lirongqing@baidu.com>
> 
> In add_direct_chain(), newly allocated direct MR entries are added to
> the local list 'tmp', which is spliced into mr->head only on success.
> On the error path, the cleanup loop was incorrectly iterating over
> mr->head instead of tmp.
> 
> Fix by iterating over 'tmp' in the err_alloc cleanup path.
> 
> Fixes: 94abbccdf291 ("vdpa/mlx5: Add shared memory registration code")
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
>  drivers/vdpa/mlx5/core/mr.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
> index 6d02ccf..1a224f0 100644
> --- a/drivers/vdpa/mlx5/core/mr.c
> +++ b/drivers/vdpa/mlx5/core/mr.c
> @@ -480,7 +480,7 @@ static int add_direct_chain(struct mlx5_vdpa_dev *mvdev,
>  	return 0;
>  
>  err_alloc:
> -	list_for_each_entry_safe(dmr, n, &mr->head, list) {
> +	list_for_each_entry_safe(dmr, n, &tmp, list) {
>  		list_del_init(&dmr->list);
>  		unmap_direct_mr(mvdev, dmr);
>  		kfree(dmr);

Thanks for your patch!
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>

Thanks,
Dragos

^ permalink raw reply

* Re: [PATCH] vdpa/mlx5: fix wrong list iterated in add_direct_chain error path
From: Eugenio Perez Martin @ 2026-07-01 13:44 UTC (permalink / raw)
  To: lirongqing
  Cc: Dragos Tatulea, Michael S . Tsirkin, Jason Wang, Xuan Zhuo,
	Kees Cook, Rosen Penev, Parav Pandit, Eli Cohen, virtualization,
	linux-kernel
In-Reply-To: <20260701113608.1972-1-lirongqing@baidu.com>

On Wed, Jul 1, 2026 at 1:36 PM lirongqing <lirongqing@baidu.com> wrote:
>
> From: Li RongQing <lirongqing@baidu.com>
>
> In add_direct_chain(), newly allocated direct MR entries are added to
> the local list 'tmp', which is spliced into mr->head only on success.
> On the error path, the cleanup loop was incorrectly iterating over
> mr->head instead of tmp.
>
> Fix by iterating over 'tmp' in the err_alloc cleanup path.
>
> Fixes: 94abbccdf291 ("vdpa/mlx5: Add shared memory registration code")

Acked-by: Eugenio Pérez <eperezma@redhat.com>

Thanks!

> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
>  drivers/vdpa/mlx5/core/mr.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
> index 6d02ccf..1a224f0 100644
> --- a/drivers/vdpa/mlx5/core/mr.c
> +++ b/drivers/vdpa/mlx5/core/mr.c
> @@ -480,7 +480,7 @@ static int add_direct_chain(struct mlx5_vdpa_dev *mvdev,
>         return 0;
>
>  err_alloc:
> -       list_for_each_entry_safe(dmr, n, &mr->head, list) {
> +       list_for_each_entry_safe(dmr, n, &tmp, list) {
>                 list_del_init(&dmr->list);
>                 unmap_direct_mr(mvdev, dmr);
>                 kfree(dmr);
> --
> 2.9.4
>


^ permalink raw reply

* Re: [PATCH v2 1/2] tools/virtio: Add missing compat definitions for vhost_net_test
From: SJ Park @ 2026-07-01 13:36 UTC (permalink / raw)
  To: Yichong Chen
  Cc: SJ Park, mst, jasowang, xuanzhuo, eperezma, akpm, rppt, ljs,
	pabeni, linux-kernel, virtualization
In-Reply-To: <20260629022124.131894-2-chenyichong@uniontech.com>

On Mon, 29 Jun 2026 10:21:23 +0800 Yichong Chen <chenyichong@uniontech.com> wrote:

> vhost_net_test builds virtio_ring.c in userspace.
> 
> Recent virtio headers pull in helper headers that are not provided by
> the tools/virtio compatibility layer, including asm/percpu_types.h,
> linux/completion.h, linux/mod_devicetable.h and
> linux/virtio_features.h.
> 
> Add the missing compat definitions and the DMA attribute used by the
> current virtio ring code.

I confirmed this patch fixes the build on my setup.

> 
> Signed-off-by: Yichong Chen <chenyichong@uniontech.com>

Tested-by: SJ Park <sj@kernel.org>


Thanks,
SJ

[...]

^ permalink raw reply

* Re: [PATCH v2 2/2] tools/include: Include stdint.h for SIZE_MAX in overflow.h
From: SJ Park @ 2026-07-01 13:35 UTC (permalink / raw)
  To: Yichong Chen
  Cc: SJ Park, mst, jasowang, xuanzhuo, eperezma, akpm, rppt, ljs,
	pabeni, linux-kernel, virtualization
In-Reply-To: <20260629022124.131894-3-chenyichong@uniontech.com>

On Mon, 29 Jun 2026 10:21:24 +0800 Yichong Chen <chenyichong@uniontech.com> wrote:

> tools/include/linux/overflow.h uses SIZE_MAX in its size helper
> functions.
> 
> Include stdint.h so tools users that include overflow.h without another
> SIZE_MAX provider can build.

On the latest mm-new reverting this patch (for test), I was able to build
tools/virtio.

    git checkout akpm.korg.mm/mm-new
    [...]
    HEAD is now at f5ea2fbe68e0c mm/swap, PM: hibernate: atomically replace hibernation pin
    $ git revert 9d462d8b9b705548451325ee4376dfd549e14aa2 -s --no-edit
    [detached HEAD f2202247e38d9] Revert "tools/include: include stdint.h for SIZE_MAX in overflow.h"
     Date: Wed Jul 1 06:33:03 2026 -0700
     1 file changed, 1 deletion(-)
    $ make -C tools/virtio/ clean
    make: Entering directory '/home/lkhack/worktree.linux/tools/virtio'
    rm -f *.o vringh_test virtio_test vhost_net_test vhost_test/*.o \
                  vhost_test/.*.cmd vhost_test/Module.symvers \
                  vhost_test/modules.order *.d
    make: Leaving directory '/home/lkhack/worktree.linux/tools/virtio'
    $ make -C tools/virtio/ test
    make: Entering directory '/home/lkhack/worktree.linux/tools/virtio'
    cc -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h -mfunction-return=thunk -fcf-protection=none -mindirect-branch-register -pthread   -c -o virtio_test.o virtio_test.c
    cc -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h -mfunction-return=thunk -fcf-protection=none -mindirect-branch-register -pthread   -c -o virtio_ring.o ../../drivers/virtio/virtio_ring.c
    cc -pthread  virtio_test.o virtio_ring.o   -o virtio_test
    cc -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h -mfunction-return=thunk -fcf-protection=none -mindirect-branch-register -pthread   -c -o vringh_test.o vringh_test.c
    cc -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h -mfunction-return=thunk -fcf-protection=none -mindirect-branch-register -pthread   -c -o vringh.o ../../drivers/vhost/vringh.c
    cc -pthread  vringh_test.o vringh.o virtio_ring.o   -o vringh_test
    cc -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h -mfunction-return=thunk -fcf-protection=none -mindirect-branch-register -pthread   -c -o vhost_net_test.o vhost_net_test.c
    cc -pthread  vhost_net_test.o virtio_ring.o   -o vhost_net_test
    make: Leaving directory '/home/lkhack/worktree.linux/tools/virtio'


Am I missing something?

> 
> Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
> ---
>  tools/include/linux/overflow.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/tools/include/linux/overflow.h b/tools/include/linux/overflow.h
> index 3427d7880326..98963688143f 100644
> --- a/tools/include/linux/overflow.h
> +++ b/tools/include/linux/overflow.h
> @@ -1,4 +1,5 @@
>  /* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +#include <stdint.h>
>  #ifndef __LINUX_OVERFLOW_H
>  #define __LINUX_OVERFLOW_H

Shouldn't the include placed after #define __LINUX_OVERFLOW_H ?


Thanks,
SJ

[...]

^ permalink raw reply

* [PATCH] vdpa/mlx5: fix wrong list iterated in add_direct_chain error path
From: lirongqing @ 2026-07-01 11:36 UTC (permalink / raw)
  To: Dragos Tatulea, Michael S . Tsirkin, Jason Wang, Xuan Zhuo,
	Eugenio Pérez, Kees Cook, Rosen Penev, Parav Pandit,
	Eli Cohen, virtualization, linux-kernel
  Cc: Li RongQing

From: Li RongQing <lirongqing@baidu.com>

In add_direct_chain(), newly allocated direct MR entries are added to
the local list 'tmp', which is spliced into mr->head only on success.
On the error path, the cleanup loop was incorrectly iterating over
mr->head instead of tmp.

Fix by iterating over 'tmp' in the err_alloc cleanup path.

Fixes: 94abbccdf291 ("vdpa/mlx5: Add shared memory registration code")
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
 drivers/vdpa/mlx5/core/mr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
index 6d02ccf..1a224f0 100644
--- a/drivers/vdpa/mlx5/core/mr.c
+++ b/drivers/vdpa/mlx5/core/mr.c
@@ -480,7 +480,7 @@ static int add_direct_chain(struct mlx5_vdpa_dev *mvdev,
 	return 0;
 
 err_alloc:
-	list_for_each_entry_safe(dmr, n, &mr->head, list) {
+	list_for_each_entry_safe(dmr, n, &tmp, list) {
 		list_del_init(&dmr->list);
 		unmap_direct_mr(mvdev, dmr);
 		kfree(dmr);
-- 
2.9.4


^ permalink raw reply related

* Re: [PATCH v2 2/3] drm/virtio: honor blob_alignment requirements
From: Alyssa Ross @ 2026-07-01 11:10 UTC (permalink / raw)
  To: Sergio Lopez
  Cc: Chia-I Wu, Jason Wang, Michael S. Tsirkin, Eugenio Pérez,
	Xuan Zhuo, linux-kernel, Simona Vetter, Dmitry Osipenko,
	Thomas Zimmermann, David Airlie, Gurchetan Singh, Gerd Hoffmann,
	virtualization, dri-devel, Maxime Ripard, Maarten Lankhorst
In-Reply-To: <20260428194450.518296-3-slp@redhat.com>

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

On Tue, Apr 28, 2026 at 09:44:49PM +0200, Sergio Lopez wrote:
> If VIRTIO_GPU_F_BLOB_ALIGNMENT has been negotiated, blob size must be
> aligned to blob_alignment. Validate this in verify_blob() so that
> invalid requests are rejected early.
>
> Signed-off-by: Sergio Lopez <slp@redhat.com>

FYI: this change breaks crosvm, which is squatting the 5 and 6 values
of VIRTIO_GPU_F_* with different meanings.  I've reported it as a
crosvm bug, so hopefully it can be taken care of there.

https://issuetracker.google.com/issues/529852979

> ---
>  drivers/gpu/drm/virtio/virtgpu_ioctl.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
> index c33c057365f8..d0c4edf1eaf4 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
> @@ -489,6 +489,11 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
>  	params->size = rc_blob->size;
>  	params->blob = true;
>  	params->blob_flags = rc_blob->blob_flags;
> +
> +	if (vgdev->has_blob_alignment &&
> +	    !IS_ALIGNED(params->size, vgdev->blob_alignment))
> +		return -EINVAL;
> +
>  	return 0;
>  }
>
> --
> 2.53.0
>

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

^ permalink raw reply

* Re: [PATCH v3 1/7] list: Add mutable iterator variants
From: Kaitao Cheng @ 2026-07-01 11:07 UTC (permalink / raw)
  To: Jani Nikula, David Laight, Christian König,
	David Hildenbrand (Arm), Alexei Starovoitov
  Cc: Andrew Morton, Jens Axboe, Tejun Heo, Alexander Viro,
	Christian Brauner, Daniel Borkmann, Andrii Nakryiko,
	Johannes Weiner, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Thomas Gleixner,
	Juri Lelli, Vincent Guittot, Paul Moore, Andy Shevchenko,
	Paul E. McKenney, Shakeel Butt, David Howells, Simona Vetter,
	Randy Dunlap, Luca Ceresoli, Philipp Stanner, linux-block,
	linux-kernel, cgroups, linux-ntfs-dev, linux-fsdevel, io-uring,
	audit, bpf, netdev, dri-devel, linux-perf-users,
	linux-trace-kernel, kexec, live-patching, linux-modules,
	linux-crypto, linux-pm, rcu, sched-ext, linux-mm, virtualization,
	damon, llvm, Kaitao Cheng, Muchun Song
In-Reply-To: <734f66ca51485ee3ec9788c0eaaead681e00664b@intel.com>

在 2026/6/25 19:00, Jani Nikula 写道:
> On Thu, 25 Jun 2026, Kaitao Cheng <kaitao.cheng@linux.dev> wrote:
>> 在 2026/6/24 22:23, David Laight 写道:
>>> On Wed, 24 Jun 2026 15:23:47 +0200
>>> Christian König <christian.koenig@amd.com> wrote:
>>>> On 6/24/26 15:14, Kaitao Cheng wrote:
>>>>> 在 2026/6/22 16:42, David Laight 写道:  
>>>>>> On Mon, 22 Jun 2026 12:05:31 +0800
>>>>>> Kaitao Cheng <kaitao.cheng@linux.dev> wrote:
>>>>>>  
>>>>>>> From: Kaitao Cheng <chengkaitao@kylinos.cn>
>>>>>>>
>>>>>>> The list_for_each*_safe() helpers are used when the loop body may
>>>>>>> remove the current entry.  Their API exposes the temporary cursor at
>>>>>>> every call site, even though most users only need it for the iterator
>>>>>>> implementation and never reference it in the loop body.
>>>>>>>
>>>>>>> Add *_mutable() variants for list and hlist iteration.  The new helpers
>>>>>>> support both forms: callers may keep passing an explicit temporary cursor
>>>>>>> when they need to inspect or reset it, or omit it and let the helper use
>>>>>>> a unique internal cursor.  
>>>>>>
>>>>>> I'm not really sure 'mutable' means anything either.
>>>>>> It is possible to make it valid for the loop body (or even other threads)
>>>>>> to delete arbitrary list items - but that needs significant extra overheads.
>>>>>>
>>>>>> It might be worth doing something that doesn't need the extra variable,
>>>>>> but there is little point doing all the churn just to rename things.
>>>>>>  
>>>>>>>
>>>>>>> This makes call sites that only mutate the list through the current entry
>>>>>>> less noisy, while keeping the existing *_safe() helpers available for
>>>>>>> compatibility.
>>>>>>>
>>>>>>> Signed-off-by: Kaitao Cheng <chengkaitao@kylinos.cn>
>>>>>>> ---
>>>>>>>  include/linux/list.h | 269 +++++++++++++++++++++++++++++++++++++------
>>>>>>>  1 file changed, 231 insertions(+), 38 deletions(-)
>>>>>>>
>>>>>>> diff --git a/include/linux/list.h b/include/linux/list.h
>>>>>>> index 09d979976b3b..1081def7cea9 100644
>>>>>>> --- a/include/linux/list.h
>>>>>>> +++ b/include/linux/list.h
>>>>>>> @@ -7,6 +7,7 @@
>>>>>>>  #include <linux/stddef.h>
>>>>>>>  #include <linux/poison.h>
>>>>>>>  #include <linux/const.h>
>>>>>>> +#include <linux/args.h>
>>>>>>>  
>>>>>>>  #include <asm/barrier.h>
>>>>>>>  
>>>>>>> @@ -763,28 +764,72 @@ static inline void list_splice_tail_init(struct list_head *list,
>>>>>>>  #define list_for_each_prev(pos, head) \
>>>>>>>  	for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev)
>>>>>>>  
>>>>>>> -/**
>>>>>>> - * list_for_each_safe - iterate over a list safe against removal of list entry
>>>>>>> - * @pos:	the &struct list_head to use as a loop cursor.
>>>>>>> - * @n:		another &struct list_head to use as temporary storage
>>>>>>> - * @head:	the head for your list.
>>>>>>> +/*
>>>>>>> + * list_for_each_safe is an old interface, use list_for_each_mutable instead.
>>>>>>>   */
>>>>>>>  #define list_for_each_safe(pos, n, head) \
>>>>>>>  	for (pos = (head)->next, n = pos->next; \
>>>>>>>  	     !list_is_head(pos, (head)); \
>>>>>>>  	     pos = n, n = pos->next)
>>>>>>>  
>>>>>>> +#define __list_for_each_mutable_internal(pos, tmp, head)		\
>>>>>>> +	for (typeof(pos) tmp = (pos = (head)->next)->next;		\  
>>>>>>
>>>>>> Use auto
>>>>>>  
>>>>>>> +	     !list_is_head(pos, (head));				\
>>>>>>> +	     pos = tmp, tmp = pos->next)
>>>>>>> +
>>>>>>> +#define __list_for_each_mutable1(pos, head)				\
>>>>>>> +	__list_for_each_mutable_internal(pos, __UNIQUE_ID(next), head)
>>>>>>> +
>>>>>>> +#define __list_for_each_mutable2(pos, next, head)			\
>>>>>>> +	list_for_each_safe(pos, next, head)
>>>>>>> +
>>>>>>>  /**
>>>>>>> - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
>>>>>>> + * list_for_each_mutable - iterate over a list safe against entry removal
>>>>>>>   * @pos:	the &struct list_head to use as a loop cursor.
>>>>>>> - * @n:		another &struct list_head to use as temporary storage
>>>>>>> - * @head:	the head for your list.
>>>>>>> + * @...:	either (head) or (next, head)
>>>>>>> + *
>>>>>>> + * next:	another &struct list_head to use as optional temporary storage.
>>>>>>> + *		The temporary cursor is internal unless explicitly supplied by
>>>>>>> + *		the caller.
>>>>>>> + * head:	the head for your list.
>>>>>>> + */
>>>>>>> +#define list_for_each_mutable(pos, ...)					\
>>>>>>> +	CONCATENATE(__list_for_each_mutable, COUNT_ARGS(__VA_ARGS__))	\
>>>>>>> +		(pos, __VA_ARGS__)  
>>>>>>
>>>>>> The variable argument count logic really just slows down compilation.
>>>>>> Maybe there aren't enough copies of this code to make that significant.
>>>>>> But just because you can do it doesn't mean it is a gooD idea.
>>>>>> I'm also not sure it really adds anything to the readability.
>>>>>>
>>>>>> And, it you are going to make the middle argument optional there is
>>>>>> no need to change the macro name.  
>>>>>
>>>>> Christian König and Jani Nikula also disagree with the variadic-argument
>>>>> implementation approach. If we abandon that method, it means we will
>>>>> inevitably need to add some new macros. If mutable is not a good name,
>>>>> suggestions for better alternatives would be welcome; coming up with a
>>>>> suitable name is indeed rather tricky.  
>>>>
>>>> I don't think you need to add a new macro for the specific use case that people want to modify the next element of the iteration.
>>>>
>>>> If I remember your numbers correctly that is a really corner case and keeping using the existing *_safe() macros for that sounds perfectly fine to me.
>>>
>>> IIRC currently you have a choice of either:
>>> 	define               Item that can't be deleted
>>> 	list_for_each()	     The current item.
>>> 	list_for_each_safe() The next item.
>>> There is also likely to be code that updates the variables to allow
>>> for other scenarios.
>>>
>>> Note that if increase a reference count and release a lock then list_for_each()
>>> is likely safer than list_for_each_safe() :-)
>>>
>>> list.h has 9 variants of the 'safe' loop.
>>> The bloat of another 9 is getting excessive.
>>>
>>> It has to be said that this is one of my least favourite type of list...
>>
>> Hi Christian König, David Laight, Jani Nikula, David Hildenbrand,
>> Andy Shevchenko, Alexei Starovoitov
>>
>> For ease of discussion, I need to summarize the currently possible
>> approaches and briefly describe their respective pros and cons,
>> using the list_for_each_entry* interfaces as examples.
>>
>> 1. Add list_for_each_entry_mutable, while keeping list_for_each_entry
>> and list_for_each_entry_safe unchanged. list_for_each_entry_mutable
>> would be used specifically for safe deletion scenarios that do not
>> need to expose the temporary cursor externally. The code can refer to
>> the v1 version.
>>
>> Pros: Does not depend on immediate per-subsystem adaptation and can be
>>       merged directly.
>> Cons: Requires adding a whole set of mutable interfaces, which makes the
>>       code somewhat redundant.
> 
> Seems fine, and the original _safe naming is ambiguous anyway.
> 
>> 2. Directly optimize away the temporary cursor in list_for_each_entry_safe
>> and define it inside the loop instead, changing the interface from four
>> arguments to three.
>>
>> Pros: Does not add redundant interfaces.
>> Cons: (1) Users need to manually update special cases that use the
>>       traversal variable of list_for_each_entry_safe, the new
>>       list_for_each_entry_safe would no longer apply there and would
>>       need to be open-coded.
>>       (2) Because the macro arguments changes, all list_for_each_entry_safe
>>       callers would need to be modified and merged together, making it
>>       difficult to merge such a large amount of code at once.
> 
> This won't fly because there are literally thousands of
> list_for_each_entry_safe() users.
> 
>> 3. Use a variadic macro approach to optimize list_for_each_entry_safe,
>> so that it supports both three and four arguments.
>>
>> Pros: (1) Does not add redundant interfaces.
>>       (2) Does not depend on immediate per-subsystem adaptation and can
>>       be merged directly.
>> Cons: (1) Increases compile time.
>>       (2) Makes the interface harder for users to use.
> 
> Basically I'm against any variadic macro tricks where the optional
> argument is not the last argument. That's just way too surprising, and
> goes against common practice in just about all other languages.
> 
>> 4. Optimize list_for_each_entry by defining the temporary cursor internally,
>> making it compatible with the functionality of list_for_each_entry_safe.
>> The code can refer to the v2 version.
>>
>> Pros: (1) Does not add redundant interfaces.
>>       (2) The number of externally visible arguments of list_for_each_entry
>>       remains unchanged, still three.
>> Cons: (1) list_for_each_entry and list_for_each_entry_safe would be merged
>>       into one, and list_for_each_entry_safe would gradually be deprecated.
>>       (2) Users need to manually update special cases that use the traversal
>>       variable of list_for_each_entry, the new list_for_each_entry would no
>>       longer apply there and would need to be open-coded. There are 15 such
>>       cases in total.
> 
> This sounds good to me, though I take it there's some code size increase
> and/or performance penalty?
> 
> Maybe the 15 cases are questionable anyway?
> 
>> 5. Use a variadic macro approach to optimize list_for_each_entry, so that
>> it supports both three and four arguments.
>>
>> Pros: (1) Does not add redundant interfaces.
>>       (2) Does not depend on immediate per-subsystem adaptation and can be
>>       merged directly.
>> Cons: (1) Increases compile time.
>>       (2) list_for_each_entry and list_for_each_entry_safe would be merged
>>       into one, and list_for_each_entry_safe would gradually be deprecated.
> 
> Please don't do the macro tricks.
> 
>> 6. Make no changes, keep the current logic unchanged, and close the current
>> email discussion.
> 
> I like hiding the temporary stuff when possible.
> 
> BR,
> Jani.

Hi all,
If there are no objections, I will make the changes using the first approach.


Hi David Laight,
You previously expressed a different opinion. Do you have any further comments
on the current proposed approach?

-- 
Thanks
Kaitao Cheng


^ permalink raw reply

* Re: [PATCH net 1/2] vsock/virtio: collapse receive queue under memory pressure
From: Stefano Garzarella @ 2026-07-01 10:13 UTC (permalink / raw)
  To: Paolo Abeni
  Cc: netdev, Jason Wang, Jakub Kicinski, Michael S. Tsirkin, kvm,
	virtualization, Xuan Zhuo, Eric Dumazet, Simon Horman,
	linux-kernel, Stefan Hajnoczi, David S. Miller,
	Eugenio Pérez, stable, Brien Oberstein
In-Reply-To: <6a6be4b0-e02d-46ca-b8bf-c27bd681d253@redhat.com>

On Tue, Jun 30, 2026 at 11:53:04AM +0200, Paolo Abeni wrote:
>On 6/26/26 3:48 PM, Stefano Garzarella wrote:
>> From: Stefano Garzarella <sgarzare@redhat.com>
>>
>> When many small packets accumulate in the receive queue, the skb overhead
>> can exceed buf_alloc even while the payload is within bounds. This causes
>> virtio_transport_inc_rx_pkt() to reject packets, leading to connection
>> resets during large transfers under backpressure.
>>
>> The issue was reported by Brien, who has a reproducer, but it is also
>> easily reproducible with iperf-vsock [1] using a small packet size:
>>
>>   iperf3 --vsock -c $CID -l 129
>>
>> which fails immediately without this patch but with commit 059b7dbd20a6
>> ("vsock/virtio: fix potential unbounded skb queue").
>>
>> Inspired by TCP's tcp_collapse() which solves a similar problem, add
>> virtio_transport_collapse_rx_queue() that walks the receive queue and
>> re-copies data into compact linear skbs to reduce the overhead.
>>
>> The collapse is triggered from virtio_transport_recv_enqueue() when
>> virtio_transport_inc_rx_pkt() fails. A pre-scan counts the eligible bytes
>> to size each allocation precisely, avoiding waste for isolated small
>> packets. Partially consumed skbs are kept as-is to preserve
>> buf_used/fwd_cnt accounting, EOM-marked skbs to maintain SEQPACKET
>> message boundaries, and skbs already larger than the collapse target
>> because they already have a good data-to-overhead ratio.
>>
>> [1] https://github.com/stefano-garzarella/iperf-vsock
>>
>> Fixes: 059b7dbd20a6 ("vsock/virtio: fix potential unbounded skb queue")
>> Cc: stable@vger.kernel.org
>> Reported-by: Brien Oberstein <brienpub@gmail.com>
>> Closes: https://lore.kernel.org/netdev/618701dd023e$063de350$12b9a9f0$@gmail.com/
>> Tested-by: Brien Oberstein <brienpub@gmail.com>
>> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
>> ---
>>  net/vmw_vsock/virtio_transport_common.c | 148 +++++++++++++++++++++++-
>>  1 file changed, 146 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
>> index 09475007165b..304ea424995d 100644
>> --- a/net/vmw_vsock/virtio_transport_common.c
>> +++ b/net/vmw_vsock/virtio_transport_common.c
>> @@ -420,6 +420,137 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
>>  	return ret;
>>  }
>>
>> +static bool virtio_transport_can_collapse(struct sk_buff *skb,
>> +					  unsigned int size)
>
>Why passing a `size` argument here? AFAICS the actual argument is always
>a constant and IMHO rightfully so.

This comes from a previous implementation where this was not constant.
With the current code, I agree that a macro should be better.

I'll fix it.

>
>> +{
>> +	/* skbs that are partially consumed, mark a SEQPACKET message boundary,
>> +	 * or are already large enough should not be collapsed: they either
>> +	 * need special accounting, carry protocol state, or already have a
>> +	 * good data-to-overhead ratio.
>> +	 */
>> +	if (VIRTIO_VSOCK_SKB_CB(skb)->offset)
>> +		return false;
>> +	if (le32_to_cpu(virtio_vsock_hdr(skb)->flags) & VIRTIO_VSOCK_SEQ_EOM)
>> +		return false;
>> +	if (skb->len >= size)
>> +		return false;
>> +	return true;
>> +}
>> +
>> +/* Iterate through the packets in the queue starting from the current skb to
>> + * count the number of bytes we can collapse.
>> + */
>> +static unsigned int
>> +virtio_transport_collapse_size(struct sk_buff *skb,
>> +			       struct sk_buff_head *queue,
>> +			       unsigned int max_size)
>> +{
>> +	unsigned int target = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
>> +
>> +	while ((skb = skb_peek_next(skb, queue)) &&
>> +	       virtio_transport_can_collapse(skb, max_size)) {
>> +		unsigned int len = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
>> +
>> +		if (len > max_size - target)
>> +			return target;
>> +
>> +		target += len;
>> +	}
>> +
>> +	return target;
>> +}
>> +
>> +/* Called under lock_sock when skb overhead exceeds the budget. */
>> +static void virtio_transport_collapse_rx_queue(struct virtio_vsock_sock *vvs)
>> +{
>> +	/* Use the same linear allocation threshold as virtio_vsock_alloc_skb()
>> +	 * to avoid adding pressure on the page allocator.
>> +	 */
>> +	unsigned int collapse_max = SKB_MAX_ORDER(VIRTIO_VSOCK_SKB_HEADROOM,
>> +						  PAGE_ALLOC_COSTLY_ORDER);
>> +	struct sk_buff *skb, *next_skb, *new_skb = NULL;
>> +	struct sk_buff_head new_queue;
>> +
>> +	__skb_queue_head_init(&new_queue);
>> +
>> +	skb_queue_walk_safe(&vvs->rx_queue, skb, next_skb) {
>
>If the queue is relevantly big, walking all of it may take a significant
>amount of time/cache misses and causes traffic burstines. I think you
>could add an additional stop condition, i.e. when the current queue size
>is below a reasonable threshold (allowing the current packet to be
>inserted plus some more slack).

Makes sense, any suggestion on the threshold?

I was thinking something like this: merge until we have space for at 
least 2 skbs (because for now we estimate the overhead based on the 
number of skbs, but in the future I'd like to support truesize), but 
still trying to fill collapse_max as much as possible.

Does that make sense, or should we be more aggressive?

>
>/P
>
>> +		struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
>> +		u32 src_off = VIRTIO_VSOCK_SKB_CB(skb)->offset;
>> +		u32 src_len = skb->len - src_off;
>> +		bool keep = false;
>> +
>> +		if (!virtio_transport_can_collapse(skb, collapse_max)) {
>
>Minor nit, possibly something alike the following lead to more
>compact/more readable code:
>
>
>		keep = !virtio_transport_can_collapse(skb, collapse_max);
>		if (keep) {
>

Yeah, so I can remove the initialization to false. I'll change it.

>> +			/* Finalize pending collapsed skb to preserve packet
>> +			 * ordering.
>> +			 */
>> +			if (new_skb) {
>> +				__skb_queue_tail(&new_queue, new_skb);
>> +				new_skb = NULL;
>> +			}
>> +			keep = true;
>> +			goto next;
>> +		}
>> +
>> +		/* Finalize if this packet won't fit in the remaining tailroom,
>> +		 * so we can allocate a right-sized new_skb.
>> +		 */
>> +		if (new_skb && src_len > skb_tailroom(new_skb)) {
>> +			__skb_queue_tail(&new_queue, new_skb);
>> +			new_skb = NULL;
>
>Possibly introduce an helper for the above 2 statements?

Do you mean something like this?

static void virtio_transport_queue_skb(struct sk_buff_head *queue,
				       struct sk_buff **skb)
{
	__skb_queue_tail(queue, *skb);
	*skb = NULL;
}

Not sure, just for 2 places, but if you prefer it, I can change.

Thanks,
Stefano


^ permalink raw reply

* [linux-next:master] BUILD REGRESSION be5c93fa674f0fc3c8f359c2143abce6bbb422e6
From: kernel test robot @ 2026-07-01 10:12 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Linux Memory Management List, apparmor, linux-arm-kernel,
	linux-input, linux-remoteproc, linux-rockchip, linux-usb,
	virtualization, Mark Brown

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
branch HEAD: be5c93fa674f0fc3c8f359c2143abce6bbb422e6  Add linux-next specific files for 20260630

Error/Warning (recently discovered and may have been fixed):

    https://lore.kernel.org/oe-kbuild-all/202607010945.6lDjBFTU-lkp@intel.com
    https://lore.kernel.org/oe-kbuild-all/202607011210.PI7XDDb1-lkp@intel.com

    drivers/remoteproc/remoteproc_internal.h:131:5: error: incompatible integer to pointer conversion assigning to 'void *' from 'int' [-Wint-conversion]
    drivers/remoteproc/remoteproc_internal.h:131:7: error: call to undeclared function 'ioremap_prot'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    drivers/remoteproc/remoteproc_internal.h:146:2: error: call to undeclared function 'iounmap'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    mm/hugetlb.c:3095:4: warning: array subscript -1 is below array bounds of 'struct list_head[1]' [-Warray-bounds]

Unverified Error/Warning (likely false positive, kindly check if interested):

    https://lore.kernel.org/oe-kbuild/202607010826.2wLg1q08-lkp@intel.com
    https://lore.kernel.org/oe-kbuild/202607011451.icwPyCIk-lkp@intel.com

    drivers/hid/hid-asus.c:620 asus_kbd_backlight_work() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/i2c/busses/i2c-rk3x.c:1131 rk3x_i2c_xfer_common() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/rpmsg/rpmsg_char.c:236 rpmsg_eptdev_read_iter() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/usb/host/ehci-hub.c:1080 ehci_hub_control() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/usb/host/ehci-hub.c:691 ehci_hub_status_data() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/usb/host/ehci-sched.c:1290 itd_urb_transaction() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/usb/host/ehci-sched.c:2093 sitd_urb_transaction() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/virtio/virtio_input.c:333 virtinput_probe() error: calling 'spin_unlock_irqrestore()' with bogus flags
    drivers/virtio/virtio_input.c:56 virtinput_recv_events() error: calling 'spin_unlock_irqrestore()' with bogus flags
    security/apparmor/apparmorfs.c:590 policy_update() warn: passing zero to 'PTR_ERR'

Error/Warning ids grouped by kconfigs:

recent_errors
|-- s390-randconfig-002-20260701
|   |-- drivers-remoteproc-remoteproc_internal.h:error:call-to-undeclared-function-ioremap_prot-ISO-C99-and-later-do-not-support-implicit-function-declarations
|   |-- drivers-remoteproc-remoteproc_internal.h:error:call-to-undeclared-function-iounmap-ISO-C99-and-later-do-not-support-implicit-function-declarations
|   `-- drivers-remoteproc-remoteproc_internal.h:error:incompatible-integer-to-pointer-conversion-assigning-to-void-from-int
|-- sparc-randconfig-r131-20260701
|   `-- mm-hugetlb.c:warning:array-subscript-is-below-array-bounds-of-struct-list_head
`-- x86_64-randconfig-161-20260701
    |-- drivers-hid-hid-asus.c-asus_kbd_backlight_work()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-i2c-busses-i2c-rk3x.c-rk3x_i2c_xfer_common()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-rpmsg-rpmsg_char.c-rpmsg_eptdev_read_iter()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-usb-host-ehci-hub.c-ehci_hub_control()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-usb-host-ehci-hub.c-ehci_hub_status_data()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-usb-host-ehci-sched.c-itd_urb_transaction()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-usb-host-ehci-sched.c-sitd_urb_transaction()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-virtio-virtio_input.c-virtinput_probe()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    |-- drivers-virtio-virtio_input.c-virtinput_recv_events()-error:calling-spin_unlock_irqrestore()-with-bogus-flags
    `-- security-apparmor-apparmorfs.c-policy_update()-warn:passing-zero-to-PTR_ERR

elapsed time: 823m

configs tested: 227
configs skipped: 6

tested configs:
alpha                             allnoconfig    gcc-16.1.0
alpha                            allyesconfig    gcc-16.1.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    clang-23
arc                              allmodconfig    gcc-16.1.0
arc                               allnoconfig    gcc-16.1.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-16.1.0
arc                                 defconfig    gcc-16.1.0
arc                   randconfig-001-20260701    gcc-12.5.0
arc                   randconfig-002-20260701    gcc-12.5.0
arm                               allnoconfig    clang-17
arm                               allnoconfig    gcc-16.1.0
arm                              allyesconfig    clang-23
arm                              allyesconfig    gcc-16.1.0
arm                                 defconfig    clang-23
arm                                 defconfig    gcc-16.1.0
arm                   randconfig-001-20260701    gcc-12.5.0
arm                   randconfig-002-20260701    gcc-12.5.0
arm                   randconfig-003-20260701    gcc-12.5.0
arm                   randconfig-004-20260701    gcc-12.5.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-16.1.0
arm64                               defconfig    gcc-16.1.0
arm64                 randconfig-001-20260701    gcc-12.5.0
arm64                 randconfig-001-20260701    gcc-16.1.0
arm64                 randconfig-002-20260701    clang-17
arm64                 randconfig-002-20260701    gcc-12.5.0
arm64                 randconfig-003-20260701    gcc-12.5.0
arm64                 randconfig-004-20260701    clang-17
arm64                 randconfig-004-20260701    gcc-12.5.0
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-16.1.0
csky                                defconfig    gcc-16.1.0
csky                  randconfig-001-20260701    gcc-10.5.0
csky                  randconfig-001-20260701    gcc-12.5.0
csky                  randconfig-002-20260701    gcc-12.5.0
hexagon                          allmodconfig    clang-23
hexagon                          allmodconfig    gcc-16.1.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-16.1.0
hexagon                             defconfig    clang-23
hexagon                             defconfig    gcc-16.1.0
hexagon                        randconfig-001    gcc-11.5.0
hexagon               randconfig-001-20260701    clang-23
hexagon               randconfig-001-20260701    gcc-11.5.0
hexagon                        randconfig-002    gcc-11.5.0
hexagon               randconfig-002-20260701    clang-17
hexagon               randconfig-002-20260701    gcc-11.5.0
i386                             allmodconfig    clang-22
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-16.1.0
i386                             allyesconfig    clang-22
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260701    clang-22
i386        buildonly-randconfig-002-20260701    clang-22
i386        buildonly-randconfig-003-20260701    clang-22
i386        buildonly-randconfig-004-20260701    clang-22
i386        buildonly-randconfig-005-20260701    clang-22
i386        buildonly-randconfig-006-20260701    clang-22
i386                                defconfig    clang-22
i386                                defconfig    gcc-16.1.0
i386                  randconfig-001-20260701    clang-22
i386                  randconfig-002-20260701    clang-22
i386                  randconfig-003-20260701    clang-22
i386                  randconfig-004-20260701    clang-22
i386                  randconfig-005-20260701    clang-22
i386                  randconfig-006-20260701    clang-22
i386                  randconfig-007-20260701    clang-22
i386                  randconfig-011-20260701    gcc-14
i386                  randconfig-012-20260701    gcc-14
i386                  randconfig-013-20260701    gcc-14
i386                  randconfig-014-20260701    gcc-14
i386                  randconfig-015-20260701    gcc-14
i386                  randconfig-016-20260701    gcc-14
i386                  randconfig-017-20260701    gcc-14
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-20
loongarch                         allnoconfig    gcc-16.1.0
loongarch                           defconfig    clang-23
loongarch                      randconfig-001    gcc-11.5.0
loongarch             randconfig-001-20260701    clang-23
loongarch             randconfig-001-20260701    gcc-11.5.0
loongarch                      randconfig-002    gcc-11.5.0
loongarch             randconfig-002-20260701    clang-19
loongarch             randconfig-002-20260701    gcc-11.5.0
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-16.1.0
m68k                             allyesconfig    clang-23
m68k                             allyesconfig    gcc-16.1.0
m68k                                defconfig    clang-23
m68k                                defconfig    gcc-16.1.0
microblaze                        allnoconfig    gcc-16.1.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    clang-23
microblaze                          defconfig    gcc-16.1.0
mips                             allmodconfig    gcc-16.1.0
mips                              allnoconfig    gcc-16.1.0
mips                             allyesconfig    gcc-16.1.0
mips                            gpr_defconfig    clang-23
nios2                            allmodconfig    clang-20
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-23
nios2                               defconfig    gcc-11.5.0
nios2                          randconfig-001    gcc-11.5.0
nios2                 randconfig-001-20260701    gcc-11.5.0
nios2                          randconfig-002    gcc-11.5.0
nios2                 randconfig-002-20260701    gcc-11.5.0
nios2                 randconfig-002-20260701    gcc-8.5.0
openrisc                         allmodconfig    clang-20
openrisc                         allmodconfig    gcc-16.1.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-16.1.0
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-16.1.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-16.1.0
parisc                           allyesconfig    clang-17
parisc                           allyesconfig    gcc-16.1.0
parisc                              defconfig    gcc-16.1.0
parisc                randconfig-001-20260701    clang-17
parisc                randconfig-001-20260701    gcc-13.4.0
parisc                randconfig-002-20260701    clang-17
parisc                randconfig-002-20260701    gcc-15.2.0
parisc64                            defconfig    clang-23
parisc64                            defconfig    gcc-16.1.0
powerpc                          allmodconfig    gcc-16.1.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-16.1.0
powerpc               randconfig-001-20260701    clang-17
powerpc               randconfig-001-20260701    gcc-8.5.0
powerpc               randconfig-002-20260701    clang-17
powerpc               randconfig-002-20260701    clang-23
powerpc64             randconfig-001-20260701    clang-17
powerpc64             randconfig-002-20260701    clang-17
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-16.1.0
riscv                            allyesconfig    clang-23
riscv                               defconfig    gcc-16.1.0
riscv                 randconfig-001-20260701    clang-23
riscv                 randconfig-002-20260701    clang-23
s390                             allmodconfig    clang-17
s390                             allmodconfig    clang-23
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-16.1.0
s390                                defconfig    gcc-16.1.0
s390                  randconfig-001-20260701    clang-23
s390                  randconfig-002-20260701    clang-23
sh                               allmodconfig    gcc-16.1.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-16.1.0
sh                               allyesconfig    clang-17
sh                               allyesconfig    gcc-16.1.0
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260701    clang-23
sh                    randconfig-002-20260701    clang-23
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-16.1.0
sparc                               defconfig    gcc-16.1.0
sparc                 randconfig-001-20260701    gcc-13.4.0
sparc                 randconfig-002-20260701    gcc-13.4.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260701    gcc-13.4.0
sparc64               randconfig-002-20260701    gcc-13.4.0
um                               allmodconfig    clang-17
um                                allnoconfig    clang-17
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-16.1.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260701    gcc-13.4.0
um                    randconfig-002-20260701    gcc-13.4.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-22
x86_64                            allnoconfig    clang-22
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-22
x86_64      buildonly-randconfig-001-20260701    clang-22
x86_64      buildonly-randconfig-001-20260701    gcc-14
x86_64      buildonly-randconfig-002-20260701    clang-22
x86_64      buildonly-randconfig-003-20260701    clang-22
x86_64      buildonly-randconfig-004-20260701    clang-22
x86_64      buildonly-randconfig-004-20260701    gcc-14
x86_64      buildonly-randconfig-005-20260701    clang-22
x86_64      buildonly-randconfig-006-20260701    clang-22
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-22
x86_64                randconfig-001-20260701    clang-22
x86_64                randconfig-001-20260701    gcc-14
x86_64                randconfig-002-20260701    gcc-14
x86_64                randconfig-003-20260701    gcc-14
x86_64                randconfig-004-20260701    clang-22
x86_64                randconfig-004-20260701    gcc-14
x86_64                randconfig-005-20260701    gcc-14
x86_64                randconfig-006-20260701    gcc-14
x86_64                randconfig-011-20260701    gcc-14
x86_64                randconfig-012-20260701    gcc-14
x86_64                randconfig-013-20260701    gcc-14
x86_64                randconfig-014-20260701    gcc-14
x86_64                randconfig-015-20260701    gcc-14
x86_64                randconfig-016-20260701    gcc-14
x86_64                randconfig-071-20260701    gcc-14
x86_64                randconfig-072-20260701    gcc-14
x86_64                randconfig-073-20260701    gcc-14
x86_64                randconfig-074-20260701    gcc-14
x86_64                randconfig-075-20260701    gcc-14
x86_64                randconfig-076-20260701    gcc-14
x86_64                               rhel-9.4    clang-22
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-22
x86_64                    rhel-9.4-kselftests    clang-22
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-22
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-16.1.0
xtensa                           allyesconfig    clang-20
xtensa                           allyesconfig    gcc-16.1.0
xtensa                randconfig-001-20260701    gcc-13.4.0
xtensa                randconfig-002-20260701    gcc-13.4.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH] drm/virtio: defer hotplug event from dequeue worker to avoid deadlock
From: Ryosuke Yasuoka @ 2026-07-01  9:23 UTC (permalink / raw)
  To: Dmitry Osipenko, David Airlie, Gerd Hoffmann, Gurchetan Singh,
	Chia-I Wu, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Simona Vetter, Dmitry Baryshkov, Javier Martinez Canillas
  Cc: dri-devel, virtualization, linux-kernel
In-Reply-To: <5aa634c1-7530-4b1f-931a-a5a5ac6c908a@collabora.com>



On 30/06/2026 16:46, Dmitry Osipenko wrote:
> Hi,
> 
> On 6/30/26 12:16, Ryosuke Yasuoka wrote:
>> A probe-time deadlock can occur between the dequeue worker and
>> drm_client_register(). During probe, drm_client_register() holds
>> clientlist_mutex and calls the fbdev hotplug callback, which triggers an
>> atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
>> waiting for virtqueue space. The dequeue worker that would free that
>> space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
>> drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
>> to acquire the same clientlist_mutex. Since wake_up() is only called
>> after the resp_cb loop, the probe thread is never woken and both threads
>> deadlock.
>> 
>> Fix this by deferring the hotplug notification from
>> virtio_gpu_cmd_get_display_info_cb() to a separate work item. The
>> display data (outputs[i].info) is still updated synchronously in the
>> callback, and the deferred work only triggers a re-probe notification to
>> DRM clients.
>> 
>> Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
>> Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
>> Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
>> Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
>> ---
>>  drivers/gpu/drm/virtio/virtgpu_drv.h |  3 +++
>>  drivers/gpu/drm/virtio/virtgpu_kms.c |  3 +++
>>  drivers/gpu/drm/virtio/virtgpu_vq.c  | 12 ++++++++++--
>>  3 files changed, 16 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> index 7449907754a4..27ffa4697ae9 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
>> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> @@ -264,6 +264,8 @@ struct virtio_gpu_device {
>>  
>>  	struct work_struct config_changed_work;
>>  
>> +	struct work_struct hotplug_work;
>> +
>>  	struct work_struct obj_free_work;
>>  	spinlock_t obj_free_lock;
>>  	struct list_head obj_free_list;
>> @@ -350,6 +352,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
>>  					uint32_t x, uint32_t y,
>>  					struct virtio_gpu_object_array *objs,
>>  					struct virtio_gpu_fence *fence);
>> +void virtio_gpu_hotplug_work_func(struct work_struct *work);
>>  void virtio_gpu_panic_cmd_resource_flush(struct virtio_gpu_device *vgdev,
>>  					 uint32_t resource_id,
>>  					 uint32_t x, uint32_t y,
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
>> index cfde9f573df6..cfb532ba43a4 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_kms.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
>> @@ -154,6 +154,8 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
>>  	INIT_WORK(&vgdev->config_changed_work,
>>  		  virtio_gpu_config_changed_work_func);
>>  
>> +	INIT_WORK(&vgdev->hotplug_work, virtio_gpu_hotplug_work_func);
>> +
>>  	INIT_WORK(&vgdev->obj_free_work,
>>  		  virtio_gpu_array_put_free_work);
>>  	INIT_LIST_HEAD(&vgdev->obj_free_list);
>> @@ -293,6 +295,7 @@ void virtio_gpu_deinit(struct drm_device *dev)
>>  	flush_work(&vgdev->obj_free_work);
>>  	flush_work(&vgdev->ctrlq.dequeue_work);
>>  	flush_work(&vgdev->cursorq.dequeue_work);
>> +	flush_work(&vgdev->hotplug_work);
>>  	flush_work(&vgdev->config_changed_work);
>>  	virtio_reset_device(vgdev->vdev);
>>  	vgdev->vdev->config->del_vqs(vgdev->vdev);
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
>> index 67865810a2e7..084d98f5dc7b 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_vq.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
>> @@ -816,6 +816,15 @@ virtio_gpu_cmd_resource_detach_backing(struct virtio_gpu_device *vgdev,
>>  	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, fence);
>>  }
>>  
>> +void virtio_gpu_hotplug_work_func(struct work_struct *work)
>> +{
>> +	struct virtio_gpu_device *vgdev =
>> +		container_of(work, struct virtio_gpu_device, hotplug_work);
>> +
>> +	if (!drm_helper_hpd_irq_event(vgdev->ddev))
>> +		drm_kms_helper_hotplug_event(vgdev->ddev);
>> +}
>> +
>>  static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
>>  					       struct virtio_gpu_vbuffer *vbuf)
>>  {
>> @@ -841,8 +850,7 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
>>  	spin_unlock(&vgdev->display_info_lock);
>>  	wake_up(&vgdev->resp_wq);
>>  
>> -	if (!drm_helper_hpd_irq_event(vgdev->ddev))
>> -		drm_kms_helper_hotplug_event(vgdev->ddev);
>> +	schedule_work(&vgdev->hotplug_work);
>>  }
>>  
>>  static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
> 

Hi,
Thank you for your review.

> Could you please move drm_kms_helper_hotplug_event() to virtio_gpu_init(), placing it after wait_event_timeout(display_info_pending)? This will avoid additional work_struct that otherwise needs to be cancelled in virtio_gpu_init() on the timeout.

IIUC, moving the drm_kms_helper_hotplug_event() and _hpd_irq_event()
into virtio_gpu_init() after wait_event_timeout() would not prevent the
issue.

Looking at the syzbot call traces[1][2], the deadlock occurs during
drm_client_setup(), which runs after virtio_gpu_init() has already
returned. The display_info_cb that triggers the deadlock is called from
the dequeue worker while drm_client_register() holds clientlist_mutex.

Thread A:
virtio_gpu_probe()
 -> virtio_gpu_init()   // sends GET_DISPLAY_INFO and waits up to 5s
 -> drm_dev_register()
 -> drm_client_setup()   // deadlock happens HERE
     -> drm_client_register()   // holds clientlist_mutex
     ...
     -> virtio_gpu_queue_fenced_ctrl_buffer()
         -> wait_event() // waits for free space

Thread B:
virtio_gpu_dequeue_ctrl_func()
 -> reclaim_vbufs()   // make free space
 -> resp_cb()
     -> virtio_gpu_cmd_get_display_info_cb
         -> drm_helper_hpd_irq_event()
         -> drm_kms_helper_hotplug_event()
             -> drm_client_dev_hotplug() // need to lock clientlist_mutex
 -> wake_up()   // never reached

IIUC the hotplug notification in display_info_cb is needed because it
notifies DRM after updating by the callback with fresh data from the host.

This work_struct ensures display_info_cb never blocks on
clientlist_mutex in the dequeue worker, while preserving the hotplug
notification with fresh data.

[1] https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
[2] https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e

Best regards,
Ryosuke


^ permalink raw reply

* Re: [PATCH 00/32] x86/msr: Drop 32-bit MSR interfaces
From: Jürgen Groß @ 2026-07-01  8:33 UTC (permalink / raw)
  To: Sean Christopherson, Ingo Molnar
  Cc: Arnd Bergmann, linux-kernel, linux-pm, linux-edac@vger.kernel.org,
	x86, linux-acpi, kvm, linux-coco, linux-pci, virtualization,
	linux-ide, dri-devel, linux-fbdev, linux-crypto,
	open list:GPIO SUBSYSTEM, linux-hyperv, linux-hwmon,
	linux-perf-users, linux-mtd, platform-driver-x86,
	Rafael J . Wysocki, Daniel Lezcano, Zhang Rui,
	lukasz.luba@arm.com, Jason Baron, Borislav Petkov, Tony Luck,
	Yazen Ghannam, Len Brown, Pavel Machek, Thomas Gleixner,
	Ingo Molnar, Dave Hansen, H. Peter Anvin, Paolo Bonzini,
	Kirill A. Shutemov, Rick Edgecombe, Pu Wen, Bjorn Helgaas,
	Ajay Kaher, Alexey Makhalov, Broadcom internal kernel review list,
	Viresh Kumar, Reinette Chatre, Dave Martin, James Morse,
	Babu Moger, Tony W Wang-oc, Damien Le Moal, Niklas Cassel,
	Dave Airlie, Helge Deller, linux-geode, Olivia Mackall,
	Herbert Xu, Linus Walleij, Bartosz Golaszewski,
	Greg Kroah-Hartman, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
	Dexuan Cui, Long Li, Guenter Roeck, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, Josh Poimboeuf, Pawan Gupta, Vitaly Kuznetsov,
	Andy Lutomirski, Boris Ostrovsky, Huang Rui, Mario Limonciello,
	Perry Yuan, K Prateek Nayak, srinivas.pandruvada@linux.intel.com,
	Artem Bityutskiy, Artem Bityutskiy, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Ashok Raj, Hans de Goede,
	Ilpo Järvinen, Rajneesh Bhardwaj, David E Box, xen-devel
In-Reply-To: <akQR9YMtMHReJTfB@google.com>


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

On 30.06.26 20:59, Sean Christopherson wrote:
> On Mon, Jun 29, 2026, Ingo Molnar wrote:
>> * Arnd Bergmann <arnd@arndb.de> wrote:
>>
>>>>>> Note that most patches of this series are independent from each other.
>>>>>> Only the patches removing a specific interface (patches 7, 15, 26 and
>>>>>> 30) and the last two patches of the series depend on all previous
>>>>>> patches.
>>>>>
>>>>> It looks like you are touching most files twice or more here, to
>>>>> first convert from rdmsr to rdmsrq and then to change the
>>>>> two-argument rdmsrq() macro to a single-argument inline. If you
>>>>> introduce the inline version of rdmsrq() first, you should be
>>>>> able to skip the second step (patch 31) as they could be able
>>>>> to coexist.
>>>>
>>>> I've discussed how to structure the series with Ingo Molnar before [1]. The
>>>> current approach was his preference.
>>>
>>> Ok.
>>
>> Note that the individual patches are IMO significantly easier to review
>> through the actual 32-bit => 64-bit variable assignment changes done
>> in isolation (which sometimes include minor cleanups), while
>> the Coccinelle semantic patch:
>>
>>     { a(b,c) => c = a(b) }
>>
>> which changes both the function signature and the order of terms as
>> well, is just a single add-on treewide patch.
> 
> Is the plan for subsystem maintainers to pick up the relevant patches, and then
> do the treewide change one release cycle later?

Yes, please.


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: [PATCH v5] virtio_net: disable cb when NAPI is busy-polled
From: patchwork-bot+netdevbpf @ 2026-07-01  0:20 UTC (permalink / raw)
  To: Longjun Tang
  Cc: kuba, horms, mst, jasowang, edumazet, virtualization, netdev,
	tanglongjun
In-Reply-To: <20260629024230.37325-1-lange_tang@163.com>

Hello:

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

On Mon, 29 Jun 2026 10:42:30 +0800 you wrote:
> From: Longjun Tang <tanglongjun@kylinos.cn>
> 
> When busy-poll is active, napi_schedule_prep() returns false in
> virtqueue_napi_schedule(), so virtqueue_disable_cb() is skipped.
> The device may keep firing irqs until reaches virtqueue_napi_complete().
> Under load (received == budget), it will lead to a large number
> of spurious interrupts.
> 
> [...]

Here is the summary with links:
  - [v5] virtio_net: disable cb when NAPI is busy-polled
    https://git.kernel.org/netdev/net/c/1eb8fc67ca41

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



^ permalink raw reply

* [PATCH v2 14/18] fuse: convert iomap ops to ->iomap_next()
From: Joanne Koong @ 2026-07-01  0:09 UTC (permalink / raw)
  To: brauner, hch
  Cc: djwong, willy, hsiangkao, linux-fsdevel, linux-xfs,
	Miklos Szeredi, German Maglione, Vivek Goyal, Stefan Hajnoczi,
	Eugenio Pérez, open list:FUSE FILESYSTEM [CORE], open list,
	open list:VIRTIO FILE SYSTEM
In-Reply-To: <20260701000949.1666714-1-joannelkoong@gmail.com>

Convert fuse iomap_ops to the new ->iomap_next() callback. This uses the
iomap_process() helper, which finishes the previous mapping if needed
and produces the next one. No functional changes are intended.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 fs/fuse/dax.c       | 10 ++++++++--
 fs/fuse/file.c      |  8 +++++++-
 fs/fuse/virtio_fs.c |  2 +-
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c
index 8b53625ac7ab..e8d8c9f5d728 100644
--- a/fs/fuse/dax.c
+++ b/fs/fuse/dax.c
@@ -653,9 +653,15 @@ static int fuse_iomap_end(struct inode *inode, loff_t pos, loff_t length,
 	return 0;
 }
 
+static int fuse_iomap_next(const struct iomap_iter *iter, struct iomap *iomap,
+			   struct iomap *srcmap)
+{
+	return iomap_process(iter, iomap, srcmap, fuse_iomap_begin,
+			     fuse_iomap_end);
+}
+
 static const struct iomap_ops fuse_iomap_ops = {
-	.iomap_begin = fuse_iomap_begin,
-	.iomap_end = fuse_iomap_end,
+	.iomap_next = fuse_iomap_next,
 };
 
 static void fuse_wait_dax_page(struct inode *inode)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e052a0d44dee..5c0d400629cc 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -890,8 +890,14 @@ static int fuse_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
 	return 0;
 }
 
+static int fuse_iomap_next(const struct iomap_iter *iter, struct iomap *iomap,
+			   struct iomap *srcmap)
+{
+	return iomap_process(iter, iomap, srcmap, fuse_iomap_begin, NULL);
+}
+
 static const struct iomap_ops fuse_iomap_ops = {
-	.iomap_begin	= fuse_iomap_begin,
+	.iomap_next	= fuse_iomap_next,
 };
 
 struct fuse_fill_read_data {
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index df25d4faca41..84e699f88574 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -1024,7 +1024,7 @@ static void virtio_fs_cleanup_vqs(struct virtio_device *vdev)
 }
 
 /* Map a window offset to a page frame number.  The window offset will have
- * been produced by .iomap_begin(), which maps a file offset to a window
+ * been produced by .iomap_next(), which maps a file offset to a window
  * offset.
  */
 static long virtio_fs_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH net-next v4] vsock/virtio: rewrite MSG_ZEROCOPY flag handling
From: patchwork-bot+netdevbpf @ 2026-06-30 20:32 UTC (permalink / raw)
  To: Arseniy Krasnov
  Cc: stefanha, sgarzare, davem, edumazet, kuba, pabeni, mst, jasowang,
	bobbyeshleman, xuanzhuo, eperezma, horms, kvm, virtualization,
	netdev, linux-kernel, oxffffaa, rulkc
In-Reply-To: <20260628182052.951760-1-avkrasnov@rulkc.org>

Hello:

This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Sun, 28 Jun 2026 21:20:52 +0300 you wrote:
> Logically it was based on TCP implementation, so to make further support
> easier, rewrite it in the TCP way (like in 'tcp_sendmsg_locked()'). By
> this way, patch also adds handling case when 'msg_ubuf' is already set.
> 
> Signed-off-by: Arseniy Krasnov <avkrasnov@rulkc.org>
> ---
>  Changelog v1->v2:
>  * Rebase on last 'net-next'. Don't need 'skb_zcopy_set()' now - it was
>    already added.
>  Changelog v2->v3:
>  * Update commit message.
>  * Remove one empty line.
>  Changelog v3->v4:
>  * Update commit message.
> 
> [...]

Here is the summary with links:
  - [net-next,v4] vsock/virtio: rewrite MSG_ZEROCOPY flag handling
    https://git.kernel.org/netdev/net-next/c/f456c1922c49

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



^ permalink raw reply

* Re: [PATCH V2] MAINTAINERS: Update Jason Wang's email address
From: patchwork-bot+netdevbpf @ 2026-06-30 20:32 UTC (permalink / raw)
  To: Jason Wang; +Cc: mst, virtualization, netdev, eperezma, kvm, linux-kernel
In-Reply-To: <20260629014525.16297-1-jasowang@redhat.com>

Hello:

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

On Mon, 29 Jun 2026 09:45:24 +0800 you wrote:
> I will use jasowangio@gmail.com for future review and discussion.
> 
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> Changes since V1:
> - Add mailmap entry
> 
> [...]

Here is the summary with links:
  - [V2] MAINTAINERS: Update Jason Wang's email address
    https://git.kernel.org/netdev/net/c/1398b1014909

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



^ permalink raw reply

* Re: [PATCH 00/32] x86/msr: Drop 32-bit MSR interfaces
From: H. Peter Anvin @ 2026-06-30 20:06 UTC (permalink / raw)
  To: Arnd Bergmann, Juergen Gross, linux-kernel, linux-pm,
	linux-edac@vger.kernel.org, x86, linux-acpi, kvm, linux-coco,
	linux-pci, virtualization, linux-ide, dri-devel, linux-fbdev,
	linux-crypto, open list:GPIO SUBSYSTEM, linux-hyperv, linux-hwmon,
	linux-perf-users, linux-mtd, platform-driver-x86
  Cc: Rafael J . Wysocki, Daniel Lezcano, Zhang Rui,
	lukasz.luba@arm.com, Jason Baron, Borislav Petkov, Tony Luck,
	Yazen Ghannam, Len Brown, Pavel Machek, Thomas Gleixner,
	Ingo Molnar, Dave Hansen, Sean Christopherson, Paolo Bonzini,
	Kirill A. Shutemov, Rick Edgecombe, Pu Wen, Bjorn Helgaas,
	Ajay Kaher, Alexey Makhalov, Broadcom internal kernel review list,
	Viresh Kumar, Reinette Chatre, Dave Martin, James Morse,
	Babu Moger, Tony W Wang-oc, Damien Le Moal, Niklas Cassel,
	Dave Airlie, Helge Deller, linux-geode, Olivia Mackall,
	Herbert Xu, Linus Walleij, Bartosz Golaszewski,
	Greg Kroah-Hartman, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
	Dexuan Cui, Long Li, Guenter Roeck, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, Josh Poimboeuf, Pawan Gupta, Vitaly Kuznetsov,
	Andy Lutomirski, Boris Ostrovsky, Huang Rui, Mario Limonciello,
	Perry Yuan, K Prateek Nayak, srinivas.pandruvada@linux.intel.com,
	Artem Bityutskiy, Artem Bityutskiy, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Ashok Raj, Hans de Goede,
	Ilpo Järvinen, Rajneesh Bhardwaj, David E Box, xen-devel
In-Reply-To: <d315e0a8-e4e9-4f7e-80a9-7c236849eabd@app.fastmail.com>

On 2026-06-29 01:38, Arnd Bergmann wrote:
>>
>> There is no RDMSRQ instruction on any x86 CPU. Are you mixing this up with
>> WRMSRNS/RDMSR using an immediate for addressing the MSR?
> 
> Yes, I was just confused about the exact definition here and assumed
> the single-register output version was actually called rdmsrq.
> 
So just to be clear:

There are three instructions(*):

	wrmsr		- implicit form only
	wrmsrns		- implicit or immediate
	rdmsr		- implicit or immediate

The implicit form are the same on 32 and 64 bits (and, in fact, 16 bits): they
take a MSR register address in %ecx and the data as two 32-bit words in
%edx:%eax. This interface predates x86-64 by about a decade, and the Linux MSR
interfaces were designed when Linux was 32-bit only, so it made sense at the
time to treat them as two halves, especially since MSRs often are various
kinds of bitfields. It didn't help that gcc at the time was extremely
inefficient in its handling of multiword arithmetic (it is much better now),
so using a u64 would have made for much worse code.

The immediate forms are 64-bit only and use a single arbitrary 64-bit
register; the MSR address is kept in an immediate in the instruction, just
like they are for most other register types. The only thing that is "special"
there is that the possible register address space is very large (2^32)
although in practice a very small fraction of that is (currently) used.

The immediate forms are expected to be faster, and provide for further
performance improvements in future microarchitectures. This is important,
because it provides a fine-grain uniform architecture for supervisor-only
state, instead of having to give a bulk ISA (XSAVES/XRSTORS) that is different
from the fine-grained architecture, and still get good performance. This gives
the kernel very fine level control over the context switch flows, for one thing.

WRMSRNS is a non-serializing form of WRMSR, which is defined as an
architecturally hard-serializing instruction, although some MSRs have been
retconned as non-serializing (and the set is different between vendors.) We
want to switch that over to the model where the kernel explicitly opts in to
nonserialization, but that means using alternatives since not all CPUs have
the WRMSRNS instruction.

Furthermore, we want to use alternatives so we can make use of the
immediate-format instructions when the MSR address is known at compile time,
which it is in *nearly* all cases. If we are smart about it we can also use
this to let the tracing framework be specific about what MSRs to trace, since
some MSRs are frequently accessed, but many are set at startup and then
rarely, if ever, touched.


(*) There are actually two more instructions:

	RDMSRLIST
	WRMSRLIST

... which are bulk versions of RDMSR and WRMSRNS respectively. They can be
useful to save and restore entire groups of MSRs in one shot, such as
performance counter configurations. By architecturally allowing the memory
operations and MSR operations to operate asynchronously, they give some of the
pipeline benefits of the immediate MSR operations without requiring the MSR
set to have been set at compile time or code to be dynamically generated.

However, they expose an entirely different programming model, whereas the
immediate- and -NS instruction choices can be entirely hidden at the C level.


^ permalink raw reply

* Re: [PATCH 00/32] x86/msr: Drop 32-bit MSR interfaces
From: Sean Christopherson @ 2026-06-30 18:59 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnd Bergmann, Juergen Gross, linux-kernel, linux-pm,
	linux-edac@vger.kernel.org, x86, linux-acpi, kvm, linux-coco,
	linux-pci, virtualization, linux-ide, dri-devel, linux-fbdev,
	linux-crypto, open list:GPIO SUBSYSTEM, linux-hyperv, linux-hwmon,
	linux-perf-users, linux-mtd, platform-driver-x86,
	Rafael J . Wysocki, Daniel Lezcano, Zhang Rui,
	lukasz.luba@arm.com, Jason Baron, Borislav Petkov, Tony Luck,
	Yazen Ghannam, Len Brown, Pavel Machek, Thomas Gleixner,
	Ingo Molnar, Dave Hansen, H. Peter Anvin, Paolo Bonzini,
	Kirill A. Shutemov, Rick Edgecombe, Pu Wen, Bjorn Helgaas,
	Ajay Kaher, Alexey Makhalov, Broadcom internal kernel review list,
	Viresh Kumar, Reinette Chatre, Dave Martin, James Morse,
	Babu Moger, Tony W Wang-oc, Damien Le Moal, Niklas Cassel,
	Dave Airlie, Helge Deller, linux-geode, Olivia Mackall,
	Herbert Xu, Linus Walleij, Bartosz Golaszewski,
	Greg Kroah-Hartman, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
	Dexuan Cui, Long Li, Guenter Roeck, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, Josh Poimboeuf, Pawan Gupta, Vitaly Kuznetsov,
	Andy Lutomirski, Boris Ostrovsky, Huang Rui, Mario Limonciello,
	Perry Yuan, K Prateek Nayak, srinivas.pandruvada@linux.intel.com,
	Artem Bityutskiy, Artem Bityutskiy, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Ashok Raj, Hans de Goede,
	Ilpo Järvinen, Rajneesh Bhardwaj, David E Box, xen-devel
In-Reply-To: <akJUz0kYkEBdLSZ3@gmail.com>

On Mon, Jun 29, 2026, Ingo Molnar wrote:
> * Arnd Bergmann <arnd@arndb.de> wrote:
> 
> > >>> Note that most patches of this series are independent from each other.
> > >>> Only the patches removing a specific interface (patches 7, 15, 26 and
> > >>> 30) and the last two patches of the series depend on all previous
> > >>> patches.
> > >> 
> > >> It looks like you are touching most files twice or more here, to
> > >> first convert from rdmsr to rdmsrq and then to change the
> > >> two-argument rdmsrq() macro to a single-argument inline. If you
> > >> introduce the inline version of rdmsrq() first, you should be
> > >> able to skip the second step (patch 31) as they could be able
> > >> to coexist.
> > >
> > > I've discussed how to structure the series with Ingo Molnar before [1]. The
> > > current approach was his preference.
> > 
> > Ok.
> 
> Note that the individual patches are IMO significantly easier to review
> through the actual 32-bit => 64-bit variable assignment changes done
> in isolation (which sometimes include minor cleanups), while
> the Coccinelle semantic patch:
> 
>    { a(b,c) => c = a(b) }
> 
> which changes both the function signature and the order of terms as
> well, is just a single add-on treewide patch.

Is the plan for subsystem maintainers to pick up the relevant patches, and then
do the treewide change one release cycle later?

^ permalink raw reply

* Re: [PATCH net-next v4] vsock/virtio: rewrite MSG_ZEROCOPY flag handling
From: Paolo Abeni @ 2026-06-30 15:52 UTC (permalink / raw)
  To: Arseniy Krasnov, Stefan Hajnoczi, Stefano Garzarella,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Michael S. Tsirkin,
	Jason Wang, Bobby Eshleman, Xuan Zhuo, Eugenio Pérez,
	Simon Horman
  Cc: kvm, virtualization, netdev, linux-kernel, oxffffaa, rulkc
In-Reply-To: <20260628182052.951760-1-avkrasnov@rulkc.org>

On 6/28/26 8:20 PM, Arseniy Krasnov wrote:
> Logically it was based on TCP implementation, so to make further support
> easier, rewrite it in the TCP way (like in 'tcp_sendmsg_locked()'). By
> this way, patch also adds handling case when 'msg_ubuf' is already set.
> 
> Signed-off-by: Arseniy Krasnov <avkrasnov@rulkc.org>

The PW bot is on holiday, no automated notifications for a while.

Applied, thanks!

/P


^ permalink raw reply

* Re: [PATCH 01/13] mm: introduce vma_flags_can_grow() and vma_can_grow()
From: Zi Yan @ 2026-06-30 15:09 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Andrew Morton, Thomas Bogendoerfer, Madhavan Srinivasan,
	Michael Ellerman, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Lucas Stach,
	Inki Dae, Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski,
	Peter Griffin, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Rob Clark, Dmitry Baryshkov, Lyude Paul,
	Danilo Krummrich, Tomi Valkeinen, Sandy Huang, Heiko Stübner,
	Andy Yan, Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Gerd Hoffmann, Dmitry Osipenko, Zack Rusin, Matthew Brost,
	Thomas Hellstrom, Oleksandr Andrushchenko, Helge Deller,
	Benjamin LaHaise, Alexander Viro, Christian Brauner, Muchun Song,
	Oscar Salvador, David Hildenbrand, Baolin Wang, Liam R . Howlett,
	Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Hugh Dickins, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
	Michal Hocko, Jann Horn, Pedro Falcato, Kees Cook,
	Jaroslav Kysela, Takashi Iwai, linux-mips, linux-kernel,
	linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
	linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
	linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
	linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <akNucoP3eaDN2_Vz@lucifer>

On Tue Jun 30, 2026 at 3:38 AM EDT, Lorenzo Stoakes wrote:
> On Mon, Jun 29, 2026 at 04:26:18PM -0400, Zi Yan wrote:
>> On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
>> > These test whether the VMA has stack sematics, i.e. is able to grow upwards
>> > or downwards depending on the architecture.
>> >
>> > In order to account for arches which do not support upward-growing stacks,
>> > introduce VMA_GROWSUP whose definition depends on the architecture
>> > supporting it, and use vma_flags_test_single_mask() in vma_flags_can_grow()
>> > to account for this.
>> >
>> > Update the VMA userland tests to reflect the changes
>> >
>> > No functional change intended.
>> >
>> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>> > ---
>> >  include/linux/mm.h              | 21 ++++++++++++++++++---
>> >  tools/testing/vma/include/dup.h |  4 ++++
>> >  2 files changed, 22 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/include/linux/mm.h b/include/linux/mm.h
>> > index 868b2334bff3..cf7df1569052 100644
>> > --- a/include/linux/mm.h
>> > +++ b/include/linux/mm.h
>> > @@ -472,6 +472,7 @@ enum {
>> >  #define VM_SAO		INIT_VM_FLAG(SAO)
>> >  #elif defined(CONFIG_PARISC)
>> >  #define VM_GROWSUP	INIT_VM_FLAG(GROWSUP)
>> > +#define VMA_GROWSUP	mk_vma_flags(VMA_GROWSUP_BIT)
>> >  #elif defined(CONFIG_SPARC64)
>> >  #define VM_SPARC_ADI	INIT_VM_FLAG(SPARC_ADI)
>> >  #define VM_ARCH_CLEAR	INIT_VM_FLAG(ARCH_CLEAR)
>> > @@ -483,6 +484,7 @@ enum {
>> >  #endif
>> >  #ifndef VM_GROWSUP
>> >  #define VM_GROWSUP	VM_NONE
>> > +#define VMA_GROWSUP	EMPTY_VMA_FLAGS
>> >  #endif
>> >  #ifdef CONFIG_ARM64_MTE
>> >  #define VM_MTE		INIT_VM_FLAG(MTE)
>> > @@ -1563,11 +1565,24 @@ static inline bool vma_is_initial_stack(const struct vm_area_struct *vma)
>> >  		vma->vm_end >= vma->vm_mm->start_stack;
>> >  }
>> >
>> > -static inline bool vma_is_temporary_stack(const struct vm_area_struct *vma)
>> > +static inline bool vma_flags_can_grow(const vma_flags_t *flags)
>> >  {
>> > -	int maybe_stack = vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP);
>> > +	if (vma_flags_test_single_mask(flags, VMA_GROWSUP))
>> > +		return true;
>> > +	if (vma_flags_test(flags, VMA_GROWSDOWN_BIT))
>> > +		return true;
>> > +
>> > +	return false;
>> > +}
>> >
>> > -	if (!maybe_stack)
>> > +static inline bool vma_can_grow(const struct vm_area_struct *vma)
>> > +{
>> > +	return vma_flags_can_grow(&vma->flags);
>>
>> Would it save vma_flags_can_grow() if we do below?
>>
>> return vma_test(vma, VMA_GROWSDOWN_BIT) || vma_test_single_mask(vma, VMA_GROWSUP);
>>
>> I find these two functions when I am reading mm.h.
>
> Yeah but we require vma_flags_can_grow() for code in mmap.c, the majority of
> checks of this have only vma_flags_t to work with not a VMA :)
>

Got it. I think I need to finish this series. :)

>>
>> > +}
>> > +
>> > +static inline bool vma_is_temporary_stack(const struct vm_area_struct *vma)
>> > +{
>> > +	if (!vma_can_grow(vma))
>> >  		return false;
>> >
>> >  	if ((vma->vm_flags & VM_STACK_INCOMPLETE_SETUP) ==
>> > diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
>> > index 5d7d0afd7765..6f5bcd7fbcd8 100644
>> > --- a/tools/testing/vma/include/dup.h
>> > +++ b/tools/testing/vma/include/dup.h
>> > @@ -245,8 +245,10 @@ enum {
>> >  #define VM_STACK	INIT_VM_FLAG(STACK)
>> >  #ifdef CONFIG_STACK_GROWS_UP
>> >  #define VM_STACK_EARLY	INIT_VM_FLAG(STACK_EARLY)
>> > +#define VMA_STACK_EARLY mk_vma_flags(VMA_STACK_EARLY_BIT)
>> >  #else
>> >  #define VM_STACK_EARLY	VM_NONE
>> > +#define VMA_STACK_EARLY EMPTY_VMA_FLAGS
>> >  #endif
>> >  #ifdef CONFIG_ARCH_HAS_PKEYS
>> >  #define VM_PKEY_SHIFT ((__force int)VMA_HIGH_ARCH_0_BIT)
>> > @@ -315,6 +317,8 @@ enum {
>> >
>> >  /* Bits set in the VMA until the stack is in its final location */
>> >  #define VM_STACK_INCOMPLETE_SETUP (VM_RAND_READ | VM_SEQ_READ | VM_STACK_EARLY)
>> > +#define VMA_STACK_INCOMPLETE_SETUP append_vma_flags(		\
>> > +	VMA_STACK_EARLY, VMA_RAND_READ_BIT, VMA_SEQ_READ_BIT)
>> >
>> >  #define TASK_EXEC_BIT ((current->personality & READ_IMPLIES_EXEC) ? \
>> >  		       VM_EXEC_BIT : VM_READ_BIT)
>>
>> Why are VMA_STACK_EARLY and VMA_STACK_INCOMPLETE_SETUP added here but
>> not in mm.h?
>
> Yeah urgh oops my bad. It doesn't really break anything but I'll fix it if a
> respin is needed...

Sure.

-- 
Best Regards,
Yan, Zi


^ permalink raw reply


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