stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)" failed to apply to 6.6-stable tree
@ 2024-10-01  9:48 gregkh
  2025-02-05 22:26 ` [PATCH 6.6.y 0/2] KVM: x86: Backport split ICR for x2AVIC James Houghton
  0 siblings, 1 reply; 8+ messages in thread
From: gregkh @ 2024-10-01  9:48 UTC (permalink / raw)
  To: seanjc, mlevitsk, suravee.suthikulpanit; +Cc: stable


The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 73b42dc69be8564d4951a14d00f827929fe5ef79
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2024100123-unreached-enrage-2cb1@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..

Possible dependencies:

73b42dc69be8 ("KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)")
d33234342f8b ("KVM: x86: Move x2APIC ICR helper above kvm_apic_write_nodecode()")
71bf395a276f ("KVM: x86: Enforce x2APIC's must-be-zero reserved ICR bits")
4b7c3f6d04bd ("KVM: x86: Make x2APIC ID 100% readonly")
c7d4c5f01961 ("KVM: x86: Drop unused check_apicv_inhibit_reasons() callback definition")
5f18c642ff7e ("KVM: VMX: Move out vmx_x86_ops to 'main.c' to dispatch VMX and TDX")
0ec3d6d1f169 ("KVM: x86: Fully defer to vendor code to decide how to force immediate exit")
bf1a49436ea3 ("KVM: x86: Move handling of is_guest_mode() into fastpath exit handlers")
11776aa0cfa7 ("KVM: VMX: Handle forced exit due to preemption timer in fastpath")
e6b5d16bbd2d ("KVM: VMX: Re-enter guest in fastpath for "spurious" preemption timer exits")
9c9025ea003a ("KVM: x86: Plumb "force_immediate_exit" into kvm_entry() tracepoint")
8ecb10bcbfa3 ("Merge tag 'kvm-x86-lam-6.8' of https://github.com/kvm-x86/linux into HEAD")

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 73b42dc69be8564d4951a14d00f827929fe5ef79 Mon Sep 17 00:00:00 2001
From: Sean Christopherson <seanjc@google.com>
Date: Fri, 19 Jul 2024 16:51:00 -0700
Subject: [PATCH] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)

Re-introduce the "split" x2APIC ICR storage that KVM used prior to Intel's
IPI virtualization support, but only for AMD.  While not stated anywhere
in the APM, despite stating the ICR is a single 64-bit register, AMD CPUs
store the 64-bit ICR as two separate 32-bit values in ICR and ICR2.  When
IPI virtualization (IPIv on Intel, all AVIC flavors on AMD) is enabled,
KVM needs to match CPU behavior as some ICR ICR writes will be handled by
the CPU, not by KVM.

Add a kvm_x86_ops knob to control the underlying format used by the CPU to
store the x2APIC ICR, and tune it to AMD vs. Intel regardless of whether
or not x2AVIC is enabled.  If KVM is handling all ICR writes, the storage
format for x2APIC mode doesn't matter, and having the behavior follow AMD
versus Intel will provide better test coverage and ease debugging.

Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode")
Cc: stable@vger.kernel.org
Cc: Maxim Levitsky <mlevitsk@redhat.com>
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Link: https://lore.kernel.org/r/20240719235107.3023592-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 95396e4cb3da..f9dfb2d62053 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1727,6 +1727,8 @@ struct kvm_x86_ops {
 	void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
 	void (*enable_irq_window)(struct kvm_vcpu *vcpu);
 	void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
+
+	const bool x2apic_icr_is_split;
 	const unsigned long required_apicv_inhibits;
 	bool allow_apicv_in_x2apic_without_x2apic_virtualization;
 	void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 63be07d7c782..c7180cb5f464 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2471,11 +2471,25 @@ int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data)
 	data &= ~APIC_ICR_BUSY;
 
 	kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32));
-	kvm_lapic_set_reg64(apic, APIC_ICR, data);
+	if (kvm_x86_ops.x2apic_icr_is_split) {
+		kvm_lapic_set_reg(apic, APIC_ICR, data);
+		kvm_lapic_set_reg(apic, APIC_ICR2, data >> 32);
+	} else {
+		kvm_lapic_set_reg64(apic, APIC_ICR, data);
+	}
 	trace_kvm_apic_write(APIC_ICR, data);
 	return 0;
 }
 
+static u64 kvm_x2apic_icr_read(struct kvm_lapic *apic)
+{
+	if (kvm_x86_ops.x2apic_icr_is_split)
+		return (u64)kvm_lapic_get_reg(apic, APIC_ICR) |
+		       (u64)kvm_lapic_get_reg(apic, APIC_ICR2) << 32;
+
+	return kvm_lapic_get_reg64(apic, APIC_ICR);
+}
+
 /* emulate APIC access in a trap manner */
 void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
 {
@@ -2493,7 +2507,7 @@ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
 	 * maybe-unecessary write, and both are in the noise anyways.
 	 */
 	if (apic_x2apic_mode(apic) && offset == APIC_ICR)
-		WARN_ON_ONCE(kvm_x2apic_icr_write(apic, kvm_lapic_get_reg64(apic, APIC_ICR)));
+		WARN_ON_ONCE(kvm_x2apic_icr_write(apic, kvm_x2apic_icr_read(apic)));
 	else
 		kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset));
 }
@@ -3013,18 +3027,22 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
 
 		/*
 		 * In x2APIC mode, the LDR is fixed and based on the id.  And
-		 * ICR is internally a single 64-bit register, but needs to be
-		 * split to ICR+ICR2 in userspace for backwards compatibility.
+		 * if the ICR is _not_ split, ICR is internally a single 64-bit
+		 * register, but needs to be split to ICR+ICR2 in userspace for
+		 * backwards compatibility.
 		 */
-		if (set) {
+		if (set)
 			*ldr = kvm_apic_calc_x2apic_ldr(x2apic_id);
 
-			icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
-			      (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;
-			__kvm_lapic_set_reg64(s->regs, APIC_ICR, icr);
-		} else {
-			icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
-			__kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
+		if (!kvm_x86_ops.x2apic_icr_is_split) {
+			if (set) {
+				icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
+				      (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;
+				__kvm_lapic_set_reg64(s->regs, APIC_ICR, icr);
+			} else {
+				icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
+				__kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
+			}
 		}
 	}
 
@@ -3222,7 +3240,7 @@ static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data)
 	u32 low;
 
 	if (reg == APIC_ICR) {
-		*data = kvm_lapic_get_reg64(apic, APIC_ICR);
+		*data = kvm_x2apic_icr_read(apic);
 		return 0;
 	}
 
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index d8cfe8f23327..eb3de01602b9 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5053,6 +5053,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
 	.enable_nmi_window = svm_enable_nmi_window,
 	.enable_irq_window = svm_enable_irq_window,
 	.update_cr8_intercept = svm_update_cr8_intercept,
+
+	.x2apic_icr_is_split = true,
 	.set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
 	.refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl,
 	.apicv_post_state_restore = avic_apicv_post_state_restore,
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 4f6023a0deb3..0a094ebad4b1 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -89,6 +89,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
 	.enable_nmi_window = vmx_enable_nmi_window,
 	.enable_irq_window = vmx_enable_irq_window,
 	.update_cr8_intercept = vmx_update_cr8_intercept,
+
+	.x2apic_icr_is_split = false,
 	.set_virtual_apic_mode = vmx_set_virtual_apic_mode,
 	.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
 	.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6.6.y 0/2] KVM: x86: Backport split ICR for x2AVIC
  2024-10-01  9:48 FAILED: patch "[PATCH] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)" failed to apply to 6.6-stable tree gregkh
@ 2025-02-05 22:26 ` James Houghton
  2025-02-05 22:26   ` [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly James Houghton
  2025-02-05 22:26   ` [PATCH 6.6.y 2/2] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC) James Houghton
  0 siblings, 2 replies; 8+ messages in thread
