Re: [RFC PATCH v3 23/58] KVM: x86/pmu: Allow RDPMC pass through when all counters exposed to guest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/20/2024 12:32 AM, Sean Christopherson wrote:
> On Thu, Aug 01, 2024, Mingwei Zhang wrote:
>> Clear RDPMC_EXITING in vmcs when all counters on the host side are exposed
>> to guest VM. This gives performance to passthrough PMU. However, when guest
>> does not get all counters, intercept RDPMC to prevent access to unexposed
>> counters. Make decision in vmx_vcpu_after_set_cpuid() when guest enables
>> PMU and passthrough PMU is enabled.
>>
>> Co-developed-by: Xiong Zhang <xiong.y.zhang@xxxxxxxxxxxxxxx>
>> Signed-off-by: Xiong Zhang <xiong.y.zhang@xxxxxxxxxxxxxxx>
>> Signed-off-by: Mingwei Zhang <mizhang@xxxxxxxxxx>
>> Signed-off-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
>> Tested-by: Yongwei Ma <yongwei.ma@xxxxxxxxx>
>> ---
>>  arch/x86/kvm/pmu.c     | 16 ++++++++++++++++
>>  arch/x86/kvm/pmu.h     |  1 +
>>  arch/x86/kvm/vmx/vmx.c |  5 +++++
>>  3 files changed, 22 insertions(+)
>>
>> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
>> index e656f72fdace..19104e16a986 100644
>> --- a/arch/x86/kvm/pmu.c
>> +++ b/arch/x86/kvm/pmu.c
>> @@ -96,6 +96,22 @@ void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops)
>>  #undef __KVM_X86_PMU_OP
>>  }
>>  
>> +bool kvm_pmu_check_rdpmc_passthrough(struct kvm_vcpu *vcpu)
> As suggested earlier, kvm_rdpmc_in_guest().

Sure.


>
>> +{
>> +	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
>> +
>> +	if (is_passthrough_pmu_enabled(vcpu) &&
>> +	    !enable_vmware_backdoor &&
> Please add a comment about the VMware backdoor, I doubt most folks know about
> VMware's tweaks to RDPMC behavior.  It's somewhat obvious from the code and
> comment in check_rdpmc(), but I think it's worth calling out here too.

Sure.


>
>> +	    pmu->nr_arch_gp_counters == kvm_pmu_cap.num_counters_gp &&
>> +	    pmu->nr_arch_fixed_counters == kvm_pmu_cap.num_counters_fixed &&
>> +	    pmu->counter_bitmask[KVM_PMC_GP] == (((u64)1 << kvm_pmu_cap.bit_width_gp) - 1) &&
>> +	    pmu->counter_bitmask[KVM_PMC_FIXED] == (((u64)1 << kvm_pmu_cap.bit_width_fixed)  - 1))
> BIT_ULL?  GENMASK_ULL?

Sure.


>
>> +		return true;
>> +
>> +	return false;
> Do this:
>
>
> 	return <true>;
>
> not:
>
> 	if (<true>)
> 		return true;
>
> 	return false;
>
> Short-circuiting on certain cases is fine, and I would probably vote for that so
> it's easier to add comments, but that's obviously not what's done here.  E.g. either
>
> 	if (!enable_mediated_pmu)
> 		return false;
>
> 	/* comment goes here */
> 	if (enable_vmware_backdoor)
> 		return false;
>
> 	return <counters checks>;
>
> or
>
> 	return <massive combined check>;

Nice suggestion. Thanks.


>
>> +}
>> +EXPORT_SYMBOL_GPL(kvm_pmu_check_rdpmc_passthrough);
> Maybe just make this an inline in a header?  enable_vmware_backdoor is exported,
> and presumably enable_mediated_pmu will be too.

Sure.


>
>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>> index 4d60a8cf2dd1..339742350b7a 100644
>> --- a/arch/x86/kvm/vmx/vmx.c
>> +++ b/arch/x86/kvm/vmx/vmx.c
>> @@ -7911,6 +7911,11 @@ void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
>>  		vmx->msr_ia32_feature_control_valid_bits &=
>>  			~FEAT_CTL_SGX_LC_ENABLED;
>>  
>> +	if (kvm_pmu_check_rdpmc_passthrough(&vmx->vcpu))
> No need to follow vmx->vcpu, @vcpu is readily available.

Yes.


>
>> +		exec_controls_clearbit(vmx, CPU_BASED_RDPMC_EXITING);
>> +	else
>> +		exec_controls_setbit(vmx, CPU_BASED_RDPMC_EXITING);
> I wonder if it makes sense to add a helper to change a bit.  IIRC, the only reason
> I didn't add one along with the set/clear helpers was because there weren't many
> users and I couldn't think of good alternative to "set".
>
> I still don't have a good name, but I think we're reaching the point where it's
> worth forcing the issue to avoid common goofs, e.g. handling only the "clear"
> case and no the "set" case.
>
> Maybe changebit?  E.g.
>
> static __always_inline void lname##_controls_changebit(struct vcpu_vmx *vmx, u##bits val,	\
> 						       bool set)				\
> {												\
> 	if (set)										\
> 		lname##_controls_setbit(vmx, val);						\
> 	else											\
> 		lname##_controls_clearbit(vmx, val);						\
> }
>
>
> and then vmx_refresh_apicv_exec_ctrl() can be:
>
> 	secondary_exec_controls_changebit(vmx,
> 					  SECONDARY_EXEC_APIC_REGISTER_VIRT |
> 					  SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY,
> 					  kvm_vcpu_apicv_active(vcpu));
> 	tertiary_exec_controls_changebit(vmx, TERTIARY_EXEC_IPI_VIRT,
> 					 kvm_vcpu_apicv_active(vcpu) && enable_ipiv);
>
> and this can be:
>
> 	exec_controls_changebit(vmx, CPU_BASED_RDPMC_EXITING,
> 				!kvm_rdpmc_in_guest(vcpu));

Sure. would add a separate patch to add these helpers.






[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux