diff mbox series

[v10,11/29] KVM: x86/pmu: Explicitly check for RDPMC of unsupported Intel PMC types

Message ID 20240109230250.424295-12-seanjc@google.com (mailing list archive)
State New, archived
Headers show
Series KVM: x86/pmu: selftests: Fixes and new tests | expand

Commit Message

Sean Christopherson Jan. 9, 2024, 11:02 p.m. UTC
Explicitly check for attempts to read unsupported PMC types instead of
letting the bounds check fail.  Functionally, letting the check fail is
ok, but it's unnecessarily subtle and does a poor job of documenting the
architectural behavior that KVM is emulating.

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

Comments

Mi, Dapeng Jan. 12, 2024, 3:50 a.m. UTC | #1
On 1/10/2024 7:02 AM, Sean Christopherson wrote:
> Explicitly check for attempts to read unsupported PMC types instead of
> letting the bounds check fail.  Functionally, letting the check fail is
> ok, but it's unnecessarily subtle and does a poor job of documenting the
> architectural behavior that KVM is emulating.
>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>   arch/x86/kvm/vmx/pmu_intel.c | 21 +++++++++++++++------
>   1 file changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index c37dd3aa056b..b41bdb0a0995 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -26,6 +26,7 @@
>    * further confuse things, non-architectural PMUs use bit 31 as a flag for
>    * "fast" reads, whereas the "type" is an explicit value.
>    */
> +#define INTEL_RDPMC_GP		0
>   #define INTEL_RDPMC_FIXED	INTEL_PMC_FIXED_RDPMC_BASE
>   
>   #define INTEL_RDPMC_TYPE_MASK	GENMASK(31, 16)
> @@ -89,21 +90,29 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
>   		return NULL;
>   
>   	/*
> -	 * Fixed PMCs are supported on all architectural PMUs.  Note, KVM only
> -	 * emulates fixed PMCs for PMU v2+, but the flag itself is still valid,
> -	 * i.e. let RDPMC fail due to accessing a non-existent counter.
> +	 * General Purpose (GP) PMCs are supported on all PMUs, and fixed PMCs
> +	 * are supported on all architectural PMUs, i.e. on all virtual PMUs
> +	 * supported by KVM.  Note, KVM only emulates fixed PMCs for PMU v2+,
> +	 * but the type itself is still valid, i.e. let RDPMC fail due to
> +	 * accessing a non-existent counter.  Reject attempts to read all other
> +	 * types, which are unknown/unsupported.
>   	 */
> -	idx &= ~INTEL_RDPMC_FIXED;
> -	if (type == INTEL_RDPMC_FIXED) {
> +	switch (type) {
> +	case INTEL_RDPMC_FIXED:
>   		counters = pmu->fixed_counters;
>   		num_counters = pmu->nr_arch_fixed_counters;
>   		bitmask = pmu->counter_bitmask[KVM_PMC_FIXED];
> -	} else {
> +		break;
> +	case INTEL_RDPMC_GP:
>   		counters = pmu->gp_counters;
>   		num_counters = pmu->nr_arch_gp_counters;
>   		bitmask = pmu->counter_bitmask[KVM_PMC_GP];
> +		break;
> +	default:
> +		return NULL;
>   	}
>   
> +	idx &= INTEL_RDPMC_INDEX_MASK;
>   	if (idx >= num_counters)
>   		return NULL;
>   
Reviewed-by: Dapeng MiĀ  <dapeng1.mi@linux.intel.com>
diff mbox series

Patch

diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index c37dd3aa056b..b41bdb0a0995 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -26,6 +26,7 @@ 
  * further confuse things, non-architectural PMUs use bit 31 as a flag for
  * "fast" reads, whereas the "type" is an explicit value.
  */
+#define INTEL_RDPMC_GP		0
 #define INTEL_RDPMC_FIXED	INTEL_PMC_FIXED_RDPMC_BASE
 
 #define INTEL_RDPMC_TYPE_MASK	GENMASK(31, 16)
@@ -89,21 +90,29 @@  static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
 		return NULL;
 
 	/*
-	 * Fixed PMCs are supported on all architectural PMUs.  Note, KVM only
-	 * emulates fixed PMCs for PMU v2+, but the flag itself is still valid,
-	 * i.e. let RDPMC fail due to accessing a non-existent counter.
+	 * General Purpose (GP) PMCs are supported on all PMUs, and fixed PMCs
+	 * are supported on all architectural PMUs, i.e. on all virtual PMUs
+	 * supported by KVM.  Note, KVM only emulates fixed PMCs for PMU v2+,
+	 * but the type itself is still valid, i.e. let RDPMC fail due to
+	 * accessing a non-existent counter.  Reject attempts to read all other
+	 * types, which are unknown/unsupported.
 	 */
-	idx &= ~INTEL_RDPMC_FIXED;
-	if (type == INTEL_RDPMC_FIXED) {
+	switch (type) {
+	case INTEL_RDPMC_FIXED:
 		counters = pmu->fixed_counters;
 		num_counters = pmu->nr_arch_fixed_counters;
 		bitmask = pmu->counter_bitmask[KVM_PMC_FIXED];
-	} else {
+		break;
+	case INTEL_RDPMC_GP:
 		counters = pmu->gp_counters;
 		num_counters = pmu->nr_arch_gp_counters;
 		bitmask = pmu->counter_bitmask[KVM_PMC_GP];
+		break;
+	default:
+		return NULL;
 	}
 
+	idx &= INTEL_RDPMC_INDEX_MASK;
 	if (idx >= num_counters)
 		return NULL;