root/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. thr
  2. test
  3. get_warnings_count
  4. main

   1 /*
   2  * mmio_warning_test
   3  *
   4  * Copyright (C) 2019, Google LLC.
   5  *
   6  * This work is licensed under the terms of the GNU GPL, version 2.
   7  *
   8  * Test that we don't get a kernel warning when we call KVM_RUN after a
   9  * triple fault occurs.  To get the triple fault to occur we call KVM_RUN
  10  * on a VCPU that hasn't been properly setup.
  11  *
  12  */
  13 
  14 #define _GNU_SOURCE
  15 #include <fcntl.h>
  16 #include <kvm_util.h>
  17 #include <linux/kvm.h>
  18 #include <processor.h>
  19 #include <pthread.h>
  20 #include <stdio.h>
  21 #include <stdlib.h>
  22 #include <string.h>
  23 #include <sys/ioctl.h>
  24 #include <sys/mman.h>
  25 #include <sys/stat.h>
  26 #include <sys/types.h>
  27 #include <sys/wait.h>
  28 #include <test_util.h>
  29 #include <unistd.h>
  30 
  31 #define NTHREAD 4
  32 #define NPROCESS 5
  33 
  34 struct thread_context {
  35         int kvmcpu;
  36         struct kvm_run *run;
  37 };
  38 
  39 void *thr(void *arg)
  40 {
  41         struct thread_context *tc = (struct thread_context *)arg;
  42         int res;
  43         int kvmcpu = tc->kvmcpu;
  44         struct kvm_run *run = tc->run;
  45 
  46         res = ioctl(kvmcpu, KVM_RUN, 0);
  47         printf("ret1=%d exit_reason=%d suberror=%d\n",
  48                 res, run->exit_reason, run->internal.suberror);
  49 
  50         return 0;
  51 }
  52 
  53 void test(void)
  54 {
  55         int i, kvm, kvmvm, kvmcpu;
  56         pthread_t th[NTHREAD];
  57         struct kvm_run *run;
  58         struct thread_context tc;
  59 
  60         kvm = open("/dev/kvm", O_RDWR);
  61         TEST_ASSERT(kvm != -1, "failed to open /dev/kvm");
  62         kvmvm = ioctl(kvm, KVM_CREATE_VM, 0);
  63         TEST_ASSERT(kvmvm != -1, "KVM_CREATE_VM failed");
  64         kvmcpu = ioctl(kvmvm, KVM_CREATE_VCPU, 0);
  65         TEST_ASSERT(kvmcpu != -1, "KVM_CREATE_VCPU failed");
  66         run = (struct kvm_run *)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED,
  67                                     kvmcpu, 0);
  68         tc.kvmcpu = kvmcpu;
  69         tc.run = run;
  70         srand(getpid());
  71         for (i = 0; i < NTHREAD; i++) {
  72                 pthread_create(&th[i], NULL, thr, (void *)(uintptr_t)&tc);
  73                 usleep(rand() % 10000);
  74         }
  75         for (i = 0; i < NTHREAD; i++)
  76                 pthread_join(th[i], NULL);
  77 }
  78 
  79 int get_warnings_count(void)
  80 {
  81         int warnings;
  82         FILE *f;
  83 
  84         f = popen("dmesg | grep \"WARNING:\" | wc -l", "r");
  85         fscanf(f, "%d", &warnings);
  86         fclose(f);
  87 
  88         return warnings;
  89 }
  90 
  91 int main(void)
  92 {
  93         int warnings_before, warnings_after;
  94 
  95         if (!is_intel_cpu()) {
  96                 printf("Must be run on an Intel CPU, skipping test\n");
  97                 exit(KSFT_SKIP);
  98         }
  99 
 100         if (vm_is_unrestricted_guest(NULL)) {
 101                 printf("Unrestricted guest must be disabled, skipping test\n");
 102                 exit(KSFT_SKIP);
 103         }
 104 
 105         warnings_before = get_warnings_count();
 106 
 107         for (int i = 0; i < NPROCESS; ++i) {
 108                 int status;
 109                 int pid = fork();
 110 
 111                 if (pid < 0)
 112                         exit(1);
 113                 if (pid == 0) {
 114                         test();
 115                         exit(0);
 116                 }
 117                 while (waitpid(pid, &status, __WALL) != pid)
 118                         ;
 119         }
 120 
 121         warnings_after = get_warnings_count();
 122         TEST_ASSERT(warnings_before == warnings_after,
 123                    "Warnings found in kernel.  Run 'dmesg' to inspect them.");
 124 
 125         return 0;
 126 }

/* [<][>][^][v][top][bottom][index][help] */