* [PATCH v4 1/5] KVM: SVM: Refactor svm_update_lbrv()
2026-07-21 5:05 [PATCH v4 0/5] KVM: SVM: Add Bus Lock Detect support and refactor LBRV Shivansh Dhiman
@ 2026-07-21 5:05 ` Shivansh Dhiman
2026-07-21 6:40 ` Nikunj A. Dadhania
2026-07-21 5:05 ` [PATCH v4 2/5] KVM: nSVM: Disable LBRV in nested control cache when unsupported Shivansh Dhiman
` (3 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Shivansh Dhiman @ 2026-07-21 5:05 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo
Cc: kvm, x86, yosry, jmattson, thomas.lendacky, nikunj.dadhania,
ravi.bangoria, santosh.shukla, shivansh.dhiman
Rewrite the enable_lbrv computation in svm_update_lbrv() as a series of
'if' statements. Rename nested_vmcb12_has_lbrv() to nested_lbrv_enabled(),
expose it, and use it instead of open-coding the nested LBRV check.
No functional change intended.
Suggested-by: Yosry Ahmed <yosry@kernel.org>
Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
Reviewed-by: Yosry Ahmed <yosry@kernel.org>
---
Changelog:
v3 -> v4:
* Rename nested_vmcb12_has_lbrv() to nested_lbrv_enabled() (Yosry).
* Collected Reviewed-by from Yosry.
v3:
* New patch.
* Refactor the enable_lbrv computation into 'if' statements (Yosry Ahmed).
---
arch/x86/kvm/svm/nested.c | 8 ++++----
arch/x86/kvm/svm/svm.c | 10 +++++++---
arch/x86/kvm/svm/svm.h | 1 +
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index c1485c3e691c..52b8d0f9b139 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -736,7 +736,7 @@ 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)
+bool nested_lbrv_enabled(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);
@@ -812,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 (nested_lbrv_enabled(vcpu)) {
/*
* Reserved bits of DEBUGCTL are ignored. Be consistent with
* svm_set_msr's definition of reserved bits.
@@ -1301,7 +1301,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 (nested_lbrv_enabled(vcpu))
svm_copy_lbrs(&vmcb12->save, &vmcb02->save);
vmcb12->control.event_inj = 0;
@@ -1379,7 +1379,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 (!nested_lbrv_enabled(vcpu)) {
svm_copy_lbrs(&vmcb01->save, &vmcb02->save);
vmcb_mark_dirty(vmcb01, VMCB_LBR);
}
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index ef69a51ab27f..e9f2456982d4 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -880,9 +880,13 @@ 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 = false;
+
+ if (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR)
+ enable_lbrv = true;
+
+ if (is_guest_mode(vcpu) && nested_lbrv_enabled(vcpu))
+ enable_lbrv = true;
if (enable_lbrv && !current_enable_lbrv)
__svm_enable_lbrv(vcpu);
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 716be21fba33..d52010e4de97 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -899,6 +899,7 @@ void nested_copy_vmcb_control_to_cache(struct vcpu_svm *svm,
void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm,
struct vmcb_save_area *save);
void nested_sync_control_from_vmcb02(struct vcpu_svm *svm);
+bool nested_lbrv_enabled(struct kvm_vcpu *vcpu);
void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v4 1/5] KVM: SVM: Refactor svm_update_lbrv()
2026-07-21 5:05 ` [PATCH v4 1/5] KVM: SVM: Refactor svm_update_lbrv() Shivansh Dhiman
@ 2026-07-21 6:40 ` Nikunj A. Dadhania
2026-07-21 9:16 ` Shivansh Dhiman
0 siblings, 1 reply; 9+ messages in thread
From: Nikunj A. Dadhania @ 2026-07-21 6:40 UTC (permalink / raw)
To: Shivansh Dhiman, seanjc, pbonzini, tglx, mingo
Cc: kvm, x86, yosry, jmattson, thomas.lendacky, nikunj.dadhania,
ravi.bangoria, santosh.shukla
On 7/21/2026 10:35 AM, Shivansh Dhiman wrote:
> Rewrite the enable_lbrv computation in svm_update_lbrv() as a series of
> 'if' statements. Rename nested_vmcb12_has_lbrv() to nested_lbrv_enabled(),
> expose it, and use it instead of open-coding the nested LBRV check.
>
> No functional change intended.
>
> Suggested-by: Yosry Ahmed <yosry@kernel.org>
> Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
> Reviewed-by: Yosry Ahmed <yosry@kernel.org>
Reviewed-by: Nikunj A Dadhania <nikunj@amd.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v4 1/5] KVM: SVM: Refactor svm_update_lbrv()
2026-07-21 6:40 ` Nikunj A. Dadhania
@ 2026-07-21 9:16 ` Shivansh Dhiman
0 siblings, 0 replies; 9+ messages in thread
From: Shivansh Dhiman @ 2026-07-21 9:16 UTC (permalink / raw)
To: Nikunj A. Dadhania
Cc: seanjc, pbonzini, tglx, mingo, kvm, x86, yosry, jmattson,
thomas.lendacky, nikunj.dadhania, ravi.bangoria, santosh.shukla,
Shivansh Dhiman
On 21-07-26 12:10, Nikunj A. Dadhania wrote:
>
>
> On 7/21/2026 10:35 AM, Shivansh Dhiman wrote:
>> Rewrite the enable_lbrv computation in svm_update_lbrv() as a series of
>> 'if' statements. Rename nested_vmcb12_has_lbrv() to nested_lbrv_enabled(),
>> expose it, and use it instead of open-coding the nested LBRV check.
>>
>> No functional change intended.
>>
>> Suggested-by: Yosry Ahmed <yosry@kernel.org>
>> Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
>> Reviewed-by: Yosry Ahmed <yosry@kernel.org>
>
> Reviewed-by: Nikunj A Dadhania <nikunj@amd.com>
>
Thanks for reviewing my patch.
Regards,
Shivansh
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 2/5] KVM: nSVM: Disable LBRV in nested control cache when unsupported
2026-07-21 5:05 [PATCH v4 0/5] KVM: SVM: Add Bus Lock Detect support and refactor LBRV Shivansh Dhiman
2026-07-21 5:05 ` [PATCH v4 1/5] KVM: SVM: Refactor svm_update_lbrv() Shivansh Dhiman
@ 2026-07-21 5:05 ` Shivansh Dhiman
2026-07-21 5:05 ` [PATCH v4 3/5] KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed() Shivansh Dhiman
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Shivansh Dhiman @ 2026-07-21 5:05 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo
Cc: kvm, x86, yosry, jmattson, thomas.lendacky, nikunj.dadhania,
ravi.bangoria, santosh.shukla, shivansh.dhiman
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>
---
Changelog:
v3 -> v4:
* Drop the redundant !lbrv check and the extra comment (Yosry).
v3:
* New patch.
* Sanitize V_LBR in the cache and drop the redundant X86_FEATURE_LBRV
checks (Yosry Ahmed).
---
arch/x86/kvm/svm/nested.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 52b8d0f9b139..8d1967f5c099 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -528,12 +528,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;
@@ -551,7 +555,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;
@@ -738,8 +741,7 @@ static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
bool nested_lbrv_enabled(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)
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 3/5] KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed()
2026-07-21 5:05 [PATCH v4 0/5] KVM: SVM: Add Bus Lock Detect support and refactor LBRV Shivansh Dhiman
2026-07-21 5:05 ` [PATCH v4 1/5] KVM: SVM: Refactor svm_update_lbrv() Shivansh Dhiman
2026-07-21 5:05 ` [PATCH v4 2/5] KVM: nSVM: Disable LBRV in nested control cache when unsupported Shivansh Dhiman
@ 2026-07-21 5:05 ` Shivansh Dhiman
2026-07-21 5:21 ` sashiko-bot
2026-07-21 5:05 ` [PATCH v4 4/5] KVM: SVM: Turn DEBUGCTL_RESERVED_BITS into a helper Shivansh Dhiman
2026-07-21 5:06 ` [PATCH v4 5/5] KVM: SVM: Add Bus Lock Detect support Shivansh Dhiman
4 siblings, 1 reply; 9+ messages in thread
From: Shivansh Dhiman @ 2026-07-21 5:05 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo
Cc: kvm, x86, yosry, jmattson, thomas.lendacky, nikunj.dadhania,
ravi.bangoria, santosh.shukla, shivansh.dhiman
When preparing vmcb02 for nested VMRUN, KVM ORs DR6_ACTIVE_LOW into the
guest DR6 to force the fixed bits to 1. DR6_ACTIVE_LOW forces bit 11
(DR6_BUS_LOCK) to 1 unconditionally.
DR6_BUS_LOCK is active-low (the CPU clears it to 0 to report a bus lock), so
forcing it to 1 unconditionally would prevent an L2 from ever observing a
bus lock (DR6.BLD == 0) across a nested VMRUN.
Use kvm_dr6_fixed() instead, which forces DR6_RTM and DR6_BUS_LOCK based on
the guest's CPUID. DR6_RTM is a reserved bit on AMD and is thus always set
to 1. DR6_BUS_LOCK is left writable once the guest supports Bus Lock
Detect.
Signed-off-by: Shivansh Dhiman <shivansh.dhiman@amd.com>
---
Changelog:
v3 -> v4:
* Spell out what breaks when DR6_BUS_LOCK is forced to 1 (Nikunj).
v3:
* New patch.
* Use kvm_dr6_fixed() instead of open-coding DR6_FIXED_1 | DR6_RTM.
---
arch/x86/kvm/regs.c | 3 ++-
arch/x86/kvm/regs.h | 1 +
arch/x86/kvm/svm/nested.c | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/regs.c b/arch/x86/kvm/regs.c
index d2caf5a67dba..1b5dfa765140 100644
--- a/arch/x86/kvm/regs.c
+++ b/arch/x86/kvm/regs.c
@@ -764,7 +764,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)
+u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu)
{
u64 fixed = DR6_FIXED_1;
@@ -775,6 +775,7 @@ static u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu)
fixed |= DR6_BUS_LOCK;
return fixed;
}
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_dr6_fixed);
int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
{
diff --git a/arch/x86/kvm/regs.h b/arch/x86/kvm/regs.h
index 94fd86728fed..e85c3ff3e120 100644
--- a/arch/x86/kvm/regs.h
+++ b/arch/x86/kvm/regs.h
@@ -23,6 +23,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
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);
+u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu);
unsigned long kvm_get_dr(struct kvm_vcpu *vcpu, int dr);
unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw);
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 8d1967f5c099..9b1afa47c54c 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -810,7 +810,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_dr6_fixed(vcpu);
vmcb_mark_dirty(vmcb02, VMCB_DR);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v4 3/5] KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed()
2026-07-21 5:05 ` [PATCH v4 3/5] KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed() Shivansh Dhiman
@ 2026-07-21 5:21 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-07-21 5:21 UTC (permalink / raw)
To: Shivansh Dhiman; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] kvm_deliver_exception_payload() incorrectly clears previously accumulated active-low DR6 events (such as DR6_BUS_LOCK and DR6_RTM) upon subsequent #DB exceptions.
--
--- Patch [3]: [PATCH v4 3/5] KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed() ---
commit eaefa84a8068404a2e75f11446b9fa345fef2bae
Author: Shivansh Dhiman <shivansh.dhiman@amd.com>
KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed()
When preparing vmcb02 for nested VMRUN, KVM ORs DR6_ACTIVE_LOW into the
guest DR6 to force the fixed bits to 1. DR6_ACTIVE_LOW forces bit 11
(DR6_BUS_LOCK) to 1 unconditionally.
> diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
> index 8d1967f5c099f..9b1afa47c54c9 100644
> --- a/arch/x86/kvm/svm/nested.c
> +++ b/arch/x86/kvm/svm/nested.c
> @@ -810,7 +810,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_dr6_fixed(vcpu);
[Severity: High]
This isn't a bug introduced by this patch, but kvm_deliver_exception_payload()
in arch/x86/kvm/x86.c has the exact same flaw with DR6_ACTIVE_LOW.
Could it be fixed using the newly exported kvm_dr6_fixed() helper?
Currently, kvm_deliver_exception_payload() executes:
case DB_VECTOR:
...
vcpu->arch.dr6 |= DR6_ACTIVE_LOW;
vcpu->arch.dr6 |= ex->payload;
vcpu->arch.dr6 ^= ex->payload & DR6_ACTIVE_LOW;
This unconditionally forces all active-low bits to 1 before applying the
current exception payload, destroying any previously accumulated 0 bits.
If a guest OS relies on the Bus Lock Detect #DB to mitigate DoS attacks,
and another #DB event (like a Single Step) occurs before the guest clears
DR6, kvm_deliver_exception_payload() will force DR6 bit 11 back to 1.
Because the new #DB payload does not have the bus lock bit set, the
subsequent XOR leaves bit 11 as 1.
Does this destroy the accumulated event and allow a malicious task to evade
detection?
Could this be updated to use kvm_dr6_fixed(vcpu) instead of DR6_ACTIVE_LOW
to avoid clearing previously accumulated active-low DR6 events?
> vmcb_mark_dirty(vmcb02, VMCB_DR);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260721050600.87268-1-shivansh.dhiman@amd.com?part=3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v4 4/5] KVM: SVM: Turn DEBUGCTL_RESERVED_BITS into a helper
2026-07-21 5:05 [PATCH v4 0/5] KVM: SVM: Add Bus Lock Detect support and refactor LBRV Shivansh Dhiman
` (2 preceding siblings ...)
2026-07-21 5:05 ` [PATCH v4 3/5] KVM: nSVM: Sanitize nested DR6 using kvm_dr6_fixed() Shivansh Dhiman
@ 2026-07-21 5:05 ` Shivansh Dhiman
2026-07-21 5:06 ` [PATCH v4 5/5] KVM: SVM: Add Bus Lock Detect support Shivansh Dhiman
4 siblings, 0 replies; 9+ messages in thread
From: Shivansh Dhiman @ 2026-07-21 5:05 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo
Cc: kvm, x86, yosry, jmattson, thomas.lendacky, nikunj.dadhania,
ravi.bangoria, santosh.shukla, shivansh.dhiman
Replace the static DEBUGCTL_RESERVED_BITS macro with a helper,
svm_get_debugctl_reserved_bits(), and plumb the vCPU into
svm_copy_vmrun_state() so it can be passed to the helper.
The vCPU argument is currently unused (marked __maybe_unused).
It'll be used by 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>
---
Changelog:
v3 -> v4:
* Make it a pure NFC macro-to-helper conversion, and move the
BUS_LOCK_DETECT gating to patch 5 (Nikunj).
* Dropped Ravi's Co-developed-by/Signed-off-by, because the
entire BLD gating is moved to patch 5. Collected Reviewed-by
from Nikunj.
v3:
* New patch.
* Replaced the static DEBUGCTL_RESERVED_BITS macro with a per-vCPU helper
that gates the bit on guest CPUID.
---
arch/x86/kvm/svm/nested.c | 8 ++++----
arch/x86/kvm/svm/svm.c | 7 +++----
arch/x86/kvm/svm/svm.h | 7 +++++--
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 9b1afa47c54c..dbde186ccb81 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -820,7 +820,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_debugctl_reserved_bits(vcpu);
} else {
svm_copy_lbrs(&vmcb02->save, &vmcb01->save);
}
@@ -1203,7 +1203,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;
@@ -1230,7 +1230,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_debugctl_reserved_bits(vcpu);
}
}
@@ -2071,7 +2071,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 e9f2456982d4..ccf85ea79d37 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3164,7 +3164,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_debugctl_reserved_bits(vcpu))
return 1;
if (svm->vmcb->save.dbgctl == data)
@@ -5037,8 +5037,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(map_save.hva + 0x400,
- &svm->vmcb01.ptr->save);
+ svm_copy_vmrun_state(vcpu, map_save.hva + 0x400, &svm->vmcb01.ptr->save);
kvm_vcpu_unmap(vcpu, &map_save);
return 0;
@@ -5081,7 +5080,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, map_save.hva + 0x400);
+ svm_copy_vmrun_state(vcpu, &svm->vmcb01.ptr->save, map_save.hva + 0x400);
/*
* Enter the nested guest now
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index d52010e4de97..696f1b4b8f8f 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -783,7 +783,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_debugctl_reserved_bits(struct kvm_vcpu *vcpu __maybe_unused)
+{
+ return ~DEBUGCTLMSR_LBR;
+}
/* svm.c */
extern bool dump_invalid_vmcb;
@@ -873,7 +876,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.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 5/5] KVM: SVM: Add Bus Lock Detect support
2026-07-21 5:05 [PATCH v4 0/5] KVM: SVM: Add Bus Lock Detect support and refactor LBRV Shivansh Dhiman
` (3 preceding siblings ...)
2026-07-21 5:05 ` [PATCH v4 4/5] KVM: SVM: Turn DEBUGCTL_RESERVED_BITS into a helper Shivansh Dhiman
@ 2026-07-21 5:06 ` Shivansh Dhiman
4 siblings, 0 replies; 9+ messages in thread
From: Shivansh Dhiman @ 2026-07-21 5:06 UTC (permalink / raw)
To: seanjc, pbonzini, tglx, mingo
Cc: kvm, x86, yosry, jmattson, thomas.lendacky, nikunj.dadhania,
ravi.bangoria, santosh.shukla, shivansh.dhiman
Add Bus Lock Detect support in AMD SVM. Bus Lock Detect is enabled through
MSR_IA32_DEBUGCTLMSR and MSR_IA32_DEBUGCTLMSR is virtualized only if LBR
Virtualization is enabled. Add this dependency in the SVM.
Also, allow DEBUGCTLMSR_BUS_LOCK_DETECT only when the guest supports Bus
Lock Detect.
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>
---
Changelog:
v3 -> v4:
* Fold in the DEBUGCTLMSR_BUS_LOCK_DETECT gating moved from patch 4.
v2 -> v3:
* Split refactor and prep changes out into patches 1-4; this patch now
only wires up the LBRV dependency and exposes the capability.
v2 Resend:
* Rebased on top of tag: kvm-x86-next-2026.06.24.
v1 -> v2:
* Rebased and used guest_cpu_cap_has() instead of guest_cpuid_has().
v2 Resend: https://lore.kernel.org/kvm/20260629081018.60618-1-shivansh.dhiman@amd.com/
v2: https://lore.kernel.org/kvm/20251121081228.426974-1-shivansh.dhiman@amd.com/
v1: https://lore.kernel.org/all/20240808062937.1149-5-ravi.bangoria@amd.com
---
arch/x86/kvm/svm/svm.c | 13 +++++++++++--
arch/x86/kvm/svm/svm.h | 9 +++++++--
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index ccf85ea79d37..b0f217721873 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -882,7 +882,8 @@ void svm_update_lbrv(struct kvm_vcpu *vcpu)
bool current_enable_lbrv = svm->vmcb->control.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR;
bool enable_lbrv = false;
- if (svm->vmcb->save.dbgctl & DEBUGCTLMSR_LBR)
+ /* Bus Lock Detect in guest depends on LBR Virtualization */
+ if (svm->vmcb->save.dbgctl & (DEBUGCTLMSR_LBR | DEBUGCTLMSR_BUS_LOCK_DETECT))
enable_lbrv = true;
if (is_guest_mode(vcpu) && nested_lbrv_enabled(vcpu))
@@ -5594,9 +5595,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 696f1b4b8f8f..1d1ff6ed1049 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -783,9 +783,14 @@ BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test)
BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear)
BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set)
-static inline u64 svm_get_debugctl_reserved_bits(struct kvm_vcpu *vcpu __maybe_unused)
+static inline u64 svm_get_debugctl_reserved_bits(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.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread