The fixed counters may not be contiguous. Intel SDM recommends how to use CPUID.0AH to determine if a Fixed Counter is supported: FxCtr[i]_is_supported := ECX[i] || (EDX[4:0] > i); For example, it's perfectly valid to have CPUID.0AH.EDX[4:0] == 3 and CPUID.0AH.ECX == 0x77, but checking the fixed counter index against CPUID.0AH.EDX[4:0] only, will deem that FxCtr[6:4] are not supported. Additionally, according to the latest Intel SDM, changed the definition of cpuidA_edx and renamed num_counters_fixed to num_contiguous_fixed. Signed-off-by: Zide Chen <zide.chen@xxxxxxxxx> Reviewed-by: Zhenyu Wang <zhenyuw@xxxxxxxxxxxxxxx> --- x86/vmx_tests.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index ffe7064c9221..5261927ad2a4 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -7332,11 +7332,17 @@ union cpuidA_eax { unsigned int full; }; +union cpuidA_ecx { + unsigned int fixed_mask; +}; + union cpuidA_edx { struct { - unsigned int num_counters_fixed:5; + unsigned int num_contiguous_fixed:5; unsigned int bit_width_fixed:8; - unsigned int reserved:9; + unsigned int reserved1:2; + unsigned int anythread_deprecated:1; + unsigned int reserved2:16; } split; unsigned int full; }; @@ -7345,14 +7351,19 @@ static bool valid_pgc(u64 val) { struct cpuid id; union cpuidA_eax eax; + union cpuidA_ecx ecx; union cpuidA_edx edx; u64 mask; id = cpuid(0xA); eax.full = id.a; + ecx.fixed_mask = id.c; edx.full = id.d; + + /* FxCtr[i]_is_supported := ECX[i] || (EDX[4:0] > i); */ mask = ~(((1ull << eax.split.num_counters_gp) - 1) | - (((1ull << edx.split.num_counters_fixed) - 1) << 32)); + (((1ull << edx.split.num_contiguous_fixed) - 1) << 32) | + ((u64)ecx.fixed_mask << 32)); return !(val & mask); } -- 2.34.1