mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support
@ 2026-09-30  1:13 Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 01/12] KVM: x86: Preserve DR6.BLD (Bus Lock Detect) when delivering #DB payload Sean Christopherson
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Fix KVM's handling of DR6.BLD, and add support for virtualizing BLD on SVM.
KUT tests: https://lore.kernel.org/all/20260925230003.2362261-1-seanjc@google.com

v5:
 - Fix the DR6.BLD clobbering bug Sashiko pointed out. [Sashiko]
 - Force-set fixed-1 bits after synchronizing DR6 from the guest (because the
   guest could set bits that are supposed to be fixed-1 due to virtualization
   holes).
 - Open code nested_vmcb12_has_lbrv().
 - Fix the Author for Ravi's patch.
 - Add svm_need_lbr_virtualization() to preserve short-circuit logic.
 - Rename kvm_dr6_fixed() to kvm_get_dr6_fixed_1().
 - Invert svm_get_debugctl_reserved_bits() into svm_get_supported_debugctl()
   to match VMX, and KVM's preferred style.

v4:
 * Rename nested_vmcb12_has_lbrv() to nested_lbrv_enabled() (Yosry).
 * Drop the redundant !lbrv check and the extra comment (Yosry).
 * Spell out in the changelog what breaks when DR6_BUS_LOCK is forced to 1
   (Nikunj).
 * Make it a pure NFC macro-to-helper conversion, and move the
   BUS_LOCK_DETECT gating to patch 5 (Nikunj).
 * Fold in the DEBUGCTLMSR_BUS_LOCK_DETECT gating moved from patch 4.
 * Collect Reviewed-by tags.

v3:
 * https://lore.kernel.org/kvm/20260709082953.69434-1-shivansh.dhiman@amd.com
 * Reworked the single v2 patch into a prep series (patches 1-4) plus the
   feature.
 * Rewrite svm_update_lbrv() as 'if' statements so the BLD LBRV
   dependency can be added cleanly (Yosry Ahmed).
 * Sanitize V_LBR in the nested control cache like NP/GMET and drop the
   redundant X86_FEATURE_LBRV checks (Yosry Ahmed).
 * Use kvm_dr6_fixed() for nested DR6 instead of DR6_FIXED_1 | DR6_RTM.
 * Compute DEBUGCTL reserved bits per-vCPU, gating BUS_LOCK_DETECT on
   guest CPUID rather than a static macro.

v2:
 * https://lore.kernel.org/kvm/20260629081018.60618-1-shivansh.dhiman@amd.com
 * Rebased on kvm-x86-next-2026.06.24.
 * Used guest_cpu_cap_has() instead of guest_cpuid_has().

v1: https://lore.kernel.org/all/20240808062937.1149-5-ravi.bangoria@amd.com

Ravi Bangoria (1):
  KVM: SVM: Add support for virtualizating Bus Lock Detect

Sean Christopherson (8):
  KVM: x86: Preserve DR6.BLD (Bus Lock Detect) when delivering #DB
    payload
  KVM: x86: Rename kvm_dr6_fixed() => kvm_get_dr6_fixed_1()
  KVM: Return an "unsigned long", not "u64" for the fixed-1 DR6 bits
  KVM: x86: Force fixed-1 bits in DR6 after synchronizing with hardware
  KVM: x86: WARN if fixed-1 DR6 bits aren't already set when delivering
    payload
  KVM: x86: Kill off DR6_FIXED_1 to prevent future misuse
  KVM: SVM: Add helper to query if LBR virtualization needs to be
    enabled
  KVM: nSVM: Open code check on LBR virtualization being enabled in
    vmcb12

Shivansh Dhiman (3):
  KVM: nSVM: Disable LBRV in nested control cache when unsupported
  KVM: nSVM: Don't assume all active-low bits DR6 are fixed-1
  KVM: SVM: Add a vCPU-aware helper to get supported DEBUGCTL bits

 arch/x86/kvm/regs.c       |  8 ++++--
 arch/x86/kvm/regs.h       | 11 ++++----
 arch/x86/kvm/svm/nested.c | 27 ++++++++----------
 arch/x86/kvm/svm/svm.c    | 31 +++++++++++++++-----
 arch/x86/kvm/svm/svm.h    | 12 ++++++--
 arch/x86/kvm/x86.c        | 59 ++++++++++++++++++++++++---------------
 6 files changed, 92 insertions(+), 56 deletions(-)


