hardware_disable_test.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * This test is intended to reproduce a crash that happens when
  4. * kvm_arch_hardware_disable is called and it attempts to unregister the user
  5. * return notifiers.
  6. */
  7. #include <fcntl.h>
  8. #include <pthread.h>
  9. #include <semaphore.h>
  10. #include <stdint.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <sys/wait.h>
  14. #include <test_util.h>
  15. #include "kvm_util.h"
  16. #define VCPU_NUM 4
  17. #define SLEEPING_THREAD_NUM (1 << 4)
  18. #define FORK_NUM (1ULL << 9)
  19. #define DELAY_US_MAX 2000
  20. #define GUEST_CODE_PIO_PORT 4
  21. sem_t *sem;
  22. static void guest_code(void)
  23. {
  24. for (;;)
  25. ; /* Some busy work */
  26. printf("Should not be reached.\n");
  27. }
  28. static void *run_vcpu(void *arg)
  29. {
  30. struct kvm_vcpu *vcpu = arg;
  31. struct kvm_run *run = vcpu->run;
  32. vcpu_run(vcpu);
  33. TEST_ASSERT(false, "%s: exited with reason %d: %s",
  34. __func__, run->exit_reason,
  35. exit_reason_str(run->exit_reason));
  36. pthread_exit(NULL);
  37. }
  38. static void *sleeping_thread(void *arg)
  39. {
  40. int fd;
  41. while (true) {
  42. fd = open("/dev/null", O_RDWR);
  43. close(fd);
  44. }
  45. TEST_ASSERT(false, "%s: exited", __func__);
  46. pthread_exit(NULL);
  47. }
  48. static inline void check_create_thread(pthread_t *thread, pthread_attr_t *attr,
  49. void *(*f)(void *), void *arg)
  50. {
  51. int r;
  52. r = pthread_create(thread, attr, f, arg);
  53. TEST_ASSERT(r == 0, "%s: failed to create thread", __func__);
  54. }
  55. static inline void check_set_affinity(pthread_t thread, cpu_set_t *cpu_set)
  56. {
  57. int r;
  58. r = pthread_setaffinity_np(thread, sizeof(cpu_set_t), cpu_set);
  59. TEST_ASSERT(r == 0, "%s: failed set affinity", __func__);
  60. }
  61. static inline void check_join(pthread_t thread, void **retval)
  62. {
  63. int r;
  64. r = pthread_join(thread, retval);
  65. TEST_ASSERT(r == 0, "%s: failed to join thread", __func__);
  66. }
  67. static void run_test(uint32_t run)
  68. {
  69. struct kvm_vcpu *vcpu;
  70. struct kvm_vm *vm;
  71. cpu_set_t cpu_set;
  72. pthread_t threads[VCPU_NUM];
  73. pthread_t throw_away;
  74. void *b;
  75. uint32_t i, j;
  76. CPU_ZERO(&cpu_set);
  77. for (i = 0; i < VCPU_NUM; i++)
  78. CPU_SET(i, &cpu_set);
  79. vm = vm_create(VCPU_NUM);
  80. pr_debug("%s: [%d] start vcpus\n", __func__, run);
  81. for (i = 0; i < VCPU_NUM; ++i) {
  82. vcpu = vm_vcpu_add(vm, i, guest_code);
  83. check_create_thread(&threads[i], NULL, run_vcpu, vcpu);
  84. check_set_affinity(threads[i], &cpu_set);
  85. for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
  86. check_create_thread(&throw_away, NULL, sleeping_thread,
  87. (void *)NULL);
  88. check_set_affinity(throw_away, &cpu_set);
  89. }
  90. }
  91. pr_debug("%s: [%d] all threads launched\n", __func__, run);
  92. sem_post(sem);
  93. for (i = 0; i < VCPU_NUM; ++i)
  94. check_join(threads[i], &b);
  95. /* Should not be reached */
  96. TEST_ASSERT(false, "%s: [%d] child escaped the ninja", __func__, run);
  97. }
  98. void wait_for_child_setup(pid_t pid)
  99. {
  100. /*
  101. * Wait for the child to post to the semaphore, but wake up periodically
  102. * to check if the child exited prematurely.
  103. */
  104. for (;;) {
  105. const struct timespec wait_period = { .tv_sec = 1 };
  106. int status;
  107. if (!sem_timedwait(sem, &wait_period))
  108. return;
  109. /* Child is still running, keep waiting. */
  110. if (pid != waitpid(pid, &status, WNOHANG))
  111. continue;
  112. /*
  113. * Child is no longer running, which is not expected.
  114. *
  115. * If it exited with a non-zero status, we explicitly forward
  116. * the child's status in case it exited with KSFT_SKIP.
  117. */
  118. if (WIFEXITED(status))
  119. exit(WEXITSTATUS(status));
  120. else
  121. TEST_ASSERT(false, "Child exited unexpectedly");
  122. }
  123. }
  124. int main(int argc, char **argv)
  125. {
  126. uint32_t i;
  127. int s, r;
  128. pid_t pid;
  129. sem = sem_open("vm_sem", O_CREAT | O_EXCL, 0644, 0);
  130. sem_unlink("vm_sem");
  131. for (i = 0; i < FORK_NUM; ++i) {
  132. pid = fork();
  133. TEST_ASSERT(pid >= 0, "%s: unable to fork", __func__);
  134. if (pid == 0)
  135. run_test(i); /* This function always exits */
  136. pr_debug("%s: [%d] waiting semaphore\n", __func__, i);
  137. wait_for_child_setup(pid);
  138. r = (rand() % DELAY_US_MAX) + 1;
  139. pr_debug("%s: [%d] waiting %dus\n", __func__, i, r);
  140. usleep(r);
  141. r = waitpid(pid, &s, WNOHANG);
  142. TEST_ASSERT(r != pid,
  143. "%s: [%d] child exited unexpectedly status: [%d]",
  144. __func__, i, s);
  145. pr_debug("%s: [%d] killing child\n", __func__, i);
  146. kill(pid, SIGKILL);
  147. }
  148. sem_destroy(sem);
  149. exit(0);
  150. }