[PATCH RESEND 5/5] KVM: x86: selftests: Fix write MSR_TSC_AUX reserved bits test failure on Hygon

Zhiquan Li posted 5 patches 1 day, 7 hours ago
[PATCH RESEND 5/5] KVM: x86: selftests: Fix write MSR_TSC_AUX reserved bits test failure on Hygon
Posted by Zhiquan Li 1 day, 7 hours ago
On Hygon processors either RDTSCP or RDPID is supported in the host,
MSR_TSC_AUX is able to be accessed.

The write reserved bits test for MSR_TSC_AUX while RDPID as "feature"
and RDTSCP as "feature2" is failed on Hygon CPUs which only support
RDTSCP but not support RDPID.  In current design, if RDPID is not
supported, vCPU0 and vCPU1 write reserved bits expects #GP, however, it
is not applicable for Hygon CPUs.  Since on Hygon architecture whether
or not RDPID is supported in the host, once RDTSCP is supported,
MSR_TSC_AUX is able to be accessed, vCPU0 and vCPU1 drop bits 63:32 and
write successfully.

Therefore, the expectation of writing MSR_TSC_AUX reserved bits on Hygon
CPUs should be:
1) either RDTSCP or RDPID is supported case, and both are supported
   case, expect success and a truncated value, not #GP.
2) neither RDTSCP nor RDPID is supported, expect #GP.

Signed-off-by: Zhiquan Li <zhiquan_li@163.com>
---
 tools/testing/selftests/kvm/x86/msrs_test.c | 26 +++++++++++++++++----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86/msrs_test.c b/tools/testing/selftests/kvm/x86/msrs_test.c
index 40d918aedce6..2f1e800fe691 100644
--- a/tools/testing/selftests/kvm/x86/msrs_test.c
+++ b/tools/testing/selftests/kvm/x86/msrs_test.c
@@ -77,11 +77,11 @@ static bool ignore_unsupported_msrs;
 static u64 fixup_rdmsr_val(u32 msr, u64 want)
 {
 	/*
-	 * AMD CPUs drop bits 63:32 on some MSRs that Intel CPUs support.  KVM
-	 * is supposed to emulate that behavior based on guest vendor model
+	 * AMD and Hygon CPUs drop bits 63:32 on some MSRs that Intel CPUs support.
+	 * KVM is supposed to emulate that behavior based on guest vendor model
 	 * (which is the same as the host vendor model for this test).
 	 */
-	if (!host_cpu_is_amd)
+	if (!host_cpu_is_amd && !host_cpu_is_hygon)
 		return want;
 
 	switch (msr) {
@@ -94,6 +94,17 @@ static u64 fixup_rdmsr_val(u32 msr, u64 want)
 	}
 }
 
+/*
+ * On Hygon processors either RDTSCP or RDPID is supported in the host,
+ * MSR_TSC_AUX is able to be accessed.
+ */
+static bool is_hygon_msr_tsc_aux_supported(const struct kvm_msr *msr)
+{
+	return host_cpu_is_hygon &&
+			msr->index == MSR_TSC_AUX &&
+			(this_cpu_has(msr->feature) || this_cpu_has(msr->feature2));
+}
+
 static void __rdmsr(u32 msr, u64 want)
 {
 	u64 val;
@@ -174,9 +185,14 @@ void guest_test_reserved_val(const struct kvm_msr *msr)
 	/*
 	 * If the CPU will truncate the written value (e.g. SYSENTER on AMD),
 	 * expect success and a truncated value, not #GP.
+	 *
+	 * On Hygon CPUs whether or not RDPID is supported in the host, once RDTSCP
+	 * is supported, MSR_TSC_AUX is able to be accessed.  So, for either RDTSCP
+	 * or RDPID is supported case and both are supported case, expect
+	 * success and a truncated value, not #GP.
 	 */
-	if (!this_cpu_has(msr->feature) ||
-	    msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val)) {
+	if (!is_hygon_msr_tsc_aux_supported(msr) && (!this_cpu_has(msr->feature) ||
+	    msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val))) {
 		u8 vec = wrmsr_safe(msr->index, msr->rsvd_val);
 
 		__GUEST_ASSERT(vec == GP_VECTOR,
-- 
2.43.0
Re: [PATCH RESEND 5/5] KVM: x86: selftests: Fix write MSR_TSC_AUX reserved bits test failure on Hygon
Posted by Sean Christopherson 18 hours ago
On Mon, Feb 09, 2026, Zhiquan Li wrote:
> Therefore, the expectation of writing MSR_TSC_AUX reserved bits on Hygon
> CPUs should be:
> 1) either RDTSCP or RDPID is supported case, and both are supported
>    case, expect success and a truncated value, not #GP.
> 2) neither RDTSCP nor RDPID is supported, expect #GP.