base-commit: a0bc8e1d7a82bb143b8f8f44ae3a01938f37c2ea
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 01/12] KVM: x86: Preserve DR6.BLD (Bus Lock Detect) when delivering #DB payload
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 02/12] KVM: x86: Rename kvm_dr6_fixed() => kvm_get_dr6_fixed_1() Sean Christopherson
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Preserve Bus Lock Detect if it isn't present in the payload.  Unlike RTM,
which is explicitly modified on every #DB,  DR6.BLD is modified if and only
if the #DB is due to a (coincident) Bus Lock Detect.

Per Intel's SDM:

  Other debug exceptions do not modify this bit.

And AMD's APM

  All other #DB exceptions leave DR6[BLD] unmodified,

Restore the explicit RTM handling that was clobbered by commit
9a3ecd5e2aa1 ("KVM: X86: Rename DR6_INIT to DR6_ACTIVE_LOW"), as the
semantics of any given bit are feature specific, i.e. are obviously not
consistent for active-high versus active-low.  In other words, while the
bug was technically introduced when support for Bus Lock Detect was added,
it's really that attempt to genericize handling of active-low bits that set
KVM up to fail.

Fixes: e8ea85fb280e ("KVM: X86: Add support for the emulation of DR6_BUS_LOCK bit")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/x86.c | 52 ++++++++++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index cf3fcdfd8ad2..ea1406c3b260 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -401,30 +401,37 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu,
 	switch (ex->vector) {
 	case DB_VECTOR:
 		/*
-		 * "Certain debug exceptions may clear bit 0-3.  The
-		 * remaining contents of the DR6 register are never
-		 * cleared by the processor".
+		 * DR6 is a mess.  Reserved/unused bits are fixed-to-1, and so
+		 * to maintain backwards compatibility with existing software,
+		 * features that use previously-reserved bits have active-low
+		 * semantics, i.e. clear the bit when the feature is present in
+		 * the payload.
+		 *
+		 * Further complicating matters, some DR6 bits are preserved by
+		 * hardware, while others are explicitly modified on every #DB.
+		 * The trap bits are always set based on the payload, as is the
+		 * RTM flag (but it's active low).  All other bits are modified
+		 * if and only if a relevant debug exception occurs, e.g. BD,
+		 * BS, and BT are never cleared by hardware, and BLD is never
+		 * set by hardware (when supported, excepting RESET).
+		 *
+		 * Lastly, the payload does NOT have active-low semantics, e.g.
+		 * so that it's compatible VMX's pending debug exceptions and
+		 * qualification fields, and to avoid bleeding the DR6 madness
+		 * into other KVM code.
+		 *
+		 * To compute DR6:
+		 *
+		 *  1. "Reset" the bits that are modified on all #DBs
+		 *  2. Clear active-low bits that are present in the payload.
+		 *  3. Set active-high bits that are present in the payload.
+		 *  4. Clear fixed-0 bits.
+		 *  5. Set fixed-1 bits.
 		 */
 		vcpu->arch.dr6 &= ~DR_TRAP_BITS;
-		/*
-		 * In order to reflect the #DB exception payload in guest
-		 * dr6, three components need to be considered: active low
-		 * bit, FIXED_1 bits and active high bits (e.g. DR6_BD,
-		 * DR6_BS and DR6_BT)
-		 * DR6_ACTIVE_LOW contains the FIXED_1 and active low bits.
-		 * In the target guest dr6:
-		 * FIXED_1 bits should always be set.
-		 * Active low bits should be cleared if 1-setting in payload.
-		 * Active high bits should be set if 1-setting in payload.
-		 *
-		 * Note, the payload is compatible with the pending debug
-		 * exceptions/exit qualification under VMX, that active_low bits
-		 * are active high in payload.
-		 * So they need to be flipped for DR6.
-		 */
-		vcpu->arch.dr6 |= DR6_ACTIVE_LOW;
-		vcpu->arch.dr6 |= ex->payload;
-		vcpu->arch.dr6 ^= ex->payload & DR6_ACTIVE_LOW;
+		vcpu->arch.dr6 |= DR6_RTM;
+		vcpu->arch.dr6 &= ~(ex->payload & DR6_ACTIVE_LOW);
+		vcpu->arch.dr6 |= (ex->payload & ~DR6_ACTIVE_LOW);
 
 		/*
 		 * The #DB payload is defined as compatible with the 'pending
@@ -433,6 +440,7 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu,
 		 * breakpoint), it is reserved and must be zero in DR6.
 		 */
 		vcpu->arch.dr6 &= ~BIT(12);
+		vcpu->arch.dr6 |= DR6_FIXED_1;
 		break;
 	case PF_VECTOR:
 		vcpu->arch.cr2 = ex->payload;
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 02/12] KVM: x86: Rename kvm_dr6_fixed() => kvm_get_dr6_fixed_1()
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 01/12] KVM: x86: Preserve DR6.BLD (Bus Lock Detect) when delivering #DB payload Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 03/12] KVM: Return an "unsigned long", not "u64" for the fixed-1 DR6 bits Sean Christopherson
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Rename kvm_dr6_fixed() to kvm_get_dr6_fixed_1() to make it more clear that
the helper retrieves the fixed-1 DR6 bits for a given vCPU.

