diff mbox series

[5/9] KVM: x86/pmu: Check CPUID.0AH.ECX consistency

Message ID 20230901072809.640175-6-xiong.y.zhang@intel.com (mailing list archive)
State New, archived
Headers show
Series Upgrade vPMU version to 5 | expand

Commit Message

Zhang, Xiong Y Sept. 1, 2023, 7:28 a.m. UTC
With Arch PMU V5, register CPUID.0AH.ECX indicates Fixed Counter
enumeration. It is a bit mask which enumerates the supported Fixed
counters.
FxCtrl[i]_is_supported := ECX[i] || (EDX[4:0] > i)
where EDX[4:0] is Number of continuous fixed-function performance
counters starting from 0 (if version ID > 1).

Here ECX and EDX[4:0] should satisfy the following consistency:
1. if 1 < pmu_version < 5, ECX == 0;
2. if pmu_version == 5 && edx[4:0] == 0, ECX[bit 0] == 0
3. if pmu_version == 5 && edx[4:0] > 0,
   ecx & ((1 << edx[4:0]) - 1) == (1 << edx[4:0]) -1

Otherwise it is mess to decide whether a fixed counter is supported
or not. i.e. pmu_version = 5, edx[4:0] = 3, ecx = 0x10, it is hard
to decide whether fixed counters 0 ~ 2 are supported or not.

User can call SET_CPUID2 ioctl to set guest CPUID.0AH, this commit
adds a check to guarantee ecx and edx consistency specified by user.

Once user specifies an un-consistency value, KVM can return an
error to user and drop user setting, or correct the un-consistency
data and accept the corrected data, this commit chooses to
return an error to user.

Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
---
 arch/x86/kvm/cpuid.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

Comments

