On Sat, Sep 26, 2026, Tharit Tangkijwanichakul wrote:
> The msr_filter_deny test covers the FILTER and UNKNOWN MSR exit
> reasons, but nothing exercises KVM_MSR_EXIT_REASON_INVAL.
> 
> Have the guest set a reserved bit (bit 63) in EFER while preserving
> the other bits, and verify that the write exits to userspace with
> KVM_MSR_EXIT_REASON_INVAL along with the attempted value.
> 
> Signed-off-by: Tharit Tangkijwanichakul <[email protected]>
> ---
> Tested on Intel Core i5-10210U (VMX). Not tested on AMD.
> ---
>  .../selftests/kvm/x86/userspace_msr_exit_test.c      | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/kvm/x86/userspace_msr_exit_test.c 
> b/tools/testing/selftests/kvm/x86/userspace_msr_exit_test.c
> index 2808ce727e5f..7446e1404264 100644
> --- a/tools/testing/selftests/kvm/x86/userspace_msr_exit_test.c
> +++ b/tools/testing/selftests/kvm/x86/userspace_msr_exit_test.c
> @@ -309,6 +309,9 @@ static void guest_msr_calls(bool trapped)
>       /* Invalid MSR, should always be handled by user space exit */
>       GUEST_ASSERT(rdmsr(0xdeadbeef) == 0xdeadbeef);
>       wrmsr(0xdeadbeef, 0x1234);
> +
> +     /* Setting a reserved EFER bit is rejected by KVM, exit with INVAL */
> +     wrmsr(MSR_EFER, rdmsr(MSR_EFER) | BIT_ULL(63));

I'd rather use an MSR that is less likely to gain supported bits in the future.
It's definitely unlikely EFER[63] will be used in the near future, but it's far
from impossible.

My vote would be to write a non-canonical (even with LA57=1) value to 
MSR_FS_BASE
and/or MSR_GS_BASE.  While it's technically possible that x86 could extend the
canonical address space, that's pretty much guaranteed to require truly massive
architectural changes.  And if we reuse the NONCANONICAL macro (which we 
should),
then even if the unlikely happens, at the very least it will be easy to find 
what
all needs to be updated.  As a bonus, the test already uses in MSR_FS_BASE and
MSR_GS_BASE, so they're naturally fits.

Alternatively, we could use PAT, as it's extremely unlikely x86 is going to gain
new memory types in the near future, but I like using a non-canonical value.

>  }
>  
>  static void guest_code_filter_deny(void)
> @@ -627,6 +630,13 @@ static void handle_wrmsr(struct kvm_run *run)
>               TEST_ASSERT(run->msr.reason == KVM_MSR_EXIT_REASON_UNKNOWN,
>                           "deadbeef trap w/o inval fault");
>       }
> +
> +     if (run->msr.index == MSR_EFER) {
> +             TEST_ASSERT(run->msr.data & BIT_ULL(63),
> +                         "MSR_EFER data missing reserved bit");
> +             TEST_ASSERT(run->msr.reason == KVM_MSR_EXIT_REASON_INVAL,
> +                         "MSR_EFER trap w/o inval fault");
> +     }
>  }
>  
>  KVM_ONE_VCPU_TEST(user_msr, msr_filter_deny, guest_code_filter_deny)
> @@ -667,7 +677,7 @@ KVM_ONE_VCPU_TEST(user_msr, msr_filter_deny, 
> guest_code_filter_deny)
>  
>  done:
>       TEST_ASSERT(msr_reads == 4, "Handled 4 rdmsr in user space");
> -     TEST_ASSERT(msr_writes == 3, "Handled 3 wrmsr in user space");
> +     TEST_ASSERT(msr_writes == 5, "Handled 5 wrmsr in user space");
>  }
>  
>  KVM_ONE_VCPU_TEST(user_msr, msr_permission_bitmap, 
> guest_code_permission_bitmap)
> -- 
> 2.53.0
> 
> 

Reply via email to