No functional change intended.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/regs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index fad31b59c622..62075443f6b9 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -772,7 +772,7 @@ void kvm_update_dr7(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_dr7);
 
-static u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu)
+static u64 kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
 {
 	u64 fixed = DR6_FIXED_1;
 
@@ -798,7 +798,7 @@ int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 	case 6:
 		if (!kvm_dr6_valid(val))
 			return 1; /* #GP */
-		vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_dr6_fixed(vcpu);
+		vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_get_dr6_fixed_1(vcpu);
 		break;
 	case 5:
 	default: /* 7 */
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 03/12] KVM: Return an "unsigned long", not "u64" for the fixed-1 DR6 bits
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 01/12] KVM: x86: Preserve DR6.BLD (Bus Lock Detect) when delivering #DB payload Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 02/12] KVM: x86: Rename kvm_dr6_fixed() => kvm_get_dr6_fixed_1() Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 04/12] KVM: x86: Force fixed-1 bits in DR6 after synchronizing with hardware Sean Christopherson
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Return an "unsigned long" instead of a "u64" from the helper to get the
fixed-1 DR6 bits, as debug registers are natural width registers, not
64-bit registers.

No functional change intended (the fixed-1 bits only set bits in 31:0, and
the sole caller truncates the value to an "unsigned long").

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

diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index 62075443f6b9..f74a29621661 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -772,15 +772,16 @@ void kvm_update_dr7(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_dr7);
 
-static u64 kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
+static unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
 {
-	u64 fixed = DR6_FIXED_1;
+	unsigned long fixed = DR6_FIXED_1;
 
 	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_RTM))
 		fixed |= DR6_RTM;
 
 	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_BUS_LOCK_DETECT))
 		fixed |= DR6_BUS_LOCK;
+
 	return fixed;
 }
 
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 04/12] KVM: x86: Force fixed-1 bits in DR6 after synchronizing with hardware
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (2 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 03/12] KVM: Return an "unsigned long", not "u64" for the fixed-1 DR6 bits Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 05/12] KVM: x86: WARN if fixed-1 DR6 bits aren't already set when delivering payload Sean Christopherson
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Set all fixed-1 bits in KVM's version of DR6 after synchronizing with
hardware to paper over as much of the virtualization hole as possible.
Because KVM dynamically disables DR interception, a guest can write any
DR6 bit that isn't fixed in bare metal, even if the bit is supposed to be
fixed from the guest's perspective.

In addition to providing some amount of consistency in KVM, this will allow
adding sanity checks that KVM never ends up with fixed-1 bits clear in its
version of DR6.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/regs.c | 2 +-
 arch/x86/kvm/regs.h | 1 +
 arch/x86/kvm/x86.c  | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index f74a29621661..db43ade8ceb1 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -772,7 +772,7 @@ void kvm_update_dr7(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_dr7);
 
-static unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
+unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
 {
 	unsigned long fixed = DR6_FIXED_1;
 
diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h
index 447f0ec3e63e..3ca5cd8a8d95 100644
--- a/arch/x86/kvm/regs.h
+++ b/arch/x86/kvm/regs.h
@@ -62,6 +62,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
 int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
 int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val);
 unsigned long kvm_get_dr(struct kvm_vcpu *vcpu, int dr);
+unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu);
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
 int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ea1406c3b260..99518e3265b4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8417,6 +8417,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 		WARN_ON(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH);
 		kvm_x86_call(sync_dirty_debug_regs)(vcpu);
 		kvm_update_dr0123(vcpu);
+		vcpu->arch.dr6 |= kvm_get_dr6_fixed_1(vcpu);
 		kvm_update_dr7(vcpu);
 	}
 
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 05/12] KVM: x86: WARN if fixed-1 DR6 bits aren't already set when delivering payload
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (3 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 04/12] KVM: x86: Force fixed-1 bits in DR6 after synchronizing with hardware Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 06/12] KVM: x86: Kill off DR6_FIXED_1 to prevent future misuse Sean Christopherson
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