That's how Intel and AMD behave as well.  I don't understand why there needs to
be a big pile of special case code for Hygon.  Presumably just fixup_rdmsr_val()
needs to be changed?

> Signed-off-by: Zhiquan Li <zhiquan_li@163.com>
> ---
>  tools/testing/selftests/kvm/x86/msrs_test.c | 26 +++++++++++++++++----
>  1 file changed, 21 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/x86/msrs_test.c b/tools/testing/selftests/kvm/x86/msrs_test.c
> index 40d918aedce6..2f1e800fe691 100644
> --- a/tools/testing/selftests/kvm/x86/msrs_test.c
> +++ b/tools/testing/selftests/kvm/x86/msrs_test.c
> @@ -77,11 +77,11 @@ static bool ignore_unsupported_msrs;
>  static u64 fixup_rdmsr_val(u32 msr, u64 want)
>  {
>  	/*
> -	 * AMD CPUs drop bits 63:32 on some MSRs that Intel CPUs support.  KVM
> -	 * is supposed to emulate that behavior based on guest vendor model
> +	 * AMD and Hygon CPUs drop bits 63:32 on some MSRs that Intel CPUs support.
> +	 * KVM is supposed to emulate that behavior based on guest vendor model
>  	 * (which is the same as the host vendor model for this test).
>  	 */
> -	if (!host_cpu_is_amd)
> +	if (!host_cpu_is_amd && !host_cpu_is_hygon)
>  		return want;
>  
>  	switch (msr) {
> @@ -94,6 +94,17 @@ static u64 fixup_rdmsr_val(u32 msr, u64 want)
>  	}
>  }
>  
> +/*
> + * On Hygon processors either RDTSCP or RDPID is supported in the host,
> + * MSR_TSC_AUX is able to be accessed.
> + */
> +static bool is_hygon_msr_tsc_aux_supported(const struct kvm_msr *msr)
> +{
> +	return host_cpu_is_hygon &&
> +			msr->index == MSR_TSC_AUX &&
> +			(this_cpu_has(msr->feature) || this_cpu_has(msr->feature2));

Align indentation, but as above, this shouldn't be necessary.

> +}
> +
>  static void __rdmsr(u32 msr, u64 want)
>  {
>  	u64 val;
> @@ -174,9 +185,14 @@ void guest_test_reserved_val(const struct kvm_msr *msr)
>  	/*
>  	 * If the CPU will truncate the written value (e.g. SYSENTER on AMD),
>  	 * expect success and a truncated value, not #GP.
> +	 *
> +	 * On Hygon CPUs whether or not RDPID is supported in the host, once RDTSCP
> +	 * is supported, MSR_TSC_AUX is able to be accessed.  So, for either RDTSCP
> +	 * or RDPID is supported case and both are supported case, expect
> +	 * success and a truncated value, not #GP.
>  	 */
> -	if (!this_cpu_has(msr->feature) ||
> -	    msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val)) {
> +	if (!is_hygon_msr_tsc_aux_supported(msr) && (!this_cpu_has(msr->feature) ||
> +	    msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val))) {
>  		u8 vec = wrmsr_safe(msr->index, msr->rsvd_val);
>  
>  		__GUEST_ASSERT(vec == GP_VECTOR,
> -- 
> 2.43.0
>
Re: [PATCH RESEND 5/5] KVM: x86: selftests: Fix write MSR_TSC_AUX reserved bits test failure on Hygon
Posted by Zhiquan Li an hour ago
On 2/10/26 00:41, Sean Christopherson wrote:
> On Mon, Feb 09, 2026, Zhiquan Li wrote:
>> Therefore, the expectation of writing MSR_TSC_AUX reserved bits on Hygon
>> CPUs should be:
>> 1) either RDTSCP or RDPID is supported case, and both are supported
>>    case, expect success and a truncated value, not #GP.
>> 2) neither RDTSCP nor RDPID is supported, expect #GP.
> 
> That's how Intel and AMD behave as well.  I don't understand why there needs to
> be a big pile of special case code for Hygon.  Presumably just fixup_rdmsr_val()
> needs to be changed?
> 

