On 10/15/2024 11:19 PM, Sean Christopherson wrote: > On Fri, Oct 04, 2024, Manali Shukla wrote: ... >> >> +static int bus_lock_exit(struct kvm_vcpu *vcpu) >> +{ >> + struct vcpu_svm *svm = to_svm(vcpu); >> + >> + vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK; >> + vcpu->run->flags |= KVM_RUN_X86_BUS_LOCK; >> + >> + /* >> + * Reload the counter with value greater than '0'. > > The value quite obviously must be exactly '1', not simply greater than '0. I also > think this is the wrong place to set the counter. Rather than set the counter at > the time of exit, KVM should implement a vcpu->arch.complete_userspace_io callback > and set the counter to '1' if and only if RIP (or LIP, but I have no objection to > keeping things simple) is unchanged. It's a bit of extra complexity, but it will > make it super obvious why KVM is setting the counter to '1'. And, if userspace > wants to stuff state and move past the instruction, e.g. by emulating the guilty > instruction, then KVM won't unnecessarily allow a bus lock in the guest. > > And then the comment can be: > > /* > * If userspace has NOT change RIP, then KVM's ABI is to let the guest > * execute the bus-locking instruction. Set the bus lock counter to '1' > * to effectively step past the bus lock. > */ > The bus lock threshold intercept feature is available for SEV-ES and SEV-SNP guests too. The rip where the bus lock exit occurred, is not available in bus_lock_exit handler for SEV-ES and SEV-SNP guests, so the above-mentioned solution won't work with SEV-ES and SEV-SNP guests. I would propose to add the above-mentioned solution only for normal and SEV guests and unconditionally reloading of bus_lock_counter to 1 in complete_userspace_io for SEV-ES and SEV-SNP guests. Any thoughts ? >> + * The bus lock exit on SVM happens with RIP pointing to the guilty >> + * instruction. So, reloading the value of bus_lock_counter to '0' >> + * results into generating continuous bus lock exits. >> + */ >> + svm->vmcb->control.bus_lock_counter = 1; >> + >> + return 0; >> +} >> + >> static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = { >> [SVM_EXIT_READ_CR0] = cr_interception, >> [SVM_EXIT_READ_CR3] = cr_interception, >> @@ -3353,6 +3374,7 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = { >> [SVM_EXIT_CR4_WRITE_TRAP] = cr_trap, >> [SVM_EXIT_CR8_WRITE_TRAP] = cr_trap, >> [SVM_EXIT_INVPCID] = invpcid_interception, >> + [SVM_EXIT_BUS_LOCK] = bus_lock_exit, >> [SVM_EXIT_NPF] = npf_interception, >> [SVM_EXIT_RSM] = rsm_interception, >> [SVM_EXIT_AVIC_INCOMPLETE_IPI] = avic_incomplete_ipi_interception, >> @@ -5227,6 +5249,11 @@ static __init void svm_set_cpu_caps(void) >> kvm_cpu_cap_set(X86_FEATURE_SVME_ADDR_CHK); >> } >> >> + if (cpu_feature_enabled(X86_FEATURE_BUS_LOCK_THRESHOLD)) { >> + pr_info("Bus Lock Threashold supported\n"); >> + kvm_caps.has_bus_lock_exit = true; >> + } >> + >> /* CPUID 0x80000008 */ >> if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD) || >> boot_cpu_has(X86_FEATURE_AMD_SSBD)) >> -- >> 2.34.1 >> -Manali