WARN if the fixed-1 bits in DR6 aren't already set when delivering a #DB
payload, as (stating the obvious) KVM should never clear fixed-1 bits.

Opportunistically switch to kvm_get_dr6_fixed_1() instead using the more
conservative DR6_FIXED_1, to ensure that bits that are fixed-1 from the
guest's perspective are indeed '1'.  In practice, this aspect should be a
glorified nop specifically because fixed-1 bits should already be set.

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

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 99518e3265b4..5b3918a4ed52 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -399,7 +399,9 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu,
 		return;
 
 	switch (ex->vector) {
-	case DB_VECTOR:
+	case DB_VECTOR: {
+		unsigned long dr6_fixed_1 = kvm_get_dr6_fixed_1(vcpu);
+
 		/*
 		 * DR6 is a mess.  Reserved/unused bits are fixed-to-1, and so
 		 * to maintain backwards compatibility with existing software,
@@ -426,7 +428,7 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu,
 		 *  2. Clear active-low bits that are present in the payload.
 		 *  3. Set active-high bits that are present in the payload.
 		 *  4. Clear fixed-0 bits.
-		 *  5. Set fixed-1 bits.
+		 *  5. Sanity check (and set, if necessary) fixed-1 bits.
 		 */
 		vcpu->arch.dr6 &= ~DR_TRAP_BITS;
 		vcpu->arch.dr6 |= DR6_RTM;
@@ -440,8 +442,10 @@ void kvm_deliver_exception_payload(struct kvm_vcpu *vcpu,
 		 * breakpoint), it is reserved and must be zero in DR6.
 		 */
 		vcpu->arch.dr6 &= ~BIT(12);
-		vcpu->arch.dr6 |= DR6_FIXED_1;
+		if (WARN_ON_ONCE((vcpu->arch.dr6 & dr6_fixed_1) != dr6_fixed_1))
+			vcpu->arch.dr6 |= dr6_fixed_1;
 		break;
+	}
 	case PF_VECTOR:
 		vcpu->arch.cr2 = ex->payload;
 		break;
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 06/12] KVM: x86: Kill off DR6_FIXED_1 to prevent future misuse
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (4 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 05/12] KVM: x86: WARN if fixed-1 DR6 bits aren't already set when delivering payload Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 07/12] KVM: SVM: Add helper to query if LBR virtualization needs to be enabled Sean Christopherson
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Now that the only user of DR6_FIXED_1 is kvm_get_dr6_fixed_1(), drop the
hardcoded macro to force all references to fixed-1 bits to use the vCPU-
aware helper.

Opportunistically reword the comment about DR6_ACTIVE_LOW to explain why
treating fixed-1 bits as active-low is correct (barring a *very* egregious
architectural goof).

No functional change intended.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/regs.c |  2 +-
 arch/x86/kvm/regs.h | 10 ++++------
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index db43ade8ceb1..0c76cf17e884 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -774,7 +774,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_dr7);
 
 unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
 {
-	unsigned long fixed = DR6_FIXED_1;
+	unsigned long fixed = DR6_ACTIVE_LOW & ~DR6_VOLATILE;
 
 	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_RTM))
 		fixed |= DR6_RTM;
diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h
index 3ca5cd8a8d95..97c17b120a57 100644
--- a/arch/x86/kvm/regs.h
+++ b/arch/x86/kvm/regs.h
@@ -38,16 +38,14 @@ static_assert(!(KVM_POSSIBLE_CR0_GUEST_BITS & X86_CR0_PDPTR_BITS));
 #define DR6_BT		(1 << 15)
 #define DR6_RTM		(1 << 16)
 /*
- * DR6_ACTIVE_LOW combines fixed-1 and active-low bits.
- * We can regard all the bits in DR6_FIXED_1 as active_low bits;
- * they will never be 0 for now, but when they are defined
- * in the future it will require no code change.
+ * DR6_ACTIVE_LOW combines fixed-1 and active-low bits (bits that are currently
+ * fixed-1 are guaranteed to have active-low semantics if they are ever used to
+ * support a new feature).
  *
- * DR6_ACTIVE_LOW is also used as the init/reset value for DR6.
+ * Note, DR6_ACTIVE_LOW is also the INIT/RESET value for DR6.
  */
 #define DR6_ACTIVE_LOW	0xffff0ff0
 #define DR6_VOLATILE	0x0001e80f