From: James Houghton @ 2025-02-05 22:26 UTC (permalink / raw)
  To: stable
  Cc: Sean Christopherson, Maxim Levitsky, Suravee Suthikulpanit,
	Gavin Guo, James Houghton

Also pull in commit 4b7c3f6d04bd ("KVM: x86: Make x2APIC ID 100%
readonly") as a dependency, which itself fixes a WARN.

Tested with xapic_state_test avic=Y.

Sean Christopherson (2):
  KVM: x86: Make x2APIC ID 100% readonly
  KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)

 arch/x86/include/asm/kvm_host.h |  2 +
 arch/x86/kvm/lapic.c            | 66 +++++++++++++++++++++++----------
 arch/x86/kvm/svm/svm.c          |  2 +
 arch/x86/kvm/vmx/vmx.c          |  2 +
 4 files changed, 52 insertions(+), 20 deletions(-)

-- 
2.48.1.362.g079036d154-goog


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly
  2025-02-05 22:26 ` [PATCH 6.6.y 0/2] KVM: x86: Backport split ICR for x2AVIC James Houghton
@ 2025-02-05 22:26   ` James Houghton
  2025-02-07 22:51     ` Sasha Levin
  2025-02-10 23:26     ` Sean Christopherson
  2025-02-05 22:26   ` [PATCH 6.6.y 2/2] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC) James Houghton
  1 sibling, 2 replies; 8+ messages in thread
From: James Houghton @ 2025-02-05 22:26 UTC (permalink / raw)
  To: stable
  Cc: Sean Christopherson, Maxim Levitsky, Suravee Suthikulpanit,
	Gavin Guo, Michal Luczaj, Haoyu Wu, syzbot+545f1326f405db4e1c3e,
	Paolo Bonzini, James Houghton

From: Sean Christopherson <seanjc@google.com>

Ignore the userspace provided x2APIC ID when fixing up APIC state for
KVM_SET_LAPIC, i.e. make the x2APIC fully readonly in KVM.  Commit
a92e2543d6a8 ("KVM: x86: use hardware-compatible format for APIC ID
register"), which added the fixup, didn't intend to allow userspace to
modify the x2APIC ID.  In fact, that commit is when KVM first started
treating the x2APIC ID as readonly, apparently to fix some race:

 static inline u32 kvm_apic_id(struct kvm_lapic *apic)
 {
-       return (kvm_lapic_get_reg(apic, APIC_ID) >> 24) & 0xff;
+       /* To avoid a race between apic_base and following APIC_ID update when
+        * switching to x2apic_mode, the x2apic mode returns initial x2apic id.
+        */
+       if (apic_x2apic_mode(apic))
+               return apic->vcpu->vcpu_id;
+
+       return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
 }

Furthermore, KVM doesn't support delivering interrupts to vCPUs with a
modified x2APIC ID, but KVM *does* return the modified value on a guest
RDMSR and for KVM_GET_LAPIC.  I.e. no remotely sane setup can actually
work with a modified x2APIC ID.

Making the x2APIC ID fully readonly fixes a WARN in KVM's optimized map
calculation, which expects the LDR to align with the x2APIC ID.

  WARNING: CPU: 2 PID: 958 at arch/x86/kvm/lapic.c:331 kvm_recalculate_apic_map+0x609/0xa00 [kvm]
  CPU: 2 PID: 958 Comm: recalc_apic_map Not tainted 6.4.0-rc3-vanilla+ #35
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.2-1-1 04/01/2014
  RIP: 0010:kvm_recalculate_apic_map+0x609/0xa00 [kvm]
  Call Trace:
   <TASK>
   kvm_apic_set_state+0x1cf/0x5b0 [kvm]
   kvm_arch_vcpu_ioctl+0x1806/0x2100 [kvm]
   kvm_vcpu_ioctl+0x663/0x8a0 [kvm]
   __x64_sys_ioctl+0xb8/0xf0
   do_syscall_64+0x56/0x80
   entry_SYSCALL_64_after_hwframe+0x46/0xb0
  RIP: 0033:0x7fade8b9dd6f

Unfortunately, the WARN can still trigger for other CPUs than the current
one by racing against KVM_SET_LAPIC, so remove it completely.

Reported-by: Michal Luczaj <mhal@rbox.co>
Closes: https://lore.kernel.org/all/814baa0c-1eaa-4503-129f-059917365e80@rbox.co
Reported-by: Haoyu Wu <haoyuwu254@gmail.com>
Closes: https://lore.kernel.org/all/20240126161633.62529-1-haoyuwu254@gmail.com
Reported-by: syzbot+545f1326f405db4e1c3e@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/000000000000c2a6b9061cbca3c3@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20240802202941.344889-2-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071)
Signed-off-by: James Houghton <jthoughton@google.com>
---
 arch/x86/kvm/lapic.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 34766abbabd8..cd9c1e1f6fd3 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -338,10 +338,8 @@ static void kvm_recalculate_logical_map(struct kvm_apic_map *new,
 	 * reversing the LDR calculation to get cluster of APICs, i.e. no
 	 * additional work is required.
 	 */
-	if (apic_x2apic_mode(apic)) {
-		WARN_ON_ONCE(ldr != kvm_apic_calc_x2apic_ldr(kvm_x2apic_id(apic)));
+	if (apic_x2apic_mode(apic))
 		return;
-	}
 
 	if (WARN_ON_ONCE(!kvm_apic_map_get_logical_dest(new, ldr,
 							&cluster, &mask))) {
@@ -2964,18 +2962,28 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
 		struct kvm_lapic_state *s, bool set)
 {
 	if (apic_x2apic_mode(vcpu->arch.apic)) {
+		u32 x2apic_id = kvm_x2apic_id(vcpu->arch.apic);
 		u32 *id = (u32 *)(s->regs + APIC_ID);
 		u32 *ldr = (u32 *)(s->regs + APIC_LDR);
 		u64 icr;
 
 		if (vcpu->kvm->arch.x2apic_format) {
-			if (*id != vcpu->vcpu_id)
+			if (*id != x2apic_id)
 				return -EINVAL;
 		} else {
+			/*
+			 * Ignore the userspace value when setting APIC state.
+			 * KVM's model is that the x2APIC ID is readonly, e.g.
+			 * KVM only supports delivering interrupts to KVM's
+			 * version of the x2APIC ID.  However, for backwards
+			 * compatibility, don't reject attempts to set a
+			 * mismatched ID for userspace that hasn't opted into
+			 * x2apic_format.
+			 */
 			if (set)
-				*id >>= 24;
+				*id = x2apic_id;
 			else
-				*id <<= 24;
+				*id = x2apic_id << 24;
 		}
 
 		/*
@@ -2984,7 +2992,7 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
 		 * split to ICR+ICR2 in userspace for backwards compatibility.
 		 */
 		if (set) {
-			*ldr = kvm_apic_calc_x2apic_ldr(*id);
+			*ldr = kvm_apic_calc_x2apic_ldr(x2apic_id);
 
 			icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
 			      (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;
-- 
2.48.1.362.g079036d154-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6.6.y 2/2] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)
  2025-02-05 22:26 ` [PATCH 6.6.y 0/2] KVM: x86: Backport split ICR for x2AVIC James Houghton
  2025-02-05 22:26   ` [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly James Houghton
@ 2025-02-05 22:26   ` James Houghton
  2025-02-10 23:27     ` Sean Christopherson
  1 sibling, 1 reply; 8+ messages in thread
From: James Houghton @ 2025-02-05 22:26 UTC (permalink / raw)
  To: stable
  Cc: Sean Christopherson, Maxim Levitsky, Suravee Suthikulpanit,
	Gavin Guo, James Houghton

From: Sean Christopherson <seanjc@google.com>

Re-introduce the "split" x2APIC ICR storage that KVM used prior to Intel's
IPI virtualization support, but only for AMD.  While not stated anywhere
in the APM, despite stating the ICR is a single 64-bit register, AMD CPUs
store the 64-bit ICR as two separate 32-bit values in ICR and ICR2.  When
IPI virtualization (IPIv on Intel, all AVIC flavors on AMD) is enabled,
KVM needs to match CPU behavior as some ICR ICR writes will be handled by
the CPU, not by KVM.

Add a kvm_x86_ops knob to control the underlying format used by the CPU to
store the x2APIC ICR, and tune it to AMD vs. Intel regardless of whether
or not x2AVIC is enabled.  If KVM is handling all ICR writes, the storage
format for x2APIC mode doesn't matter, and having the behavior follow AMD
versus Intel will provide better test coverage and ease debugging.

Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode")
Cc: stable@vger.kernel.org
Cc: Maxim Levitsky <mlevitsk@redhat.com>
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Link: https://lore.kernel.org/r/20240719235107.3023592-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
(cherry picked from commit 73b42dc69be8564d4951a14d00f827929fe5ef79)
[JH: fixed conflict with vmx_x86_ops reshuffle due to missing commit
5f18c642ff7e2]
Signed-off-by: James Houghton <jthoughton@google.com>
---
 arch/x86/include/asm/kvm_host.h |  2 ++
 arch/x86/kvm/lapic.c            | 42 +++++++++++++++++++++++----------
 arch/x86/kvm/svm/svm.c          |  2 ++
 arch/x86/kvm/vmx/vmx.c          |  2 ++
 4 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 257bf2e71d06..39672561c6be 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1650,6 +1650,8 @@ struct kvm_x86_ops {
 	void (*enable_irq_window)(struct kvm_vcpu *vcpu);
 	void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
 	bool (*check_apicv_inhibit_reasons)(enum kvm_apicv_inhibit reason);
+
+	const bool x2apic_icr_is_split;
 	const unsigned long required_apicv_inhibits;
 	bool allow_apicv_in_x2apic_without_x2apic_virtualization;
 	void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index cd9c1e1f6fd3..66c7f2367bb3 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2459,11 +2459,25 @@ int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data)
 	data &= ~APIC_ICR_BUSY;
 
 	kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32));
-	kvm_lapic_set_reg64(apic, APIC_ICR, data);
+	if (kvm_x86_ops.x2apic_icr_is_split) {
+		kvm_lapic_set_reg(apic, APIC_ICR, data);
+		kvm_lapic_set_reg(apic, APIC_ICR2, data >> 32);
+	} else {
+		kvm_lapic_set_reg64(apic, APIC_ICR, data);
+	}
 	trace_kvm_apic_write(APIC_ICR, data);
 	return 0;
 }
 
+static u64 kvm_x2apic_icr_read(struct kvm_lapic *apic)
+{
+	if (kvm_x86_ops.x2apic_icr_is_split)
+		return (u64)kvm_lapic_get_reg(apic, APIC_ICR) |
+		       (u64)kvm_lapic_get_reg(apic, APIC_ICR2) << 32;
+
+	return kvm_lapic_get_reg64(apic, APIC_ICR);
+}
+
 /* emulate APIC access in a trap manner */
 void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
 {
@@ -2481,7 +2495,7 @@ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
 	 * maybe-unecessary write, and both are in the noise anyways.
 	 */
 	if (apic_x2apic_mode(apic) && offset == APIC_ICR)
-		WARN_ON_ONCE(kvm_x2apic_icr_write(apic, kvm_lapic_get_reg64(apic, APIC_ICR)));
+		WARN_ON_ONCE(kvm_x2apic_icr_write(apic, kvm_x2apic_icr_read(apic)));
 	else
 		kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset));
 }
@@ -2988,18 +3002,22 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
 
 		/*
 		 * In x2APIC mode, the LDR is fixed and based on the id.  And
-		 * ICR is internally a single 64-bit register, but needs to be
-		 * split to ICR+ICR2 in userspace for backwards compatibility.
+		 * if the ICR is _not_ split, ICR is internally a single 64-bit
+		 * register, but needs to be split to ICR+ICR2 in userspace for
+		 * backwards compatibility.
 		 */
-		if (set) {
+		if (set)
 			*ldr = kvm_apic_calc_x2apic_ldr(x2apic_id);
 
-			icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
-			      (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;
-			__kvm_lapic_set_reg64(s->regs, APIC_ICR, icr);
-		} else {
-			icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
-			__kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
+		if (!kvm_x86_ops.x2apic_icr_is_split) {
+			if (set) {
+				icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
+				      (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;
+				__kvm_lapic_set_reg64(s->regs, APIC_ICR, icr);
+			} else {
+				icr = __kvm_lapic_get_reg64(s->regs, APIC_ICR);
+				__kvm_lapic_set_reg(s->regs, APIC_ICR2, icr >> 32);
+			}
 		}
 	}
 
@@ -3196,7 +3214,7 @@ static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data)
 	u32 low;
 
 	if (reg == APIC_ICR) {
-		*data = kvm_lapic_get_reg64(apic, APIC_ICR);
+		*data = kvm_x2apic_icr_read(apic);
 		return 0;
 	}
 
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 413f1f2aadd1..d762330bce16 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -5014,6 +5014,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
 	.enable_nmi_window = svm_enable_nmi_window,
 	.enable_irq_window = svm_enable_irq_window,
 	.update_cr8_intercept = svm_update_cr8_intercept,
+
+	.x2apic_icr_is_split = true,
 	.set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
 	.refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl,
 	.apicv_post_state_restore = avic_apicv_post_state_restore,
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 479ef26626f2..52098844290a 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -8323,6 +8323,8 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
 	.enable_nmi_window = vmx_enable_nmi_window,
 	.enable_irq_window = vmx_enable_irq_window,
 	.update_cr8_intercept = vmx_update_cr8_intercept,
+
+	.x2apic_icr_is_split = false,
 	.set_virtual_apic_mode = vmx_set_virtual_apic_mode,
 	.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
 	.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
-- 
2.48.1.362.g079036d154-goog


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly
  2025-02-05 22:26   ` [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly James Houghton
@ 2025-02-07 22:51     ` Sasha Levin
  2025-02-10 23:26     ` Sean Christopherson
  1 sibling, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2025-02-07 22:51 UTC (permalink / raw)
  To: stable; +Cc: James Houghton, Sasha Levin

[ Sasha's backport helper bot ]

Hi,

Found matching upstream commit: 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071

WARNING: Author mismatch between patch and found commit:
Backport author: James Houghton<jthoughton@google.com>
Commit author: Sean Christopherson<seanjc@google.com>


Status in newer kernel trees:
6.13.y | Present (exact SHA1)
6.12.y | Present (exact SHA1)
6.6.y | Not found

Note: The patch differs from the upstream commit:
---
1:  4b7c3f6d04bd5 ! 1:  60f5174104fc8 KVM: x86: Make x2APIC ID 100% readonly
    @@ Commit message
         Signed-off-by: Sean Christopherson <seanjc@google.com>
         Message-ID: <20240802202941.344889-2-seanjc@google.com>
         Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    +    (cherry picked from commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071)
    +    Signed-off-by: James Houghton <jthoughton@google.com>
     
      ## arch/x86/kvm/lapic.c ##
     @@ arch/x86/kvm/lapic.c: static void kvm_recalculate_logical_map(struct kvm_apic_map *new,
---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-6.6.y        |  Success    |  Failed    |

Build Errors:
Build error for stable/linux-6.6.y:
    ssh: connect to host 192.168.1.58 port 22: No route to host

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly
  2025-02-05 22:26   ` [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly James Houghton
  2025-02-07 22:51     ` Sasha Levin
@ 2025-02-10 23:26     ` Sean Christopherson
  2025-02-11  8:35       ` Greg KH
  1 sibling, 1 reply; 8+ messages in thread
From: Sean Christopherson @ 2025-02-10 23:26 UTC (permalink / raw)
  To: James Houghton
  Cc: stable, Maxim Levitsky, Suravee Suthikulpanit, Gavin Guo,
	Michal Luczaj, Haoyu Wu, syzbot+545f1326f405db4e1c3e,
	Paolo Bonzini

On Wed, Feb 05, 2025, James Houghton wrote:
> From: Sean Christopherson <seanjc@google.com>
> 
> Ignore the userspace provided x2APIC ID when fixing up APIC state for
> KVM_SET_LAPIC, i.e. make the x2APIC fully readonly in KVM.  Commit
> a92e2543d6a8 ("KVM: x86: use hardware-compatible format for APIC ID
> register"), which added the fixup, didn't intend to allow userspace to
> modify the x2APIC ID.  In fact, that commit is when KVM first started
> treating the x2APIC ID as readonly, apparently to fix some race:
> 
>  static inline u32 kvm_apic_id(struct kvm_lapic *apic)
>  {
> -       return (kvm_lapic_get_reg(apic, APIC_ID) >> 24) & 0xff;
> +       /* To avoid a race between apic_base and following APIC_ID update when
> +        * switching to x2apic_mode, the x2apic mode returns initial x2apic id.
> +        */
> +       if (apic_x2apic_mode(apic))
> +               return apic->vcpu->vcpu_id;
> +
> +       return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
>  }
> 
> Furthermore, KVM doesn't support delivering interrupts to vCPUs with a
> modified x2APIC ID, but KVM *does* return the modified value on a guest
> RDMSR and for KVM_GET_LAPIC.  I.e. no remotely sane setup can actually
> work with a modified x2APIC ID.
> 
> Making the x2APIC ID fully readonly fixes a WARN in KVM's optimized map
> calculation, which expects the LDR to align with the x2APIC ID.
> 
>   WARNING: CPU: 2 PID: 958 at arch/x86/kvm/lapic.c:331 kvm_recalculate_apic_map+0x609/0xa00 [kvm]
>   CPU: 2 PID: 958 Comm: recalc_apic_map Not tainted 6.4.0-rc3-vanilla+ #35
>   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.2-1-1 04/01/2014
>   RIP: 0010:kvm_recalculate_apic_map+0x609/0xa00 [kvm]
>   Call Trace:
>    <TASK>
>    kvm_apic_set_state+0x1cf/0x5b0 [kvm]
>    kvm_arch_vcpu_ioctl+0x1806/0x2100 [kvm]
>    kvm_vcpu_ioctl+0x663/0x8a0 [kvm]
>    __x64_sys_ioctl+0xb8/0xf0
>    do_syscall_64+0x56/0x80
>    entry_SYSCALL_64_after_hwframe+0x46/0xb0
>   RIP: 0033:0x7fade8b9dd6f
> 
> Unfortunately, the WARN can still trigger for other CPUs than the current
> one by racing against KVM_SET_LAPIC, so remove it completely.
> 
> Reported-by: Michal Luczaj <mhal@rbox.co>
> Closes: https://lore.kernel.org/all/814baa0c-1eaa-4503-129f-059917365e80@rbox.co
> Reported-by: Haoyu Wu <haoyuwu254@gmail.com>
> Closes: https://lore.kernel.org/all/20240126161633.62529-1-haoyuwu254@gmail.com
> Reported-by: syzbot+545f1326f405db4e1c3e@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/000000000000c2a6b9061cbca3c3@google.com
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> Message-ID: <20240802202941.344889-2-seanjc@google.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> (cherry picked from commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071)

FWIW, for upstream LTS backports, the upstream commit information is usually place
at the top, before the original commit's changelog begins, and the blurb explicitly
calls out that it's an upstream commit.  I personally like this style:

  [ Upstream commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071 ]

as I find it easy to visually parse/separate from the original changelog.

> Signed-off-by: James Houghton <jthoughton@google.com>
> ---

Acked-by: Sean Christopherson <seanjc@google.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 6.6.y 2/2] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)
  2025-02-05 22:26   ` [PATCH 6.6.y 2/2] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC) James Houghton
@ 2025-02-10 23:27     ` Sean Christopherson
  0 siblings, 0 replies; 8+ messages in thread
From: Sean Christopherson @ 2025-02-10 23:27 UTC (permalink / raw)
  To: James Houghton; +Cc: stable, Maxim Levitsky, Suravee Suthikulpanit, Gavin Guo

On Wed, Feb 05, 2025, James Houghton wrote:
> From: Sean Christopherson <seanjc@google.com>
> 
> Re-introduce the "split" x2APIC ICR storage that KVM used prior to Intel's
> IPI virtualization support, but only for AMD.  While not stated anywhere
> in the APM, despite stating the ICR is a single 64-bit register, AMD CPUs
> store the 64-bit ICR as two separate 32-bit values in ICR and ICR2.  When
> IPI virtualization (IPIv on Intel, all AVIC flavors on AMD) is enabled,
> KVM needs to match CPU behavior as some ICR ICR writes will be handled by
> the CPU, not by KVM.
> 
> Add a kvm_x86_ops knob to control the underlying format used by the CPU to
> store the x2APIC ICR, and tune it to AMD vs. Intel regardless of whether
> or not x2AVIC is enabled.  If KVM is handling all ICR writes, the storage
> format for x2APIC mode doesn't matter, and having the behavior follow AMD
> versus Intel will provide better test coverage and ease debugging.
> 
> Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode")
> Cc: stable@vger.kernel.org
> Cc: Maxim Levitsky <mlevitsk@redhat.com>
> Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> Link: https://lore.kernel.org/r/20240719235107.3023592-4-seanjc@google.com
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> (cherry picked from commit 73b42dc69be8564d4951a14d00f827929fe5ef79)

Same nit on the upstream info here.  Don't think it warrants a v2? (that's a
question for Sasha and/or Greg).

Acked-by: Sean Christopherson <seanjc@google.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly
  2025-02-10 23:26     ` Sean Christopherson
@ 2025-02-11  8:35       ` Greg KH
  0 siblings, 0 replies; 8+ messages in thread
From: Greg KH @ 2025-02-11  8:35 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: James Houghton, stable, Maxim Levitsky, Suravee Suthikulpanit,
	Gavin Guo, Michal Luczaj, Haoyu Wu, syzbot+545f1326f405db4e1c3e,
	Paolo Bonzini

On Mon, Feb 10, 2025 at 03:26:33PM -0800, Sean Christopherson wrote:
> On Wed, Feb 05, 2025, James Houghton wrote:
> > From: Sean Christopherson <seanjc@google.com>
> > 
> > Ignore the userspace provided x2APIC ID when fixing up APIC state for
> > KVM_SET_LAPIC, i.e. make the x2APIC fully readonly in KVM.  Commit
> > a92e2543d6a8 ("KVM: x86: use hardware-compatible format for APIC ID
> > register"), which added the fixup, didn't intend to allow userspace to
> > modify the x2APIC ID.  In fact, that commit is when KVM first started
> > treating the x2APIC ID as readonly, apparently to fix some race:
> > 
> >  static inline u32 kvm_apic_id(struct kvm_lapic *apic)
> >  {
> > -       return (kvm_lapic_get_reg(apic, APIC_ID) >> 24) & 0xff;
> > +       /* To avoid a race between apic_base and following APIC_ID update when
> > +        * switching to x2apic_mode, the x2apic mode returns initial x2apic id.
> > +        */
> > +       if (apic_x2apic_mode(apic))
> > +               return apic->vcpu->vcpu_id;
> > +
> > +       return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
> >  }
> > 
> > Furthermore, KVM doesn't support delivering interrupts to vCPUs with a
> > modified x2APIC ID, but KVM *does* return the modified value on a guest
> > RDMSR and for KVM_GET_LAPIC.  I.e. no remotely sane setup can actually
> > work with a modified x2APIC ID.
> > 
> > Making the x2APIC ID fully readonly fixes a WARN in KVM's optimized map
> > calculation, which expects the LDR to align with the x2APIC ID.
> > 
> >   WARNING: CPU: 2 PID: 958 at arch/x86/kvm/lapic.c:331 kvm_recalculate_apic_map+0x609/0xa00 [kvm]
> >   CPU: 2 PID: 958 Comm: recalc_apic_map Not tainted 6.4.0-rc3-vanilla+ #35
> >   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.2-1-1 04/01/2014
> >   RIP: 0010:kvm_recalculate_apic_map+0x609/0xa00 [kvm]
> >   Call Trace:
> >    <TASK>
> >    kvm_apic_set_state+0x1cf/0x5b0 [kvm]
> >    kvm_arch_vcpu_ioctl+0x1806/0x2100 [kvm]
> >    kvm_vcpu_ioctl+0x663/0x8a0 [kvm]
> >    __x64_sys_ioctl+0xb8/0xf0
> >    do_syscall_64+0x56/0x80
> >    entry_SYSCALL_64_after_hwframe+0x46/0xb0
> >   RIP: 0033:0x7fade8b9dd6f
> > 
> > Unfortunately, the WARN can still trigger for other CPUs than the current
> > one by racing against KVM_SET_LAPIC, so remove it completely.
> > 
> > Reported-by: Michal Luczaj <mhal@rbox.co>
> > Closes: https://lore.kernel.org/all/814baa0c-1eaa-4503-129f-059917365e80@rbox.co
> > Reported-by: Haoyu Wu <haoyuwu254@gmail.com>
> > Closes: https://lore.kernel.org/all/20240126161633.62529-1-haoyuwu254@gmail.com
> > Reported-by: syzbot+545f1326f405db4e1c3e@syzkaller.appspotmail.com
> > Closes: https://lore.kernel.org/all/000000000000c2a6b9061cbca3c3@google.com
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > Message-ID: <20240802202941.344889-2-seanjc@google.com>
> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> > (cherry picked from commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071)
> 
> FWIW, for upstream LTS backports, the upstream commit information is usually place
> at the top, before the original commit's changelog begins, and the blurb explicitly
> calls out that it's an upstream commit.  I personally like this style:
> 
>   [ Upstream commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071 ]
> 
> as I find it easy to visually parse/separate from the original changelog.

Yes, we prefer it at the top as our tools take it that way, BUT we can
handle it in the footer down here and our tools will rewrite it to the
proper place, so it's not a big deal.

The only problem is when it's not included at all.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-02-11  8:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-01  9:48 FAILED: patch "[PATCH] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)" failed to apply to 6.6-stable tree gregkh
2025-02-05 22:26 ` [PATCH 6.6.y 0/2] KVM: x86: Backport split ICR for x2AVIC James Houghton
2025-02-05 22:26   ` [PATCH 6.6.y 1/2] KVM: x86: Make x2APIC ID 100% readonly James Houghton
2025-02-07 22:51     ` Sasha Levin
2025-02-10 23:26     ` Sean Christopherson
2025-02-11  8:35       ` Greg KH
2025-02-05 22:26   ` [PATCH 6.6.y 2/2] KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC) James Houghton
2025-02-10 23:27     ` Sean Christopherson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).