| 1 | |
| 2 |
|
| 3 | |
| 4 | * Include rseq.c without _GNU_SOURCE defined, before including any headers, so
|
| 5 | * that rseq.c is compiled with its configuration, not KVM selftests' config.
|
| 6 |
|
| 7 | #undef _GNU_SOURCE
|
| 8 | #include "../rseq/rseq.c"
|
| 9 | #define _GNU_SOURCE
|
| 10 |
|
| 11 | #include <errno.h>
|
| 12 | #include <fcntl.h>
|
| 13 | #include <pthread.h>
|
| 14 | #include <sched.h>
|
| 15 | #include <stdio.h>
|
| 16 | #include <stdlib.h>
|
| 17 | #include <string.h>
|
| 18 | #include <signal.h>
|
| 19 | #include <syscall.h>
|
| 20 | #include <sys/ioctl.h>
|
| 21 | #include <sys/sysinfo.h>
|
| 22 | #include <asm/barrier.h>
|
| 23 | #include <linux/atomic.h>
|
| 24 | #include <linux/rseq.h>
|
| 25 | #include <linux/unistd.h>
|
| 26 |
|
| 27 | #include "kvm_util.h"
|
| 28 | #include "processor.h"
|
| 29 | #include "test_util.h"
|
| 30 | #include "ucall_common.h"
|
| 31 |
|
| 32 | |
| 33 | * Any bug related to task migration is likely to be timing-dependent; perform
|
| 34 | * a large number of migrations to reduce the odds of a false negative.
|
| 35 |
|
| 36 | #define NR_TASK_MIGRATIONS 100000
|
| 37 |
|
| 38 | static pthread_t migration_thread;
|
| 39 | static cpu_set_t possible_mask;
|
| 40 | static int min_cpu, max_cpu;
|
| 41 | static bool done;
|
| 42 |
|
| 43 | static atomic_t seq_cnt;
|
| 44 |
|
| 45 | static void guest_code(void)
|
| 46 | {
|
| 47 | for (;;)
|
| 48 | GUEST_SYNC(0);
|
| 49 | }
|
| 50 |
|
| 51 | static int next_cpu(int cpu)
|
| 52 | {
|
| 53 | |
| 54 | * Advance to the next CPU, skipping those that weren't in the original
|
| 55 | * affinity set. Sadly, there is no CPU_SET_FOR_EACH, and cpu_set_t's
|
| 56 | * data storage is considered as opaque. Note, if this task is pinned
|
| 57 | * to a small set of discontigous CPUs, e.g. 2 and 1023, this loop will
|
| 58 | * burn a lot cycles and the test will take longer than normal to
|
| 59 | * complete.
|
| 60 |
|
| 61 | do {
|
| 62 | cpu++;
|
| 63 | if (cpu > max_cpu) {
|
| 64 | cpu = min_cpu;
|
| 65 | TEST_ASSERT(CPU_ISSET(cpu, &possible_mask),
|
| 66 | "Min CPU = %d must always be usable", cpu);
|
| 67 | break;
|
| 68 | }
|
| 69 | } while (!CPU_ISSET(cpu, &possible_mask));
|
| 70 |
|
| 71 | return cpu;
|
| 72 | }
|
| 73 |
|
| 74 | static void *migration_worker(void *__rseq_tid)
|
| 75 | {
|
| 76 | pid_t rseq_tid = (pid_t)(unsigned long)__rseq_tid;
|
| 77 | cpu_set_t allowed_mask;
|
| 78 | int i, cpu;
|
| 79 |
|
| 80 | CPU_ZERO(&allowed_mask);
|
| 81 |
|
| 82 | for (i = 0, cpu = min_cpu; i < NR_TASK_MIGRATIONS; i++, cpu = next_cpu(cpu)) {
|
| 83 | CPU_SET(cpu, &allowed_mask);
|
| 84 |
|
| 85 | |
| 86 | * Bump the sequence count twice to allow the reader to detect
|
| 87 | * that a migration may have occurred in between rseq and sched
|
| 88 | * CPU ID reads. An odd sequence count indicates a migration
|
| 89 | * is in-progress, while a completely different count indicates
|
| 90 | * a migration occurred since the count was last read.
|
| 91 |
|
| 92 | atomic_inc(&seq_cnt);
|
| 93 |
|
| 94 | |
| 95 | * Ensure the odd count is visible while getcpu() isn't
|
| 96 | * stable, i.e. while changing affinity is in-progress.
|
| 97 |
|
| 98 | smp_wmb();
|
| 99 | kvm_sched_setaffinity(rseq_tid, sizeof(allowed_mask), &allowed_mask);
|
| 100 | smp_wmb();
|
| 101 | atomic_inc(&seq_cnt);
|
| 102 |
|
| 103 | CPU_CLR(cpu, &allowed_mask);
|
| 104 |
|
| 105 | |
| 106 | * Wait 1-10us before proceeding to the next iteration and more
|
| 107 | * specifically, before bumping seq_cnt again. A delay is
|
| 108 | * needed on three fronts:
|
| 109 | *
|
| 110 | * 1. To allow sched_setaffinity() to prompt migration before
|
| 111 | * ioctl(KVM_RUN) enters the guest so that TIF_NOTIFY_RESUME
|
| 112 | * (or TIF_NEED_RESCHED, which indirectly leads to handling
|
| 113 | * NOTIFY_RESUME) is handled in KVM context.
|
| 114 | *
|
| 115 | * If NOTIFY_RESUME/NEED_RESCHED is set after KVM enters
|
| 116 | * the guest, the guest will trigger a IO/MMIO exit all the
|
| 117 | * way to userspace and the TIF flags will be handled by
|
| 118 | * the generic "exit to userspace" logic, not by KVM. The
|
| 119 | * exit to userspace is necessary to give the test a chance
|
| 120 | * to check the rseq CPU ID (see #2).
|
| 121 | *
|
| 122 | * Alternatively, guest_code() could include an instruction
|
| 123 | * to trigger an exit that is handled by KVM, but any such
|
| 124 | * exit requires architecture specific code.
|
| 125 | *
|
| 126 | * 2. To let ioctl(KVM_RUN) make its way back to the test
|
| 127 | * before the next round of migration. The test's check on
|
| 128 | * the rseq CPU ID must wait for migration to complete in
|
| 129 | * order to avoid false positive, thus any kernel rseq bug
|
| 130 | * will be missed if the next migration starts before the
|
| 131 | * check completes.
|
| 132 | *
|
| 133 | * 3. To ensure the read-side makes efficient forward progress,
|
| 134 | * e.g. if getcpu() involves a syscall. Stalling the read-side
|
| 135 | * means the test will spend more time waiting for getcpu()
|
| 136 | * to stabilize and less time trying to hit the timing-dependent
|
| 137 | * bug.
|
| 138 | *
|
| 139 | * Because any bug in this area is likely to be timing-dependent,
|
| 140 | * run with a range of delays at 1us intervals from 1us to 10us
|
| 141 | * as a best effort to avoid tuning the test to the point where
|
| 142 | * it can hit _only_ the original bug and not detect future
|
| 143 | * regressions.
|
| 144 | *
|
| 145 | * The original bug can reproduce with a delay up to ~500us on
|
| 146 | * x86-64, but starts to require more iterations to reproduce
|
| 147 | * as the delay creeps above ~10us, and the average runtime of
|
| 148 | * each iteration obviously increases as well. Cap the delay
|
| 149 | * at 10us to keep test runtime reasonable while minimizing
|
| 150 | * potential coverage loss.
|
| 151 | *
|
| 152 | * The lower bound for reproducing the bug is likely below 1us,
|
| 153 | * e.g. failures occur on x86-64 with nanosleep(0), but at that
|
| 154 | * point the overhead of the syscall likely dominates the delay.
|
| 155 | * Use usleep() for simplicity and to avoid unnecessary kernel
|
| 156 | * dependencies.
|
| 157 |
|
| 158 | usleep((i % 10) + 1);
|
| 159 | }
|
| 160 | done = true;
|
| 161 | return NULL;
|
| 162 | }
|
| 163 |
|
| 164 | static void calc_min_max_cpu(void)
|
| 165 | {
|
| 166 | int i, cnt, nproc;
|
| 167 |
|
| 168 | TEST_REQUIRE(CPU_COUNT(&possible_mask) >= 2);
|
| 169 |
|
| 170 | |
| 171 | * CPU_SET doesn't provide a FOR_EACH helper, get the min/max CPU that
|
| 172 | * this task is affined to in order to reduce the time spent querying
|
| 173 | * unusable CPUs, e.g. if this task is pinned to a small percentage of
|
| 174 | * total CPUs.
|
| 175 |
|
| 176 | nproc = get_nprocs_conf();
|
| 177 | min_cpu = -1;
|
| 178 | max_cpu = -1;
|
| 179 | cnt = 0;
|
| 180 |
|
| 181 | for (i = 0; i < nproc; i++) {
|
| 182 | if (!CPU_ISSET(i, &possible_mask))
|
| 183 | continue;
|
| 184 | if (min_cpu == -1)
|
| 185 | min_cpu = i;
|
| 186 | max_cpu = i;
|
| 187 | cnt++;
|
| 188 | }
|
| 189 |
|
| 190 | __TEST_REQUIRE(cnt >= 2,
|
| 191 | "Only one usable CPU, task migration not possible");
|
| 192 | }
|
| 193 |
|
| 194 | static void help(const char *name)
|
| 195 | {
|
| 196 | puts("");
|
| 197 | printf("usage: %s [-h] [-u] [-l latency]\n", name);
|
| 198 | printf(" -u: Don't sanity check the number of successful KVM_RUNs\n");
|
| 199 | printf(" -l: Set /dev/cpu_dma_latency to suppress deep sleep states\n");
|
| 200 | puts("");
|
| 201 | exit(0);
|
| 202 | }
|
| 203 |
|
| 204 | int main(int argc, char *argv[])
|
| 205 | {
|
| 206 | int r, i, snapshot, opt, fd = -1, latency = -1;
|
| 207 | bool skip_sanity_check = false;
|
| 208 | struct kvm_vm *vm;
|
| 209 | struct kvm_vcpu *vcpu;
|
| 210 | u32 cpu, rseq_cpu;
|
| 211 |
|
| 212 | while ((opt = getopt(argc, argv, "hl:u")) != -1) {
|
| 213 | switch (opt) {
|
| 214 | case 'u':
|
| 215 | skip_sanity_check = true;
|
| 216 | break;
|
| 217 | case 'l':
|
| 218 | latency = atoi_paranoid(optarg);
|
| 219 | break;
|
| 220 | case 'h':
|
| 221 | default:
|
| 222 | help(argv[0]);
|
| 223 | break;
|
| 224 | }
|
| 225 | }
|
| 226 |
|
| 227 | kvm_sched_getaffinity(0, sizeof(possible_mask), &possible_mask);
|
| 228 |
|
| 229 | calc_min_max_cpu();
|
| 230 |
|
| 231 | r = rseq_register_current_thread();
|
| 232 | TEST_ASSERT(!r, "rseq_register_current_thread failed, errno = %d (%s)",
|
| 233 | errno, strerror(errno));
|
| 234 |
|
| 235 | |
| 236 | * Create and run a dummy VM that immediately exits to userspace via
|
| 237 | * GUEST_SYNC, while concurrently migrating the process by setting its
|
| 238 | * CPU affinity.
|
| 239 |
|
| 240 | vm = vm_create_with_one_vcpu(&vcpu, guest_code);
|
| 241 |
|
| 242 | kvm_pthread_create(&migration_thread, NULL, migration_worker,
|
| 243 | (void *)(unsigned long)kvm_gettid());
|
| 244 |
|
| 245 | if (latency >= 0) {
|
| 246 | |
| 247 | * Writes to cpu_dma_latency persist only while the file is
|
| 248 | * open, i.e. it allows userspace to provide guaranteed latency
|
| 249 | * while running a workload. Keep the file open until the test
|
| 250 | * completes, otherwise writing cpu_dma_latency is meaningless.
|
| 251 |
|
| 252 | fd = open("/dev/cpu_dma_latency", O_RDWR);
|
| 253 | TEST_ASSERT(fd >= 0, __KVM_SYSCALL_ERROR("open() /dev/cpu_dma_latency", fd));
|
| 254 |
|
| 255 | r = write(fd, &latency, 4);
|
| 256 | TEST_ASSERT(r >= 1, "Error setting /dev/cpu_dma_latency");
|
| 257 | }
|
| 258 |
|
| 259 | for (i = 0; !done; i++) {
|
| 260 | vcpu_run(vcpu);
|
| 261 | TEST_ASSERT(get_ucall(vcpu, NULL) == UCALL_SYNC,
|
| 262 | "Guest failed?");
|
| 263 |
|
| 264 | |
| 265 | * Verify rseq's CPU matches sched's CPU. Ensure migration
|
| 266 | * doesn't occur between getcpu() and reading the rseq cpu_id
|
| 267 | * by rereading both if the sequence count changes, or if the
|
| 268 | * count is odd (migration in-progress).
|
| 269 |
|
| 270 | do {
|
| 271 | |
| 272 | * Drop bit 0 to force a mismatch if the count is odd,
|
| 273 | * i.e. if a migration is in-progress.
|
| 274 |
|
| 275 | snapshot = atomic_read(&seq_cnt) & ~1;
|
| 276 |
|
| 277 | |
| 278 | * Ensure calling getcpu() and reading rseq.cpu_id complete
|
| 279 | * in a single "no migration" window, i.e. are not reordered
|
| 280 | * across the seq_cnt reads.
|
| 281 |
|
| 282 | smp_rmb();
|
| 283 | r = sys_getcpu(&cpu, NULL);
|
| 284 | TEST_ASSERT(!r, "getcpu failed, errno = %d (%s)",
|
| 285 | errno, strerror(errno));
|
| 286 | rseq_cpu = rseq_current_cpu_raw();
|
| 287 | smp_rmb();
|
| 288 | } while (snapshot != atomic_read(&seq_cnt));
|
| 289 |
|
| 290 | TEST_ASSERT(rseq_cpu == cpu,
|
| 291 | "rseq CPU = %d, sched CPU = %d", rseq_cpu, cpu);
|
| 292 | }
|
| 293 |
|
| 294 | if (fd > 0)
|
| 295 | close(fd);
|
| 296 |
|
| 297 | |
| 298 | * Sanity check that the test was able to enter the guest a reasonable
|
| 299 | * number of times, e.g. didn't get stalled too often/long waiting for
|
| 300 | * getcpu() to stabilize. A 2:1 migration:KVM_RUN ratio is a fairly
|
| 301 | * conservative ratio on x86-64, which can do _more_ KVM_RUNs than
|
| 302 | * migrations given the 1us+ delay in the migration task.
|
| 303 | *
|
| 304 | * Another reason why it may have small migration:KVM_RUN ratio is that,
|
| 305 | * on systems with large low power mode wakeup latency, it may happen
|
| 306 | * quite often that the scheduler is not able to wake up the target CPU
|
| 307 | * before the vCPU thread is scheduled to another CPU.
|
| 308 |
|
| 309 | TEST_ASSERT(skip_sanity_check || i > (NR_TASK_MIGRATIONS / 2),
|
| 310 | "Only performed %d KVM_RUNs, task stalled too much?\n\n"
|
| 311 | " Try disabling deep sleep states to reduce CPU wakeup latency,\n"
|
| 312 | " e.g. via cpuidle.off=1 or via -l <latency>, or run with -u to\n"
|
| 313 | " disable this sanity check.", i);
|
| 314 |
|
| 315 | kvm_pthread_join(migration_thread, NULL);
|
| 316 |
|
| 317 | kvm_vm_free(vm);
|
| 318 |
|
| 319 | rseq_unregister_current_thread();
|
| 320 |
|
| 321 | return 0;
|
| 322 | }
|