-#define DR6_FIXED_1	(DR6_ACTIVE_LOW & ~DR6_VOLATILE)
 
 #define DR7_BP_EN_MASK	0x000000ff
 #define DR7_GE		(1 << 9)
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 07/12] KVM: SVM: Add helper to query if LBR virtualization needs to be enabled
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (5 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 06/12] KVM: x86: Kill off DR6_FIXED_1 to prevent future misuse Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 08/12] KVM: nSVM: Disable LBRV in nested control cache when unsupported Sean Christopherson
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Extract the logic for determining whether or not LBR virtualization needs
to be enabled into a helper in anticipation of growing the list of features
that depend on LBR virtualization.

No functional change intended.

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

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 0eb1623052c1..775eccfb7b24 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -875,13 +875,22 @@ static void __svm_disable_lbrv(struct kvm_vcpu *vcpu)
 	to_svm(vcpu)->vmcb->control.misc_ctl2 &= ~SVM_MISC2_ENABLE_V_LBR;
 }
 
+static bool svm_need_lbr_virtualization(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	if (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR)
+		return true;
+
+	return is_guest_mode(vcpu) && guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) &&
+	       (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR);
+}
+
 void svm_update_lbrv(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 	bool current_enable_lbrv = svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR;
-	bool enable_lbrv = (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR) ||
-			    (is_guest_mode(vcpu) && guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) &&
-			    (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR));
+	bool enable_lbrv = svm_need_lbr_virtualization(vcpu);
 
 	if (enable_lbrv && !current_enable_lbrv)
 		__svm_enable_lbrv(vcpu);
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 08/12] KVM: nSVM: Disable LBRV in nested control cache when unsupported
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (6 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 07/12] KVM: SVM: Add helper to query if LBR virtualization needs to be enabled Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 09/12] KVM: nSVM: Open code check on LBR virtualization being enabled in vmcb12 Sean Christopherson
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

From: Shivansh Dhiman <shivansh.dhiman@amd.com>

Clear SVM_MISC2_ENABLE_V_LBR in __nested_copy_vmcb_control_to_cache() when
the vCPU does not support LBR Virtualization. This lets the cached value be
consumed directly instead of re-checking X86_FEATURE_LBRV on every access.

Suggested-by: Yosry Ahmed <yosry@kernel.org>
Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/nested.c | 8 +++++---
 arch/x86/kvm/svm/svm.c    | 2 +-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index b61149814acc..aca2bbc66f47 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -527,12 +527,16 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcpu *vcpu,
 
 	/* Always clear misc_ctl bits that the guest cannot use */
 	to->misc_ctl = from->misc_ctl;
+	to->misc_ctl2 = from->misc_ctl2;
 	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_NPT))
 		to->misc_ctl &= ~SVM_MISC_ENABLE_NP;
 
 	if (!gmet_enabled || !guest_cpu_cap_has(vcpu, X86_FEATURE_GMET))
 		to->misc_ctl &= ~SVM_MISC_ENABLE_GMET;
 
+	if (!guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV))
+		to->misc_ctl2 &= ~SVM_MISC2_ENABLE_V_LBR;
+
 	to->iopm_base_pa        = from->iopm_base_pa & PAGE_MASK;
 	to->msrpm_base_pa       = from->msrpm_base_pa & PAGE_MASK;
 	to->tsc_offset          = from->tsc_offset;
@@ -550,7 +554,6 @@ void __nested_copy_vmcb_control_to_cache(struct kvm_vcpu *vcpu,
 	to->event_inj_err       = from->event_inj_err;
 	to->next_rip            = from->next_rip;
 	to->nested_cr3          = from->nested_cr3;
-	to->misc_ctl2		= from->misc_ctl2;
 	to->pause_filter_count  = from->pause_filter_count;
 	to->pause_filter_thresh = from->pause_filter_thresh;
 
@@ -737,8 +740,7 @@ static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
 
 static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vcpu)
 {
-	return guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) &&
-		(to_svm(vcpu)->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR);
+	return to_svm(vcpu)->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR;
 }
 
 static void nested_vmcb02_prepare_save(struct vcpu_svm *svm)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 775eccfb7b24..5253c0143666 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -882,7 +882,7 @@ static bool svm_need_lbr_virtualization(struct kvm_vcpu *vcpu)
 	if (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR)
 		return true;
 
-	return is_guest_mode(vcpu) && guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) &&
+	return is_guest_mode(vcpu) &&
 	       (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR);
 }
 
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 09/12] KVM: nSVM: Open code check on LBR virtualization being enabled in vmcb12
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (7 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 08/12] KVM: nSVM: Disable LBRV in nested control cache when unsupported Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 10/12] KVM: nSVM: Don't assume all active-low bits DR6 are fixed-1 Sean Christopherson
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

Now that KVM clears ENABLE_V_LBR if LBR virtualization isn't supported when
caching vmcb12 control fields, i.e. now that the logic is a simple
one-liner, open the check and drop the now-superfluous wrapper.

No functional change intended.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/nested.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index aca2bbc66f47..d3f249cd0f2d 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -738,11 +738,6 @@ static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
 	return 0;
 }
 
-static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vcpu)
-{
-	return to_svm(vcpu)->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR;
-}
-
 static void nested_vmcb02_prepare_save(struct vcpu_svm *svm)
 {
 	struct vmcb_ctrl_area_cached *control = &svm->nested.ctl;
@@ -817,7 +812,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm)
 		vmcb_mark_dirty(vmcb02, VMCB_DR);
 	}
 
-	if (nested_vmcb12_has_lbrv(vcpu)) {
+	if (control->misc_ctl2 & SVM_MISC2_ENABLE_V_LBR) {
 		/*
 		 * Reserved bits of DEBUGCTL are ignored.  Be consistent with
 		 * svm_set_msr's definition of reserved bits.
@@ -1310,7 +1305,7 @@ static int nested_svm_vmexit_update_vmcb12(struct kvm_vcpu *vcpu)
 	if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS))
 		vmcb12->control.next_rip  = vmcb02->control.next_rip;
 
-	if (nested_vmcb12_has_lbrv(vcpu))
+	if (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR)
 		svm_copy_lbrs(&vmcb12->save, &vmcb02->save);
 
 	vmcb12->control.event_inj	  = 0;
@@ -1387,7 +1382,7 @@ void nested_svm_vmexit(struct vcpu_svm *svm)
 	if (!nested_exit_on_intr(svm))
 		kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 
-	if (!nested_vmcb12_has_lbrv(vcpu)) {
+	if (!(svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR)) {
 		svm_copy_lbrs(&vmcb01->save, &vmcb02->save);
 		vmcb_mark_dirty(vmcb01, VMCB_LBR);
 	}
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 10/12] KVM: nSVM: Don't assume all active-low bits DR6 are fixed-1
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (8 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 09/12] KVM: nSVM: Open code check on LBR virtualization being enabled in vmcb12 Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 11/12] KVM: SVM: Add a vCPU-aware helper to get supported DEBUGCTL bits Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 12/12] KVM: SVM: Add support for virtualizating Bus Lock Detect Sean Christopherson
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

From: Shivansh Dhiman <shivansh.dhiman@amd.com>

When preparing vmcb02 for nested VMRUN, force only the actual fixed-1 bits
instead of setting all active-low bits.  The flaw is currently benign, as
the only active-low bits supported by KVM are RTM (Restricted Transactional
Memory) and BLD (Bus Lock Detect), neither of which is currently supported
on SVM, but that's about to change.

Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
[sean: massage changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/regs.c       | 1 +
 arch/x86/kvm/svm/nested.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index 0c76cf17e884..3621f1a47d37 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -784,6 +784,7 @@ unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu)
 
 	return fixed;
 }
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_dr6_fixed_1);
 
 int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 {
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index d3f249cd0f2d..c7a69e309a36 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -808,7 +808,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm)
 
 	if (unlikely(new_vmcb12 || vmcb12_is_dirty(control, VMCB_DR))) {
 		vmcb02->save.dr7 = svm->nested.save.dr7 | DR7_FIXED_1;
-		svm->vcpu.arch.dr6  = svm->nested.save.dr6 | DR6_ACTIVE_LOW;
+		svm->vcpu.arch.dr6  = svm->nested.save.dr6 | kvm_get_dr6_fixed_1(vcpu);
 		vmcb_mark_dirty(vmcb02, VMCB_DR);
 	}
 
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 11/12] KVM: SVM: Add a vCPU-aware helper to get supported DEBUGCTL bits
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (9 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 10/12] KVM: nSVM: Don't assume all active-low bits DR6 are fixed-1 Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  2026-09-30  1:13 ` [PATCH v5 12/12] KVM: SVM: Add support for virtualizating Bus Lock Detect Sean Christopherson
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

From: Shivansh Dhiman <shivansh.dhiman@amd.com>

Replace DEBUGCTL_RESERVED_BITS with a vCPU-aware helper that provides the
set of supported bits so that KVM can handle bits that are conditionally
supported based on the vCPU model, e.g. for features like Bus Lock Detect.

No functional change intended.

Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
Reviewed-by: Nikunj A Dadhania <nikunj@amd.com>
[sean: invert from reserved => supported, massage changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/nested.c | 8 ++++----
 arch/x86/kvm/svm/svm.c    | 6 +++---
 arch/x86/kvm/svm/svm.h    | 7 +++++--
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index c7a69e309a36..af0ef678433d 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -818,7 +818,7 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm)
 		 * svm_set_msr's definition of reserved bits.
 		 */
 		svm_copy_lbrs(&vmcb02->save, save);
-		vmcb02->save.dbgctl &= ~DEBUGCTL_RESERVED_BITS;
+		vmcb02->save.dbgctl &= svm_get_supported_debugctl(vcpu);
 	} else {
 		svm_copy_lbrs(&vmcb02->save, &vmcb01->save);
 	}
@@ -1207,7 +1207,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu)
 }
 
 /* Copy state save area fields which are handled by VMRUN */
-void svm_copy_vmrun_state(struct vmcb_save_area *to_save,
+void svm_copy_vmrun_state(struct kvm_vcpu *vcpu, struct vmcb_save_area *to_save,
 			  struct vmcb_save_area *from_save)
 {
 	to_save->es = from_save->es;
@@ -1234,7 +1234,7 @@ void svm_copy_vmrun_state(struct vmcb_save_area *to_save,
 
 	if (kvm_cpu_cap_has(X86_FEATURE_LBRV)) {
 		svm_copy_lbrs(to_save, from_save);
-		to_save->dbgctl &= ~DEBUGCTL_RESERVED_BITS;
+		to_save->dbgctl &= svm_get_supported_debugctl(vcpu);
 	}
 }
 
@@ -2081,7 +2081,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
 
 	svm->nested.vmcb12_gpa = kvm_state->hdr.svm.vmcb_pa;
 
-	svm_copy_vmrun_state(&svm->vmcb01.ptr->save, save);
+	svm_copy_vmrun_state(vcpu, &svm->vmcb01.ptr->save, save);
 	nested_copy_vmcb_control_to_cache(svm, ctl);
 
 	svm_switch_vmcb(svm, &svm->nested.vmcb02);
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 5253c0143666..1e58ad8691e9 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3210,7 +3210,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 			data &= ~DEBUGCTLMSR_BTF;
 		}
 
-		if (data & DEBUGCTL_RESERVED_BITS)
+		if (data & ~svm_get_supported_debugctl(vcpu))
 			return 1;
 
 		if (svm->vmcb->save.dbgctl == data)
@@ -5164,7 +5164,7 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram)
 
 	BUILD_BUG_ON(offsetof(struct vmcb, save) != 0x400);
 
-	svm_copy_vmrun_state(m_save.map.hva + 0x400, &svm->vmcb01.ptr->save);
+	svm_copy_vmrun_state(vcpu, m_save.map.hva + 0x400, &svm->vmcb01.ptr->save);
 	return 0;
 }
 
@@ -5204,7 +5204,7 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram)
 	 * used during SMM (see svm_enter_smm())
 	 */
 
-	svm_copy_vmrun_state(&svm->vmcb01.ptr->save, m_save.map.hva + 0x400);
+	svm_copy_vmrun_state(vcpu, &svm->vmcb01.ptr->save, m_save.map.hva + 0x400);
 
 	/*
 	 * Enter the nested guest now
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index ac6160d78e15..c3380d865b75 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -787,7 +787,10 @@ BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test)
 BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear)
 BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set)
 
-#define DEBUGCTL_RESERVED_BITS (~DEBUGCTLMSR_LBR)
+static inline u64 svm_get_supported_debugctl(struct kvm_vcpu *vcpu)
+{
+	return DEBUGCTLMSR_LBR;
+}
 
 /* svm.c */
 extern bool dump_invalid_vmcb;
@@ -877,7 +880,7 @@ void svm_leave_nested(struct kvm_vcpu *vcpu);
 void svm_free_nested(struct vcpu_svm *svm);
 int svm_allocate_nested(struct vcpu_svm *svm);
 int nested_svm_vmrun(struct kvm_vcpu *vcpu);
