mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ravi Bangoria <ravi.bangoria@amd.com>
To: Sean Christopherson <seanjc@google.com>
Cc: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	dave.hansen@linux.intel.com, pbonzini@redhat.com,
	thomas.lendacky@amd.com, jmattson@google.com, hpa@zytor.com,
	rmk+kernel@armlinux.org.uk, peterz@infradead.org,
	james.morse@arm.com, lukas.bulwahn@gmail.com,
	arjan@linux.intel.com, j.granados@samsung.com,
	sibs@chinatelecom.cn, nik.borisov@suse.com, michael.roth@amd.com,
	nikunj.dadhania@amd.com, babu.moger@amd.com, x86@kernel.org,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	santosh.shukla@amd.com, ananth.narayan@amd.com,
	sandipan.das@amd.com, manali.shukla@amd.com,
	Ravi Bangoria <ravi.bangoria@amd.com>
Subject: Re: [PATCH v4 4/4] KVM: SVM: Add Bus Lock Detect support
Date: Thu, 5 Sep 2024 17:10:47 +0530	[thread overview]
Message-ID: <46d610e5-3f4f-4113-ac56-3ecdc66e4029@amd.com> (raw)
In-Reply-To: <d391cba7-e20a-41dd-b395-3923893bdbc0@amd.com>

On 20-Aug-24 10:08 PM, Ravi Bangoria wrote:
> Sean,
> 
>>> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
>>> index e1b6a16e97c0..9f3d31a5d231 100644
>>> --- a/arch/x86/kvm/svm/svm.c
>>> +++ b/arch/x86/kvm/svm/svm.c
>>> @@ -1047,7 +1047,8 @@ void svm_update_lbrv(struct kvm_vcpu *vcpu)
>>>  {
>>>  	struct vcpu_svm *svm = to_svm(vcpu);
>>>  	bool current_enable_lbrv = svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK;
>>> -	bool enable_lbrv = (svm_get_lbr_vmcb(svm)->save.dbgctl & DEBUGCTLMSR_LBR) ||
>>> +	u64 dbgctl_buslock_lbr = DEBUGCTLMSR_BUS_LOCK_DETECT | DEBUGCTLMSR_LBR;
>>> +	bool enable_lbrv = (svm_get_lbr_vmcb(svm)->save.dbgctl & dbgctl_buslock_lbr) ||
>>>  			    (is_guest_mode(vcpu) && guest_can_use(vcpu, X86_FEATURE_LBRV) &&
>>>  			    (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK));
>>
>> Out of sight, but this leads to calling svm_enable_lbrv() even when the guest
>> just wants to enable BUS_LOCK_DETECT.  Ignoring SEV-ES guests, KVM will intercept
>> writes to DEBUGCTL, so can't KVM defer mucking with the intercepts and
>> svm_copy_lbrs() until the guest actually wants to use LBRs?
>>
>> Hmm, and I think the existing code is broken.  If L1 passes DEBUGCTL through to
>> L2, then KVM will handles writes to L1's effective value.  And if L1 also passes
>> through the LBRs, then KVM will fail to update the MSR bitmaps for vmcb02.
>>
>> Ah, it's just a performance issue though, because KVM will still emulate RDMSR.
>>
>> Ugh, this code is silly.  The LBR MSRs are read-only, yet KVM passes them through
>> for write.
>>
>> Anyways, I'm thinking something like this?  Note, using msr_write_intercepted()
>> is wrong, because that'll check L2's bitmap if is_guest_mode(), and the idea is
>> to use L1's bitmap as the canary.
>>
>> static void svm_update_passthrough_lbrs(struct kvm_vcpu *vcpu, bool passthrough)
>> {
>> 	struct vcpu_svm *svm = to_svm(vcpu);
>>
>> 	KVM_BUG_ON(!passthrough && sev_es_guest(vcpu->kvm), vcpu->kvm);
>>
>> 	if (!msr_write_intercepted(vcpu, MSR_IA32_LASTBRANCHFROMIP) == passthrough)
>> 		return;
>>
>> 	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHFROMIP, passthrough, 0);
>> 	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, passthrough, 0);
>> 	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, passthrough, 0);
>> 	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, passthrough, 0);
>>
>> 	/*
>> 	 * When enabling, move the LBR msrs to vmcb02 so that L2 can see them,
>> 	 * and then move them back to vmcb01 when disabling to avoid copying
>> 	 * them on nested guest entries.
>> 	 */
>> 	if (is_guest_mode(vcpu)) {
>> 		if (passthrough)
>> 			svm_copy_lbrs(svm->vmcb, svm->vmcb01.ptr);
>> 		else
>> 			svm_copy_lbrs(svm->vmcb01.ptr, svm->vmcb);
>> 	}
>> }
>>
>> void svm_enable_lbrv(struct kvm_vcpu *vcpu)
>> {
>> 	struct vcpu_svm *svm = to_svm(vcpu);
>>
>> 	if (WARN_ON_ONCE(!sev_es_guest(vcpu->kvm)))
>> 		return;
>>
>> 	svm->vmcb->control.virt_ext |= LBR_CTL_ENABLE_MASK;
>> 	svm_update_passthrough_lbrs(vcpu, true);
>>
>> 	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_DEBUGCTLMSR, 1, 1);
>> }
>>
>> static struct vmcb *svm_get_lbr_vmcb(struct vcpu_svm *svm)
>> {
>> 	/*
>> 	 * If LBR virtualization is disabled, the LBR MSRs are always kept in
>> 	 * vmcb01.  If LBR virtualization is enabled and L1 is running VMs of
>> 	 * its own, the MSRs are moved between vmcb01 and vmcb02 as needed.
>> 	 */
>> 	return svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK ? svm->vmcb :
>> 								   svm->vmcb01.ptr;
>> }
>>
>> void svm_update_lbrv(struct kvm_vcpu *vcpu)
>> {
>> 	struct vcpu_svm *svm = to_svm(vcpu);
>> 	u64 guest_debugctl = svm_get_lbr_vmcb(svm)->save.dbgctl;
>> 	bool enable_lbrv = (guest_debugctl & DEBUGCTLMSR_LBR) ||
>> 			    (is_guest_mode(vcpu) && guest_can_use(vcpu, X86_FEATURE_LBRV) &&
>> 			    (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK));
>>
>> 	if (enable_lbrv || (guest_debugctl & DEBUGCTLMSR_BUS_LOCK_DETECT))
>> 		svm->vmcb->control.virt_ext |= LBR_CTL_ENABLE_MASK;
>> 	else
>> 		svm->vmcb->control.virt_ext &= ~LBR_CTL_ENABLE_MASK;
>>
>> 	svm_update_passthrough_lbrs(vcpu, enable_lbrv);
>> }
> 
> This refactored code looks fine. I did some sanity testing with SVM/SEV/SEV-ES
> guests and not seeing any issues. I'll respin with above change included.

Realised that KUT LBR tests were failing with this change and I had
to do this to fix those:

---
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 0b807099cb19..3dd737db85ef 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -795,6 +795,21 @@ static bool valid_msr_intercept(u32 index)
 	return direct_access_msr_slot(index) != -ENOENT;
 }
 
+static bool msr_read_intercepted_msrpm(u32 *msrpm, u32 msr)
+{
+	unsigned long tmp;
+	u8 bit_read;
+	u32 offset;
+
+	offset = svm_msrpm_offset(msr);
+	bit_read = 2 * (msr & 0x0f);
+	tmp = msrpm[offset];
+
+	BUG_ON(offset == MSR_INVALID);
+
+	return test_bit(bit_read, &tmp);
+}
+
 static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
 {
 	u8 bit_write;
@@ -1000,7 +1015,7 @@ static void svm_update_passthrough_lbrs(struct kvm_vcpu *vcpu, bool passthrough)
 
 	KVM_BUG_ON(!passthrough && sev_es_guest(vcpu->kvm), vcpu->kvm);
 
-	if (!msr_write_intercepted(vcpu, MSR_IA32_LASTBRANCHFROMIP) == passthrough)
+	if (!msr_read_intercepted_msrpm(svm->msrpm, MSR_IA32_LASTBRANCHFROMIP) == passthrough)
 		return;
 
 	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHFROMIP, passthrough, 0);
---

I've added a new api for read interception since LBR register writes are
always intercepted.

Does this looks good?

Thanks,
Ravi

  reply	other threads:[~2024-09-05 11:41 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-08  6:29 [PATCH v4 0/4] x86/cpu: Add Bus Lock Detect support for AMD Ravi Bangoria
2024-08-08  6:29 ` [PATCH v4 1/4] x86/split_lock: Move Split and Bus lock code to a dedicated file Ravi Bangoria
2024-08-08 16:07   ` [tip: x86/splitlock] " tip-bot2 for Ravi Bangoria
2024-08-08  6:29 ` [PATCH v4 2/4] x86/bus_lock: Add support for AMD Ravi Bangoria
2024-08-08 16:07   ` [tip: x86/splitlock] " tip-bot2 for Ravi Bangoria
2024-08-08  6:29 ` [PATCH v4 3/4] KVM: SVM: Don't advertise Bus Lock Detect to guest if SVM support is missing Ravi Bangoria
2024-08-08  6:29 ` [PATCH v4 4/4] KVM: SVM: Add Bus Lock Detect support Ravi Bangoria
2024-08-17  0:13   ` Sean Christopherson
2024-08-20 16:38     ` Ravi Bangoria
2024-09-05 11:40       ` Ravi Bangoria [this message]
2024-08-21  5:36     ` Ravi Bangoria
2024-08-21 10:40       ` Ravi Bangoria
2024-08-26 18:31         ` Sean Christopherson
2025-11-11 10:03     ` Shivansh Dhiman
2025-11-11 15:15       ` Sean Christopherson
2025-11-14  8:50         ` Shivansh Dhiman
2024-08-23 23:47 ` [PATCH v4 0/4] x86/cpu: Add Bus Lock Detect support for AMD Sean Christopherson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46d610e5-3f4f-4113-ac56-3ecdc66e4029@amd.com \
    --to=ravi.bangoria@amd.com \
    --cc=ananth.narayan@amd.com \
    --cc=arjan@linux.intel.com \
    --cc=babu.moger@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=j.granados@samsung.com \
    --cc=james.morse@arm.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas.bulwahn@gmail.com \
    --cc=manali.shukla@amd.com \
    --cc=michael.roth@amd.com \
    --cc=mingo@redhat.com \
    --cc=nik.borisov@suse.com \
    --cc=nikunj.dadhania@amd.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rmk+kernel@armlinux.org.uk \
    --cc=sandipan.das@amd.com \
    --cc=santosh.shukla@amd.com \
    --cc=seanjc@google.com \
    --cc=sibs@chinatelecom.cn \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®