platform_info_test.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Test for x86 KVM_CAP_MSR_PLATFORM_INFO
  4. *
  5. * Copyright (C) 2018, Google LLC.
  6. *
  7. * This work is licensed under the terms of the GNU GPL, version 2.
  8. *
  9. * Verifies expected behavior of controlling guest access to
  10. * MSR_PLATFORM_INFO.
  11. */
  12. #define _GNU_SOURCE /* for program_invocation_short_name */
  13. #include <fcntl.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/ioctl.h>
  18. #include "test_util.h"
  19. #include "kvm_util.h"
  20. #include "x86.h"
  21. #define VCPU_ID 0
  22. #define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
  23. static void guest_code(void)
  24. {
  25. uint64_t msr_platform_info;
  26. for (;;) {
  27. msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
  28. GUEST_SYNC(msr_platform_info);
  29. asm volatile ("inc %r11");
  30. }
  31. }
  32. static void set_msr_platform_info_enabled(struct kvm_vm *vm, bool enable)
  33. {
  34. struct kvm_enable_cap cap = {};
  35. cap.cap = KVM_CAP_MSR_PLATFORM_INFO;
  36. cap.flags = 0;
  37. cap.args[0] = (int)enable;
  38. vm_enable_cap(vm, &cap);
  39. }
  40. static void test_msr_platform_info_enabled(struct kvm_vm *vm)
  41. {
  42. struct kvm_run *run = vcpu_state(vm, VCPU_ID);
  43. struct guest_args args;
  44. set_msr_platform_info_enabled(vm, true);
  45. vcpu_run(vm, VCPU_ID);
  46. TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
  47. "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
  48. run->exit_reason,
  49. exit_reason_str(run->exit_reason));
  50. guest_args_read(vm, VCPU_ID, &args);
  51. TEST_ASSERT(args.port == GUEST_PORT_SYNC,
  52. "Received IO from port other than PORT_HOST_SYNC: %u\n",
  53. run->io.port);
  54. TEST_ASSERT((args.arg1 & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
  55. MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
  56. "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
  57. MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
  58. }
  59. static void test_msr_platform_info_disabled(struct kvm_vm *vm)
  60. {
  61. struct kvm_run *run = vcpu_state(vm, VCPU_ID);
  62. set_msr_platform_info_enabled(vm, false);
  63. vcpu_run(vm, VCPU_ID);
  64. TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
  65. "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
  66. run->exit_reason,
  67. exit_reason_str(run->exit_reason));
  68. }
  69. int main(int argc, char *argv[])
  70. {
  71. struct kvm_vm *vm;
  72. struct kvm_run *state;
  73. int rv;
  74. uint64_t msr_platform_info;
  75. /* Tell stdout not to buffer its content */
  76. setbuf(stdout, NULL);
  77. rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
  78. if (!rv) {
  79. fprintf(stderr,
  80. "KVM_CAP_MSR_PLATFORM_INFO not supported, skip test\n");
  81. exit(KSFT_SKIP);
  82. }
  83. vm = vm_create_default(VCPU_ID, 0, guest_code);
  84. msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
  85. vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
  86. msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
  87. test_msr_platform_info_enabled(vm);
  88. test_msr_platform_info_disabled(vm);
  89. vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
  90. kvm_vm_free(vm);
  91. return 0;
  92. }