0001
0002
0003
0004
0005
0006
0007
0008 #define _GNU_SOURCE
0009
0010 #include <fcntl.h>
0011 #include <pthread.h>
0012 #include <semaphore.h>
0013 #include <stdint.h>
0014 #include <stdlib.h>
0015 #include <unistd.h>
0016 #include <sys/wait.h>
0017
0018 #include <test_util.h>
0019
0020 #include "kvm_util.h"
0021
0022 #define VCPU_NUM 4
0023 #define SLEEPING_THREAD_NUM (1 << 4)
0024 #define FORK_NUM (1ULL << 9)
0025 #define DELAY_US_MAX 2000
0026 #define GUEST_CODE_PIO_PORT 4
0027
0028 sem_t *sem;
0029
0030 static void guest_code(void)
0031 {
0032 for (;;)
0033 ;
0034 printf("Should not be reached.\n");
0035 }
0036
0037 static void *run_vcpu(void *arg)
0038 {
0039 struct kvm_vcpu *vcpu = arg;
0040 struct kvm_run *run = vcpu->run;
0041
0042 vcpu_run(vcpu);
0043
0044 TEST_ASSERT(false, "%s: exited with reason %d: %s\n",
0045 __func__, run->exit_reason,
0046 exit_reason_str(run->exit_reason));
0047 pthread_exit(NULL);
0048 }
0049
0050 static void *sleeping_thread(void *arg)
0051 {
0052 int fd;
0053
0054 while (true) {
0055 fd = open("/dev/null", O_RDWR);
0056 close(fd);
0057 }
0058 TEST_ASSERT(false, "%s: exited\n", __func__);
0059 pthread_exit(NULL);
0060 }
0061
0062 static inline void check_create_thread(pthread_t *thread, pthread_attr_t *attr,
0063 void *(*f)(void *), void *arg)
0064 {
0065 int r;
0066
0067 r = pthread_create(thread, attr, f, arg);
0068 TEST_ASSERT(r == 0, "%s: failed to create thread", __func__);
0069 }
0070
0071 static inline void check_set_affinity(pthread_t thread, cpu_set_t *cpu_set)
0072 {
0073 int r;
0074
0075 r = pthread_setaffinity_np(thread, sizeof(cpu_set_t), cpu_set);
0076 TEST_ASSERT(r == 0, "%s: failed set affinity", __func__);
0077 }
0078
0079 static inline void check_join(pthread_t thread, void **retval)
0080 {
0081 int r;
0082
0083 r = pthread_join(thread, retval);
0084 TEST_ASSERT(r == 0, "%s: failed to join thread", __func__);
0085 }
0086
0087 static void run_test(uint32_t run)
0088 {
0089 struct kvm_vcpu *vcpu;
0090 struct kvm_vm *vm;
0091 cpu_set_t cpu_set;
0092 pthread_t threads[VCPU_NUM];
0093 pthread_t throw_away;
0094 void *b;
0095 uint32_t i, j;
0096
0097 CPU_ZERO(&cpu_set);
0098 for (i = 0; i < VCPU_NUM; i++)
0099 CPU_SET(i, &cpu_set);
0100
0101 vm = vm_create(VCPU_NUM);
0102
0103 pr_debug("%s: [%d] start vcpus\n", __func__, run);
0104 for (i = 0; i < VCPU_NUM; ++i) {
0105 vcpu = vm_vcpu_add(vm, i, guest_code);
0106
0107 check_create_thread(&threads[i], NULL, run_vcpu, vcpu);
0108 check_set_affinity(threads[i], &cpu_set);
0109
0110 for (j = 0; j < SLEEPING_THREAD_NUM; ++j) {
0111 check_create_thread(&throw_away, NULL, sleeping_thread,
0112 (void *)NULL);
0113 check_set_affinity(throw_away, &cpu_set);
0114 }
0115 }
0116 pr_debug("%s: [%d] all threads launched\n", __func__, run);
0117 sem_post(sem);
0118 for (i = 0; i < VCPU_NUM; ++i)
0119 check_join(threads[i], &b);
0120
0121 TEST_ASSERT(false, "%s: [%d] child escaped the ninja\n", __func__, run);
0122 }
0123
0124 void wait_for_child_setup(pid_t pid)
0125 {
0126
0127
0128
0129
0130 for (;;) {
0131 const struct timespec wait_period = { .tv_sec = 1 };
0132 int status;
0133
0134 if (!sem_timedwait(sem, &wait_period))
0135 return;
0136
0137
0138 if (pid != waitpid(pid, &status, WNOHANG))
0139 continue;
0140
0141
0142
0143
0144
0145
0146
0147 if (WIFEXITED(status))
0148 exit(WEXITSTATUS(status));
0149 else
0150 TEST_ASSERT(false, "Child exited unexpectedly");
0151 }
0152 }
0153
0154 int main(int argc, char **argv)
0155 {
0156 uint32_t i;
0157 int s, r;
0158 pid_t pid;
0159
0160 sem = sem_open("vm_sem", O_CREAT | O_EXCL, 0644, 0);
0161 sem_unlink("vm_sem");
0162
0163 for (i = 0; i < FORK_NUM; ++i) {
0164 pid = fork();
0165 TEST_ASSERT(pid >= 0, "%s: unable to fork", __func__);
0166 if (pid == 0)
0167 run_test(i);
0168
0169 pr_debug("%s: [%d] waiting semaphore\n", __func__, i);
0170 wait_for_child_setup(pid);
0171 r = (rand() % DELAY_US_MAX) + 1;
0172 pr_debug("%s: [%d] waiting %dus\n", __func__, i, r);
0173 usleep(r);
0174 r = waitpid(pid, &s, WNOHANG);
0175 TEST_ASSERT(r != pid,
0176 "%s: [%d] child exited unexpectedly status: [%d]",
0177 __func__, i, s);
0178 pr_debug("%s: [%d] killing child\n", __func__, i);
0179 kill(pid, SIGKILL);
0180 }
0181
0182 sem_destroy(sem);
0183 exit(0);
0184 }