feature_msrs_test.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020, Red Hat, Inc.
  4. */
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/ioctl.h>
  10. #include "test_util.h"
  11. #include "kvm_util.h"
  12. #include "processor.h"
  13. static bool is_kvm_controlled_msr(uint32_t msr)
  14. {
  15. return msr == MSR_IA32_VMX_CR0_FIXED1 || msr == MSR_IA32_VMX_CR4_FIXED1;
  16. }
  17. /*
  18. * For VMX MSRs with a "true" variant, KVM requires userspace to set the "true"
  19. * MSR, and doesn't allow setting the hidden version.
  20. */
  21. static bool is_hidden_vmx_msr(uint32_t msr)
  22. {
  23. switch (msr) {
  24. case MSR_IA32_VMX_PINBASED_CTLS:
  25. case MSR_IA32_VMX_PROCBASED_CTLS:
  26. case MSR_IA32_VMX_EXIT_CTLS:
  27. case MSR_IA32_VMX_ENTRY_CTLS:
  28. return true;
  29. default:
  30. return false;
  31. }
  32. }
  33. static bool is_quirked_msr(uint32_t msr)
  34. {
  35. return msr != MSR_AMD64_DE_CFG;
  36. }
  37. static void test_feature_msr(uint32_t msr)
  38. {
  39. const uint64_t supported_mask = kvm_get_feature_msr(msr);
  40. uint64_t reset_value = is_quirked_msr(msr) ? supported_mask : 0;
  41. struct kvm_vcpu *vcpu;
  42. struct kvm_vm *vm;
  43. /*
  44. * Don't bother testing KVM-controlled MSRs beyond verifying that the
  45. * MSR can be read from userspace. Any value is effectively legal, as
  46. * KVM is bound by x86 architecture, not by ABI.
  47. */
  48. if (is_kvm_controlled_msr(msr))
  49. return;
  50. /*
  51. * More goofy behavior. KVM reports the host CPU's actual revision ID,
  52. * but initializes the vCPU's revision ID to an arbitrary value.
  53. */
  54. if (msr == MSR_IA32_UCODE_REV)
  55. reset_value = host_cpu_is_intel ? 0x100000000ULL : 0x01000065;
  56. /*
  57. * For quirked MSRs, KVM's ABI is to initialize the vCPU's value to the
  58. * full set of features supported by KVM. For non-quirked MSRs, and
  59. * when the quirk is disabled, KVM must zero-initialize the MSR and let
  60. * userspace do the configuration.
  61. */
  62. vm = vm_create_with_one_vcpu(&vcpu, NULL);
  63. TEST_ASSERT(vcpu_get_msr(vcpu, msr) == reset_value,
  64. "Wanted 0x%lx for %squirked MSR 0x%x, got 0x%lx",
  65. reset_value, is_quirked_msr(msr) ? "" : "non-", msr,
  66. vcpu_get_msr(vcpu, msr));
  67. if (!is_hidden_vmx_msr(msr))
  68. vcpu_set_msr(vcpu, msr, supported_mask);
  69. kvm_vm_free(vm);
  70. if (is_hidden_vmx_msr(msr))
  71. return;
  72. if (!kvm_has_cap(KVM_CAP_DISABLE_QUIRKS2) ||
  73. !(kvm_check_cap(KVM_CAP_DISABLE_QUIRKS2) & KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
  74. return;
  75. vm = vm_create(1);
  76. vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, KVM_X86_QUIRK_STUFF_FEATURE_MSRS);
  77. vcpu = vm_vcpu_add(vm, 0, NULL);
  78. TEST_ASSERT(!vcpu_get_msr(vcpu, msr),
  79. "Quirk disabled, wanted '0' for MSR 0x%x, got 0x%lx",
  80. msr, vcpu_get_msr(vcpu, msr));
  81. kvm_vm_free(vm);
  82. }
  83. int main(int argc, char *argv[])
  84. {
  85. const struct kvm_msr_list *feature_list;
  86. int i;
  87. /*
  88. * Skip the entire test if MSR_FEATURES isn't supported, other tests
  89. * will cover the "regular" list of MSRs, the coverage here is purely
  90. * opportunistic and not interesting on its own.
  91. */
  92. TEST_REQUIRE(kvm_has_cap(KVM_CAP_GET_MSR_FEATURES));
  93. (void)kvm_get_msr_index_list();
  94. feature_list = kvm_get_feature_msr_index_list();
  95. for (i = 0; i < feature_list->nmsrs; i++)
  96. test_feature_msr(feature_list->indices[i]);
  97. }