7.1-stable patches added patches: kvm-vmx-grab-vmcs12-on-cr8-interception-update-iff-vcpu-is-in-guest-mode.patch kvm-x86-move-update_cr8_intercept-to-lapic.c.patch kvm-x86-unconditionally-recompute-cr8-intercept-on-ppr-update.patch
diff --git a/queue-7.1/kvm-vmx-grab-vmcs12-on-cr8-interception-update-iff-vcpu-is-in-guest-mode.patch b/queue-7.1/kvm-vmx-grab-vmcs12-on-cr8-interception-update-iff-vcpu-is-in-guest-mode.patch new file mode 100644 index 0000000..07966f0 --- /dev/null +++ b/queue-7.1/kvm-vmx-grab-vmcs12-on-cr8-interception-update-iff-vcpu-is-in-guest-mode.patch
@@ -0,0 +1,70 @@ +From clopez@suse.de Thu Jul 9 15:28:56 2026 +From: "Carlos López" <clopez@suse.de> +Date: Thu, 9 Jul 2026 15:21:08 +0200 +Subject: KVM: VMX: Grab vmcs12 on CR8 interception update iff vCPU is in guest mode +To: stable@vger.kernel.org +Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org, "Sean Christopherson" <seanjc@google.com>, "syzbot ci" <syzbot+ci493c6d734b63e050@syzkaller.appspotmail.com>, "Paolo Bonzini" <pbonzini@redhat.com>, "Carlos López" <clopez@suse.de>, "Thomas Gleixner" <tglx@kernel.org>, "Ingo Molnar" <mingo@redhat.com>, "Borislav Petkov" <bp@alien8.de>, "Dave Hansen" <dave.hansen@linux.intel.com>, x86@kernel.org (maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)), "H. Peter Anvin" <hpa@zytor.com> +Message-ID: <20260709132109.3423488-4-clopez@suse.de> + +From: Sean Christopherson <seanjc@google.com> + +[ Upstream commit 7ef78d71ca713d8c00f7c34ddcf276c808143f77 ] + +When updating CR8 intercepts, get vmcs12 if and only if the vCPU is in +guest mode so that a future change can have update CR8 intercepts during +vCPU creation, without running afoul of get_vmcs12()'s lockdep assertion. + + ------------[ cut here ]------------ + debug_locks && !(lock_is_held(&(&vcpu->mutex)->dep_map) || !refcount_read(&vcpu->kvm->users_count)) + WARNING: arch/x86/kvm/vmx/nested.h:61 at get_vmcs12 arch/x86/kvm/vmx/nested.h:60 [inline], CPU#0: syz.2.19/5879 + WARNING: arch/x86/kvm/vmx/nested.h:61 at vmx_update_cr8_intercept+0x3de/0x4e0 arch/x86/kvm/vmx/vmx.c:6879, CPU#0: syz.2.19/5879 + Modules linked in: + CPU: 0 UID: 0 PID: 5879 Comm: syz.2.19 Not tainted syzkaller #0 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 + RIP: 0010:get_vmcs12 arch/x86/kvm/vmx/nested.h:60 [inline] + RIP: 0010:vmx_update_cr8_intercept+0x3de/0x4e0 arch/x86/kvm/vmx/vmx.c:6879 + Call Trace: + <TASK> + apic_update_ppr arch/x86/kvm/lapic.c:984 [inline] + kvm_lapic_reset+0x1c24/0x2980 arch/x86/kvm/lapic.c:3023 + kvm_vcpu_reset+0x44c/0x1bf0 arch/x86/kvm/x86.c:12986 + kvm_arch_vcpu_create+0x746/0x8b0 arch/x86/kvm/x86.c:12847 + kvm_vm_ioctl_create_vcpu+0x428/0x930 virt/kvm/kvm_main.c:4201 + kvm_vm_ioctl+0x893/0xd50 virt/kvm/kvm_main.c:5159 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:597 [inline] + __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + </TASK> + +No functional change intended. + +Reported-by: syzbot ci <syzbot+ci493c6d734b63e050@syzkaller.appspotmail.com> +Closes: https://lore.kernel.org/all/6a2adf3b.3b0a2d4e.8c8d1.0012.GAE@google.com +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson <seanjc@google.com> +Message-ID: <20260618174347.1981064-2-seanjc@google.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +Signed-off-by: Carlos López <clopez@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + arch/x86/kvm/vmx/vmx.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -6855,11 +6855,10 @@ int vmx_handle_exit(struct kvm_vcpu *vcp + + void vmx_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) + { +- struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + int tpr_threshold; + + if (is_guest_mode(vcpu) && +- nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) ++ nested_cpu_has(get_vmcs12(vcpu), CPU_BASED_TPR_SHADOW)) + return; + + guard(vmx_vmcs01)(vcpu);
diff --git a/queue-7.1/kvm-x86-move-update_cr8_intercept-to-lapic.c.patch b/queue-7.1/kvm-x86-move-update_cr8_intercept-to-lapic.c.patch new file mode 100644 index 0000000..6a485ed --- /dev/null +++ b/queue-7.1/kvm-x86-move-update_cr8_intercept-to-lapic.c.patch
@@ -0,0 +1,147 @@ +From clopez@suse.de Thu Jul 9 15:28:57 2026 +From: "Carlos López" <clopez@suse.de> +Date: Thu, 9 Jul 2026 15:21:07 +0200 +Subject: KVM: x86: Move update_cr8_intercept() to lapic.c +To: stable@vger.kernel.org +Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org, "Sean Christopherson" <seanjc@google.com>, "Kai Huang" <kai.huang@intel.com>, "Yosry Ahmed" <yosry@kernel.org>, "Carlos López" <clopez@suse.de>, "Paolo Bonzini" <pbonzini@redhat.com>, "Thomas Gleixner" <tglx@kernel.org>, "Ingo Molnar" <mingo@redhat.com>, "Borislav Petkov" <bp@alien8.de>, "Dave Hansen" <dave.hansen@linux.intel.com>, x86@kernel.org (maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)), "H. Peter Anvin" <hpa@zytor.com> +Message-ID: <20260709132109.3423488-3-clopez@suse.de> + +From: Sean Christopherson <seanjc@google.com> + +[ Upstream Commit c7722e5e1daeeabbd9f969554d52bb7158120b27 ] + +Move update_cr8_intercept() to lapic.c so that it's globally visible +in anticipation of extracting most of the register-specific code out of +x86.c and into a new compilation unit. Opportunistically prefix the +helper kvm_lapic_ to make its role/scope more obvious. + +No functional change intended. + +Reviewed-by: Kai Huang <kai.huang@intel.com> +Reviewed-by: Yosry Ahmed <yosry@kernel.org> +Link: https://patch.msgid.link/20260529222223.870923-14-seanjc@google.com +Signed-off-by: Sean Christopherson <seanjc@google.com> +Signed-off-by: Carlos López <clopez@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + arch/x86/kvm/lapic.c | 26 ++++++++++++++++++++++++++ + arch/x86/kvm/lapic.h | 1 + + arch/x86/kvm/x86.c | 34 +++------------------------------- + 3 files changed, 30 insertions(+), 31 deletions(-) + +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -2744,6 +2744,32 @@ u64 kvm_lapic_get_cr8(struct kvm_vcpu *v + return (tpr & 0xf0) >> 4; + } + ++void kvm_lapic_update_cr8_intercept(struct kvm_vcpu *vcpu) ++{ ++ int max_irr, tpr; ++ ++ if (!kvm_x86_ops.update_cr8_intercept) ++ return; ++ ++ if (!lapic_in_kernel(vcpu)) ++ return; ++ ++ if (vcpu->arch.apic->apicv_active) ++ return; ++ ++ if (!vcpu->arch.apic->vapic_addr) ++ max_irr = kvm_lapic_find_highest_irr(vcpu); ++ else ++ max_irr = -1; ++ ++ if (max_irr != -1) ++ max_irr >>= 4; ++ ++ tpr = kvm_lapic_get_cr8(vcpu); ++ ++ kvm_x86_call(update_cr8_intercept)(vcpu, tpr, max_irr); ++} ++ + static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value) + { + u64 old_value = vcpu->arch.apic_base; +--- a/arch/x86/kvm/lapic.h ++++ b/arch/x86/kvm/lapic.h +@@ -100,6 +100,7 @@ int kvm_apic_accept_events(struct kvm_vc + void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event); + u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu); + void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8); ++void kvm_lapic_update_cr8_intercept(struct kvm_vcpu *vcpu); + void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu); + void kvm_apic_set_version(struct kvm_vcpu *vcpu); + void kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu); +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -128,7 +128,6 @@ static u64 __read_mostly efer_reserved_b + KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST | \ + KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST) + +-static void update_cr8_intercept(struct kvm_vcpu *vcpu); + static void process_nmi(struct kvm_vcpu *vcpu); + static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags); + static void store_regs(struct kvm_vcpu *vcpu); +@@ -5340,7 +5339,7 @@ static int kvm_vcpu_ioctl_set_lapic(stru + r = kvm_apic_set_state(vcpu, s); + if (r) + return r; +- update_cr8_intercept(vcpu); ++ kvm_lapic_update_cr8_intercept(vcpu); + + return 0; + } +@@ -10595,33 +10594,6 @@ static void post_kvm_run_save(struct kvm + kvm_run->flags |= KVM_RUN_X86_GUEST_MODE; + } + +-static void update_cr8_intercept(struct kvm_vcpu *vcpu) +-{ +- int max_irr, tpr; +- +- if (!kvm_x86_ops.update_cr8_intercept) +- return; +- +- if (!lapic_in_kernel(vcpu)) +- return; +- +- if (vcpu->arch.apic->apicv_active) +- return; +- +- if (!vcpu->arch.apic->vapic_addr) +- max_irr = kvm_lapic_find_highest_irr(vcpu); +- else +- max_irr = -1; +- +- if (max_irr != -1) +- max_irr >>= 4; +- +- tpr = kvm_lapic_get_cr8(vcpu); +- +- kvm_x86_call(update_cr8_intercept)(vcpu, tpr, max_irr); +-} +- +- + int kvm_check_nested_events(struct kvm_vcpu *vcpu) + { + if (kvm_test_request(KVM_REQ_TRIPLE_FAULT, vcpu)) { +@@ -11362,7 +11334,7 @@ static int vcpu_enter_guest(struct kvm_v + kvm_x86_call(enable_irq_window)(vcpu); + + if (kvm_lapic_enabled(vcpu)) { +- update_cr8_intercept(vcpu); ++ kvm_lapic_update_cr8_intercept(vcpu); + kvm_lapic_sync_to_vapic(vcpu); + } + } +@@ -12511,7 +12483,7 @@ static int __set_sregs_common(struct kvm + kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR); + kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); + +- update_cr8_intercept(vcpu); ++ kvm_lapic_update_cr8_intercept(vcpu); + + /* Older userspace won't unhalt the vcpu on reset. */ + if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 &&
diff --git a/queue-7.1/kvm-x86-unconditionally-recompute-cr8-intercept-on-ppr-update.patch b/queue-7.1/kvm-x86-unconditionally-recompute-cr8-intercept-on-ppr-update.patch new file mode 100644 index 0000000..9f81353 --- /dev/null +++ b/queue-7.1/kvm-x86-unconditionally-recompute-cr8-intercept-on-ppr-update.patch
@@ -0,0 +1,104 @@ +From clopez@suse.de Thu Jul 9 15:29:01 2026 +From: "Carlos López" <clopez@suse.de> +Date: Thu, 9 Jul 2026 15:21:09 +0200 +Subject: KVM: x86: Unconditionally recompute CR8 intercept on PPR update +To: stable@vger.kernel.org +Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org, "Carlos López" <clopez@suse.de>, "Stefano Garzarella" <sgarzare@redhat.com>, "Sean Christopherson" <seanjc@google.com>, "Paolo Bonzini" <pbonzini@redhat.com>, "Thomas Gleixner" <tglx@kernel.org>, "Ingo Molnar" <mingo@redhat.com>, "Borislav Petkov" <bp@alien8.de>, "Dave Hansen" <dave.hansen@linux.intel.com>, x86@kernel.org (maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)), "H. Peter Anvin" <hpa@zytor.com>, "Roman Kagan" <rkagan@virtuozzo.com> +Message-ID: <20260709132109.3423488-5-clopez@suse.de> + +From: "Carlos López" <clopez@suse.de> + +[ Upstream commit bb365a506b1e6fb050c0fceaad354fe395385ef0 ] + +The TPR_THRESHOLD field in the VMCS is used by VMX to induce VM exits +when the guest's virtual TPR falls under the specified threshold, +allowing KVM to inject previously masked interrupts. + +KVM handles these VM exits in handle_tpr_below_threshold(). +Commit eb90f3417a0c ("KVM: vmx: speed up TPR below threshold vmexits") +optimized this function by calling apic_update_ppr() instead of raising +KVM_REQ_EVENT. apic_update_ppr() then raises KVM_REQ_EVENT if there is +a pending, deliverable interrupt. + +However, if there are no new interrupts pending, apic_update_ppr() does +not issue the request. Thus, kvm_lapic_update_cr8_intercept() and +vmx_update_cr8_intercept() are not called before VM entry, which results +in a high, stale TPR_THRESHOLD. This is problematic due to the following +sentence in 28.2.1.1 "VM-Execution Control Fields" in the SDM: + + The following check is performed if the “use TPR shadow” VM-execution + control is 1 and the “virtualize APIC accesses” and “virtual-interrupt + delivery” VM-execution controls are both 0: the value of bits 3:0 of + the TPR threshold VM-execution control field should not be greater + than the value of bits 7:4 of VTPR. + +This error condition is typically not observed when KVM runs on a bare +metal system because modern processors support APICv, which enables +virtual-interrupt delivery, and which KVM uses when possible. This +causes the processor to no longer generate TPR-below-threshold exits +and to no longer check TPR_THRESHOLD on entry. However, when running +on older platforms, or under nested virtualization on a hypervisor that +does not support virtual-interrupt delivery and enforces this check +(like Hyper-V) this can cause a VM entry failure with hardware error +0x7, as seen in [1]. + +Call kvm_lapic_update_cr8_intercept() if apic_update_ppr() does not +find a deliverable interrupt (and thus does not raise KVM_REQ_EVENT). +Remove calls to kvm_lapic_update_cr8_intercept() on paths that end up in +apic_update_ppr(), as they now become redundant. This ensures that any +path that updates the guest's PPR also figures out if KVM needs to wait +for a TPR change (using TPR_THRESHOLD on VMX or CR8 intercepts on SVM). + +Link: https://github.com/coconut-svsm/svsm/issues/1081 [1] +Tested-by: Stefano Garzarella <sgarzare@redhat.com> +Cc: stable@vger.kernel.org +Fixes: eb90f3417a0c ("KVM: vmx: speed up TPR below threshold vmexits") +Signed-off-by: Carlos López <clopez@suse.de> +Signed-off-by: Sean Christopherson <seanjc@google.com> +Message-ID: <20260618174347.1981064-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + arch/x86/kvm/lapic.c | 2 ++ + arch/x86/kvm/x86.c | 5 +---- + 2 files changed, 3 insertions(+), 4 deletions(-) + +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -980,6 +980,8 @@ static void apic_update_ppr(struct kvm_l + if (__apic_update_ppr(apic, &ppr) && + apic_has_interrupt_for_ppr(apic, ppr) != -1) + kvm_make_request(KVM_REQ_EVENT, apic->vcpu); ++ else ++ kvm_lapic_update_cr8_intercept(apic->vcpu); + } + + void kvm_apic_update_ppr(struct kvm_vcpu *vcpu) +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5339,7 +5339,6 @@ static int kvm_vcpu_ioctl_set_lapic(stru + r = kvm_apic_set_state(vcpu, s); + if (r) + return r; +- kvm_lapic_update_cr8_intercept(vcpu); + + return 0; + } +@@ -12453,8 +12452,6 @@ static int __set_sregs_common(struct kvm + kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3); + kvm_x86_call(post_set_cr3)(vcpu, sregs->cr3); + +- kvm_set_cr8(vcpu, sregs->cr8); +- + *mmu_reset_needed |= vcpu->arch.efer != sregs->efer; + kvm_x86_call(set_efer)(vcpu, sregs->efer); + +@@ -12483,7 +12480,7 @@ static int __set_sregs_common(struct kvm + kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR); + kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); + +- kvm_lapic_update_cr8_intercept(vcpu); ++ kvm_set_cr8(vcpu, sregs->cr8); + + /* Older userspace won't unhalt the vcpu on reset. */ + if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 &&
diff --git a/queue-7.1/series b/queue-7.1/series index 86a91d0..2eb3bfe 100644 --- a/queue-7.1/series +++ b/queue-7.1/series
@@ -5,3 +5,6 @@ mm-khugepaged-write-all-dirty-file-folios-when-colla.patch slab-recognize-gfp-parameter-as-optional-in-kernel-doc.patch perf-trace-beauty-fcntl-fix-build-with-older-kernel-headers.patch +kvm-x86-move-update_cr8_intercept-to-lapic.c.patch +kvm-vmx-grab-vmcs12-on-cr8-interception-update-iff-vcpu-is-in-guest-mode.patch +kvm-x86-unconditionally-recompute-cr8-intercept-on-ppr-update.patch