Mi, Dapeng Sept. 6, 2023, 9:44 a.m. UTC | #1
On 9/1/2023 3:28 PM, Xiong Zhang wrote:
> With Arch PMU V5, register CPUID.0AH.ECX indicates Fixed Counter
> enumeration. It is a bit mask which enumerates the supported Fixed
> counters.
> FxCtrl[i]_is_supported := ECX[i] || (EDX[4:0] > i)
> where EDX[4:0] is Number of continuous fixed-function performance
> counters starting from 0 (if version ID > 1).
>
> Here ECX and EDX[4:0] should satisfy the following consistency:
> 1. if 1 < pmu_version < 5, ECX == 0;
> 2. if pmu_version == 5 && edx[4:0] == 0, ECX[bit 0] == 0
> 3. if pmu_version == 5 && edx[4:0] > 0,
>     ecx & ((1 << edx[4:0]) - 1) == (1 << edx[4:0]) -1
>
> Otherwise it is mess to decide whether a fixed counter is supported
> or not. i.e. pmu_version = 5, edx[4:0] = 3, ecx = 0x10, it is hard
> to decide whether fixed counters 0 ~ 2 are supported or not.
>
> User can call SET_CPUID2 ioctl to set guest CPUID.0AH, this commit
> adds a check to guarantee ecx and edx consistency specified by user.
>
> Once user specifies an un-consistency value, KVM can return an
> error to user and drop user setting, or correct the un-consistency
> data and accept the corrected data, this commit chooses to
> return an error to user.
>
> Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
> ---
>   arch/x86/kvm/cpuid.c | 27 +++++++++++++++++++++++++++
>   1 file changed, 27 insertions(+)
>
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index e961e9a05847..95dc5e8847e0 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -150,6 +150,33 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
>   			return -EINVAL;
>   	}
>   
> +	best = cpuid_entry2_find(entries, nent, 0xa,
> +				 KVM_CPUID_INDEX_NOT_SIGNIFICANT);
> +	if (best && vcpu->kvm->arch.enable_pmu) {
> +		union cpuid10_eax eax;
> +		union cpuid10_edx   edx;


Remove the redundant space before edx.


> +
> +		eax.full = best->eax;
> +		edx.full = best->edx;
> +

We may add SDM quotes as comments here. That makes reader to understand 
the logic easily.


> +		if (eax.split.version_id > 1 &&
> +		    eax.split.version_id < 5 &&
> +		    best->ecx != 0) {
> +			return -EINVAL;
> +		} else if (eax.split.version_id >= 5) {
> +			int fixed_count = edx.split.num_counters_fixed;
> +
> +			if (fixed_count == 0 && (best->ecx & 0x1)) {
> +				return -EINVAL;
> +			} else if (fixed_count > 0) {
> +				int low_fixed_mask = (1 << fixed_count) - 1;
> +
> +				if ((best->ecx & low_fixed_mask) != low_fixed_mask)
> +					return -EINVAL;
> +			}
> +		}
> +	}
> +
>   	/*
>   	 * Exposing dynamic xfeatures to the guest requires additional
>   	 * enabling in the FPU, e.g. to expand the guest XSAVE state size.
Zhang, Xiong Y Sept. 12, 2023, 12:45 a.m. UTC | #2
> On 9/1/2023 3:28 PM, Xiong Zhang wrote:
> > With Arch PMU V5, register CPUID.0AH.ECX indicates Fixed Counter
> > enumeration. It is a bit mask which enumerates the supported Fixed
> > counters.
> > FxCtrl[i]_is_supported := ECX[i] || (EDX[4:0] > i) where EDX[4:0] is
> > Number of continuous fixed-function performance counters starting from
> > 0 (if version ID > 1).
> >
> > Here ECX and EDX[4:0] should satisfy the following consistency:
> > 1. if 1 < pmu_version < 5, ECX == 0;
> > 2. if pmu_version == 5 && edx[4:0] == 0, ECX[bit 0] == 0 3. if
> > pmu_version == 5 && edx[4:0] > 0,
> >     ecx & ((1 << edx[4:0]) - 1) == (1 << edx[4:0]) -1
> >
> > Otherwise it is mess to decide whether a fixed counter is supported or
> > not. i.e. pmu_version = 5, edx[4:0] = 3, ecx = 0x10, it is hard to
> > decide whether fixed counters 0 ~ 2 are supported or not.
> >
> > User can call SET_CPUID2 ioctl to set guest CPUID.0AH, this commit
> > adds a check to guarantee ecx and edx consistency specified by user.
> >
> > Once user specifies an un-consistency value, KVM can return an error
> > to user and drop user setting, or correct the un-consistency data and
> > accept the corrected data, this commit chooses to return an error to
> > user.
> >
> > Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
> > ---
> >   arch/x86/kvm/cpuid.c | 27 +++++++++++++++++++++++++++
> >   1 file changed, 27 insertions(+)
> >
> > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index
> > e961e9a05847..95dc5e8847e0 100644
> > --- a/arch/x86/kvm/cpuid.c
> > +++ b/arch/x86/kvm/cpuid.c
> > @@ -150,6 +150,33 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
> >   			return -EINVAL;
> >   	}
> >
> > +	best = cpuid_entry2_find(entries, nent, 0xa,
> > +				 KVM_CPUID_INDEX_NOT_SIGNIFICANT);
> > +	if (best && vcpu->kvm->arch.enable_pmu) {
> > +		union cpuid10_eax eax;
> > +		union cpuid10_edx   edx;
> 
> 
> Remove the redundant space before edx.
> 
> 
> > +
> > +		eax.full = best->eax;
> > +		edx.full = best->edx;
> > +
> 
> We may add SDM quotes as comments here. That makes reader to understand
> the logic easily.
Ok, do it in next version.
thanks
> 
> 
> > +		if (eax.split.version_id > 1 &&
> > +		    eax.split.version_id < 5 &&
> > +		    best->ecx != 0) {
> > +			return -EINVAL;
> > +		} else if (eax.split.version_id >= 5) {
> > +			int fixed_count = edx.split.num_counters_fixed;
> > +
> > +			if (fixed_count == 0 && (best->ecx & 0x1)) {
> > +				return -EINVAL;
> > +			} else if (fixed_count > 0) {
> > +				int low_fixed_mask = (1 << fixed_count) - 1;
> > +
> > +				if ((best->ecx & low_fixed_mask) !=
> low_fixed_mask)
> > +					return -EINVAL;
> > +			}
> > +		}
> > +	}
> > +
> >   	/*
> >   	 * Exposing dynamic xfeatures to the guest requires additional
> >   	 * enabling in the FPU, e.g. to expand the guest XSAVE state size.
Like Xu Sept. 12, 2023, 11:31 a.m. UTC | #3
On 1/9/2023 3:28 pm, Xiong Zhang wrote:
> Once user specifies an un-consistency value, KVM can return an
> error to user and drop user setting, or correct the un-consistency
> data and accept the corrected data, this commit chooses to
> return an error to user.

Doing so is inconsistent with other vPMU CPUID configurations.

This issue is generic and not just for this PMU CPUID leaf.
Make sure this part of the design is covered in the vPMU documentation.
Zhang, Xiong Y Sept. 13, 2023, 4:25 a.m. UTC | #4
> On 1/9/2023 3:28 pm, Xiong Zhang wrote:
> > Once user specifies an un-consistency value, KVM can return an error
> > to user and drop user setting, or correct the un-consistency data and
> > accept the corrected data, this commit chooses to return an error to
> > user.
> 
> Doing so is inconsistent with other vPMU CPUID configurations.
> 
> This issue is generic and not just for this PMU CPUID leaf.
> Make sure this part of the design is covered in the vPMU documentation.
So I will drop this commit.
thanks
diff mbox series

Patch

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index e961e9a05847..95dc5e8847e0 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -150,6 +150,33 @@  static int kvm_check_cpuid(struct kvm_vcpu *vcpu,
 			return -EINVAL;
 	}
 
+	best = cpuid_entry2_find(entries, nent, 0xa,
+				 KVM_CPUID_INDEX_NOT_SIGNIFICANT);
+	if (best && vcpu->kvm->arch.enable_pmu) {
+		union cpuid10_eax eax;
+		union cpuid10_edx   edx;
+
+		eax.full = best->eax;
+		edx.full = best->edx;
+
+		if (eax.split.version_id > 1 &&
+		    eax.split.version_id < 5 &&
+		    best->ecx != 0) {
+			return -EINVAL;
+		} else if (eax.split.version_id >= 5) {
+			int fixed_count = edx.split.num_counters_fixed;
+
+			if (fixed_count == 0 && (best->ecx & 0x1)) {
+				return -EINVAL;
+			} else if (fixed_count > 0) {
+				int low_fixed_mask = (1 << fixed_count) - 1;
+
+				if ((best->ecx & low_fixed_mask) != low_fixed_mask)
+					return -EINVAL;
+			}
+		}
+	}
+
 	/*
 	 * Exposing dynamic xfeatures to the guest requires additional
 	 * enabling in the FPU, e.g. to expand the guest XSAVE state size.