Currently the conditions cannot cover the case that the host *only* supports
RDTSCP but not support RDPID, like Hygon CPU.  Let me give more details for this
test failure.

When testing the case MSR_TEST2(MSR_TSC_AUX, 0x12345678, u64_val, RDPID,
RDTSCP), the cupid bit for RDPID (as feature) of vCPU 0 and vCPU1 will be
removed because host is not supported it, but please note RDTSCP (as feature2)
is supported.  Therefore, the preceding condition “!this_cpu_has(msr->feature)”
here is true and then the test run into the first branch.  Because the feature2
RDTSCP is supported, writing reserved bits (that is, guest_test_reserved_val())
will succeed, unfortunately, the expectation for the first branch is #GP.

The check to fixup_rdmsr_val() is too late, since the preceding condition
already leads to the test run into the wrong branch.

The test can be passed on AMD CPU is because RDPID is usually supported by host,
the cupid bit for RDPID of vCPU 0 and vCPU1 can be kept, then fixup_rdmsr_val()
can drive it to the second branch.  Theoretically, the failure also can be
reproduced on some old AMD CPUs which only support RDTSCP, it’s hard to find
such an old machine to confirm it, but I suppose this case can be covered by
slight changes based on this patch.

Intel CPU no such failure, because writing MSR_TSC_AUX reserved bits results in
#GP is expected behavior.


>>  tools/testing/selftests/kvm/x86/msrs_test.c | 26 +++++++++++++++++----
>>  1 file changed, 21 insertions(+), 5 deletions(-)
>>
>> diff --git a/tools/testing/selftests/kvm/x86/msrs_test.c b/tools/testing/selftests/kvm/x86/msrs_test.c
>> index 40d918aedce6..2f1e800fe691 100644
>> --- a/tools/testing/selftests/kvm/x86/msrs_test.c
>> +++ b/tools/testing/selftests/kvm/x86/msrs_test.c
>> @@ -94,6 +94,17 @@ static u64 fixup_rdmsr_val(u32 msr, u64 want)
>>  	}
>>  }
>>  
>> +/*
>> + * On Hygon processors either RDTSCP or RDPID is supported in the host,
>> + * MSR_TSC_AUX is able to be accessed.
>> + */
>> +static bool is_hygon_msr_tsc_aux_supported(const struct kvm_msr *msr)
>> +{
>> +	return host_cpu_is_hygon &&
>> +			msr->index == MSR_TSC_AUX &&
>> +			(this_cpu_has(msr->feature) || this_cpu_has(msr->feature2));
> 
> Align indentation, but as above, this shouldn't be necessary.
> 

OK, let me fix it if this chunk still needed.

Best Regards,
Zhiquan

>> +}
>> +
>>  static void __rdmsr(u32 msr, u64 want)
>>  {
>>  	u64 val;
>> @@ -174,9 +185,14 @@ void guest_test_reserved_val(const struct kvm_msr *msr)
>>  	/*
>>  	 * If the CPU will truncate the written value (e.g. SYSENTER on AMD),
>>  	 * expect success and a truncated value, not #GP.
>> +	 *
>> +	 * On Hygon CPUs whether or not RDPID is supported in the host, once RDTSCP
>> +	 * is supported, MSR_TSC_AUX is able to be accessed.  So, for either RDTSCP
>> +	 * or RDPID is supported case and both are supported case, expect
>> +	 * success and a truncated value, not #GP.
>>  	 */
>> -	if (!this_cpu_has(msr->feature) ||
>> -	    msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val)) {
>> +	if (!is_hygon_msr_tsc_aux_supported(msr) && (!this_cpu_has(msr->feature) ||
>> +	    msr->rsvd_val == fixup_rdmsr_val(msr->index, msr->rsvd_val))) {
>>  		u8 vec = wrmsr_safe(msr->index, msr->rsvd_val);
>>  
>>  		__GUEST_ASSERT(vec == GP_VECTOR,
>> -- 
>> 2.43.0
>>