-void svm_copy_vmrun_state(struct vmcb_save_area *to_save,
+void svm_copy_vmrun_state(struct kvm_vcpu *vcpu, struct vmcb_save_area *to_save,
 			  struct vmcb_save_area *from_save);
 void svm_copy_vmloadsave_state(struct vmcb *to_vmcb, struct vmcb *from_vmcb);
 void nested_svm_vmexit(struct vcpu_svm *svm);
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

* [PATCH v5 12/12] KVM: SVM: Add support for virtualizating Bus Lock Detect
  2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
                   ` (10 preceding siblings ...)
  2026-09-30  1:13 ` [PATCH v5 11/12] KVM: SVM: Add a vCPU-aware helper to get supported DEBUGCTL bits Sean Christopherson
@ 2026-09-30  1:13 ` Sean Christopherson
  11 siblings, 0 replies; 13+ messages in thread
From: Sean Christopherson @ 2026-09-30  1:13 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini
  Cc: kvm, linux-kernel, Yosry Ahmed, Shivansh Dhiman,
	Nikunj A Dadhania, Ravi Bangoria, Tom Lendacky

From: Ravi Bangoria <ravi.bangoria@amd.com>

Advertise support for virtualizing Bus Lock Detect and allow the guest to
enable BUS_LOCK_DETECT if LBR Virtualization is enabled (Bus Lock Detect is
enabled through MSR_IA32_DEBUGCTLMSR, which context-switched if and only if
LBR Virtualization is enabled).

Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Co-developed-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
[sean: massage changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/svm.c | 12 ++++++++++--
 arch/x86/kvm/svm/svm.h |  7 ++++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 1e58ad8691e9..e7c296c52591 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -879,7 +879,7 @@ static bool svm_need_lbr_virtualization(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR)
+	if (svm->vmcb->save.dbgctl & (DEBUGCTLMSR_LBR | DEBUGCTLMSR_BUS_LOCK_DETECT))
 		return true;
 
 	return is_guest_mode(vcpu) &&
@@ -5712,9 +5712,17 @@ static __init void svm_set_cpu_caps(void)
 	 * Clear capabilities that are automatically configured by common code,
 	 * but that require explicit SVM support (that isn't yet implemented).
 	 */
-	kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
 	kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);
 
+	/*
+	 * LBR Virtualization must be enabled to support BusLockTrap inside the
+	 * guest, since BusLockTrap is enabled through MSR_IA32_DEBUGCTLMSR and
+	 * MSR_IA32_DEBUGCTLMSR is virtualized only if LBR Virtualization is
+	 * enabled.
+	 */
+	if (!lbrv)
+		kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
+
 	kvm_setup_xss_caps();
 	kvm_finalize_cpu_caps();
 }
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index c3380d865b75..6d0242966dc8 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -789,7 +789,12 @@ BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set)
 
 static inline u64 svm_get_supported_debugctl(struct kvm_vcpu *vcpu)
 {
-	return DEBUGCTLMSR_LBR;
+	u64 debugctl = DEBUGCTLMSR_LBR;
+
+	if (guest_cpu_cap_has(vcpu, X86_FEATURE_BUS_LOCK_DETECT))
+		debugctl |= DEBUGCTLMSR_BUS_LOCK_DETECT;
+
+	return debugctl;
 }
 
 /* svm.c */
-- 
2.56.0.rc1.315.gc6ed9934b7-goog


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

end of thread, other threads:[~2026-09-30  1:13 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-30  1:13 [PATCH v5 00/12] KVM: x86: Bus Lock Detect fixes and SVM support Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 01/12] KVM: x86: Preserve DR6.BLD (Bus Lock Detect) when delivering #DB payload Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 02/12] KVM: x86: Rename kvm_dr6_fixed() => kvm_get_dr6_fixed_1() Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 03/12] KVM: Return an "unsigned long", not "u64" for the fixed-1 DR6 bits Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 04/12] KVM: x86: Force fixed-1 bits in DR6 after synchronizing with hardware Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 05/12] KVM: x86: WARN if fixed-1 DR6 bits aren't already set when delivering payload Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 06/12] KVM: x86: Kill off DR6_FIXED_1 to prevent future misuse Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 07/12] KVM: SVM: Add helper to query if LBR virtualization needs to be enabled Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 08/12] KVM: nSVM: Disable LBRV in nested control cache when unsupported Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 09/12] KVM: nSVM: Open code check on LBR virtualization being enabled in vmcb12 Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 10/12] KVM: nSVM: Don't assume all active-low bits DR6 are fixed-1 Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 11/12] KVM: SVM: Add a vCPU-aware helper to get supported DEBUGCTL bits Sean Christopherson
2026-09-30  1:13 ` [PATCH v5 12/12] KVM: SVM: Add support for virtualizating Bus Lock Detect Sean Christopherson

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

all inboxes | Powered by JetHome®