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

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

DEFINITIONS

This source file includes following definitions.
  1. cr4_cpuid_is_sync
  2. guest_code
  3. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * CR4 and CPUID sync test
   4  *
   5  * Copyright 2018, Red Hat, Inc. and/or its affiliates.
   6  *
   7  * Author:
   8  *   Wei Huang <wei@redhat.com>
   9  */
  10 
  11 #include <fcntl.h>
  12 #include <stdio.h>
  13 #include <stdlib.h>
  14 #include <string.h>
  15 #include <sys/ioctl.h>
  16 
  17 #include "test_util.h"
  18 
  19 #include "kvm_util.h"
  20 #include "processor.h"
  21 
  22 #define X86_FEATURE_XSAVE       (1<<26)
  23 #define X86_FEATURE_OSXSAVE     (1<<27)
  24 #define VCPU_ID                 1
  25 
  26 static inline bool cr4_cpuid_is_sync(void)
  27 {
  28         int func, subfunc;
  29         uint32_t eax, ebx, ecx, edx;
  30         uint64_t cr4;
  31 
  32         func = 0x1;
  33         subfunc = 0x0;
  34         __asm__ __volatile__("cpuid"
  35                              : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
  36                              : "a"(func), "c"(subfunc));
  37 
  38         cr4 = get_cr4();
  39 
  40         return (!!(ecx & X86_FEATURE_OSXSAVE)) == (!!(cr4 & X86_CR4_OSXSAVE));
  41 }
  42 
  43 static void guest_code(void)
  44 {
  45         uint64_t cr4;
  46 
  47         /* turn on CR4.OSXSAVE */
  48         cr4 = get_cr4();
  49         cr4 |= X86_CR4_OSXSAVE;
  50         set_cr4(cr4);
  51 
  52         /* verify CR4.OSXSAVE == CPUID.OSXSAVE */
  53         GUEST_ASSERT(cr4_cpuid_is_sync());
  54 
  55         /* notify hypervisor to change CR4 */
  56         GUEST_SYNC(0);
  57 
  58         /* check again */
  59         GUEST_ASSERT(cr4_cpuid_is_sync());
  60 
  61         GUEST_DONE();
  62 }
  63 
  64 int main(int argc, char *argv[])
  65 {
  66         struct kvm_run *run;
  67         struct kvm_vm *vm;
  68         struct kvm_sregs sregs;
  69         struct kvm_cpuid_entry2 *entry;
  70         struct ucall uc;
  71         int rc;
  72 
  73         entry = kvm_get_supported_cpuid_entry(1);
  74         if (!(entry->ecx & X86_FEATURE_XSAVE)) {
  75                 printf("XSAVE feature not supported, skipping test\n");
  76                 return 0;
  77         }
  78 
  79         /* Tell stdout not to buffer its content */
  80         setbuf(stdout, NULL);
  81 
  82         /* Create VM */
  83         vm = vm_create_default(VCPU_ID, 0, guest_code);
  84         vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
  85         run = vcpu_state(vm, VCPU_ID);
  86 
  87         while (1) {
  88                 rc = _vcpu_run(vm, VCPU_ID);
  89 
  90                 TEST_ASSERT(rc == 0, "vcpu_run failed: %d\n", rc);
  91                 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
  92                             "Unexpected exit reason: %u (%s),\n",
  93                             run->exit_reason,
  94                             exit_reason_str(run->exit_reason));
  95 
  96                 switch (get_ucall(vm, VCPU_ID, &uc)) {
  97                 case UCALL_SYNC:
  98                         /* emulate hypervisor clearing CR4.OSXSAVE */
  99                         vcpu_sregs_get(vm, VCPU_ID, &sregs);
 100                         sregs.cr4 &= ~X86_CR4_OSXSAVE;
 101                         vcpu_sregs_set(vm, VCPU_ID, &sregs);
 102                         break;
 103                 case UCALL_ABORT:
 104                         TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
 105                         break;
 106                 case UCALL_DONE:
 107                         goto done;
 108                 default:
 109                         TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
 110                 }
 111         }
 112 
 113         kvm_vm_free(vm);
 114 
 115 done:
 116         return 0;
 117 }

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