]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
kvm: selftests: move arch-specific files to arch-specific locations
authorAndrew Jones <drjones@redhat.com>
Tue, 18 Sep 2018 17:54:26 +0000 (19:54 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 16 Oct 2018 22:26:16 +0000 (00:26 +0200)
Signed-off-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
29 files changed:
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/cr4_cpuid_sync_test.c [deleted file]
tools/testing/selftests/kvm/dirty_log_test.c [deleted file]
tools/testing/selftests/kvm/include/kvm_util.h
tools/testing/selftests/kvm/include/sparsebit.h
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/include/vmx.h [deleted file]
tools/testing/selftests/kvm/include/x86.h [deleted file]
tools/testing/selftests/kvm/include/x86_64/processor.h [new file with mode: 0644]
tools/testing/selftests/kvm/include/x86_64/vmx.h [new file with mode: 0644]
tools/testing/selftests/kvm/lib/assert.c
tools/testing/selftests/kvm/lib/kvm_util_internal.h
tools/testing/selftests/kvm/lib/vmx.c [deleted file]
tools/testing/selftests/kvm/lib/x86.c [deleted file]
tools/testing/selftests/kvm/lib/x86_64/processor.c [new file with mode: 0644]
tools/testing/selftests/kvm/lib/x86_64/vmx.c [new file with mode: 0644]
tools/testing/selftests/kvm/platform_info_test.c [deleted file]
tools/testing/selftests/kvm/set_sregs_test.c [deleted file]
tools/testing/selftests/kvm/state_test.c [deleted file]
tools/testing/selftests/kvm/sync_regs_test.c [deleted file]
tools/testing/selftests/kvm/vmx_tsc_adjust_test.c [deleted file]
tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/dirty_log_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/platform_info_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/set_sregs_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/state_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/sync_regs_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c [new file with mode: 0644]

index 5c34752e1cff099ff884ffa0a78bb8deaa088dd6..e0aa5411cf9ba7a1deb61b31128c0d0abaedd3c3 100644 (file)
@@ -1,6 +1,7 @@
-cr4_cpuid_sync_test
-platform_info_test
-set_sregs_test
-sync_regs_test
-vmx_tsc_adjust_test
-state_test
+/x86_64/cr4_cpuid_sync_test
+/x86_64/platform_info_test
+/x86_64/set_sregs_test
+/x86_64/sync_regs_test
+/x86_64/vmx_tsc_adjust_test
+/x86_64/state_test
+/x86_64/dirty_log_test
index 08426f0363537c139ad4fb94aa8dec7022bdabf9..734a60da977606793886d3f4ef7dc4f7545ba2be 100644 (file)
@@ -1,26 +1,26 @@
 all:
 
-top_srcdir = ../../../../
+top_srcdir = ../../../..
 UNAME_M := $(shell uname -m)
 
 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/ucall.c lib/sparsebit.c
-LIBKVM_x86_64 = lib/x86.c lib/vmx.c
+LIBKVM_x86_64 = lib/x86_64/processor.c lib/x86_64/vmx.c
 
-TEST_GEN_PROGS_x86_64 = platform_info_test
-TEST_GEN_PROGS_x86_64 += set_sregs_test
-TEST_GEN_PROGS_x86_64 += sync_regs_test
-TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
-TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test
-TEST_GEN_PROGS_x86_64 += state_test
-TEST_GEN_PROGS_x86_64 += dirty_log_test
+TEST_GEN_PROGS_x86_64 = x86_64/platform_info_test
+TEST_GEN_PROGS_x86_64 += x86_64/set_sregs_test
+TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test
+TEST_GEN_PROGS_x86_64 += x86_64/vmx_tsc_adjust_test
+TEST_GEN_PROGS_x86_64 += x86_64/cr4_cpuid_sync_test
+TEST_GEN_PROGS_x86_64 += x86_64/state_test
+TEST_GEN_PROGS_x86_64 += x86_64/dirty_log_test
 
 TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M))
 LIBKVM += $(LIBKVM_$(UNAME_M))
 
 INSTALL_HDR_PATH = $(top_srcdir)/usr
 LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
-LINUX_TOOL_INCLUDE = $(top_srcdir)tools/include
-CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_TOOL_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I..
+LINUX_TOOL_INCLUDE = $(top_srcdir)/tools/include
+CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_TOOL_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -Iinclude/$(UNAME_M) -I..
 LDFLAGS += -pthread
 
 # After inclusion, $(OUTPUT) is defined and
diff --git a/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c b/tools/testing/selftests/kvm/cr4_cpuid_sync_test.c
deleted file mode 100644 (file)
index fd4f419..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * CR4 and CPUID sync test
- *
- * Copyright 2018, Red Hat, Inc. and/or its affiliates.
- *
- * Author:
- *   Wei Huang <wei@redhat.com>
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "test_util.h"
-
-#include "kvm_util.h"
-#include "x86.h"
-
-#define X86_FEATURE_XSAVE      (1<<26)
-#define X86_FEATURE_OSXSAVE    (1<<27)
-#define VCPU_ID                        1
-
-static inline bool cr4_cpuid_is_sync(void)
-{
-       int func, subfunc;
-       uint32_t eax, ebx, ecx, edx;
-       uint64_t cr4;
-
-       func = 0x1;
-       subfunc = 0x0;
-       __asm__ __volatile__("cpuid"
-                            : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
-                            : "a"(func), "c"(subfunc));
-
-       cr4 = get_cr4();
-
-       return (!!(ecx & X86_FEATURE_OSXSAVE)) == (!!(cr4 & X86_CR4_OSXSAVE));
-}
-
-static void guest_code(void)
-{
-       uint64_t cr4;
-
-       /* turn on CR4.OSXSAVE */
-       cr4 = get_cr4();
-       cr4 |= X86_CR4_OSXSAVE;
-       set_cr4(cr4);
-
-       /* verify CR4.OSXSAVE == CPUID.OSXSAVE */
-       GUEST_ASSERT(cr4_cpuid_is_sync());
-
-       /* notify hypervisor to change CR4 */
-       GUEST_SYNC(0);
-
-       /* check again */
-       GUEST_ASSERT(cr4_cpuid_is_sync());
-
-       GUEST_DONE();
-}
-
-int main(int argc, char *argv[])
-{
-       struct kvm_run *run;
-       struct kvm_vm *vm;
-       struct kvm_sregs sregs;
-       struct kvm_cpuid_entry2 *entry;
-       struct ucall uc;
-       int rc;
-
-       entry = kvm_get_supported_cpuid_entry(1);
-       if (!(entry->ecx & X86_FEATURE_XSAVE)) {
-               printf("XSAVE feature not supported, skipping test\n");
-               return 0;
-       }
-
-       /* Tell stdout not to buffer its content */
-       setbuf(stdout, NULL);
-
-       /* Create VM */
-       vm = vm_create_default(VCPU_ID, 0, guest_code);
-       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-       run = vcpu_state(vm, VCPU_ID);
-
-       while (1) {
-               rc = _vcpu_run(vm, VCPU_ID);
-
-               if (run->exit_reason == KVM_EXIT_IO) {
-                       switch (get_ucall(vm, VCPU_ID, &uc)) {
-                       case UCALL_SYNC:
-                               /* emulate hypervisor clearing CR4.OSXSAVE */
-                               vcpu_sregs_get(vm, VCPU_ID, &sregs);
-                               sregs.cr4 &= ~X86_CR4_OSXSAVE;
-                               vcpu_sregs_set(vm, VCPU_ID, &sregs);
-                               break;
-                       case UCALL_ABORT:
-                               TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
-                               break;
-                       case UCALL_DONE:
-                               goto done;
-                       default:
-                               TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
-                       }
-               }
-       }
-
-       kvm_vm_free(vm);
-
-done:
-       return 0;
-}
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
deleted file mode 100644 (file)
index 7cf3e4a..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * KVM dirty page logging test
- *
- * Copyright (C) 2018, Red Hat, Inc.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <pthread.h>
-#include <linux/bitmap.h>
-#include <linux/bitops.h>
-
-#include "test_util.h"
-#include "kvm_util.h"
-
-#define  DEBUG                 printf
-
-#define  VCPU_ID                        1
-/* The memory slot index to track dirty pages */
-#define  TEST_MEM_SLOT_INDEX            1
-/*
- * GPA offset of the testing memory slot. Must be bigger than the
- * default vm mem slot, which is DEFAULT_GUEST_PHY_PAGES.
- */
-#define  TEST_MEM_OFFSET                (1ULL << 30) /* 1G */
-/* Size of the testing memory slot */
-#define  TEST_MEM_PAGES                 (1ULL << 18) /* 1G for 4K pages */
-/* How many pages to dirty for each guest loop */
-#define  TEST_PAGES_PER_LOOP            1024
-/* How many host loops to run (one KVM_GET_DIRTY_LOG for each loop) */
-#define  TEST_HOST_LOOP_N               32
-/* Interval for each host loop (ms) */
-#define  TEST_HOST_LOOP_INTERVAL        10
-
-/*
- * Guest variables.  We use these variables to share data between host
- * and guest.  There are two copies of the variables, one in host memory
- * (which is unused) and one in guest memory.  When the host wants to
- * access these variables, it needs to call addr_gva2hva() to access the
- * guest copy.
- */
-uint64_t guest_random_array[TEST_PAGES_PER_LOOP];
-uint64_t guest_iteration;
-uint64_t guest_page_size;
-
-/*
- * Writes to the first byte of a random page within the testing memory
- * region continuously.
- */
-void guest_code(void)
-{
-       int i = 0;
-       uint64_t volatile *array = guest_random_array;
-       uint64_t volatile *guest_addr;
-
-       while (true) {
-               for (i = 0; i < TEST_PAGES_PER_LOOP; i++) {
-                       /*
-                        * Write to the first 8 bytes of a random page
-                        * on the testing memory region.
-                        */
-                       guest_addr = (uint64_t *)
-                           (TEST_MEM_OFFSET +
-                            (array[i] % TEST_MEM_PAGES) * guest_page_size);
-                       *guest_addr = guest_iteration;
-               }
-               /* Tell the host that we need more random numbers */
-               GUEST_SYNC(1);
-       }
-}
-
-/*
- * Host variables.  These variables should only be used by the host
- * rather than the guest.
- */
-bool host_quit;
-
-/* Points to the test VM memory region on which we track dirty logs */
-void *host_test_mem;
-
-/* For statistics only */
-uint64_t host_dirty_count;
-uint64_t host_clear_count;
-uint64_t host_track_next_count;
-
-/*
- * We use this bitmap to track some pages that should have its dirty
- * bit set in the _next_ iteration.  For example, if we detected the
- * page value changed to current iteration but at the same time the
- * page bit is cleared in the latest bitmap, then the system must
- * report that write in the next get dirty log call.
- */
-unsigned long *host_bmap_track;
-
-void generate_random_array(uint64_t *guest_array, uint64_t size)
-{
-       uint64_t i;
-
-       for (i = 0; i < size; i++) {
-               guest_array[i] = random();
-       }
-}
-
-void *vcpu_worker(void *data)
-{
-       int ret;
-       uint64_t loops, *guest_array, pages_count = 0;
-       struct kvm_vm *vm = data;
-       struct kvm_run *run;
-       struct ucall uc;
-
-       run = vcpu_state(vm, VCPU_ID);
-
-       /* Retrieve the guest random array pointer and cache it */
-       guest_array = addr_gva2hva(vm, (vm_vaddr_t)guest_random_array);
-
-       DEBUG("VCPU starts\n");
-
-       generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
-
-       while (!READ_ONCE(host_quit)) {
-               /* Let the guest to dirty these random pages */
-               ret = _vcpu_run(vm, VCPU_ID);
-               if (run->exit_reason == KVM_EXIT_IO &&
-                   get_ucall(vm, VCPU_ID, &uc) == UCALL_SYNC) {
-                       pages_count += TEST_PAGES_PER_LOOP;
-                       generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
-               } else {
-                       TEST_ASSERT(false,
-                                   "Invalid guest sync status: "
-                                   "exit_reason=%s\n",
-                                   exit_reason_str(run->exit_reason));
-               }
-       }
-
-       DEBUG("VCPU exits, dirtied %"PRIu64" pages\n", pages_count);
-
-       return NULL;
-}
-
-void vm_dirty_log_verify(unsigned long *bmap, uint64_t iteration)
-{
-       uint64_t page;
-       uint64_t volatile *value_ptr;
-
-       for (page = 0; page < TEST_MEM_PAGES; page++) {
-               value_ptr = host_test_mem + page * getpagesize();
-
-               /* If this is a special page that we were tracking... */
-               if (test_and_clear_bit(page, host_bmap_track)) {
-                       host_track_next_count++;
-                       TEST_ASSERT(test_bit(page, bmap),
-                                   "Page %"PRIu64" should have its dirty bit "
-                                   "set in this iteration but it is missing",
-                                   page);
-               }
-
-               if (test_bit(page, bmap)) {
-                       host_dirty_count++;
-                       /*
-                        * If the bit is set, the value written onto
-                        * the corresponding page should be either the
-                        * previous iteration number or the current one.
-                        */
-                       TEST_ASSERT(*value_ptr == iteration ||
-                                   *value_ptr == iteration - 1,
-                                   "Set page %"PRIu64" value %"PRIu64
-                                   " incorrect (iteration=%"PRIu64")",
-                                   page, *value_ptr, iteration);
-               } else {
-                       host_clear_count++;
-                       /*
-                        * If cleared, the value written can be any
-                        * value smaller or equals to the iteration
-                        * number.  Note that the value can be exactly
-                        * (iteration-1) if that write can happen
-                        * like this:
-                        *
-                        * (1) increase loop count to "iteration-1"
-                        * (2) write to page P happens (with value
-                        *     "iteration-1")
-                        * (3) get dirty log for "iteration-1"; we'll
-                        *     see that page P bit is set (dirtied),
-                        *     and not set the bit in host_bmap_track
-                        * (4) increase loop count to "iteration"
-                        *     (which is current iteration)
-                        * (5) get dirty log for current iteration,
-                        *     we'll see that page P is cleared, with
-                        *     value "iteration-1".
-                        */
-                       TEST_ASSERT(*value_ptr <= iteration,
-                                   "Clear page %"PRIu64" value %"PRIu64
-                                   " incorrect (iteration=%"PRIu64")",
-                                   page, *value_ptr, iteration);
-                       if (*value_ptr == iteration) {
-                               /*
-                                * This page is _just_ modified; it
-                                * should report its dirtyness in the
-                                * next run
-                                */
-                               set_bit(page, host_bmap_track);
-                       }
-               }
-       }
-}
-
-void help(char *name)
-{
-       puts("");
-       printf("usage: %s [-i iterations] [-I interval] [-h]\n", name);
-       puts("");
-       printf(" -i: specify iteration counts (default: %"PRIu64")\n",
-              TEST_HOST_LOOP_N);
-       printf(" -I: specify interval in ms (default: %"PRIu64" ms)\n",
-              TEST_HOST_LOOP_INTERVAL);
-       puts("");
-       exit(0);
-}
-
-int main(int argc, char *argv[])
-{
-       pthread_t vcpu_thread;
-       struct kvm_vm *vm;
-       uint64_t volatile *psize, *iteration;
-       unsigned long *bmap, iterations = TEST_HOST_LOOP_N,
-           interval = TEST_HOST_LOOP_INTERVAL;
-       int opt;
-
-       while ((opt = getopt(argc, argv, "hi:I:")) != -1) {
-               switch (opt) {
-               case 'i':
-                       iterations = strtol(optarg, NULL, 10);
-                       break;
-               case 'I':
-                       interval = strtol(optarg, NULL, 10);
-                       break;
-               case 'h':
-               default:
-                       help(argv[0]);
-                       break;
-               }
-       }
-
-       TEST_ASSERT(iterations > 2, "Iteration must be bigger than zero\n");
-       TEST_ASSERT(interval > 0, "Interval must be bigger than zero");
-
-       DEBUG("Test iterations: %"PRIu64", interval: %"PRIu64" (ms)\n",
-             iterations, interval);
-
-       srandom(time(0));
-
-       bmap = bitmap_alloc(TEST_MEM_PAGES);
-       host_bmap_track = bitmap_alloc(TEST_MEM_PAGES);
-
-       vm = vm_create_default(VCPU_ID, TEST_MEM_PAGES, guest_code);
-
-       /* Add an extra memory slot for testing dirty logging */
-       vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
-                                   TEST_MEM_OFFSET,
-                                   TEST_MEM_SLOT_INDEX,
-                                   TEST_MEM_PAGES,
-                                   KVM_MEM_LOG_DIRTY_PAGES);
-       /* Cache the HVA pointer of the region */
-       host_test_mem = addr_gpa2hva(vm, (vm_paddr_t)TEST_MEM_OFFSET);
-
-       /* Do 1:1 mapping for the dirty track memory slot */
-       virt_map(vm, TEST_MEM_OFFSET, TEST_MEM_OFFSET,
-                TEST_MEM_PAGES * getpagesize(), 0);
-
-       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-
-       /* Tell the guest about the page size on the system */
-       psize = addr_gva2hva(vm, (vm_vaddr_t)&guest_page_size);
-       *psize = getpagesize();
-
-       /* Start the iterations */
-       iteration = addr_gva2hva(vm, (vm_vaddr_t)&guest_iteration);
-       *iteration = 1;
-
-       /* Start dirtying pages */
-       pthread_create(&vcpu_thread, NULL, vcpu_worker, vm);
-
-       while (*iteration < iterations) {
-               /* Give the vcpu thread some time to dirty some pages */
-               usleep(interval * 1000);
-               kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
-               vm_dirty_log_verify(bmap, *iteration);
-               (*iteration)++;
-       }
-
-       /* Tell the vcpu thread to quit */
-       host_quit = true;
-       pthread_join(vcpu_thread, NULL);
-
-       DEBUG("Total bits checked: dirty (%"PRIu64"), clear (%"PRIu64"), "
-             "track_next (%"PRIu64")\n", host_dirty_count, host_clear_count,
-             host_track_next_count);
-
-       free(bmap);
-       free(host_bmap_track);
-       kvm_vm_free(vm);
-
-       return 0;
-}
index 22667dd48a9c164628667d0cac1b77875a1fe5c8..7830c46f27d8b3f578164576746e419a6b9d1b7d 100644 (file)
@@ -7,7 +7,7 @@
  *
  */
 #ifndef SELFTEST_KVM_UTIL_H
-#define SELFTEST_KVM_UTIL_H 1
+#define SELFTEST_KVM_UTIL_H
 
 #include "test_util.h"
 
index 54cfeb6568d342f20369fd7bf0e9a82b665c1f25..31e030915c1f40d66fc4eb76dc8761240c14eed0 100644 (file)
@@ -15,8 +15,8 @@
  * even in the case where most bits are set.
  */
 
-#ifndef _TEST_SPARSEBIT_H_
-#define _TEST_SPARSEBIT_H_
+#ifndef SELFTEST_KVM_SPARSEBIT_H
+#define SELFTEST_KVM_SPARSEBIT_H
 
 #include <stdbool.h>
 #include <stdint.h>
@@ -72,4 +72,4 @@ void sparsebit_validate_internal(struct sparsebit *sbit);
 }
 #endif
 
-#endif /* _TEST_SPARSEBIT_H_ */
+#endif /* SELFTEST_KVM_SPARSEBIT_H */
index 73c3933436ecc1206b8f90f2e4991ac4ddcf7bea..c7dafe8bd02c284abbb5f08cd032b1bff55549ad 100644 (file)
@@ -7,8 +7,8 @@
  *
  */
 
-#ifndef TEST_UTIL_H
-#define TEST_UTIL_H 1
+#ifndef SELFTEST_KVM_TEST_UTIL_H
+#define SELFTEST_KVM_TEST_UTIL_H
 
 #include <stdlib.h>
 #include <stdarg.h>
@@ -41,4 +41,4 @@ void test_assert(bool exp, const char *exp_str,
                    #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \
 } while (0)
 
-#endif /* TEST_UTIL_H */
+#endif /* SELFTEST_KVM_TEST_UTIL_H */
diff --git a/tools/testing/selftests/kvm/include/vmx.h b/tools/testing/selftests/kvm/include/vmx.h
deleted file mode 100644 (file)
index b9ffe10..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * tools/testing/selftests/kvm/include/vmx.h
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- */
-
-#ifndef SELFTEST_KVM_VMX_H
-#define SELFTEST_KVM_VMX_H
-
-#include <stdint.h>
-#include "x86.h"
-
-#define CPUID_VMX_BIT                          5
-
-#define CPUID_VMX                              (1 << 5)
-
-/*
- * Definitions of Primary Processor-Based VM-Execution Controls.
- */
-#define CPU_BASED_VIRTUAL_INTR_PENDING         0x00000004
-#define CPU_BASED_USE_TSC_OFFSETING            0x00000008
-#define CPU_BASED_HLT_EXITING                  0x00000080
-#define CPU_BASED_INVLPG_EXITING               0x00000200
-#define CPU_BASED_MWAIT_EXITING                        0x00000400
-#define CPU_BASED_RDPMC_EXITING                        0x00000800
-#define CPU_BASED_RDTSC_EXITING                        0x00001000
-#define CPU_BASED_CR3_LOAD_EXITING             0x00008000
-#define CPU_BASED_CR3_STORE_EXITING            0x00010000
-#define CPU_BASED_CR8_LOAD_EXITING             0x00080000
-#define CPU_BASED_CR8_STORE_EXITING            0x00100000
-#define CPU_BASED_TPR_SHADOW                   0x00200000
-#define CPU_BASED_VIRTUAL_NMI_PENDING          0x00400000
-#define CPU_BASED_MOV_DR_EXITING               0x00800000
-#define CPU_BASED_UNCOND_IO_EXITING            0x01000000
-#define CPU_BASED_USE_IO_BITMAPS               0x02000000
-#define CPU_BASED_MONITOR_TRAP                 0x08000000
-#define CPU_BASED_USE_MSR_BITMAPS              0x10000000
-#define CPU_BASED_MONITOR_EXITING              0x20000000
-#define CPU_BASED_PAUSE_EXITING                        0x40000000
-#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS  0x80000000
-
-#define CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR    0x0401e172
-
-/*
- * Definitions of Secondary Processor-Based VM-Execution Controls.
- */
-#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
-#define SECONDARY_EXEC_ENABLE_EPT              0x00000002
-#define SECONDARY_EXEC_DESC                    0x00000004
-#define SECONDARY_EXEC_RDTSCP                  0x00000008
-#define SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE  0x00000010
-#define SECONDARY_EXEC_ENABLE_VPID             0x00000020
-#define SECONDARY_EXEC_WBINVD_EXITING          0x00000040
-#define SECONDARY_EXEC_UNRESTRICTED_GUEST      0x00000080
-#define SECONDARY_EXEC_APIC_REGISTER_VIRT      0x00000100
-#define SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY   0x00000200
-#define SECONDARY_EXEC_PAUSE_LOOP_EXITING      0x00000400
-#define SECONDARY_EXEC_RDRAND_EXITING          0x00000800
-#define SECONDARY_EXEC_ENABLE_INVPCID          0x00001000
-#define SECONDARY_EXEC_ENABLE_VMFUNC           0x00002000
-#define SECONDARY_EXEC_SHADOW_VMCS             0x00004000
-#define SECONDARY_EXEC_RDSEED_EXITING          0x00010000
-#define SECONDARY_EXEC_ENABLE_PML              0x00020000
-#define SECONDARY_EPT_VE                       0x00040000
-#define SECONDARY_ENABLE_XSAV_RESTORE          0x00100000
-#define SECONDARY_EXEC_TSC_SCALING             0x02000000
-
-#define PIN_BASED_EXT_INTR_MASK                        0x00000001
-#define PIN_BASED_NMI_EXITING                  0x00000008
-#define PIN_BASED_VIRTUAL_NMIS                 0x00000020
-#define PIN_BASED_VMX_PREEMPTION_TIMER         0x00000040
-#define PIN_BASED_POSTED_INTR                  0x00000080
-
-#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR    0x00000016
-
-#define VM_EXIT_SAVE_DEBUG_CONTROLS            0x00000004
-#define VM_EXIT_HOST_ADDR_SPACE_SIZE           0x00000200
-#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL     0x00001000
-#define VM_EXIT_ACK_INTR_ON_EXIT               0x00008000
-#define VM_EXIT_SAVE_IA32_PAT                  0x00040000
-#define VM_EXIT_LOAD_IA32_PAT                  0x00080000
-#define VM_EXIT_SAVE_IA32_EFER                 0x00100000
-#define VM_EXIT_LOAD_IA32_EFER                 0x00200000
-#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER      0x00400000
-
-#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR      0x00036dff
-
-#define VM_ENTRY_LOAD_DEBUG_CONTROLS           0x00000004
-#define VM_ENTRY_IA32E_MODE                    0x00000200
-#define VM_ENTRY_SMM                           0x00000400
-#define VM_ENTRY_DEACT_DUAL_MONITOR            0x00000800
-#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL    0x00002000
-#define VM_ENTRY_LOAD_IA32_PAT                 0x00004000
-#define VM_ENTRY_LOAD_IA32_EFER                        0x00008000
-
-#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR     0x000011ff
-
-#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK    0x0000001f
-#define VMX_MISC_SAVE_EFER_LMA                 0x00000020
-
-#define EXIT_REASON_FAILED_VMENTRY     0x80000000
-#define EXIT_REASON_EXCEPTION_NMI      0
-#define EXIT_REASON_EXTERNAL_INTERRUPT 1
-#define EXIT_REASON_TRIPLE_FAULT       2
-#define EXIT_REASON_PENDING_INTERRUPT  7
-#define EXIT_REASON_NMI_WINDOW         8
-#define EXIT_REASON_TASK_SWITCH                9
-#define EXIT_REASON_CPUID              10
-#define EXIT_REASON_HLT                        12
-#define EXIT_REASON_INVD               13
-#define EXIT_REASON_INVLPG             14
-#define EXIT_REASON_RDPMC              15
-#define EXIT_REASON_RDTSC              16
-#define EXIT_REASON_VMCALL             18
-#define EXIT_REASON_VMCLEAR            19
-#define EXIT_REASON_VMLAUNCH           20
-#define EXIT_REASON_VMPTRLD            21
-#define EXIT_REASON_VMPTRST            22
-#define EXIT_REASON_VMREAD             23
-#define EXIT_REASON_VMRESUME           24
-#define EXIT_REASON_VMWRITE            25
-#define EXIT_REASON_VMOFF              26
-#define EXIT_REASON_VMON               27
-#define EXIT_REASON_CR_ACCESS          28
-#define EXIT_REASON_DR_ACCESS          29
-#define EXIT_REASON_IO_INSTRUCTION     30
-#define EXIT_REASON_MSR_READ           31
-#define EXIT_REASON_MSR_WRITE          32
-#define EXIT_REASON_INVALID_STATE      33
-#define EXIT_REASON_MWAIT_INSTRUCTION  36
-#define EXIT_REASON_MONITOR_INSTRUCTION 39
-#define EXIT_REASON_PAUSE_INSTRUCTION  40
-#define EXIT_REASON_MCE_DURING_VMENTRY 41
-#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
-#define EXIT_REASON_APIC_ACCESS                44
-#define EXIT_REASON_EOI_INDUCED                45
-#define EXIT_REASON_EPT_VIOLATION      48
-#define EXIT_REASON_EPT_MISCONFIG      49
-#define EXIT_REASON_INVEPT             50
-#define EXIT_REASON_RDTSCP             51
-#define EXIT_REASON_PREEMPTION_TIMER   52
-#define EXIT_REASON_INVVPID            53
-#define EXIT_REASON_WBINVD             54
-#define EXIT_REASON_XSETBV             55
-#define EXIT_REASON_APIC_WRITE         56
-#define EXIT_REASON_INVPCID            58
-#define EXIT_REASON_PML_FULL           62
-#define EXIT_REASON_XSAVES             63
-#define EXIT_REASON_XRSTORS            64
-#define LAST_EXIT_REASON               64
-
-enum vmcs_field {
-       VIRTUAL_PROCESSOR_ID            = 0x00000000,
-       POSTED_INTR_NV                  = 0x00000002,
-       GUEST_ES_SELECTOR               = 0x00000800,
-       GUEST_CS_SELECTOR               = 0x00000802,
-       GUEST_SS_SELECTOR               = 0x00000804,
-       GUEST_DS_SELECTOR               = 0x00000806,
-       GUEST_FS_SELECTOR               = 0x00000808,
-       GUEST_GS_SELECTOR               = 0x0000080a,
-       GUEST_LDTR_SELECTOR             = 0x0000080c,
-       GUEST_TR_SELECTOR               = 0x0000080e,
-       GUEST_INTR_STATUS               = 0x00000810,
-       GUEST_PML_INDEX                 = 0x00000812,
-       HOST_ES_SELECTOR                = 0x00000c00,
-       HOST_CS_SELECTOR                = 0x00000c02,
-       HOST_SS_SELECTOR                = 0x00000c04,
-       HOST_DS_SELECTOR                = 0x00000c06,
-       HOST_FS_SELECTOR                = 0x00000c08,
-       HOST_GS_SELECTOR                = 0x00000c0a,
-       HOST_TR_SELECTOR                = 0x00000c0c,
-       IO_BITMAP_A                     = 0x00002000,
-       IO_BITMAP_A_HIGH                = 0x00002001,
-       IO_BITMAP_B                     = 0x00002002,
-       IO_BITMAP_B_HIGH                = 0x00002003,
-       MSR_BITMAP                      = 0x00002004,
-       MSR_BITMAP_HIGH                 = 0x00002005,
-       VM_EXIT_MSR_STORE_ADDR          = 0x00002006,
-       VM_EXIT_MSR_STORE_ADDR_HIGH     = 0x00002007,
-       VM_EXIT_MSR_LOAD_ADDR           = 0x00002008,
-       VM_EXIT_MSR_LOAD_ADDR_HIGH      = 0x00002009,
-       VM_ENTRY_MSR_LOAD_ADDR          = 0x0000200a,
-       VM_ENTRY_MSR_LOAD_ADDR_HIGH     = 0x0000200b,
-       PML_ADDRESS                     = 0x0000200e,
-       PML_ADDRESS_HIGH                = 0x0000200f,
-       TSC_OFFSET                      = 0x00002010,
-       TSC_OFFSET_HIGH                 = 0x00002011,
-       VIRTUAL_APIC_PAGE_ADDR          = 0x00002012,
-       VIRTUAL_APIC_PAGE_ADDR_HIGH     = 0x00002013,
-       APIC_ACCESS_ADDR                = 0x00002014,
-       APIC_ACCESS_ADDR_HIGH           = 0x00002015,
-       POSTED_INTR_DESC_ADDR           = 0x00002016,
-       POSTED_INTR_DESC_ADDR_HIGH      = 0x00002017,
-       EPT_POINTER                     = 0x0000201a,
-       EPT_POINTER_HIGH                = 0x0000201b,
-       EOI_EXIT_BITMAP0                = 0x0000201c,
-       EOI_EXIT_BITMAP0_HIGH           = 0x0000201d,
-       EOI_EXIT_BITMAP1                = 0x0000201e,
-       EOI_EXIT_BITMAP1_HIGH           = 0x0000201f,
-       EOI_EXIT_BITMAP2                = 0x00002020,
-       EOI_EXIT_BITMAP2_HIGH           = 0x00002021,
-       EOI_EXIT_BITMAP3                = 0x00002022,
-       EOI_EXIT_BITMAP3_HIGH           = 0x00002023,
-       VMREAD_BITMAP                   = 0x00002026,
-       VMREAD_BITMAP_HIGH              = 0x00002027,
-       VMWRITE_BITMAP                  = 0x00002028,
-       VMWRITE_BITMAP_HIGH             = 0x00002029,
-       XSS_EXIT_BITMAP                 = 0x0000202C,
-       XSS_EXIT_BITMAP_HIGH            = 0x0000202D,
-       TSC_MULTIPLIER                  = 0x00002032,
-       TSC_MULTIPLIER_HIGH             = 0x00002033,
-       GUEST_PHYSICAL_ADDRESS          = 0x00002400,
-       GUEST_PHYSICAL_ADDRESS_HIGH     = 0x00002401,
-       VMCS_LINK_POINTER               = 0x00002800,
-       VMCS_LINK_POINTER_HIGH          = 0x00002801,
-       GUEST_IA32_DEBUGCTL             = 0x00002802,
-       GUEST_IA32_DEBUGCTL_HIGH        = 0x00002803,
-       GUEST_IA32_PAT                  = 0x00002804,
-       GUEST_IA32_PAT_HIGH             = 0x00002805,
-       GUEST_IA32_EFER                 = 0x00002806,
-       GUEST_IA32_EFER_HIGH            = 0x00002807,
-       GUEST_IA32_PERF_GLOBAL_CTRL     = 0x00002808,
-       GUEST_IA32_PERF_GLOBAL_CTRL_HIGH= 0x00002809,
-       GUEST_PDPTR0                    = 0x0000280a,
-       GUEST_PDPTR0_HIGH               = 0x0000280b,
-       GUEST_PDPTR1                    = 0x0000280c,
-       GUEST_PDPTR1_HIGH               = 0x0000280d,
-       GUEST_PDPTR2                    = 0x0000280e,
-       GUEST_PDPTR2_HIGH               = 0x0000280f,
-       GUEST_PDPTR3                    = 0x00002810,
-       GUEST_PDPTR3_HIGH               = 0x00002811,
-       GUEST_BNDCFGS                   = 0x00002812,
-       GUEST_BNDCFGS_HIGH              = 0x00002813,
-       HOST_IA32_PAT                   = 0x00002c00,
-       HOST_IA32_PAT_HIGH              = 0x00002c01,
-       HOST_IA32_EFER                  = 0x00002c02,
-       HOST_IA32_EFER_HIGH             = 0x00002c03,
-       HOST_IA32_PERF_GLOBAL_CTRL      = 0x00002c04,
-       HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,
-       PIN_BASED_VM_EXEC_CONTROL       = 0x00004000,
-       CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,
-       EXCEPTION_BITMAP                = 0x00004004,
-       PAGE_FAULT_ERROR_CODE_MASK      = 0x00004006,
-       PAGE_FAULT_ERROR_CODE_MATCH     = 0x00004008,
-       CR3_TARGET_COUNT                = 0x0000400a,
-       VM_EXIT_CONTROLS                = 0x0000400c,
-       VM_EXIT_MSR_STORE_COUNT         = 0x0000400e,
-       VM_EXIT_MSR_LOAD_COUNT          = 0x00004010,
-       VM_ENTRY_CONTROLS               = 0x00004012,
-       VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
-       VM_ENTRY_INTR_INFO_FIELD        = 0x00004016,
-       VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
-       VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
-       TPR_THRESHOLD                   = 0x0000401c,
-       SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
-       PLE_GAP                         = 0x00004020,
-       PLE_WINDOW                      = 0x00004022,
-       VM_INSTRUCTION_ERROR            = 0x00004400,
-       VM_EXIT_REASON                  = 0x00004402,
-       VM_EXIT_INTR_INFO               = 0x00004404,
-       VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
-       IDT_VECTORING_INFO_FIELD        = 0x00004408,
-       IDT_VECTORING_ERROR_CODE        = 0x0000440a,
-       VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
-       VMX_INSTRUCTION_INFO            = 0x0000440e,
-       GUEST_ES_LIMIT                  = 0x00004800,
-       GUEST_CS_LIMIT                  = 0x00004802,
-       GUEST_SS_LIMIT                  = 0x00004804,
-       GUEST_DS_LIMIT                  = 0x00004806,
-       GUEST_FS_LIMIT                  = 0x00004808,
-       GUEST_GS_LIMIT                  = 0x0000480a,
-       GUEST_LDTR_LIMIT                = 0x0000480c,
-       GUEST_TR_LIMIT                  = 0x0000480e,
-       GUEST_GDTR_LIMIT                = 0x00004810,
-       GUEST_IDTR_LIMIT                = 0x00004812,
-       GUEST_ES_AR_BYTES               = 0x00004814,
-       GUEST_CS_AR_BYTES               = 0x00004816,
-       GUEST_SS_AR_BYTES               = 0x00004818,
-       GUEST_DS_AR_BYTES               = 0x0000481a,
-       GUEST_FS_AR_BYTES               = 0x0000481c,
-       GUEST_GS_AR_BYTES               = 0x0000481e,
-       GUEST_LDTR_AR_BYTES             = 0x00004820,
-       GUEST_TR_AR_BYTES               = 0x00004822,
-       GUEST_INTERRUPTIBILITY_INFO     = 0x00004824,
-       GUEST_ACTIVITY_STATE            = 0X00004826,
-       GUEST_SYSENTER_CS               = 0x0000482A,
-       VMX_PREEMPTION_TIMER_VALUE      = 0x0000482E,
-       HOST_IA32_SYSENTER_CS           = 0x00004c00,
-       CR0_GUEST_HOST_MASK             = 0x00006000,
-       CR4_GUEST_HOST_MASK             = 0x00006002,
-       CR0_READ_SHADOW                 = 0x00006004,
-       CR4_READ_SHADOW                 = 0x00006006,
-       CR3_TARGET_VALUE0               = 0x00006008,
-       CR3_TARGET_VALUE1               = 0x0000600a,
-       CR3_TARGET_VALUE2               = 0x0000600c,
-       CR3_TARGET_VALUE3               = 0x0000600e,
-       EXIT_QUALIFICATION              = 0x00006400,
-       GUEST_LINEAR_ADDRESS            = 0x0000640a,
-       GUEST_CR0                       = 0x00006800,
-       GUEST_CR3                       = 0x00006802,
-       GUEST_CR4                       = 0x00006804,
-       GUEST_ES_BASE                   = 0x00006806,
-       GUEST_CS_BASE                   = 0x00006808,
-       GUEST_SS_BASE                   = 0x0000680a,
-       GUEST_DS_BASE                   = 0x0000680c,
-       GUEST_FS_BASE                   = 0x0000680e,
-       GUEST_GS_BASE                   = 0x00006810,
-       GUEST_LDTR_BASE                 = 0x00006812,
-       GUEST_TR_BASE                   = 0x00006814,
-       GUEST_GDTR_BASE                 = 0x00006816,
-       GUEST_IDTR_BASE                 = 0x00006818,
-       GUEST_DR7                       = 0x0000681a,
-       GUEST_RSP                       = 0x0000681c,
-       GUEST_RIP                       = 0x0000681e,
-       GUEST_RFLAGS                    = 0x00006820,
-       GUEST_PENDING_DBG_EXCEPTIONS    = 0x00006822,
-       GUEST_SYSENTER_ESP              = 0x00006824,
-       GUEST_SYSENTER_EIP              = 0x00006826,
-       HOST_CR0                        = 0x00006c00,
-       HOST_CR3                        = 0x00006c02,
-       HOST_CR4                        = 0x00006c04,
-       HOST_FS_BASE                    = 0x00006c06,
-       HOST_GS_BASE                    = 0x00006c08,
-       HOST_TR_BASE                    = 0x00006c0a,
-       HOST_GDTR_BASE                  = 0x00006c0c,
-       HOST_IDTR_BASE                  = 0x00006c0e,
-       HOST_IA32_SYSENTER_ESP          = 0x00006c10,
-       HOST_IA32_SYSENTER_EIP          = 0x00006c12,
-       HOST_RSP                        = 0x00006c14,
-       HOST_RIP                        = 0x00006c16,
-};
-
-struct vmx_msr_entry {
-       uint32_t index;
-       uint32_t reserved;
-       uint64_t value;
-} __attribute__ ((aligned(16)));
-
-static inline int vmxon(uint64_t phys)
-{
-       uint8_t ret;
-
-       __asm__ __volatile__ ("vmxon %[pa]; setna %[ret]"
-               : [ret]"=rm"(ret)
-               : [pa]"m"(phys)
-               : "cc", "memory");
-
-       return ret;
-}
-
-static inline void vmxoff(void)
-{
-       __asm__ __volatile__("vmxoff");
-}
-
-static inline int vmclear(uint64_t vmcs_pa)
-{
-       uint8_t ret;
-
-       __asm__ __volatile__ ("vmclear %[pa]; setna %[ret]"
-               : [ret]"=rm"(ret)
-               : [pa]"m"(vmcs_pa)
-               : "cc", "memory");
-
-       return ret;
-}
-
-static inline int vmptrld(uint64_t vmcs_pa)
-{
-       uint8_t ret;
-
-       __asm__ __volatile__ ("vmptrld %[pa]; setna %[ret]"
-               : [ret]"=rm"(ret)
-               : [pa]"m"(vmcs_pa)
-               : "cc", "memory");
-
-       return ret;
-}
-
-static inline int vmptrst(uint64_t *value)
-{
-       uint64_t tmp;
-       uint8_t ret;
-
-       __asm__ __volatile__("vmptrst %[value]; setna %[ret]"
-               : [value]"=m"(tmp), [ret]"=rm"(ret)
-               : : "cc", "memory");
-
-       *value = tmp;
-       return ret;
-}
-
-/*
- * A wrapper around vmptrst that ignores errors and returns zero if the
- * vmptrst instruction fails.
- */
-static inline uint64_t vmptrstz(void)
-{
-       uint64_t value = 0;
-       vmptrst(&value);
-       return value;
-}
-
-/*
- * No guest state (e.g. GPRs) is established by this vmlaunch.
- */
-static inline int vmlaunch(void)
-{
-       int ret;
-
-       __asm__ __volatile__("push %%rbp;"
-                            "push %%rcx;"
-                            "push %%rdx;"
-                            "push %%rsi;"
-                            "push %%rdi;"
-                            "push $0;"
-                            "vmwrite %%rsp, %[host_rsp];"
-                            "lea 1f(%%rip), %%rax;"
-                            "vmwrite %%rax, %[host_rip];"
-                            "vmlaunch;"
-                            "incq (%%rsp);"
-                            "1: pop %%rax;"
-                            "pop %%rdi;"
-                            "pop %%rsi;"
-                            "pop %%rdx;"
-                            "pop %%rcx;"
-                            "pop %%rbp;"
-                            : [ret]"=&a"(ret)
-                            : [host_rsp]"r"((uint64_t)HOST_RSP),
-                              [host_rip]"r"((uint64_t)HOST_RIP)
-                            : "memory", "cc", "rbx", "r8", "r9", "r10",
-                              "r11", "r12", "r13", "r14", "r15");
-       return ret;
-}
-
-/*
- * No guest state (e.g. GPRs) is established by this vmresume.
- */
-static inline int vmresume(void)
-{
-       int ret;
-
-       __asm__ __volatile__("push %%rbp;"
-                            "push %%rcx;"
-                            "push %%rdx;"
-                            "push %%rsi;"
-                            "push %%rdi;"
-                            "push $0;"
-                            "vmwrite %%rsp, %[host_rsp];"
-                            "lea 1f(%%rip), %%rax;"
-                            "vmwrite %%rax, %[host_rip];"
-                            "vmresume;"
-                            "incq (%%rsp);"
-                            "1: pop %%rax;"
-                            "pop %%rdi;"
-                            "pop %%rsi;"
-                            "pop %%rdx;"
-                            "pop %%rcx;"
-                            "pop %%rbp;"
-                            : [ret]"=&a"(ret)
-                            : [host_rsp]"r"((uint64_t)HOST_RSP),
-                              [host_rip]"r"((uint64_t)HOST_RIP)
-                            : "memory", "cc", "rbx", "r8", "r9", "r10",
-                              "r11", "r12", "r13", "r14", "r15");
-       return ret;
-}
-
-static inline void vmcall(void)
-{
-       /* Currently, L1 destroys our GPRs during vmexits.  */
-       __asm__ __volatile__("push %%rbp; vmcall; pop %%rbp" : : :
-                            "rax", "rbx", "rcx", "rdx",
-                            "rsi", "rdi", "r8", "r9", "r10", "r11", "r12",
-                            "r13", "r14", "r15");
-}
-
-static inline int vmread(uint64_t encoding, uint64_t *value)
-{
-       uint64_t tmp;
-       uint8_t ret;
-
-       __asm__ __volatile__("vmread %[encoding], %[value]; setna %[ret]"
-               : [value]"=rm"(tmp), [ret]"=rm"(ret)
-               : [encoding]"r"(encoding)
-               : "cc", "memory");
-
-       *value = tmp;
-       return ret;
-}
-
-/*
- * A wrapper around vmread that ignores errors and returns zero if the
- * vmread instruction fails.
- */
-static inline uint64_t vmreadz(uint64_t encoding)
-{
-       uint64_t value = 0;
-       vmread(encoding, &value);
-       return value;
-}
-
-static inline int vmwrite(uint64_t encoding, uint64_t value)
-{
-       uint8_t ret;
-
-       __asm__ __volatile__ ("vmwrite %[value], %[encoding]; setna %[ret]"
-               : [ret]"=rm"(ret)
-               : [value]"rm"(value), [encoding]"r"(encoding)
-               : "cc", "memory");
-
-       return ret;
-}
-
-static inline uint32_t vmcs_revision(void)
-{
-       return rdmsr(MSR_IA32_VMX_BASIC);
-}
-
-struct vmx_pages {
-       void *vmxon_hva;
-       uint64_t vmxon_gpa;
-       void *vmxon;
-
-       void *vmcs_hva;
-       uint64_t vmcs_gpa;
-       void *vmcs;
-
-       void *msr_hva;
-       uint64_t msr_gpa;
-       void *msr;
-
-       void *shadow_vmcs_hva;
-       uint64_t shadow_vmcs_gpa;
-       void *shadow_vmcs;
-
-       void *vmread_hva;
-       uint64_t vmread_gpa;
-       void *vmread;
-
-       void *vmwrite_hva;
-       uint64_t vmwrite_gpa;
-       void *vmwrite;
-};
-
-struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva);
-bool prepare_for_vmx_operation(struct vmx_pages *vmx);
-void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp);
-
-#endif /* !SELFTEST_KVM_VMX_H */
diff --git a/tools/testing/selftests/kvm/include/x86.h b/tools/testing/selftests/kvm/include/x86.h
deleted file mode 100644 (file)
index 42c3596..0000000
+++ /dev/null
@@ -1,1047 +0,0 @@
-/*
- * tools/testing/selftests/kvm/include/x86.h
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- */
-
-#ifndef SELFTEST_KVM_X86_H
-#define SELFTEST_KVM_X86_H
-
-#include <assert.h>
-#include <stdint.h>
-
-#define X86_EFLAGS_FIXED        (1u << 1)
-
-#define X86_CR4_VME            (1ul << 0)
-#define X86_CR4_PVI            (1ul << 1)
-#define X86_CR4_TSD            (1ul << 2)
-#define X86_CR4_DE             (1ul << 3)
-#define X86_CR4_PSE            (1ul << 4)
-#define X86_CR4_PAE            (1ul << 5)
-#define X86_CR4_MCE            (1ul << 6)
-#define X86_CR4_PGE            (1ul << 7)
-#define X86_CR4_PCE            (1ul << 8)
-#define X86_CR4_OSFXSR         (1ul << 9)
-#define X86_CR4_OSXMMEXCPT     (1ul << 10)
-#define X86_CR4_UMIP           (1ul << 11)
-#define X86_CR4_VMXE           (1ul << 13)
-#define X86_CR4_SMXE           (1ul << 14)
-#define X86_CR4_FSGSBASE       (1ul << 16)
-#define X86_CR4_PCIDE          (1ul << 17)
-#define X86_CR4_OSXSAVE                (1ul << 18)
-#define X86_CR4_SMEP           (1ul << 20)
-#define X86_CR4_SMAP           (1ul << 21)
-#define X86_CR4_PKE            (1ul << 22)
-
-/* The enum values match the intruction encoding of each register */
-enum x86_register {
-       RAX = 0,
-       RCX,
-       RDX,
-       RBX,
-       RSP,
-       RBP,
-       RSI,
-       RDI,
-       R8,
-       R9,
-       R10,
-       R11,
-       R12,
-       R13,
-       R14,
-       R15,
-};
-
-struct desc64 {
-       uint16_t limit0;
-       uint16_t base0;
-       unsigned base1:8, s:1, type:4, dpl:2, p:1;
-       unsigned limit1:4, avl:1, l:1, db:1, g:1, base2:8;
-       uint32_t base3;
-       uint32_t zero1;
-} __attribute__((packed));
-
-struct desc_ptr {
-       uint16_t size;
-       uint64_t address;
-} __attribute__((packed));
-
-static inline uint64_t get_desc64_base(const struct desc64 *desc)
-{
-       return ((uint64_t)desc->base3 << 32) |
-               (desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
-}
-
-static inline uint64_t rdtsc(void)
-{
-       uint32_t eax, edx;
-
-       /*
-        * The lfence is to wait (on Intel CPUs) until all previous
-        * instructions have been executed.
-        */
-       __asm__ __volatile__("lfence; rdtsc" : "=a"(eax), "=d"(edx));
-       return ((uint64_t)edx) << 32 | eax;
-}
-
-static inline uint64_t rdtscp(uint32_t *aux)
-{
-       uint32_t eax, edx;
-
-       __asm__ __volatile__("rdtscp" : "=a"(eax), "=d"(edx), "=c"(*aux));
-       return ((uint64_t)edx) << 32 | eax;
-}
-
-static inline uint64_t rdmsr(uint32_t msr)
-{
-       uint32_t a, d;
-
-       __asm__ __volatile__("rdmsr" : "=a"(a), "=d"(d) : "c"(msr) : "memory");
-
-       return a | ((uint64_t) d << 32);
-}
-
-static inline void wrmsr(uint32_t msr, uint64_t value)
-{
-       uint32_t a = value;
-       uint32_t d = value >> 32;
-
-       __asm__ __volatile__("wrmsr" :: "a"(a), "d"(d), "c"(msr) : "memory");
-}
-
-
-static inline uint16_t inw(uint16_t port)
-{
-       uint16_t tmp;
-
-       __asm__ __volatile__("in %%dx, %%ax"
-               : /* output */ "=a" (tmp)
-               : /* input */ "d" (port));
-
-       return tmp;
-}
-
-static inline uint16_t get_es(void)
-{
-       uint16_t es;
-
-       __asm__ __volatile__("mov %%es, %[es]"
-                            : /* output */ [es]"=rm"(es));
-       return es;
-}
-
-static inline uint16_t get_cs(void)
-{
-       uint16_t cs;
-
-       __asm__ __volatile__("mov %%cs, %[cs]"
-                            : /* output */ [cs]"=rm"(cs));
-       return cs;
-}
-
-static inline uint16_t get_ss(void)
-{
-       uint16_t ss;
-
-       __asm__ __volatile__("mov %%ss, %[ss]"
-                            : /* output */ [ss]"=rm"(ss));
-       return ss;
-}
-
-static inline uint16_t get_ds(void)
-{
-       uint16_t ds;
-
-       __asm__ __volatile__("mov %%ds, %[ds]"
-                            : /* output */ [ds]"=rm"(ds));
-       return ds;
-}
-
-static inline uint16_t get_fs(void)
-{
-       uint16_t fs;
-
-       __asm__ __volatile__("mov %%fs, %[fs]"
-                            : /* output */ [fs]"=rm"(fs));
-       return fs;
-}
-
-static inline uint16_t get_gs(void)
-{
-       uint16_t gs;
-
-       __asm__ __volatile__("mov %%gs, %[gs]"
-                            : /* output */ [gs]"=rm"(gs));
-       return gs;
-}
-
-static inline uint16_t get_tr(void)
-{
-       uint16_t tr;
-
-       __asm__ __volatile__("str %[tr]"
-                            : /* output */ [tr]"=rm"(tr));
-       return tr;
-}
-
-static inline uint64_t get_cr0(void)
-{
-       uint64_t cr0;
-
-       __asm__ __volatile__("mov %%cr0, %[cr0]"
-                            : /* output */ [cr0]"=r"(cr0));
-       return cr0;
-}
-
-static inline uint64_t get_cr3(void)
-{
-       uint64_t cr3;
-
-       __asm__ __volatile__("mov %%cr3, %[cr3]"
-                            : /* output */ [cr3]"=r"(cr3));
-       return cr3;
-}
-
-static inline uint64_t get_cr4(void)
-{
-       uint64_t cr4;
-
-       __asm__ __volatile__("mov %%cr4, %[cr4]"
-                            : /* output */ [cr4]"=r"(cr4));
-       return cr4;
-}
-
-static inline void set_cr4(uint64_t val)
-{
-       __asm__ __volatile__("mov %0, %%cr4" : : "r" (val) : "memory");
-}
-
-static inline uint64_t get_gdt_base(void)
-{
-       struct desc_ptr gdt;
-       __asm__ __volatile__("sgdt %[gdt]"
-                            : /* output */ [gdt]"=m"(gdt));
-       return gdt.address;
-}
-
-static inline uint64_t get_idt_base(void)
-{
-       struct desc_ptr idt;
-       __asm__ __volatile__("sidt %[idt]"
-                            : /* output */ [idt]"=m"(idt));
-       return idt.address;
-}
-
-#define SET_XMM(__var, __xmm) \
-       asm volatile("movq %0, %%"#__xmm : : "r"(__var) : #__xmm)
-
-static inline void set_xmm(int n, unsigned long val)
-{
-       switch (n) {
-       case 0:
-               SET_XMM(val, xmm0);
-               break;
-       case 1:
-               SET_XMM(val, xmm1);
-               break;
-       case 2:
-               SET_XMM(val, xmm2);
-               break;
-       case 3:
-               SET_XMM(val, xmm3);
-               break;
-       case 4:
-               SET_XMM(val, xmm4);
-               break;
-       case 5:
-               SET_XMM(val, xmm5);
-               break;
-       case 6:
-               SET_XMM(val, xmm6);
-               break;
-       case 7:
-               SET_XMM(val, xmm7);
-               break;
-       }
-}
-
-typedef unsigned long v1di __attribute__ ((vector_size (8)));
-static inline unsigned long get_xmm(int n)
-{
-       assert(n >= 0 && n <= 7);
-
-       register v1di xmm0 __asm__("%xmm0");
-       register v1di xmm1 __asm__("%xmm1");
-       register v1di xmm2 __asm__("%xmm2");
-       register v1di xmm3 __asm__("%xmm3");
-       register v1di xmm4 __asm__("%xmm4");
-       register v1di xmm5 __asm__("%xmm5");
-       register v1di xmm6 __asm__("%xmm6");
-       register v1di xmm7 __asm__("%xmm7");
-       switch (n) {
-       case 0:
-               return (unsigned long)xmm0;
-       case 1:
-               return (unsigned long)xmm1;
-       case 2:
-               return (unsigned long)xmm2;
-       case 3:
-               return (unsigned long)xmm3;
-       case 4:
-               return (unsigned long)xmm4;
-       case 5:
-               return (unsigned long)xmm5;
-       case 6:
-               return (unsigned long)xmm6;
-       case 7:
-               return (unsigned long)xmm7;
-       }
-       return 0;
-}
-
-struct kvm_x86_state;
-struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid);
-void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state);
-
-/*
- * Basic CPU control in CR0
- */
-#define X86_CR0_PE          (1UL<<0) /* Protection Enable */
-#define X86_CR0_MP          (1UL<<1) /* Monitor Coprocessor */
-#define X86_CR0_EM          (1UL<<2) /* Emulation */
-#define X86_CR0_TS          (1UL<<3) /* Task Switched */
-#define X86_CR0_ET          (1UL<<4) /* Extension Type */
-#define X86_CR0_NE          (1UL<<5) /* Numeric Error */
-#define X86_CR0_WP          (1UL<<16) /* Write Protect */
-#define X86_CR0_AM          (1UL<<18) /* Alignment Mask */
-#define X86_CR0_NW          (1UL<<29) /* Not Write-through */
-#define X86_CR0_CD          (1UL<<30) /* Cache Disable */
-#define X86_CR0_PG          (1UL<<31) /* Paging */
-
-/*
- * CPU model specific register (MSR) numbers.
- */
-
-/* x86-64 specific MSRs */
-#define MSR_EFER               0xc0000080 /* extended feature register */
-#define MSR_STAR               0xc0000081 /* legacy mode SYSCALL target */
-#define MSR_LSTAR              0xc0000082 /* long mode SYSCALL target */
-#define MSR_CSTAR              0xc0000083 /* compat mode SYSCALL target */
-#define MSR_SYSCALL_MASK       0xc0000084 /* EFLAGS mask for syscall */
-#define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
-#define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
-#define MSR_KERNEL_GS_BASE     0xc0000102 /* SwapGS GS shadow */
-#define MSR_TSC_AUX            0xc0000103 /* Auxiliary TSC */
-
-/* EFER bits: */
-#define EFER_SCE               (1<<0)  /* SYSCALL/SYSRET */
-#define EFER_LME               (1<<8)  /* Long mode enable */
-#define EFER_LMA               (1<<10) /* Long mode active (read-only) */
-#define EFER_NX                        (1<<11) /* No execute enable */
-#define EFER_SVME              (1<<12) /* Enable virtualization */
-#define EFER_LMSLE             (1<<13) /* Long Mode Segment Limit Enable */
-#define EFER_FFXSR             (1<<14) /* Enable Fast FXSAVE/FXRSTOR */
-
-/* Intel MSRs. Some also available on other CPUs */
-
-#define MSR_PPIN_CTL                   0x0000004e
-#define MSR_PPIN                       0x0000004f
-
-#define MSR_IA32_PERFCTR0              0x000000c1
-#define MSR_IA32_PERFCTR1              0x000000c2
-#define MSR_FSB_FREQ                   0x000000cd
-#define MSR_PLATFORM_INFO              0x000000ce
-#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT      31
-#define MSR_PLATFORM_INFO_CPUID_FAULT          BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT)
-
-#define MSR_PKG_CST_CONFIG_CONTROL     0x000000e2
-#define NHM_C3_AUTO_DEMOTE             (1UL << 25)
-#define NHM_C1_AUTO_DEMOTE             (1UL << 26)
-#define ATM_LNC_C6_AUTO_DEMOTE         (1UL << 25)
-#define SNB_C1_AUTO_UNDEMOTE           (1UL << 27)
-#define SNB_C3_AUTO_UNDEMOTE           (1UL << 28)
-
-#define MSR_MTRRcap                    0x000000fe
-#define MSR_IA32_BBL_CR_CTL            0x00000119
-#define MSR_IA32_BBL_CR_CTL3           0x0000011e
-
-#define MSR_IA32_SYSENTER_CS           0x00000174
-#define MSR_IA32_SYSENTER_ESP          0x00000175
-#define MSR_IA32_SYSENTER_EIP          0x00000176
-
-#define MSR_IA32_MCG_CAP               0x00000179
-#define MSR_IA32_MCG_STATUS            0x0000017a
-#define MSR_IA32_MCG_CTL               0x0000017b
-#define MSR_IA32_MCG_EXT_CTL           0x000004d0
-
-#define MSR_OFFCORE_RSP_0              0x000001a6
-#define MSR_OFFCORE_RSP_1              0x000001a7
-#define MSR_TURBO_RATIO_LIMIT          0x000001ad
-#define MSR_TURBO_RATIO_LIMIT1         0x000001ae
-#define MSR_TURBO_RATIO_LIMIT2         0x000001af
-
-#define MSR_LBR_SELECT                 0x000001c8
-#define MSR_LBR_TOS                    0x000001c9
-#define MSR_LBR_NHM_FROM               0x00000680
-#define MSR_LBR_NHM_TO                 0x000006c0
-#define MSR_LBR_CORE_FROM              0x00000040
-#define MSR_LBR_CORE_TO                        0x00000060
-
-#define MSR_LBR_INFO_0                 0x00000dc0 /* ... 0xddf for _31 */
-#define LBR_INFO_MISPRED               BIT_ULL(63)
-#define LBR_INFO_IN_TX                 BIT_ULL(62)
-#define LBR_INFO_ABORT                 BIT_ULL(61)
-#define LBR_INFO_CYCLES                        0xffff
-
-#define MSR_IA32_PEBS_ENABLE           0x000003f1
-#define MSR_IA32_DS_AREA               0x00000600
-#define MSR_IA32_PERF_CAPABILITIES     0x00000345
-#define MSR_PEBS_LD_LAT_THRESHOLD      0x000003f6
-
-#define MSR_IA32_RTIT_CTL              0x00000570
-#define MSR_IA32_RTIT_STATUS           0x00000571
-#define MSR_IA32_RTIT_ADDR0_A          0x00000580
-#define MSR_IA32_RTIT_ADDR0_B          0x00000581
-#define MSR_IA32_RTIT_ADDR1_A          0x00000582
-#define MSR_IA32_RTIT_ADDR1_B          0x00000583
-#define MSR_IA32_RTIT_ADDR2_A          0x00000584
-#define MSR_IA32_RTIT_ADDR2_B          0x00000585
-#define MSR_IA32_RTIT_ADDR3_A          0x00000586
-#define MSR_IA32_RTIT_ADDR3_B          0x00000587
-#define MSR_IA32_RTIT_CR3_MATCH                0x00000572
-#define MSR_IA32_RTIT_OUTPUT_BASE      0x00000560
-#define MSR_IA32_RTIT_OUTPUT_MASK      0x00000561
-
-#define MSR_MTRRfix64K_00000           0x00000250
-#define MSR_MTRRfix16K_80000           0x00000258
-#define MSR_MTRRfix16K_A0000           0x00000259
-#define MSR_MTRRfix4K_C0000            0x00000268
-#define MSR_MTRRfix4K_C8000            0x00000269
-#define MSR_MTRRfix4K_D0000            0x0000026a
-#define MSR_MTRRfix4K_D8000            0x0000026b
-#define MSR_MTRRfix4K_E0000            0x0000026c
-#define MSR_MTRRfix4K_E8000            0x0000026d
-#define MSR_MTRRfix4K_F0000            0x0000026e
-#define MSR_MTRRfix4K_F8000            0x0000026f
-#define MSR_MTRRdefType                        0x000002ff
-
-#define MSR_IA32_CR_PAT                        0x00000277
-
-#define MSR_IA32_DEBUGCTLMSR           0x000001d9
-#define MSR_IA32_LASTBRANCHFROMIP      0x000001db
-#define MSR_IA32_LASTBRANCHTOIP                0x000001dc
-#define MSR_IA32_LASTINTFROMIP         0x000001dd
-#define MSR_IA32_LASTINTTOIP           0x000001de
-
-/* DEBUGCTLMSR bits (others vary by model): */
-#define DEBUGCTLMSR_LBR                        (1UL <<  0) /* last branch recording */
-#define DEBUGCTLMSR_BTF_SHIFT          1
-#define DEBUGCTLMSR_BTF                        (1UL <<  1) /* single-step on branches */
-#define DEBUGCTLMSR_TR                 (1UL <<  6)
-#define DEBUGCTLMSR_BTS                        (1UL <<  7)
-#define DEBUGCTLMSR_BTINT              (1UL <<  8)
-#define DEBUGCTLMSR_BTS_OFF_OS         (1UL <<  9)
-#define DEBUGCTLMSR_BTS_OFF_USR                (1UL << 10)
-#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
-#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT  14
-#define DEBUGCTLMSR_FREEZE_IN_SMM      (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT)
-
-#define MSR_PEBS_FRONTEND              0x000003f7
-
-#define MSR_IA32_POWER_CTL             0x000001fc
-
-#define MSR_IA32_MC0_CTL               0x00000400
-#define MSR_IA32_MC0_STATUS            0x00000401
-#define MSR_IA32_MC0_ADDR              0x00000402
-#define MSR_IA32_MC0_MISC              0x00000403
-
-/* C-state Residency Counters */
-#define MSR_PKG_C3_RESIDENCY           0x000003f8
-#define MSR_PKG_C6_RESIDENCY           0x000003f9
-#define MSR_ATOM_PKG_C6_RESIDENCY      0x000003fa
-#define MSR_PKG_C7_RESIDENCY           0x000003fa
-#define MSR_CORE_C3_RESIDENCY          0x000003fc
-#define MSR_CORE_C6_RESIDENCY          0x000003fd
-#define MSR_CORE_C7_RESIDENCY          0x000003fe
-#define MSR_KNL_CORE_C6_RESIDENCY      0x000003ff
-#define MSR_PKG_C2_RESIDENCY           0x0000060d
-#define MSR_PKG_C8_RESIDENCY           0x00000630
-#define MSR_PKG_C9_RESIDENCY           0x00000631
-#define MSR_PKG_C10_RESIDENCY          0x00000632
-
-/* Interrupt Response Limit */
-#define MSR_PKGC3_IRTL                 0x0000060a
-#define MSR_PKGC6_IRTL                 0x0000060b
-#define MSR_PKGC7_IRTL                 0x0000060c
-#define MSR_PKGC8_IRTL                 0x00000633
-#define MSR_PKGC9_IRTL                 0x00000634
-#define MSR_PKGC10_IRTL                        0x00000635
-
-/* Run Time Average Power Limiting (RAPL) Interface */
-
-#define MSR_RAPL_POWER_UNIT            0x00000606
-
-#define MSR_PKG_POWER_LIMIT            0x00000610
-#define MSR_PKG_ENERGY_STATUS          0x00000611
-#define MSR_PKG_PERF_STATUS            0x00000613
-#define MSR_PKG_POWER_INFO             0x00000614
-
-#define MSR_DRAM_POWER_LIMIT           0x00000618
-#define MSR_DRAM_ENERGY_STATUS         0x00000619
-#define MSR_DRAM_PERF_STATUS           0x0000061b
-#define MSR_DRAM_POWER_INFO            0x0000061c
-
-#define MSR_PP0_POWER_LIMIT            0x00000638
-#define MSR_PP0_ENERGY_STATUS          0x00000639
-#define MSR_PP0_POLICY                 0x0000063a
-#define MSR_PP0_PERF_STATUS            0x0000063b
-
-#define MSR_PP1_POWER_LIMIT            0x00000640
-#define MSR_PP1_ENERGY_STATUS          0x00000641
-#define MSR_PP1_POLICY                 0x00000642
-
-/* Config TDP MSRs */
-#define MSR_CONFIG_TDP_NOMINAL         0x00000648
-#define MSR_CONFIG_TDP_LEVEL_1         0x00000649
-#define MSR_CONFIG_TDP_LEVEL_2         0x0000064A
-#define MSR_CONFIG_TDP_CONTROL         0x0000064B
-#define MSR_TURBO_ACTIVATION_RATIO     0x0000064C
-
-#define MSR_PLATFORM_ENERGY_STATUS     0x0000064D
-
-#define MSR_PKG_WEIGHTED_CORE_C0_RES   0x00000658
-#define MSR_PKG_ANY_CORE_C0_RES                0x00000659
-#define MSR_PKG_ANY_GFXE_C0_RES                0x0000065A
-#define MSR_PKG_BOTH_CORE_GFXE_C0_RES  0x0000065B
-
-#define MSR_CORE_C1_RES                        0x00000660
-#define MSR_MODULE_C6_RES_MS           0x00000664
-
-#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668
-#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669
-
-#define MSR_ATOM_CORE_RATIOS           0x0000066a
-#define MSR_ATOM_CORE_VIDS             0x0000066b
-#define MSR_ATOM_CORE_TURBO_RATIOS     0x0000066c
-#define MSR_ATOM_CORE_TURBO_VIDS       0x0000066d
-
-
-#define MSR_CORE_PERF_LIMIT_REASONS    0x00000690
-#define MSR_GFX_PERF_LIMIT_REASONS     0x000006B0
-#define MSR_RING_PERF_LIMIT_REASONS    0x000006B1
-
-/* Hardware P state interface */
-#define MSR_PPERF                      0x0000064e
-#define MSR_PERF_LIMIT_REASONS         0x0000064f
-#define MSR_PM_ENABLE                  0x00000770
-#define MSR_HWP_CAPABILITIES           0x00000771
-#define MSR_HWP_REQUEST_PKG            0x00000772
-#define MSR_HWP_INTERRUPT              0x00000773
-#define MSR_HWP_REQUEST                        0x00000774
-#define MSR_HWP_STATUS                 0x00000777
-
-/* CPUID.6.EAX */
-#define HWP_BASE_BIT                   (1<<7)
-#define HWP_NOTIFICATIONS_BIT          (1<<8)
-#define HWP_ACTIVITY_WINDOW_BIT                (1<<9)
-#define HWP_ENERGY_PERF_PREFERENCE_BIT (1<<10)
-#define HWP_PACKAGE_LEVEL_REQUEST_BIT  (1<<11)
-
-/* IA32_HWP_CAPABILITIES */
-#define HWP_HIGHEST_PERF(x)            (((x) >> 0) & 0xff)
-#define HWP_GUARANTEED_PERF(x)         (((x) >> 8) & 0xff)
-#define HWP_MOSTEFFICIENT_PERF(x)      (((x) >> 16) & 0xff)
-#define HWP_LOWEST_PERF(x)             (((x) >> 24) & 0xff)
-
-/* IA32_HWP_REQUEST */
-#define HWP_MIN_PERF(x)                        (x & 0xff)
-#define HWP_MAX_PERF(x)                        ((x & 0xff) << 8)
-#define HWP_DESIRED_PERF(x)            ((x & 0xff) << 16)
-#define HWP_ENERGY_PERF_PREFERENCE(x)  (((unsigned long long) x & 0xff) << 24)
-#define HWP_EPP_PERFORMANCE            0x00
-#define HWP_EPP_BALANCE_PERFORMANCE    0x80
-#define HWP_EPP_BALANCE_POWERSAVE      0xC0
-#define HWP_EPP_POWERSAVE              0xFF
-#define HWP_ACTIVITY_WINDOW(x)         ((unsigned long long)(x & 0xff3) << 32)
-#define HWP_PACKAGE_CONTROL(x)         ((unsigned long long)(x & 0x1) << 42)
-
-/* IA32_HWP_STATUS */
-#define HWP_GUARANTEED_CHANGE(x)       (x & 0x1)
-#define HWP_EXCURSION_TO_MINIMUM(x)    (x & 0x4)
-
-/* IA32_HWP_INTERRUPT */
-#define HWP_CHANGE_TO_GUARANTEED_INT(x)        (x & 0x1)
-#define HWP_EXCURSION_TO_MINIMUM_INT(x)        (x & 0x2)
-
-#define MSR_AMD64_MC0_MASK             0xc0010044
-
-#define MSR_IA32_MCx_CTL(x)            (MSR_IA32_MC0_CTL + 4*(x))
-#define MSR_IA32_MCx_STATUS(x)         (MSR_IA32_MC0_STATUS + 4*(x))
-#define MSR_IA32_MCx_ADDR(x)           (MSR_IA32_MC0_ADDR + 4*(x))
-#define MSR_IA32_MCx_MISC(x)           (MSR_IA32_MC0_MISC + 4*(x))
-
-#define MSR_AMD64_MCx_MASK(x)          (MSR_AMD64_MC0_MASK + (x))
-
-/* These are consecutive and not in the normal 4er MCE bank block */
-#define MSR_IA32_MC0_CTL2              0x00000280
-#define MSR_IA32_MCx_CTL2(x)           (MSR_IA32_MC0_CTL2 + (x))
-
-#define MSR_P6_PERFCTR0                        0x000000c1
-#define MSR_P6_PERFCTR1                        0x000000c2
-#define MSR_P6_EVNTSEL0                        0x00000186
-#define MSR_P6_EVNTSEL1                        0x00000187
-
-#define MSR_KNC_PERFCTR0               0x00000020
-#define MSR_KNC_PERFCTR1               0x00000021
-#define MSR_KNC_EVNTSEL0               0x00000028
-#define MSR_KNC_EVNTSEL1               0x00000029
-
-/* Alternative perfctr range with full access. */
-#define MSR_IA32_PMC0                  0x000004c1
-
-/* AMD64 MSRs. Not complete. See the architecture manual for a more
-   complete list. */
-
-#define MSR_AMD64_PATCH_LEVEL          0x0000008b
-#define MSR_AMD64_TSC_RATIO            0xc0000104
-#define MSR_AMD64_NB_CFG               0xc001001f
-#define MSR_AMD64_PATCH_LOADER         0xc0010020
-#define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
-#define MSR_AMD64_OSVW_STATUS          0xc0010141
-#define MSR_AMD64_LS_CFG               0xc0011020
-#define MSR_AMD64_DC_CFG               0xc0011022
-#define MSR_AMD64_BU_CFG2              0xc001102a
-#define MSR_AMD64_IBSFETCHCTL          0xc0011030
-#define MSR_AMD64_IBSFETCHLINAD                0xc0011031
-#define MSR_AMD64_IBSFETCHPHYSAD       0xc0011032
-#define MSR_AMD64_IBSFETCH_REG_COUNT   3
-#define MSR_AMD64_IBSFETCH_REG_MASK    ((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
-#define MSR_AMD64_IBSOPCTL             0xc0011033
-#define MSR_AMD64_IBSOPRIP             0xc0011034
-#define MSR_AMD64_IBSOPDATA            0xc0011035
-#define MSR_AMD64_IBSOPDATA2           0xc0011036
-#define MSR_AMD64_IBSOPDATA3           0xc0011037
-#define MSR_AMD64_IBSDCLINAD           0xc0011038
-#define MSR_AMD64_IBSDCPHYSAD          0xc0011039
-#define MSR_AMD64_IBSOP_REG_COUNT      7
-#define MSR_AMD64_IBSOP_REG_MASK       ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
-#define MSR_AMD64_IBSCTL               0xc001103a
-#define MSR_AMD64_IBSBRTARGET          0xc001103b
-#define MSR_AMD64_IBSOPDATA4           0xc001103d
-#define MSR_AMD64_IBS_REG_COUNT_MAX    8 /* includes MSR_AMD64_IBSBRTARGET */
-#define MSR_AMD64_SEV                  0xc0010131
-#define MSR_AMD64_SEV_ENABLED_BIT      0
-#define MSR_AMD64_SEV_ENABLED          BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
-
-/* Fam 17h MSRs */
-#define MSR_F17H_IRPERF                        0xc00000e9
-
-/* Fam 16h MSRs */
-#define MSR_F16H_L2I_PERF_CTL          0xc0010230
-#define MSR_F16H_L2I_PERF_CTR          0xc0010231
-#define MSR_F16H_DR1_ADDR_MASK         0xc0011019
-#define MSR_F16H_DR2_ADDR_MASK         0xc001101a
-#define MSR_F16H_DR3_ADDR_MASK         0xc001101b
-#define MSR_F16H_DR0_ADDR_MASK         0xc0011027
-
-/* Fam 15h MSRs */
-#define MSR_F15H_PERF_CTL              0xc0010200
-#define MSR_F15H_PERF_CTR              0xc0010201
-#define MSR_F15H_NB_PERF_CTL           0xc0010240
-#define MSR_F15H_NB_PERF_CTR           0xc0010241
-#define MSR_F15H_PTSC                  0xc0010280
-#define MSR_F15H_IC_CFG                        0xc0011021
-
-/* Fam 10h MSRs */
-#define MSR_FAM10H_MMIO_CONF_BASE      0xc0010058
-#define FAM10H_MMIO_CONF_ENABLE                (1<<0)
-#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
-#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
-#define FAM10H_MMIO_CONF_BASE_MASK     0xfffffffULL
-#define FAM10H_MMIO_CONF_BASE_SHIFT    20
-#define MSR_FAM10H_NODE_ID             0xc001100c
-#define MSR_F10H_DECFG                 0xc0011029
-#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT    1
-#define MSR_F10H_DECFG_LFENCE_SERIALIZE                BIT_ULL(MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT)
-
-/* K8 MSRs */
-#define MSR_K8_TOP_MEM1                        0xc001001a
-#define MSR_K8_TOP_MEM2                        0xc001001d
-#define MSR_K8_SYSCFG                  0xc0010010
-#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT  23
-#define MSR_K8_SYSCFG_MEM_ENCRYPT      BIT_ULL(MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
-#define MSR_K8_INT_PENDING_MSG         0xc0010055
-/* C1E active bits in int pending message */
-#define K8_INTP_C1E_ACTIVE_MASK                0x18000000
-#define MSR_K8_TSEG_ADDR               0xc0010112
-#define MSR_K8_TSEG_MASK               0xc0010113
-#define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
-#define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
-#define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
-
-/* K7 MSRs */
-#define MSR_K7_EVNTSEL0                        0xc0010000
-#define MSR_K7_PERFCTR0                        0xc0010004
-#define MSR_K7_EVNTSEL1                        0xc0010001
-#define MSR_K7_PERFCTR1                        0xc0010005
-#define MSR_K7_EVNTSEL2                        0xc0010002
-#define MSR_K7_PERFCTR2                        0xc0010006
-#define MSR_K7_EVNTSEL3                        0xc0010003
-#define MSR_K7_PERFCTR3                        0xc0010007
-#define MSR_K7_CLK_CTL                 0xc001001b
-#define MSR_K7_HWCR                    0xc0010015
-#define MSR_K7_HWCR_SMMLOCK_BIT                0
-#define MSR_K7_HWCR_SMMLOCK            BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
-#define MSR_K7_FID_VID_CTL             0xc0010041
-#define MSR_K7_FID_VID_STATUS          0xc0010042
-
-/* K6 MSRs */
-#define MSR_K6_WHCR                    0xc0000082
-#define MSR_K6_UWCCR                   0xc0000085
-#define MSR_K6_EPMR                    0xc0000086
-#define MSR_K6_PSOR                    0xc0000087
-#define MSR_K6_PFIR                    0xc0000088
-
-/* Centaur-Hauls/IDT defined MSRs. */
-#define MSR_IDT_FCR1                   0x00000107
-#define MSR_IDT_FCR2                   0x00000108
-#define MSR_IDT_FCR3                   0x00000109
-#define MSR_IDT_FCR4                   0x0000010a
-
-#define MSR_IDT_MCR0                   0x00000110
-#define MSR_IDT_MCR1                   0x00000111
-#define MSR_IDT_MCR2                   0x00000112
-#define MSR_IDT_MCR3                   0x00000113
-#define MSR_IDT_MCR4                   0x00000114
-#define MSR_IDT_MCR5                   0x00000115
-#define MSR_IDT_MCR6                   0x00000116
-#define MSR_IDT_MCR7                   0x00000117
-#define MSR_IDT_MCR_CTRL               0x00000120
-
-/* VIA Cyrix defined MSRs*/
-#define MSR_VIA_FCR                    0x00001107
-#define MSR_VIA_LONGHAUL               0x0000110a
-#define MSR_VIA_RNG                    0x0000110b
-#define MSR_VIA_BCR2                   0x00001147
-
-/* Transmeta defined MSRs */
-#define MSR_TMTA_LONGRUN_CTRL          0x80868010
-#define MSR_TMTA_LONGRUN_FLAGS         0x80868011
-#define MSR_TMTA_LRTI_READOUT          0x80868018
-#define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
-
-/* Intel defined MSRs. */
-#define MSR_IA32_P5_MC_ADDR            0x00000000
-#define MSR_IA32_P5_MC_TYPE            0x00000001
-#define MSR_IA32_TSC                   0x00000010
-#define MSR_IA32_PLATFORM_ID           0x00000017
-#define MSR_IA32_EBL_CR_POWERON                0x0000002a
-#define MSR_EBC_FREQUENCY_ID           0x0000002c
-#define MSR_SMI_COUNT                  0x00000034
-#define MSR_IA32_FEATURE_CONTROL        0x0000003a
-#define MSR_IA32_TSC_ADJUST             0x0000003b
-#define MSR_IA32_BNDCFGS               0x00000d90
-
-#define MSR_IA32_BNDCFGS_RSVD          0x00000ffc
-
-#define MSR_IA32_XSS                   0x00000da0
-
-#define FEATURE_CONTROL_LOCKED                         (1<<0)
-#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX       (1<<1)
-#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX      (1<<2)
-#define FEATURE_CONTROL_LMCE                           (1<<20)
-
-#define MSR_IA32_APICBASE              0x0000001b
-#define MSR_IA32_APICBASE_BSP          (1<<8)
-#define MSR_IA32_APICBASE_ENABLE       (1<<11)
-#define MSR_IA32_APICBASE_BASE         (0xfffff<<12)
-
-#define MSR_IA32_TSCDEADLINE           0x000006e0
-
-#define MSR_IA32_UCODE_WRITE           0x00000079
-#define MSR_IA32_UCODE_REV             0x0000008b
-
-#define MSR_IA32_SMM_MONITOR_CTL       0x0000009b
-#define MSR_IA32_SMBASE                        0x0000009e
-
-#define MSR_IA32_PERF_STATUS           0x00000198
-#define MSR_IA32_PERF_CTL              0x00000199
-#define INTEL_PERF_CTL_MASK            0xffff
-#define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
-#define MSR_AMD_PERF_STATUS            0xc0010063
-#define MSR_AMD_PERF_CTL               0xc0010062
-
-#define MSR_IA32_MPERF                 0x000000e7
-#define MSR_IA32_APERF                 0x000000e8
-
-#define MSR_IA32_THERM_CONTROL         0x0000019a
-#define MSR_IA32_THERM_INTERRUPT       0x0000019b
-
-#define THERM_INT_HIGH_ENABLE          (1 << 0)
-#define THERM_INT_LOW_ENABLE           (1 << 1)
-#define THERM_INT_PLN_ENABLE           (1 << 24)
-
-#define MSR_IA32_THERM_STATUS          0x0000019c
-
-#define THERM_STATUS_PROCHOT           (1 << 0)
-#define THERM_STATUS_POWER_LIMIT       (1 << 10)
-
-#define MSR_THERM2_CTL                 0x0000019d
-
-#define MSR_THERM2_CTL_TM_SELECT       (1ULL << 16)
-
-#define MSR_IA32_MISC_ENABLE           0x000001a0
-
-#define MSR_IA32_TEMPERATURE_TARGET    0x000001a2
-
-#define MSR_MISC_FEATURE_CONTROL       0x000001a4
-#define MSR_MISC_PWR_MGMT              0x000001aa
-
-#define MSR_IA32_ENERGY_PERF_BIAS      0x000001b0
-#define ENERGY_PERF_BIAS_PERFORMANCE           0
-#define ENERGY_PERF_BIAS_BALANCE_PERFORMANCE   4
-#define ENERGY_PERF_BIAS_NORMAL                        6
-#define ENERGY_PERF_BIAS_BALANCE_POWERSAVE     8
-#define ENERGY_PERF_BIAS_POWERSAVE             15
-
-#define MSR_IA32_PACKAGE_THERM_STATUS          0x000001b1
-
-#define PACKAGE_THERM_STATUS_PROCHOT           (1 << 0)
-#define PACKAGE_THERM_STATUS_POWER_LIMIT       (1 << 10)
-
-#define MSR_IA32_PACKAGE_THERM_INTERRUPT       0x000001b2
-
-#define PACKAGE_THERM_INT_HIGH_ENABLE          (1 << 0)
-#define PACKAGE_THERM_INT_LOW_ENABLE           (1 << 1)
-#define PACKAGE_THERM_INT_PLN_ENABLE           (1 << 24)
-
-/* Thermal Thresholds Support */
-#define THERM_INT_THRESHOLD0_ENABLE    (1 << 15)
-#define THERM_SHIFT_THRESHOLD0        8
-#define THERM_MASK_THRESHOLD0          (0x7f << THERM_SHIFT_THRESHOLD0)
-#define THERM_INT_THRESHOLD1_ENABLE    (1 << 23)
-#define THERM_SHIFT_THRESHOLD1        16
-#define THERM_MASK_THRESHOLD1          (0x7f << THERM_SHIFT_THRESHOLD1)
-#define THERM_STATUS_THRESHOLD0        (1 << 6)
-#define THERM_LOG_THRESHOLD0           (1 << 7)
-#define THERM_STATUS_THRESHOLD1        (1 << 8)
-#define THERM_LOG_THRESHOLD1           (1 << 9)
-
-/* MISC_ENABLE bits: architectural */
-#define MSR_IA32_MISC_ENABLE_FAST_STRING_BIT           0
-#define MSR_IA32_MISC_ENABLE_FAST_STRING               (1ULL << MSR_IA32_MISC_ENABLE_FAST_STRING_BIT)
-#define MSR_IA32_MISC_ENABLE_TCC_BIT                   1
-#define MSR_IA32_MISC_ENABLE_TCC                       (1ULL << MSR_IA32_MISC_ENABLE_TCC_BIT)
-#define MSR_IA32_MISC_ENABLE_EMON_BIT                  7
-#define MSR_IA32_MISC_ENABLE_EMON                      (1ULL << MSR_IA32_MISC_ENABLE_EMON_BIT)
-#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT           11
-#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL               (1ULL << MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT)
-#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT          12
-#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL              (1ULL << MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT)
-#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT    16
-#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP                (1ULL << MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT)
-#define MSR_IA32_MISC_ENABLE_MWAIT_BIT                 18
-#define MSR_IA32_MISC_ENABLE_MWAIT                     (1ULL << MSR_IA32_MISC_ENABLE_MWAIT_BIT)
-#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT           22
-#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID               (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT)
-#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT          23
-#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE              (1ULL << MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT            34
-#define MSR_IA32_MISC_ENABLE_XD_DISABLE                        (1ULL << MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT)
-
-/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
-#define MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT            2
-#define MSR_IA32_MISC_ENABLE_X87_COMPAT                        (1ULL << MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT)
-#define MSR_IA32_MISC_ENABLE_TM1_BIT                   3
-#define MSR_IA32_MISC_ENABLE_TM1                       (1ULL << MSR_IA32_MISC_ENABLE_TM1_BIT)
-#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT    4
-#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE                (1ULL << MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT       6
-#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT         8
-#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK             (1ULL << MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT)
-#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT      9
-#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_FERR_BIT                  10
-#define MSR_IA32_MISC_ENABLE_FERR                      (1ULL << MSR_IA32_MISC_ENABLE_FERR_BIT)
-#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT                10
-#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX            (1ULL << MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT)
-#define MSR_IA32_MISC_ENABLE_TM2_BIT                   13
-#define MSR_IA32_MISC_ENABLE_TM2                       (1ULL << MSR_IA32_MISC_ENABLE_TM2_BIT)
-#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT      19
-#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT                20
-#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK            (1ULL << MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT)
-#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT           24
-#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT               (1ULL << MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT)
-#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT      37
-#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT         38
-#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE             (1ULL << MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT)
-#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT       39
-#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT)
-
-/* MISC_FEATURES_ENABLES non-architectural features */
-#define MSR_MISC_FEATURES_ENABLES      0x00000140
-
-#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT      0
-#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT          BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT)
-#define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT       1
-
-#define MSR_IA32_TSC_DEADLINE          0x000006E0
-
-/* P4/Xeon+ specific */
-#define MSR_IA32_MCG_EAX               0x00000180
-#define MSR_IA32_MCG_EBX               0x00000181
-#define MSR_IA32_MCG_ECX               0x00000182
-#define MSR_IA32_MCG_EDX               0x00000183
-#define MSR_IA32_MCG_ESI               0x00000184
-#define MSR_IA32_MCG_EDI               0x00000185
-#define MSR_IA32_MCG_EBP               0x00000186
-#define MSR_IA32_MCG_ESP               0x00000187
-#define MSR_IA32_MCG_EFLAGS            0x00000188
-#define MSR_IA32_MCG_EIP               0x00000189
-#define MSR_IA32_MCG_RESERVED          0x0000018a
-
-/* Pentium IV performance counter MSRs */
-#define MSR_P4_BPU_PERFCTR0            0x00000300
-#define MSR_P4_BPU_PERFCTR1            0x00000301
-#define MSR_P4_BPU_PERFCTR2            0x00000302
-#define MSR_P4_BPU_PERFCTR3            0x00000303
-#define MSR_P4_MS_PERFCTR0             0x00000304
-#define MSR_P4_MS_PERFCTR1             0x00000305
-#define MSR_P4_MS_PERFCTR2             0x00000306
-#define MSR_P4_MS_PERFCTR3             0x00000307
-#define MSR_P4_FLAME_PERFCTR0          0x00000308
-#define MSR_P4_FLAME_PERFCTR1          0x00000309
-#define MSR_P4_FLAME_PERFCTR2          0x0000030a
-#define MSR_P4_FLAME_PERFCTR3          0x0000030b
-#define MSR_P4_IQ_PERFCTR0             0x0000030c
-#define MSR_P4_IQ_PERFCTR1             0x0000030d
-#define MSR_P4_IQ_PERFCTR2             0x0000030e
-#define MSR_P4_IQ_PERFCTR3             0x0000030f
-#define MSR_P4_IQ_PERFCTR4             0x00000310
-#define MSR_P4_IQ_PERFCTR5             0x00000311
-#define MSR_P4_BPU_CCCR0               0x00000360
-#define MSR_P4_BPU_CCCR1               0x00000361
-#define MSR_P4_BPU_CCCR2               0x00000362
-#define MSR_P4_BPU_CCCR3               0x00000363
-#define MSR_P4_MS_CCCR0                        0x00000364
-#define MSR_P4_MS_CCCR1                        0x00000365
-#define MSR_P4_MS_CCCR2                        0x00000366
-#define MSR_P4_MS_CCCR3                        0x00000367
-#define MSR_P4_FLAME_CCCR0             0x00000368
-#define MSR_P4_FLAME_CCCR1             0x00000369
-#define MSR_P4_FLAME_CCCR2             0x0000036a
-#define MSR_P4_FLAME_CCCR3             0x0000036b
-#define MSR_P4_IQ_CCCR0                        0x0000036c
-#define MSR_P4_IQ_CCCR1                        0x0000036d
-#define MSR_P4_IQ_CCCR2                        0x0000036e
-#define MSR_P4_IQ_CCCR3                        0x0000036f
-#define MSR_P4_IQ_CCCR4                        0x00000370
-#define MSR_P4_IQ_CCCR5                        0x00000371
-#define MSR_P4_ALF_ESCR0               0x000003ca
-#define MSR_P4_ALF_ESCR1               0x000003cb
-#define MSR_P4_BPU_ESCR0               0x000003b2
-#define MSR_P4_BPU_ESCR1               0x000003b3
-#define MSR_P4_BSU_ESCR0               0x000003a0
-#define MSR_P4_BSU_ESCR1               0x000003a1
-#define MSR_P4_CRU_ESCR0               0x000003b8
-#define MSR_P4_CRU_ESCR1               0x000003b9
-#define MSR_P4_CRU_ESCR2               0x000003cc
-#define MSR_P4_CRU_ESCR3               0x000003cd
-#define MSR_P4_CRU_ESCR4               0x000003e0
-#define MSR_P4_CRU_ESCR5               0x000003e1
-#define MSR_P4_DAC_ESCR0               0x000003a8
-#define MSR_P4_DAC_ESCR1               0x000003a9
-#define MSR_P4_FIRM_ESCR0              0x000003a4
-#define MSR_P4_FIRM_ESCR1              0x000003a5
-#define MSR_P4_FLAME_ESCR0             0x000003a6
-#define MSR_P4_FLAME_ESCR1             0x000003a7
-#define MSR_P4_FSB_ESCR0               0x000003a2
-#define MSR_P4_FSB_ESCR1               0x000003a3
-#define MSR_P4_IQ_ESCR0                        0x000003ba
-#define MSR_P4_IQ_ESCR1                        0x000003bb
-#define MSR_P4_IS_ESCR0                        0x000003b4
-#define MSR_P4_IS_ESCR1                        0x000003b5
-#define MSR_P4_ITLB_ESCR0              0x000003b6
-#define MSR_P4_ITLB_ESCR1              0x000003b7
-#define MSR_P4_IX_ESCR0                        0x000003c8
-#define MSR_P4_IX_ESCR1                        0x000003c9
-#define MSR_P4_MOB_ESCR0               0x000003aa
-#define MSR_P4_MOB_ESCR1               0x000003ab
-#define MSR_P4_MS_ESCR0                        0x000003c0
-#define MSR_P4_MS_ESCR1                        0x000003c1
-#define MSR_P4_PMH_ESCR0               0x000003ac
-#define MSR_P4_PMH_ESCR1               0x000003ad
-#define MSR_P4_RAT_ESCR0               0x000003bc
-#define MSR_P4_RAT_ESCR1               0x000003bd
-#define MSR_P4_SAAT_ESCR0              0x000003ae
-#define MSR_P4_SAAT_ESCR1              0x000003af
-#define MSR_P4_SSU_ESCR0               0x000003be
-#define MSR_P4_SSU_ESCR1               0x000003bf /* guess: not in manual */
-
-#define MSR_P4_TBPU_ESCR0              0x000003c2
-#define MSR_P4_TBPU_ESCR1              0x000003c3
-#define MSR_P4_TC_ESCR0                        0x000003c4
-#define MSR_P4_TC_ESCR1                        0x000003c5
-#define MSR_P4_U2L_ESCR0               0x000003b0
-#define MSR_P4_U2L_ESCR1               0x000003b1
-
-#define MSR_P4_PEBS_MATRIX_VERT                0x000003f2
-
-/* Intel Core-based CPU performance counters */
-#define MSR_CORE_PERF_FIXED_CTR0       0x00000309
-#define MSR_CORE_PERF_FIXED_CTR1       0x0000030a
-#define MSR_CORE_PERF_FIXED_CTR2       0x0000030b
-#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x0000038d
-#define MSR_CORE_PERF_GLOBAL_STATUS    0x0000038e
-#define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
-#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
-
-/* Geode defined MSRs */
-#define MSR_GEODE_BUSCONT_CONF0                0x00001900
-
-/* Intel VT MSRs */
-#define MSR_IA32_VMX_BASIC              0x00000480
-#define MSR_IA32_VMX_PINBASED_CTLS      0x00000481
-#define MSR_IA32_VMX_PROCBASED_CTLS     0x00000482
-#define MSR_IA32_VMX_EXIT_CTLS          0x00000483
-#define MSR_IA32_VMX_ENTRY_CTLS         0x00000484
-#define MSR_IA32_VMX_MISC               0x00000485
-#define MSR_IA32_VMX_CR0_FIXED0         0x00000486
-#define MSR_IA32_VMX_CR0_FIXED1         0x00000487
-#define MSR_IA32_VMX_CR4_FIXED0         0x00000488
-#define MSR_IA32_VMX_CR4_FIXED1         0x00000489
-#define MSR_IA32_VMX_VMCS_ENUM          0x0000048a
-#define MSR_IA32_VMX_PROCBASED_CTLS2    0x0000048b
-#define MSR_IA32_VMX_EPT_VPID_CAP       0x0000048c
-#define MSR_IA32_VMX_TRUE_PINBASED_CTLS  0x0000048d
-#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
-#define MSR_IA32_VMX_TRUE_EXIT_CTLS      0x0000048f
-#define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
-#define MSR_IA32_VMX_VMFUNC             0x00000491
-
-/* VMX_BASIC bits and bitmasks */
-#define VMX_BASIC_VMCS_SIZE_SHIFT      32
-#define VMX_BASIC_TRUE_CTLS            (1ULL << 55)
-#define VMX_BASIC_64           0x0001000000000000LLU
-#define VMX_BASIC_MEM_TYPE_SHIFT       50
-#define VMX_BASIC_MEM_TYPE_MASK        0x003c000000000000LLU
-#define VMX_BASIC_MEM_TYPE_WB  6LLU
-#define VMX_BASIC_INOUT                0x0040000000000000LLU
-
-/* MSR_IA32_VMX_MISC bits */
-#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
-#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE   0x1F
-/* AMD-V MSRs */
-
-#define MSR_VM_CR                       0xc0010114
-#define MSR_VM_IGNNE                    0xc0010115
-#define MSR_VM_HSAVE_PA                 0xc0010117
-
-#endif /* !SELFTEST_KVM_X86_H */
diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
new file mode 100644 (file)
index 0000000..bb76e8d
--- /dev/null
@@ -0,0 +1,1047 @@
+/*
+ * tools/testing/selftests/kvm/include/x86_64/processor.h
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ */
+
+#ifndef SELFTEST_KVM_PROCESSOR_H
+#define SELFTEST_KVM_PROCESSOR_H
+
+#include <assert.h>
+#include <stdint.h>
+
+#define X86_EFLAGS_FIXED        (1u << 1)
+
+#define X86_CR4_VME            (1ul << 0)
+#define X86_CR4_PVI            (1ul << 1)
+#define X86_CR4_TSD            (1ul << 2)
+#define X86_CR4_DE             (1ul << 3)
+#define X86_CR4_PSE            (1ul << 4)
+#define X86_CR4_PAE            (1ul << 5)
+#define X86_CR4_MCE            (1ul << 6)
+#define X86_CR4_PGE            (1ul << 7)
+#define X86_CR4_PCE            (1ul << 8)
+#define X86_CR4_OSFXSR         (1ul << 9)
+#define X86_CR4_OSXMMEXCPT     (1ul << 10)
+#define X86_CR4_UMIP           (1ul << 11)
+#define X86_CR4_VMXE           (1ul << 13)
+#define X86_CR4_SMXE           (1ul << 14)
+#define X86_CR4_FSGSBASE       (1ul << 16)
+#define X86_CR4_PCIDE          (1ul << 17)
+#define X86_CR4_OSXSAVE                (1ul << 18)
+#define X86_CR4_SMEP           (1ul << 20)
+#define X86_CR4_SMAP           (1ul << 21)
+#define X86_CR4_PKE            (1ul << 22)
+
+/* The enum values match the intruction encoding of each register */
+enum x86_register {
+       RAX = 0,
+       RCX,
+       RDX,
+       RBX,
+       RSP,
+       RBP,
+       RSI,
+       RDI,
+       R8,
+       R9,
+       R10,
+       R11,
+       R12,
+       R13,
+       R14,
+       R15,
+};
+
+struct desc64 {
+       uint16_t limit0;
+       uint16_t base0;
+       unsigned base1:8, s:1, type:4, dpl:2, p:1;
+       unsigned limit1:4, avl:1, l:1, db:1, g:1, base2:8;
+       uint32_t base3;
+       uint32_t zero1;
+} __attribute__((packed));
+
+struct desc_ptr {
+       uint16_t size;
+       uint64_t address;
+} __attribute__((packed));
+
+static inline uint64_t get_desc64_base(const struct desc64 *desc)
+{
+       return ((uint64_t)desc->base3 << 32) |
+               (desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
+}
+
+static inline uint64_t rdtsc(void)
+{
+       uint32_t eax, edx;
+
+       /*
+        * The lfence is to wait (on Intel CPUs) until all previous
+        * instructions have been executed.
+        */
+       __asm__ __volatile__("lfence; rdtsc" : "=a"(eax), "=d"(edx));
+       return ((uint64_t)edx) << 32 | eax;
+}
+
+static inline uint64_t rdtscp(uint32_t *aux)
+{
+       uint32_t eax, edx;
+
+       __asm__ __volatile__("rdtscp" : "=a"(eax), "=d"(edx), "=c"(*aux));
+       return ((uint64_t)edx) << 32 | eax;
+}
+
+static inline uint64_t rdmsr(uint32_t msr)
+{
+       uint32_t a, d;
+
+       __asm__ __volatile__("rdmsr" : "=a"(a), "=d"(d) : "c"(msr) : "memory");
+
+       return a | ((uint64_t) d << 32);
+}
+
+static inline void wrmsr(uint32_t msr, uint64_t value)
+{
+       uint32_t a = value;
+       uint32_t d = value >> 32;
+
+       __asm__ __volatile__("wrmsr" :: "a"(a), "d"(d), "c"(msr) : "memory");
+}
+
+
+static inline uint16_t inw(uint16_t port)
+{
+       uint16_t tmp;
+
+       __asm__ __volatile__("in %%dx, %%ax"
+               : /* output */ "=a" (tmp)
+               : /* input */ "d" (port));
+
+       return tmp;
+}
+
+static inline uint16_t get_es(void)
+{
+       uint16_t es;
+
+       __asm__ __volatile__("mov %%es, %[es]"
+                            : /* output */ [es]"=rm"(es));
+       return es;
+}
+
+static inline uint16_t get_cs(void)
+{
+       uint16_t cs;
+
+       __asm__ __volatile__("mov %%cs, %[cs]"
+                            : /* output */ [cs]"=rm"(cs));
+       return cs;
+}
+
+static inline uint16_t get_ss(void)
+{
+       uint16_t ss;
+
+       __asm__ __volatile__("mov %%ss, %[ss]"
+                            : /* output */ [ss]"=rm"(ss));
+       return ss;
+}
+
+static inline uint16_t get_ds(void)
+{
+       uint16_t ds;
+
+       __asm__ __volatile__("mov %%ds, %[ds]"
+                            : /* output */ [ds]"=rm"(ds));
+       return ds;
+}
+
+static inline uint16_t get_fs(void)
+{
+       uint16_t fs;
+
+       __asm__ __volatile__("mov %%fs, %[fs]"
+                            : /* output */ [fs]"=rm"(fs));
+       return fs;
+}
+
+static inline uint16_t get_gs(void)
+{
+       uint16_t gs;
+
+       __asm__ __volatile__("mov %%gs, %[gs]"
+                            : /* output */ [gs]"=rm"(gs));
+       return gs;
+}
+
+static inline uint16_t get_tr(void)
+{
+       uint16_t tr;
+
+       __asm__ __volatile__("str %[tr]"
+                            : /* output */ [tr]"=rm"(tr));
+       return tr;
+}
+
+static inline uint64_t get_cr0(void)
+{
+       uint64_t cr0;
+
+       __asm__ __volatile__("mov %%cr0, %[cr0]"
+                            : /* output */ [cr0]"=r"(cr0));
+       return cr0;
+}
+
+static inline uint64_t get_cr3(void)
+{
+       uint64_t cr3;
+
+       __asm__ __volatile__("mov %%cr3, %[cr3]"
+                            : /* output */ [cr3]"=r"(cr3));
+       return cr3;
+}
+
+static inline uint64_t get_cr4(void)
+{
+       uint64_t cr4;
+
+       __asm__ __volatile__("mov %%cr4, %[cr4]"
+                            : /* output */ [cr4]"=r"(cr4));
+       return cr4;
+}
+
+static inline void set_cr4(uint64_t val)
+{
+       __asm__ __volatile__("mov %0, %%cr4" : : "r" (val) : "memory");
+}
+
+static inline uint64_t get_gdt_base(void)
+{
+       struct desc_ptr gdt;
+       __asm__ __volatile__("sgdt %[gdt]"
+                            : /* output */ [gdt]"=m"(gdt));
+       return gdt.address;
+}
+
+static inline uint64_t get_idt_base(void)
+{
+       struct desc_ptr idt;
+       __asm__ __volatile__("sidt %[idt]"
+                            : /* output */ [idt]"=m"(idt));
+       return idt.address;
+}
+
+#define SET_XMM(__var, __xmm) \
+       asm volatile("movq %0, %%"#__xmm : : "r"(__var) : #__xmm)
+
+static inline void set_xmm(int n, unsigned long val)
+{
+       switch (n) {
+       case 0:
+               SET_XMM(val, xmm0);
+               break;
+       case 1:
+               SET_XMM(val, xmm1);
+               break;
+       case 2:
+               SET_XMM(val, xmm2);
+               break;
+       case 3:
+               SET_XMM(val, xmm3);
+               break;
+       case 4:
+               SET_XMM(val, xmm4);
+               break;
+       case 5:
+               SET_XMM(val, xmm5);
+               break;
+       case 6:
+               SET_XMM(val, xmm6);
+               break;
+       case 7:
+               SET_XMM(val, xmm7);
+               break;
+       }
+}
+
+typedef unsigned long v1di __attribute__ ((vector_size (8)));
+static inline unsigned long get_xmm(int n)
+{
+       assert(n >= 0 && n <= 7);
+
+       register v1di xmm0 __asm__("%xmm0");
+       register v1di xmm1 __asm__("%xmm1");
+       register v1di xmm2 __asm__("%xmm2");
+       register v1di xmm3 __asm__("%xmm3");
+       register v1di xmm4 __asm__("%xmm4");
+       register v1di xmm5 __asm__("%xmm5");
+       register v1di xmm6 __asm__("%xmm6");
+       register v1di xmm7 __asm__("%xmm7");
+       switch (n) {
+       case 0:
+               return (unsigned long)xmm0;
+       case 1:
+               return (unsigned long)xmm1;
+       case 2:
+               return (unsigned long)xmm2;
+       case 3:
+               return (unsigned long)xmm3;
+       case 4:
+               return (unsigned long)xmm4;
+       case 5:
+               return (unsigned long)xmm5;
+       case 6:
+               return (unsigned long)xmm6;
+       case 7:
+               return (unsigned long)xmm7;
+       }
+       return 0;
+}
+
+struct kvm_x86_state;
+struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid);
+void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state);
+
+/*
+ * Basic CPU control in CR0
+ */
+#define X86_CR0_PE          (1UL<<0) /* Protection Enable */
+#define X86_CR0_MP          (1UL<<1) /* Monitor Coprocessor */
+#define X86_CR0_EM          (1UL<<2) /* Emulation */
+#define X86_CR0_TS          (1UL<<3) /* Task Switched */
+#define X86_CR0_ET          (1UL<<4) /* Extension Type */
+#define X86_CR0_NE          (1UL<<5) /* Numeric Error */
+#define X86_CR0_WP          (1UL<<16) /* Write Protect */
+#define X86_CR0_AM          (1UL<<18) /* Alignment Mask */
+#define X86_CR0_NW          (1UL<<29) /* Not Write-through */
+#define X86_CR0_CD          (1UL<<30) /* Cache Disable */
+#define X86_CR0_PG          (1UL<<31) /* Paging */
+
+/*
+ * CPU model specific register (MSR) numbers.
+ */
+
+/* x86-64 specific MSRs */
+#define MSR_EFER               0xc0000080 /* extended feature register */
+#define MSR_STAR               0xc0000081 /* legacy mode SYSCALL target */
+#define MSR_LSTAR              0xc0000082 /* long mode SYSCALL target */
+#define MSR_CSTAR              0xc0000083 /* compat mode SYSCALL target */
+#define MSR_SYSCALL_MASK       0xc0000084 /* EFLAGS mask for syscall */
+#define MSR_FS_BASE            0xc0000100 /* 64bit FS base */
+#define MSR_GS_BASE            0xc0000101 /* 64bit GS base */
+#define MSR_KERNEL_GS_BASE     0xc0000102 /* SwapGS GS shadow */
+#define MSR_TSC_AUX            0xc0000103 /* Auxiliary TSC */
+
+/* EFER bits: */
+#define EFER_SCE               (1<<0)  /* SYSCALL/SYSRET */
+#define EFER_LME               (1<<8)  /* Long mode enable */
+#define EFER_LMA               (1<<10) /* Long mode active (read-only) */
+#define EFER_NX                        (1<<11) /* No execute enable */
+#define EFER_SVME              (1<<12) /* Enable virtualization */
+#define EFER_LMSLE             (1<<13) /* Long Mode Segment Limit Enable */
+#define EFER_FFXSR             (1<<14) /* Enable Fast FXSAVE/FXRSTOR */
+
+/* Intel MSRs. Some also available on other CPUs */
+
+#define MSR_PPIN_CTL                   0x0000004e
+#define MSR_PPIN                       0x0000004f
+
+#define MSR_IA32_PERFCTR0              0x000000c1
+#define MSR_IA32_PERFCTR1              0x000000c2
+#define MSR_FSB_FREQ                   0x000000cd
+#define MSR_PLATFORM_INFO              0x000000ce
+#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT      31
+#define MSR_PLATFORM_INFO_CPUID_FAULT          BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT)
+
+#define MSR_PKG_CST_CONFIG_CONTROL     0x000000e2
+#define NHM_C3_AUTO_DEMOTE             (1UL << 25)
+#define NHM_C1_AUTO_DEMOTE             (1UL << 26)
+#define ATM_LNC_C6_AUTO_DEMOTE         (1UL << 25)
+#define SNB_C1_AUTO_UNDEMOTE           (1UL << 27)
+#define SNB_C3_AUTO_UNDEMOTE           (1UL << 28)
+
+#define MSR_MTRRcap                    0x000000fe
+#define MSR_IA32_BBL_CR_CTL            0x00000119
+#define MSR_IA32_BBL_CR_CTL3           0x0000011e
+
+#define MSR_IA32_SYSENTER_CS           0x00000174
+#define MSR_IA32_SYSENTER_ESP          0x00000175
+#define MSR_IA32_SYSENTER_EIP          0x00000176
+
+#define MSR_IA32_MCG_CAP               0x00000179
+#define MSR_IA32_MCG_STATUS            0x0000017a
+#define MSR_IA32_MCG_CTL               0x0000017b
+#define MSR_IA32_MCG_EXT_CTL           0x000004d0
+
+#define MSR_OFFCORE_RSP_0              0x000001a6
+#define MSR_OFFCORE_RSP_1              0x000001a7
+#define MSR_TURBO_RATIO_LIMIT          0x000001ad
+#define MSR_TURBO_RATIO_LIMIT1         0x000001ae
+#define MSR_TURBO_RATIO_LIMIT2         0x000001af
+
+#define MSR_LBR_SELECT                 0x000001c8
+#define MSR_LBR_TOS                    0x000001c9
+#define MSR_LBR_NHM_FROM               0x00000680
+#define MSR_LBR_NHM_TO                 0x000006c0
+#define MSR_LBR_CORE_FROM              0x00000040
+#define MSR_LBR_CORE_TO                        0x00000060
+
+#define MSR_LBR_INFO_0                 0x00000dc0 /* ... 0xddf for _31 */
+#define LBR_INFO_MISPRED               BIT_ULL(63)
+#define LBR_INFO_IN_TX                 BIT_ULL(62)
+#define LBR_INFO_ABORT                 BIT_ULL(61)
+#define LBR_INFO_CYCLES                        0xffff
+
+#define MSR_IA32_PEBS_ENABLE           0x000003f1
+#define MSR_IA32_DS_AREA               0x00000600
+#define MSR_IA32_PERF_CAPABILITIES     0x00000345
+#define MSR_PEBS_LD_LAT_THRESHOLD      0x000003f6
+
+#define MSR_IA32_RTIT_CTL              0x00000570
+#define MSR_IA32_RTIT_STATUS           0x00000571
+#define MSR_IA32_RTIT_ADDR0_A          0x00000580
+#define MSR_IA32_RTIT_ADDR0_B          0x00000581
+#define MSR_IA32_RTIT_ADDR1_A          0x00000582
+#define MSR_IA32_RTIT_ADDR1_B          0x00000583
+#define MSR_IA32_RTIT_ADDR2_A          0x00000584
+#define MSR_IA32_RTIT_ADDR2_B          0x00000585
+#define MSR_IA32_RTIT_ADDR3_A          0x00000586
+#define MSR_IA32_RTIT_ADDR3_B          0x00000587
+#define MSR_IA32_RTIT_CR3_MATCH                0x00000572
+#define MSR_IA32_RTIT_OUTPUT_BASE      0x00000560
+#define MSR_IA32_RTIT_OUTPUT_MASK      0x00000561
+
+#define MSR_MTRRfix64K_00000           0x00000250
+#define MSR_MTRRfix16K_80000           0x00000258
+#define MSR_MTRRfix16K_A0000           0x00000259
+#define MSR_MTRRfix4K_C0000            0x00000268
+#define MSR_MTRRfix4K_C8000            0x00000269
+#define MSR_MTRRfix4K_D0000            0x0000026a
+#define MSR_MTRRfix4K_D8000            0x0000026b
+#define MSR_MTRRfix4K_E0000            0x0000026c
+#define MSR_MTRRfix4K_E8000            0x0000026d
+#define MSR_MTRRfix4K_F0000            0x0000026e
+#define MSR_MTRRfix4K_F8000            0x0000026f
+#define MSR_MTRRdefType                        0x000002ff
+
+#define MSR_IA32_CR_PAT                        0x00000277
+
+#define MSR_IA32_DEBUGCTLMSR           0x000001d9
+#define MSR_IA32_LASTBRANCHFROMIP      0x000001db
+#define MSR_IA32_LASTBRANCHTOIP                0x000001dc
+#define MSR_IA32_LASTINTFROMIP         0x000001dd
+#define MSR_IA32_LASTINTTOIP           0x000001de
+
+/* DEBUGCTLMSR bits (others vary by model): */
+#define DEBUGCTLMSR_LBR                        (1UL <<  0) /* last branch recording */
+#define DEBUGCTLMSR_BTF_SHIFT          1
+#define DEBUGCTLMSR_BTF                        (1UL <<  1) /* single-step on branches */
+#define DEBUGCTLMSR_TR                 (1UL <<  6)
+#define DEBUGCTLMSR_BTS                        (1UL <<  7)
+#define DEBUGCTLMSR_BTINT              (1UL <<  8)
+#define DEBUGCTLMSR_BTS_OFF_OS         (1UL <<  9)
+#define DEBUGCTLMSR_BTS_OFF_USR                (1UL << 10)
+#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
+#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT  14
+#define DEBUGCTLMSR_FREEZE_IN_SMM      (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT)
+
+#define MSR_PEBS_FRONTEND              0x000003f7
+
+#define MSR_IA32_POWER_CTL             0x000001fc
+
+#define MSR_IA32_MC0_CTL               0x00000400
+#define MSR_IA32_MC0_STATUS            0x00000401
+#define MSR_IA32_MC0_ADDR              0x00000402
+#define MSR_IA32_MC0_MISC              0x00000403
+
+/* C-state Residency Counters */
+#define MSR_PKG_C3_RESIDENCY           0x000003f8
+#define MSR_PKG_C6_RESIDENCY           0x000003f9
+#define MSR_ATOM_PKG_C6_RESIDENCY      0x000003fa
+#define MSR_PKG_C7_RESIDENCY           0x000003fa
+#define MSR_CORE_C3_RESIDENCY          0x000003fc
+#define MSR_CORE_C6_RESIDENCY          0x000003fd
+#define MSR_CORE_C7_RESIDENCY          0x000003fe
+#define MSR_KNL_CORE_C6_RESIDENCY      0x000003ff
+#define MSR_PKG_C2_RESIDENCY           0x0000060d
+#define MSR_PKG_C8_RESIDENCY           0x00000630
+#define MSR_PKG_C9_RESIDENCY           0x00000631
+#define MSR_PKG_C10_RESIDENCY          0x00000632
+
+/* Interrupt Response Limit */
+#define MSR_PKGC3_IRTL                 0x0000060a
+#define MSR_PKGC6_IRTL                 0x0000060b
+#define MSR_PKGC7_IRTL                 0x0000060c
+#define MSR_PKGC8_IRTL                 0x00000633
+#define MSR_PKGC9_IRTL                 0x00000634
+#define MSR_PKGC10_IRTL                        0x00000635
+
+/* Run Time Average Power Limiting (RAPL) Interface */
+
+#define MSR_RAPL_POWER_UNIT            0x00000606
+
+#define MSR_PKG_POWER_LIMIT            0x00000610
+#define MSR_PKG_ENERGY_STATUS          0x00000611
+#define MSR_PKG_PERF_STATUS            0x00000613
+#define MSR_PKG_POWER_INFO             0x00000614
+
+#define MSR_DRAM_POWER_LIMIT           0x00000618
+#define MSR_DRAM_ENERGY_STATUS         0x00000619
+#define MSR_DRAM_PERF_STATUS           0x0000061b
+#define MSR_DRAM_POWER_INFO            0x0000061c
+
+#define MSR_PP0_POWER_LIMIT            0x00000638
+#define MSR_PP0_ENERGY_STATUS          0x00000639
+#define MSR_PP0_POLICY                 0x0000063a
+#define MSR_PP0_PERF_STATUS            0x0000063b
+
+#define MSR_PP1_POWER_LIMIT            0x00000640
+#define MSR_PP1_ENERGY_STATUS          0x00000641
+#define MSR_PP1_POLICY                 0x00000642
+
+/* Config TDP MSRs */
+#define MSR_CONFIG_TDP_NOMINAL         0x00000648
+#define MSR_CONFIG_TDP_LEVEL_1         0x00000649
+#define MSR_CONFIG_TDP_LEVEL_2         0x0000064A
+#define MSR_CONFIG_TDP_CONTROL         0x0000064B
+#define MSR_TURBO_ACTIVATION_RATIO     0x0000064C
+
+#define MSR_PLATFORM_ENERGY_STATUS     0x0000064D
+
+#define MSR_PKG_WEIGHTED_CORE_C0_RES   0x00000658
+#define MSR_PKG_ANY_CORE_C0_RES                0x00000659
+#define MSR_PKG_ANY_GFXE_C0_RES                0x0000065A
+#define MSR_PKG_BOTH_CORE_GFXE_C0_RES  0x0000065B
+
+#define MSR_CORE_C1_RES                        0x00000660
+#define MSR_MODULE_C6_RES_MS           0x00000664
+
+#define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668
+#define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669
+
+#define MSR_ATOM_CORE_RATIOS           0x0000066a
+#define MSR_ATOM_CORE_VIDS             0x0000066b
+#define MSR_ATOM_CORE_TURBO_RATIOS     0x0000066c
+#define MSR_ATOM_CORE_TURBO_VIDS       0x0000066d
+
+
+#define MSR_CORE_PERF_LIMIT_REASONS    0x00000690
+#define MSR_GFX_PERF_LIMIT_REASONS     0x000006B0
+#define MSR_RING_PERF_LIMIT_REASONS    0x000006B1
+
+/* Hardware P state interface */
+#define MSR_PPERF                      0x0000064e
+#define MSR_PERF_LIMIT_REASONS         0x0000064f
+#define MSR_PM_ENABLE                  0x00000770
+#define MSR_HWP_CAPABILITIES           0x00000771
+#define MSR_HWP_REQUEST_PKG            0x00000772
+#define MSR_HWP_INTERRUPT              0x00000773
+#define MSR_HWP_REQUEST                        0x00000774
+#define MSR_HWP_STATUS                 0x00000777
+
+/* CPUID.6.EAX */
+#define HWP_BASE_BIT                   (1<<7)
+#define HWP_NOTIFICATIONS_BIT          (1<<8)
+#define HWP_ACTIVITY_WINDOW_BIT                (1<<9)
+#define HWP_ENERGY_PERF_PREFERENCE_BIT (1<<10)
+#define HWP_PACKAGE_LEVEL_REQUEST_BIT  (1<<11)
+
+/* IA32_HWP_CAPABILITIES */
+#define HWP_HIGHEST_PERF(x)            (((x) >> 0) & 0xff)
+#define HWP_GUARANTEED_PERF(x)         (((x) >> 8) & 0xff)
+#define HWP_MOSTEFFICIENT_PERF(x)      (((x) >> 16) & 0xff)
+#define HWP_LOWEST_PERF(x)             (((x) >> 24) & 0xff)
+
+/* IA32_HWP_REQUEST */
+#define HWP_MIN_PERF(x)                        (x & 0xff)
+#define HWP_MAX_PERF(x)                        ((x & 0xff) << 8)
+#define HWP_DESIRED_PERF(x)            ((x & 0xff) << 16)
+#define HWP_ENERGY_PERF_PREFERENCE(x)  (((unsigned long long) x & 0xff) << 24)
+#define HWP_EPP_PERFORMANCE            0x00
+#define HWP_EPP_BALANCE_PERFORMANCE    0x80
+#define HWP_EPP_BALANCE_POWERSAVE      0xC0
+#define HWP_EPP_POWERSAVE              0xFF
+#define HWP_ACTIVITY_WINDOW(x)         ((unsigned long long)(x & 0xff3) << 32)
+#define HWP_PACKAGE_CONTROL(x)         ((unsigned long long)(x & 0x1) << 42)
+
+/* IA32_HWP_STATUS */
+#define HWP_GUARANTEED_CHANGE(x)       (x & 0x1)
+#define HWP_EXCURSION_TO_MINIMUM(x)    (x & 0x4)
+
+/* IA32_HWP_INTERRUPT */
+#define HWP_CHANGE_TO_GUARANTEED_INT(x)        (x & 0x1)
+#define HWP_EXCURSION_TO_MINIMUM_INT(x)        (x & 0x2)
+
+#define MSR_AMD64_MC0_MASK             0xc0010044
+
+#define MSR_IA32_MCx_CTL(x)            (MSR_IA32_MC0_CTL + 4*(x))
+#define MSR_IA32_MCx_STATUS(x)         (MSR_IA32_MC0_STATUS + 4*(x))
+#define MSR_IA32_MCx_ADDR(x)           (MSR_IA32_MC0_ADDR + 4*(x))
+#define MSR_IA32_MCx_MISC(x)           (MSR_IA32_MC0_MISC + 4*(x))
+
+#define MSR_AMD64_MCx_MASK(x)          (MSR_AMD64_MC0_MASK + (x))
+
+/* These are consecutive and not in the normal 4er MCE bank block */
+#define MSR_IA32_MC0_CTL2              0x00000280
+#define MSR_IA32_MCx_CTL2(x)           (MSR_IA32_MC0_CTL2 + (x))
+
+#define MSR_P6_PERFCTR0                        0x000000c1
+#define MSR_P6_PERFCTR1                        0x000000c2
+#define MSR_P6_EVNTSEL0                        0x00000186
+#define MSR_P6_EVNTSEL1                        0x00000187
+
+#define MSR_KNC_PERFCTR0               0x00000020
+#define MSR_KNC_PERFCTR1               0x00000021
+#define MSR_KNC_EVNTSEL0               0x00000028
+#define MSR_KNC_EVNTSEL1               0x00000029
+
+/* Alternative perfctr range with full access. */
+#define MSR_IA32_PMC0                  0x000004c1
+
+/* AMD64 MSRs. Not complete. See the architecture manual for a more
+   complete list. */
+
+#define MSR_AMD64_PATCH_LEVEL          0x0000008b
+#define MSR_AMD64_TSC_RATIO            0xc0000104
+#define MSR_AMD64_NB_CFG               0xc001001f
+#define MSR_AMD64_PATCH_LOADER         0xc0010020
+#define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
+#define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD64_LS_CFG               0xc0011020
+#define MSR_AMD64_DC_CFG               0xc0011022
+#define MSR_AMD64_BU_CFG2              0xc001102a
+#define MSR_AMD64_IBSFETCHCTL          0xc0011030
+#define MSR_AMD64_IBSFETCHLINAD                0xc0011031
+#define MSR_AMD64_IBSFETCHPHYSAD       0xc0011032
+#define MSR_AMD64_IBSFETCH_REG_COUNT   3
+#define MSR_AMD64_IBSFETCH_REG_MASK    ((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
+#define MSR_AMD64_IBSOPCTL             0xc0011033
+#define MSR_AMD64_IBSOPRIP             0xc0011034
+#define MSR_AMD64_IBSOPDATA            0xc0011035
+#define MSR_AMD64_IBSOPDATA2           0xc0011036
+#define MSR_AMD64_IBSOPDATA3           0xc0011037
+#define MSR_AMD64_IBSDCLINAD           0xc0011038
+#define MSR_AMD64_IBSDCPHYSAD          0xc0011039
+#define MSR_AMD64_IBSOP_REG_COUNT      7
+#define MSR_AMD64_IBSOP_REG_MASK       ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
+#define MSR_AMD64_IBSCTL               0xc001103a
+#define MSR_AMD64_IBSBRTARGET          0xc001103b
+#define MSR_AMD64_IBSOPDATA4           0xc001103d
+#define MSR_AMD64_IBS_REG_COUNT_MAX    8 /* includes MSR_AMD64_IBSBRTARGET */
+#define MSR_AMD64_SEV                  0xc0010131
+#define MSR_AMD64_SEV_ENABLED_BIT      0
+#define MSR_AMD64_SEV_ENABLED          BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
+
+/* Fam 17h MSRs */
+#define MSR_F17H_IRPERF                        0xc00000e9
+
+/* Fam 16h MSRs */
+#define MSR_F16H_L2I_PERF_CTL          0xc0010230
+#define MSR_F16H_L2I_PERF_CTR          0xc0010231
+#define MSR_F16H_DR1_ADDR_MASK         0xc0011019
+#define MSR_F16H_DR2_ADDR_MASK         0xc001101a
+#define MSR_F16H_DR3_ADDR_MASK         0xc001101b
+#define MSR_F16H_DR0_ADDR_MASK         0xc0011027
+
+/* Fam 15h MSRs */
+#define MSR_F15H_PERF_CTL              0xc0010200
+#define MSR_F15H_PERF_CTR              0xc0010201
+#define MSR_F15H_NB_PERF_CTL           0xc0010240
+#define MSR_F15H_NB_PERF_CTR           0xc0010241
+#define MSR_F15H_PTSC                  0xc0010280
+#define MSR_F15H_IC_CFG                        0xc0011021
+
+/* Fam 10h MSRs */
+#define MSR_FAM10H_MMIO_CONF_BASE      0xc0010058
+#define FAM10H_MMIO_CONF_ENABLE                (1<<0)
+#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
+#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
+#define FAM10H_MMIO_CONF_BASE_MASK     0xfffffffULL
+#define FAM10H_MMIO_CONF_BASE_SHIFT    20
+#define MSR_FAM10H_NODE_ID             0xc001100c
+#define MSR_F10H_DECFG                 0xc0011029
+#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT    1
+#define MSR_F10H_DECFG_LFENCE_SERIALIZE                BIT_ULL(MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT)
+
+/* K8 MSRs */
+#define MSR_K8_TOP_MEM1                        0xc001001a
+#define MSR_K8_TOP_MEM2                        0xc001001d
+#define MSR_K8_SYSCFG                  0xc0010010
+#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT  23
+#define MSR_K8_SYSCFG_MEM_ENCRYPT      BIT_ULL(MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
+#define MSR_K8_INT_PENDING_MSG         0xc0010055
+/* C1E active bits in int pending message */
+#define K8_INTP_C1E_ACTIVE_MASK                0x18000000
+#define MSR_K8_TSEG_ADDR               0xc0010112
+#define MSR_K8_TSEG_MASK               0xc0010113
+#define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
+#define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
+#define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
+
+/* K7 MSRs */
+#define MSR_K7_EVNTSEL0                        0xc0010000
+#define MSR_K7_PERFCTR0                        0xc0010004
+#define MSR_K7_EVNTSEL1                        0xc0010001
+#define MSR_K7_PERFCTR1                        0xc0010005
+#define MSR_K7_EVNTSEL2                        0xc0010002
+#define MSR_K7_PERFCTR2                        0xc0010006
+#define MSR_K7_EVNTSEL3                        0xc0010003
+#define MSR_K7_PERFCTR3                        0xc0010007
+#define MSR_K7_CLK_CTL                 0xc001001b
+#define MSR_K7_HWCR                    0xc0010015
+#define MSR_K7_HWCR_SMMLOCK_BIT                0
+#define MSR_K7_HWCR_SMMLOCK            BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
+#define MSR_K7_FID_VID_CTL             0xc0010041
+#define MSR_K7_FID_VID_STATUS          0xc0010042
+
+/* K6 MSRs */
+#define MSR_K6_WHCR                    0xc0000082
+#define MSR_K6_UWCCR                   0xc0000085
+#define MSR_K6_EPMR                    0xc0000086
+#define MSR_K6_PSOR                    0xc0000087
+#define MSR_K6_PFIR                    0xc0000088
+
+/* Centaur-Hauls/IDT defined MSRs. */
+#define MSR_IDT_FCR1                   0x00000107
+#define MSR_IDT_FCR2                   0x00000108
+#define MSR_IDT_FCR3                   0x00000109
+#define MSR_IDT_FCR4                   0x0000010a
+
+#define MSR_IDT_MCR0                   0x00000110
+#define MSR_IDT_MCR1                   0x00000111
+#define MSR_IDT_MCR2                   0x00000112
+#define MSR_IDT_MCR3                   0x00000113
+#define MSR_IDT_MCR4                   0x00000114
+#define MSR_IDT_MCR5                   0x00000115
+#define MSR_IDT_MCR6                   0x00000116
+#define MSR_IDT_MCR7                   0x00000117
+#define MSR_IDT_MCR_CTRL               0x00000120
+
+/* VIA Cyrix defined MSRs*/
+#define MSR_VIA_FCR                    0x00001107
+#define MSR_VIA_LONGHAUL               0x0000110a
+#define MSR_VIA_RNG                    0x0000110b
+#define MSR_VIA_BCR2                   0x00001147
+
+/* Transmeta defined MSRs */
+#define MSR_TMTA_LONGRUN_CTRL          0x80868010
+#define MSR_TMTA_LONGRUN_FLAGS         0x80868011
+#define MSR_TMTA_LRTI_READOUT          0x80868018
+#define MSR_TMTA_LRTI_VOLT_MHZ         0x8086801a
+
+/* Intel defined MSRs. */
+#define MSR_IA32_P5_MC_ADDR            0x00000000
+#define MSR_IA32_P5_MC_TYPE            0x00000001
+#define MSR_IA32_TSC                   0x00000010
+#define MSR_IA32_PLATFORM_ID           0x00000017
+#define MSR_IA32_EBL_CR_POWERON                0x0000002a
+#define MSR_EBC_FREQUENCY_ID           0x0000002c
+#define MSR_SMI_COUNT                  0x00000034
+#define MSR_IA32_FEATURE_CONTROL        0x0000003a
+#define MSR_IA32_TSC_ADJUST             0x0000003b
+#define MSR_IA32_BNDCFGS               0x00000d90
+
+#define MSR_IA32_BNDCFGS_RSVD          0x00000ffc
+
+#define MSR_IA32_XSS                   0x00000da0
+
+#define FEATURE_CONTROL_LOCKED                         (1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX       (1<<1)
+#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX      (1<<2)
+#define FEATURE_CONTROL_LMCE                           (1<<20)
+
+#define MSR_IA32_APICBASE              0x0000001b
+#define MSR_IA32_APICBASE_BSP          (1<<8)
+#define MSR_IA32_APICBASE_ENABLE       (1<<11)
+#define MSR_IA32_APICBASE_BASE         (0xfffff<<12)
+
+#define MSR_IA32_TSCDEADLINE           0x000006e0
+
+#define MSR_IA32_UCODE_WRITE           0x00000079
+#define MSR_IA32_UCODE_REV             0x0000008b
+
+#define MSR_IA32_SMM_MONITOR_CTL       0x0000009b
+#define MSR_IA32_SMBASE                        0x0000009e
+
+#define MSR_IA32_PERF_STATUS           0x00000198
+#define MSR_IA32_PERF_CTL              0x00000199
+#define INTEL_PERF_CTL_MASK            0xffff
+#define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
+#define MSR_AMD_PERF_STATUS            0xc0010063
+#define MSR_AMD_PERF_CTL               0xc0010062
+
+#define MSR_IA32_MPERF                 0x000000e7
+#define MSR_IA32_APERF                 0x000000e8
+
+#define MSR_IA32_THERM_CONTROL         0x0000019a
+#define MSR_IA32_THERM_INTERRUPT       0x0000019b
+
+#define THERM_INT_HIGH_ENABLE          (1 << 0)
+#define THERM_INT_LOW_ENABLE           (1 << 1)
+#define THERM_INT_PLN_ENABLE           (1 << 24)
+
+#define MSR_IA32_THERM_STATUS          0x0000019c
+
+#define THERM_STATUS_PROCHOT           (1 << 0)
+#define THERM_STATUS_POWER_LIMIT       (1 << 10)
+
+#define MSR_THERM2_CTL                 0x0000019d
+
+#define MSR_THERM2_CTL_TM_SELECT       (1ULL << 16)
+
+#define MSR_IA32_MISC_ENABLE           0x000001a0
+
+#define MSR_IA32_TEMPERATURE_TARGET    0x000001a2
+
+#define MSR_MISC_FEATURE_CONTROL       0x000001a4
+#define MSR_MISC_PWR_MGMT              0x000001aa
+
+#define MSR_IA32_ENERGY_PERF_BIAS      0x000001b0
+#define ENERGY_PERF_BIAS_PERFORMANCE           0
+#define ENERGY_PERF_BIAS_BALANCE_PERFORMANCE   4
+#define ENERGY_PERF_BIAS_NORMAL                        6
+#define ENERGY_PERF_BIAS_BALANCE_POWERSAVE     8
+#define ENERGY_PERF_BIAS_POWERSAVE             15
+
+#define MSR_IA32_PACKAGE_THERM_STATUS          0x000001b1
+
+#define PACKAGE_THERM_STATUS_PROCHOT           (1 << 0)
+#define PACKAGE_THERM_STATUS_POWER_LIMIT       (1 << 10)
+
+#define MSR_IA32_PACKAGE_THERM_INTERRUPT       0x000001b2
+
+#define PACKAGE_THERM_INT_HIGH_ENABLE          (1 << 0)
+#define PACKAGE_THERM_INT_LOW_ENABLE           (1 << 1)
+#define PACKAGE_THERM_INT_PLN_ENABLE           (1 << 24)
+
+/* Thermal Thresholds Support */
+#define THERM_INT_THRESHOLD0_ENABLE    (1 << 15)
+#define THERM_SHIFT_THRESHOLD0        8
+#define THERM_MASK_THRESHOLD0          (0x7f << THERM_SHIFT_THRESHOLD0)
+#define THERM_INT_THRESHOLD1_ENABLE    (1 << 23)
+#define THERM_SHIFT_THRESHOLD1        16
+#define THERM_MASK_THRESHOLD1          (0x7f << THERM_SHIFT_THRESHOLD1)
+#define THERM_STATUS_THRESHOLD0        (1 << 6)
+#define THERM_LOG_THRESHOLD0           (1 << 7)
+#define THERM_STATUS_THRESHOLD1        (1 << 8)
+#define THERM_LOG_THRESHOLD1           (1 << 9)
+
+/* MISC_ENABLE bits: architectural */
+#define MSR_IA32_MISC_ENABLE_FAST_STRING_BIT           0
+#define MSR_IA32_MISC_ENABLE_FAST_STRING               (1ULL << MSR_IA32_MISC_ENABLE_FAST_STRING_BIT)
+#define MSR_IA32_MISC_ENABLE_TCC_BIT                   1
+#define MSR_IA32_MISC_ENABLE_TCC                       (1ULL << MSR_IA32_MISC_ENABLE_TCC_BIT)
+#define MSR_IA32_MISC_ENABLE_EMON_BIT                  7
+#define MSR_IA32_MISC_ENABLE_EMON                      (1ULL << MSR_IA32_MISC_ENABLE_EMON_BIT)
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT           11
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL               (1ULL << MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT)
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT          12
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL              (1ULL << MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT)
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT    16
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP                (1ULL << MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT)
+#define MSR_IA32_MISC_ENABLE_MWAIT_BIT                 18
+#define MSR_IA32_MISC_ENABLE_MWAIT                     (1ULL << MSR_IA32_MISC_ENABLE_MWAIT_BIT)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT           22
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID               (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT)
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT          23
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE              (1ULL << MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT            34
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE                        (1ULL << MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT)
+
+/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT            2
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT                        (1ULL << MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT)
+#define MSR_IA32_MISC_ENABLE_TM1_BIT                   3
+#define MSR_IA32_MISC_ENABLE_TM1                       (1ULL << MSR_IA32_MISC_ENABLE_TM1_BIT)
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT    4
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE                (1ULL << MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT       6
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT         8
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK             (1ULL << MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT)
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT      9
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_FERR_BIT                  10
+#define MSR_IA32_MISC_ENABLE_FERR                      (1ULL << MSR_IA32_MISC_ENABLE_FERR_BIT)
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT                10
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX            (1ULL << MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT)
+#define MSR_IA32_MISC_ENABLE_TM2_BIT                   13
+#define MSR_IA32_MISC_ENABLE_TM2                       (1ULL << MSR_IA32_MISC_ENABLE_TM2_BIT)
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT      19
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT                20
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK            (1ULL << MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT)
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT           24
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT               (1ULL << MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT)
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT      37
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT         38
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE             (1ULL << MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT       39
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT)
+
+/* MISC_FEATURES_ENABLES non-architectural features */
+#define MSR_MISC_FEATURES_ENABLES      0x00000140
+
+#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT      0
+#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT          BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT)
+#define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT       1
+
+#define MSR_IA32_TSC_DEADLINE          0x000006E0
+
+/* P4/Xeon+ specific */
+#define MSR_IA32_MCG_EAX               0x00000180
+#define MSR_IA32_MCG_EBX               0x00000181
+#define MSR_IA32_MCG_ECX               0x00000182
+#define MSR_IA32_MCG_EDX               0x00000183
+#define MSR_IA32_MCG_ESI               0x00000184
+#define MSR_IA32_MCG_EDI               0x00000185
+#define MSR_IA32_MCG_EBP               0x00000186
+#define MSR_IA32_MCG_ESP               0x00000187
+#define MSR_IA32_MCG_EFLAGS            0x00000188
+#define MSR_IA32_MCG_EIP               0x00000189
+#define MSR_IA32_MCG_RESERVED          0x0000018a
+
+/* Pentium IV performance counter MSRs */
+#define MSR_P4_BPU_PERFCTR0            0x00000300
+#define MSR_P4_BPU_PERFCTR1            0x00000301
+#define MSR_P4_BPU_PERFCTR2            0x00000302
+#define MSR_P4_BPU_PERFCTR3            0x00000303
+#define MSR_P4_MS_PERFCTR0             0x00000304
+#define MSR_P4_MS_PERFCTR1             0x00000305
+#define MSR_P4_MS_PERFCTR2             0x00000306
+#define MSR_P4_MS_PERFCTR3             0x00000307
+#define MSR_P4_FLAME_PERFCTR0          0x00000308
+#define MSR_P4_FLAME_PERFCTR1          0x00000309
+#define MSR_P4_FLAME_PERFCTR2          0x0000030a
+#define MSR_P4_FLAME_PERFCTR3          0x0000030b
+#define MSR_P4_IQ_PERFCTR0             0x0000030c
+#define MSR_P4_IQ_PERFCTR1             0x0000030d
+#define MSR_P4_IQ_PERFCTR2             0x0000030e
+#define MSR_P4_IQ_PERFCTR3             0x0000030f
+#define MSR_P4_IQ_PERFCTR4             0x00000310
+#define MSR_P4_IQ_PERFCTR5             0x00000311
+#define MSR_P4_BPU_CCCR0               0x00000360
+#define MSR_P4_BPU_CCCR1               0x00000361
+#define MSR_P4_BPU_CCCR2               0x00000362
+#define MSR_P4_BPU_CCCR3               0x00000363
+#define MSR_P4_MS_CCCR0                        0x00000364
+#define MSR_P4_MS_CCCR1                        0x00000365
+#define MSR_P4_MS_CCCR2                        0x00000366
+#define MSR_P4_MS_CCCR3                        0x00000367
+#define MSR_P4_FLAME_CCCR0             0x00000368
+#define MSR_P4_FLAME_CCCR1             0x00000369
+#define MSR_P4_FLAME_CCCR2             0x0000036a
+#define MSR_P4_FLAME_CCCR3             0x0000036b
+#define MSR_P4_IQ_CCCR0                        0x0000036c
+#define MSR_P4_IQ_CCCR1                        0x0000036d
+#define MSR_P4_IQ_CCCR2                        0x0000036e
+#define MSR_P4_IQ_CCCR3                        0x0000036f
+#define MSR_P4_IQ_CCCR4                        0x00000370
+#define MSR_P4_IQ_CCCR5                        0x00000371
+#define MSR_P4_ALF_ESCR0               0x000003ca
+#define MSR_P4_ALF_ESCR1               0x000003cb
+#define MSR_P4_BPU_ESCR0               0x000003b2
+#define MSR_P4_BPU_ESCR1               0x000003b3
+#define MSR_P4_BSU_ESCR0               0x000003a0
+#define MSR_P4_BSU_ESCR1               0x000003a1
+#define MSR_P4_CRU_ESCR0               0x000003b8
+#define MSR_P4_CRU_ESCR1               0x000003b9
+#define MSR_P4_CRU_ESCR2               0x000003cc
+#define MSR_P4_CRU_ESCR3               0x000003cd
+#define MSR_P4_CRU_ESCR4               0x000003e0
+#define MSR_P4_CRU_ESCR5               0x000003e1
+#define MSR_P4_DAC_ESCR0               0x000003a8
+#define MSR_P4_DAC_ESCR1               0x000003a9
+#define MSR_P4_FIRM_ESCR0              0x000003a4
+#define MSR_P4_FIRM_ESCR1              0x000003a5
+#define MSR_P4_FLAME_ESCR0             0x000003a6
+#define MSR_P4_FLAME_ESCR1             0x000003a7
+#define MSR_P4_FSB_ESCR0               0x000003a2
+#define MSR_P4_FSB_ESCR1               0x000003a3
+#define MSR_P4_IQ_ESCR0                        0x000003ba
+#define MSR_P4_IQ_ESCR1                        0x000003bb
+#define MSR_P4_IS_ESCR0                        0x000003b4
+#define MSR_P4_IS_ESCR1                        0x000003b5
+#define MSR_P4_ITLB_ESCR0              0x000003b6
+#define MSR_P4_ITLB_ESCR1              0x000003b7
+#define MSR_P4_IX_ESCR0                        0x000003c8
+#define MSR_P4_IX_ESCR1                        0x000003c9
+#define MSR_P4_MOB_ESCR0               0x000003aa
+#define MSR_P4_MOB_ESCR1               0x000003ab
+#define MSR_P4_MS_ESCR0                        0x000003c0
+#define MSR_P4_MS_ESCR1                        0x000003c1
+#define MSR_P4_PMH_ESCR0               0x000003ac
+#define MSR_P4_PMH_ESCR1               0x000003ad
+#define MSR_P4_RAT_ESCR0               0x000003bc
+#define MSR_P4_RAT_ESCR1               0x000003bd
+#define MSR_P4_SAAT_ESCR0              0x000003ae
+#define MSR_P4_SAAT_ESCR1              0x000003af
+#define MSR_P4_SSU_ESCR0               0x000003be
+#define MSR_P4_SSU_ESCR1               0x000003bf /* guess: not in manual */
+
+#define MSR_P4_TBPU_ESCR0              0x000003c2
+#define MSR_P4_TBPU_ESCR1              0x000003c3
+#define MSR_P4_TC_ESCR0                        0x000003c4
+#define MSR_P4_TC_ESCR1                        0x000003c5
+#define MSR_P4_U2L_ESCR0               0x000003b0
+#define MSR_P4_U2L_ESCR1               0x000003b1
+
+#define MSR_P4_PEBS_MATRIX_VERT                0x000003f2
+
+/* Intel Core-based CPU performance counters */
+#define MSR_CORE_PERF_FIXED_CTR0       0x00000309
+#define MSR_CORE_PERF_FIXED_CTR1       0x0000030a
+#define MSR_CORE_PERF_FIXED_CTR2       0x0000030b
+#define MSR_CORE_PERF_FIXED_CTR_CTRL   0x0000038d
+#define MSR_CORE_PERF_GLOBAL_STATUS    0x0000038e
+#define MSR_CORE_PERF_GLOBAL_CTRL      0x0000038f
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL  0x00000390
+
+/* Geode defined MSRs */
+#define MSR_GEODE_BUSCONT_CONF0                0x00001900
+
+/* Intel VT MSRs */
+#define MSR_IA32_VMX_BASIC              0x00000480
+#define MSR_IA32_VMX_PINBASED_CTLS      0x00000481
+#define MSR_IA32_VMX_PROCBASED_CTLS     0x00000482
+#define MSR_IA32_VMX_EXIT_CTLS          0x00000483
+#define MSR_IA32_VMX_ENTRY_CTLS         0x00000484
+#define MSR_IA32_VMX_MISC               0x00000485
+#define MSR_IA32_VMX_CR0_FIXED0         0x00000486
+#define MSR_IA32_VMX_CR0_FIXED1         0x00000487
+#define MSR_IA32_VMX_CR4_FIXED0         0x00000488
+#define MSR_IA32_VMX_CR4_FIXED1         0x00000489
+#define MSR_IA32_VMX_VMCS_ENUM          0x0000048a
+#define MSR_IA32_VMX_PROCBASED_CTLS2    0x0000048b
+#define MSR_IA32_VMX_EPT_VPID_CAP       0x0000048c
+#define MSR_IA32_VMX_TRUE_PINBASED_CTLS  0x0000048d
+#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e
+#define MSR_IA32_VMX_TRUE_EXIT_CTLS      0x0000048f
+#define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
+#define MSR_IA32_VMX_VMFUNC             0x00000491
+
+/* VMX_BASIC bits and bitmasks */
+#define VMX_BASIC_VMCS_SIZE_SHIFT      32
+#define VMX_BASIC_TRUE_CTLS            (1ULL << 55)
+#define VMX_BASIC_64           0x0001000000000000LLU
+#define VMX_BASIC_MEM_TYPE_SHIFT       50
+#define VMX_BASIC_MEM_TYPE_MASK        0x003c000000000000LLU
+#define VMX_BASIC_MEM_TYPE_WB  6LLU
+#define VMX_BASIC_INOUT                0x0040000000000000LLU
+
+/* MSR_IA32_VMX_MISC bits */
+#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
+#define MSR_IA32_VMX_MISC_PREEMPTION_TIMER_SCALE   0x1F
+/* AMD-V MSRs */
+
+#define MSR_VM_CR                       0xc0010114
+#define MSR_VM_IGNNE                    0xc0010115
+#define MSR_VM_HSAVE_PA                 0xc0010117
+
+#endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/include/x86_64/vmx.h b/tools/testing/selftests/kvm/include/x86_64/vmx.h
new file mode 100644 (file)
index 0000000..12ebd83
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * tools/testing/selftests/kvm/include/x86_64/vmx.h
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ */
+
+#ifndef SELFTEST_KVM_VMX_H
+#define SELFTEST_KVM_VMX_H
+
+#include <stdint.h>
+#include "processor.h"
+
+#define CPUID_VMX_BIT                          5
+
+#define CPUID_VMX                              (1 << 5)
+
+/*
+ * Definitions of Primary Processor-Based VM-Execution Controls.
+ */
+#define CPU_BASED_VIRTUAL_INTR_PENDING         0x00000004
+#define CPU_BASED_USE_TSC_OFFSETING            0x00000008
+#define CPU_BASED_HLT_EXITING                  0x00000080
+#define CPU_BASED_INVLPG_EXITING               0x00000200
+#define CPU_BASED_MWAIT_EXITING                        0x00000400
+#define CPU_BASED_RDPMC_EXITING                        0x00000800
+#define CPU_BASED_RDTSC_EXITING                        0x00001000
+#define CPU_BASED_CR3_LOAD_EXITING             0x00008000
+#define CPU_BASED_CR3_STORE_EXITING            0x00010000
+#define CPU_BASED_CR8_LOAD_EXITING             0x00080000
+#define CPU_BASED_CR8_STORE_EXITING            0x00100000
+#define CPU_BASED_TPR_SHADOW                   0x00200000
+#define CPU_BASED_VIRTUAL_NMI_PENDING          0x00400000
+#define CPU_BASED_MOV_DR_EXITING               0x00800000
+#define CPU_BASED_UNCOND_IO_EXITING            0x01000000
+#define CPU_BASED_USE_IO_BITMAPS               0x02000000
+#define CPU_BASED_MONITOR_TRAP                 0x08000000
+#define CPU_BASED_USE_MSR_BITMAPS              0x10000000
+#define CPU_BASED_MONITOR_EXITING              0x20000000
+#define CPU_BASED_PAUSE_EXITING                        0x40000000
+#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS  0x80000000
+
+#define CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR    0x0401e172
+
+/*
+ * Definitions of Secondary Processor-Based VM-Execution Controls.
+ */
+#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
+#define SECONDARY_EXEC_ENABLE_EPT              0x00000002
+#define SECONDARY_EXEC_DESC                    0x00000004
+#define SECONDARY_EXEC_RDTSCP                  0x00000008
+#define SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE  0x00000010
+#define SECONDARY_EXEC_ENABLE_VPID             0x00000020
+#define SECONDARY_EXEC_WBINVD_EXITING          0x00000040
+#define SECONDARY_EXEC_UNRESTRICTED_GUEST      0x00000080
+#define SECONDARY_EXEC_APIC_REGISTER_VIRT      0x00000100
+#define SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY   0x00000200
+#define SECONDARY_EXEC_PAUSE_LOOP_EXITING      0x00000400
+#define SECONDARY_EXEC_RDRAND_EXITING          0x00000800
+#define SECONDARY_EXEC_ENABLE_INVPCID          0x00001000
+#define SECONDARY_EXEC_ENABLE_VMFUNC           0x00002000
+#define SECONDARY_EXEC_SHADOW_VMCS             0x00004000
+#define SECONDARY_EXEC_RDSEED_EXITING          0x00010000
+#define SECONDARY_EXEC_ENABLE_PML              0x00020000
+#define SECONDARY_EPT_VE                       0x00040000
+#define SECONDARY_ENABLE_XSAV_RESTORE          0x00100000
+#define SECONDARY_EXEC_TSC_SCALING             0x02000000
+
+#define PIN_BASED_EXT_INTR_MASK                        0x00000001
+#define PIN_BASED_NMI_EXITING                  0x00000008
+#define PIN_BASED_VIRTUAL_NMIS                 0x00000020
+#define PIN_BASED_VMX_PREEMPTION_TIMER         0x00000040
+#define PIN_BASED_POSTED_INTR                  0x00000080
+
+#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR    0x00000016
+
+#define VM_EXIT_SAVE_DEBUG_CONTROLS            0x00000004
+#define VM_EXIT_HOST_ADDR_SPACE_SIZE           0x00000200
+#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL     0x00001000
+#define VM_EXIT_ACK_INTR_ON_EXIT               0x00008000
+#define VM_EXIT_SAVE_IA32_PAT                  0x00040000
+#define VM_EXIT_LOAD_IA32_PAT                  0x00080000
+#define VM_EXIT_SAVE_IA32_EFER                 0x00100000
+#define VM_EXIT_LOAD_IA32_EFER                 0x00200000
+#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER      0x00400000
+
+#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR      0x00036dff
+
+#define VM_ENTRY_LOAD_DEBUG_CONTROLS           0x00000004
+#define VM_ENTRY_IA32E_MODE                    0x00000200
+#define VM_ENTRY_SMM                           0x00000400
+#define VM_ENTRY_DEACT_DUAL_MONITOR            0x00000800
+#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL    0x00002000
+#define VM_ENTRY_LOAD_IA32_PAT                 0x00004000
+#define VM_ENTRY_LOAD_IA32_EFER                        0x00008000
+
+#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR     0x000011ff
+
+#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK    0x0000001f
+#define VMX_MISC_SAVE_EFER_LMA                 0x00000020
+
+#define EXIT_REASON_FAILED_VMENTRY     0x80000000
+#define EXIT_REASON_EXCEPTION_NMI      0
+#define EXIT_REASON_EXTERNAL_INTERRUPT 1
+#define EXIT_REASON_TRIPLE_FAULT       2
+#define EXIT_REASON_PENDING_INTERRUPT  7
+#define EXIT_REASON_NMI_WINDOW         8
+#define EXIT_REASON_TASK_SWITCH                9
+#define EXIT_REASON_CPUID              10
+#define EXIT_REASON_HLT                        12
+#define EXIT_REASON_INVD               13
+#define EXIT_REASON_INVLPG             14
+#define EXIT_REASON_RDPMC              15
+#define EXIT_REASON_RDTSC              16
+#define EXIT_REASON_VMCALL             18
+#define EXIT_REASON_VMCLEAR            19
+#define EXIT_REASON_VMLAUNCH           20
+#define EXIT_REASON_VMPTRLD            21
+#define EXIT_REASON_VMPTRST            22
+#define EXIT_REASON_VMREAD             23
+#define EXIT_REASON_VMRESUME           24
+#define EXIT_REASON_VMWRITE            25
+#define EXIT_REASON_VMOFF              26
+#define EXIT_REASON_VMON               27
+#define EXIT_REASON_CR_ACCESS          28
+#define EXIT_REASON_DR_ACCESS          29
+#define EXIT_REASON_IO_INSTRUCTION     30
+#define EXIT_REASON_MSR_READ           31
+#define EXIT_REASON_MSR_WRITE          32
+#define EXIT_REASON_INVALID_STATE      33
+#define EXIT_REASON_MWAIT_INSTRUCTION  36
+#define EXIT_REASON_MONITOR_INSTRUCTION 39
+#define EXIT_REASON_PAUSE_INSTRUCTION  40
+#define EXIT_REASON_MCE_DURING_VMENTRY 41
+#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
+#define EXIT_REASON_APIC_ACCESS                44
+#define EXIT_REASON_EOI_INDUCED                45
+#define EXIT_REASON_EPT_VIOLATION      48
+#define EXIT_REASON_EPT_MISCONFIG      49
+#define EXIT_REASON_INVEPT             50
+#define EXIT_REASON_RDTSCP             51
+#define EXIT_REASON_PREEMPTION_TIMER   52
+#define EXIT_REASON_INVVPID            53
+#define EXIT_REASON_WBINVD             54
+#define EXIT_REASON_XSETBV             55
+#define EXIT_REASON_APIC_WRITE         56
+#define EXIT_REASON_INVPCID            58
+#define EXIT_REASON_PML_FULL           62
+#define EXIT_REASON_XSAVES             63
+#define EXIT_REASON_XRSTORS            64
+#define LAST_EXIT_REASON               64
+
+enum vmcs_field {
+       VIRTUAL_PROCESSOR_ID            = 0x00000000,
+       POSTED_INTR_NV                  = 0x00000002,
+       GUEST_ES_SELECTOR               = 0x00000800,
+       GUEST_CS_SELECTOR               = 0x00000802,
+       GUEST_SS_SELECTOR               = 0x00000804,
+       GUEST_DS_SELECTOR               = 0x00000806,
+       GUEST_FS_SELECTOR               = 0x00000808,
+       GUEST_GS_SELECTOR               = 0x0000080a,
+       GUEST_LDTR_SELECTOR             = 0x0000080c,
+       GUEST_TR_SELECTOR               = 0x0000080e,
+       GUEST_INTR_STATUS               = 0x00000810,
+       GUEST_PML_INDEX                 = 0x00000812,
+       HOST_ES_SELECTOR                = 0x00000c00,
+       HOST_CS_SELECTOR                = 0x00000c02,
+       HOST_SS_SELECTOR                = 0x00000c04,
+       HOST_DS_SELECTOR                = 0x00000c06,
+       HOST_FS_SELECTOR                = 0x00000c08,
+       HOST_GS_SELECTOR                = 0x00000c0a,
+       HOST_TR_SELECTOR                = 0x00000c0c,
+       IO_BITMAP_A                     = 0x00002000,
+       IO_BITMAP_A_HIGH                = 0x00002001,
+       IO_BITMAP_B                     = 0x00002002,
+       IO_BITMAP_B_HIGH                = 0x00002003,
+       MSR_BITMAP                      = 0x00002004,
+       MSR_BITMAP_HIGH                 = 0x00002005,
+       VM_EXIT_MSR_STORE_ADDR          = 0x00002006,
+       VM_EXIT_MSR_STORE_ADDR_HIGH     = 0x00002007,
+       VM_EXIT_MSR_LOAD_ADDR           = 0x00002008,
+       VM_EXIT_MSR_LOAD_ADDR_HIGH      = 0x00002009,
+       VM_ENTRY_MSR_LOAD_ADDR          = 0x0000200a,
+       VM_ENTRY_MSR_LOAD_ADDR_HIGH     = 0x0000200b,
+       PML_ADDRESS                     = 0x0000200e,
+       PML_ADDRESS_HIGH                = 0x0000200f,
+       TSC_OFFSET                      = 0x00002010,
+       TSC_OFFSET_HIGH                 = 0x00002011,
+       VIRTUAL_APIC_PAGE_ADDR          = 0x00002012,
+       VIRTUAL_APIC_PAGE_ADDR_HIGH     = 0x00002013,
+       APIC_ACCESS_ADDR                = 0x00002014,
+       APIC_ACCESS_ADDR_HIGH           = 0x00002015,
+       POSTED_INTR_DESC_ADDR           = 0x00002016,
+       POSTED_INTR_DESC_ADDR_HIGH      = 0x00002017,
+       EPT_POINTER                     = 0x0000201a,
+       EPT_POINTER_HIGH                = 0x0000201b,
+       EOI_EXIT_BITMAP0                = 0x0000201c,
+       EOI_EXIT_BITMAP0_HIGH           = 0x0000201d,
+       EOI_EXIT_BITMAP1                = 0x0000201e,
+       EOI_EXIT_BITMAP1_HIGH           = 0x0000201f,
+       EOI_EXIT_BITMAP2                = 0x00002020,
+       EOI_EXIT_BITMAP2_HIGH           = 0x00002021,
+       EOI_EXIT_BITMAP3                = 0x00002022,
+       EOI_EXIT_BITMAP3_HIGH           = 0x00002023,
+       VMREAD_BITMAP                   = 0x00002026,
+       VMREAD_BITMAP_HIGH              = 0x00002027,
+       VMWRITE_BITMAP                  = 0x00002028,
+       VMWRITE_BITMAP_HIGH             = 0x00002029,
+       XSS_EXIT_BITMAP                 = 0x0000202C,
+       XSS_EXIT_BITMAP_HIGH            = 0x0000202D,
+       TSC_MULTIPLIER                  = 0x00002032,
+       TSC_MULTIPLIER_HIGH             = 0x00002033,
+       GUEST_PHYSICAL_ADDRESS          = 0x00002400,
+       GUEST_PHYSICAL_ADDRESS_HIGH     = 0x00002401,
+       VMCS_LINK_POINTER               = 0x00002800,
+       VMCS_LINK_POINTER_HIGH          = 0x00002801,
+       GUEST_IA32_DEBUGCTL             = 0x00002802,
+       GUEST_IA32_DEBUGCTL_HIGH        = 0x00002803,
+       GUEST_IA32_PAT                  = 0x00002804,
+       GUEST_IA32_PAT_HIGH             = 0x00002805,
+       GUEST_IA32_EFER                 = 0x00002806,
+       GUEST_IA32_EFER_HIGH            = 0x00002807,
+       GUEST_IA32_PERF_GLOBAL_CTRL     = 0x00002808,
+       GUEST_IA32_PERF_GLOBAL_CTRL_HIGH= 0x00002809,
+       GUEST_PDPTR0                    = 0x0000280a,
+       GUEST_PDPTR0_HIGH               = 0x0000280b,
+       GUEST_PDPTR1                    = 0x0000280c,
+       GUEST_PDPTR1_HIGH               = 0x0000280d,
+       GUEST_PDPTR2                    = 0x0000280e,
+       GUEST_PDPTR2_HIGH               = 0x0000280f,
+       GUEST_PDPTR3                    = 0x00002810,
+       GUEST_PDPTR3_HIGH               = 0x00002811,
+       GUEST_BNDCFGS                   = 0x00002812,
+       GUEST_BNDCFGS_HIGH              = 0x00002813,
+       HOST_IA32_PAT                   = 0x00002c00,
+       HOST_IA32_PAT_HIGH              = 0x00002c01,
+       HOST_IA32_EFER                  = 0x00002c02,
+       HOST_IA32_EFER_HIGH             = 0x00002c03,
+       HOST_IA32_PERF_GLOBAL_CTRL      = 0x00002c04,
+       HOST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002c05,
+       PIN_BASED_VM_EXEC_CONTROL       = 0x00004000,
+       CPU_BASED_VM_EXEC_CONTROL       = 0x00004002,
+       EXCEPTION_BITMAP                = 0x00004004,
+       PAGE_FAULT_ERROR_CODE_MASK      = 0x00004006,
+       PAGE_FAULT_ERROR_CODE_MATCH     = 0x00004008,
+       CR3_TARGET_COUNT                = 0x0000400a,
+       VM_EXIT_CONTROLS                = 0x0000400c,
+       VM_EXIT_MSR_STORE_COUNT         = 0x0000400e,
+       VM_EXIT_MSR_LOAD_COUNT          = 0x00004010,
+       VM_ENTRY_CONTROLS               = 0x00004012,
+       VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
+       VM_ENTRY_INTR_INFO_FIELD        = 0x00004016,
+       VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
+       VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
+       TPR_THRESHOLD                   = 0x0000401c,
+       SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
+       PLE_GAP                         = 0x00004020,
+       PLE_WINDOW                      = 0x00004022,
+       VM_INSTRUCTION_ERROR            = 0x00004400,
+       VM_EXIT_REASON                  = 0x00004402,
+       VM_EXIT_INTR_INFO               = 0x00004404,
+       VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
+       IDT_VECTORING_INFO_FIELD        = 0x00004408,
+       IDT_VECTORING_ERROR_CODE        = 0x0000440a,
+       VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
+       VMX_INSTRUCTION_INFO            = 0x0000440e,
+       GUEST_ES_LIMIT                  = 0x00004800,
+       GUEST_CS_LIMIT                  = 0x00004802,
+       GUEST_SS_LIMIT                  = 0x00004804,
+       GUEST_DS_LIMIT                  = 0x00004806,
+       GUEST_FS_LIMIT                  = 0x00004808,
+       GUEST_GS_LIMIT                  = 0x0000480a,
+       GUEST_LDTR_LIMIT                = 0x0000480c,
+       GUEST_TR_LIMIT                  = 0x0000480e,
+       GUEST_GDTR_LIMIT                = 0x00004810,
+       GUEST_IDTR_LIMIT                = 0x00004812,
+       GUEST_ES_AR_BYTES               = 0x00004814,
+       GUEST_CS_AR_BYTES               = 0x00004816,
+       GUEST_SS_AR_BYTES               = 0x00004818,
+       GUEST_DS_AR_BYTES               = 0x0000481a,
+       GUEST_FS_AR_BYTES               = 0x0000481c,
+       GUEST_GS_AR_BYTES               = 0x0000481e,
+       GUEST_LDTR_AR_BYTES             = 0x00004820,
+       GUEST_TR_AR_BYTES               = 0x00004822,
+       GUEST_INTERRUPTIBILITY_INFO     = 0x00004824,
+       GUEST_ACTIVITY_STATE            = 0X00004826,
+       GUEST_SYSENTER_CS               = 0x0000482A,
+       VMX_PREEMPTION_TIMER_VALUE      = 0x0000482E,
+       HOST_IA32_SYSENTER_CS           = 0x00004c00,
+       CR0_GUEST_HOST_MASK             = 0x00006000,
+       CR4_GUEST_HOST_MASK             = 0x00006002,
+       CR0_READ_SHADOW                 = 0x00006004,
+       CR4_READ_SHADOW                 = 0x00006006,
+       CR3_TARGET_VALUE0               = 0x00006008,
+       CR3_TARGET_VALUE1               = 0x0000600a,
+       CR3_TARGET_VALUE2               = 0x0000600c,
+       CR3_TARGET_VALUE3               = 0x0000600e,
+       EXIT_QUALIFICATION              = 0x00006400,
+       GUEST_LINEAR_ADDRESS            = 0x0000640a,
+       GUEST_CR0                       = 0x00006800,
+       GUEST_CR3                       = 0x00006802,
+       GUEST_CR4                       = 0x00006804,
+       GUEST_ES_BASE                   = 0x00006806,
+       GUEST_CS_BASE                   = 0x00006808,
+       GUEST_SS_BASE                   = 0x0000680a,
+       GUEST_DS_BASE                   = 0x0000680c,
+       GUEST_FS_BASE                   = 0x0000680e,
+       GUEST_GS_BASE                   = 0x00006810,
+       GUEST_LDTR_BASE                 = 0x00006812,
+       GUEST_TR_BASE                   = 0x00006814,
+       GUEST_GDTR_BASE                 = 0x00006816,
+       GUEST_IDTR_BASE                 = 0x00006818,
+       GUEST_DR7                       = 0x0000681a,
+       GUEST_RSP                       = 0x0000681c,
+       GUEST_RIP                       = 0x0000681e,
+       GUEST_RFLAGS                    = 0x00006820,
+       GUEST_PENDING_DBG_EXCEPTIONS    = 0x00006822,
+       GUEST_SYSENTER_ESP              = 0x00006824,
+       GUEST_SYSENTER_EIP              = 0x00006826,
+       HOST_CR0                        = 0x00006c00,
+       HOST_CR3                        = 0x00006c02,
+       HOST_CR4                        = 0x00006c04,
+       HOST_FS_BASE                    = 0x00006c06,
+       HOST_GS_BASE                    = 0x00006c08,
+       HOST_TR_BASE                    = 0x00006c0a,
+       HOST_GDTR_BASE                  = 0x00006c0c,
+       HOST_IDTR_BASE                  = 0x00006c0e,
+       HOST_IA32_SYSENTER_ESP          = 0x00006c10,
+       HOST_IA32_SYSENTER_EIP          = 0x00006c12,
+       HOST_RSP                        = 0x00006c14,
+       HOST_RIP                        = 0x00006c16,
+};
+
+struct vmx_msr_entry {
+       uint32_t index;
+       uint32_t reserved;
+       uint64_t value;
+} __attribute__ ((aligned(16)));
+
+static inline int vmxon(uint64_t phys)
+{
+       uint8_t ret;
+
+       __asm__ __volatile__ ("vmxon %[pa]; setna %[ret]"
+               : [ret]"=rm"(ret)
+               : [pa]"m"(phys)
+               : "cc", "memory");
+
+       return ret;
+}
+
+static inline void vmxoff(void)
+{
+       __asm__ __volatile__("vmxoff");
+}
+
+static inline int vmclear(uint64_t vmcs_pa)
+{
+       uint8_t ret;
+
+       __asm__ __volatile__ ("vmclear %[pa]; setna %[ret]"
+               : [ret]"=rm"(ret)
+               : [pa]"m"(vmcs_pa)
+               : "cc", "memory");
+
+       return ret;
+}
+
+static inline int vmptrld(uint64_t vmcs_pa)
+{
+       uint8_t ret;
+
+       __asm__ __volatile__ ("vmptrld %[pa]; setna %[ret]"
+               : [ret]"=rm"(ret)
+               : [pa]"m"(vmcs_pa)
+               : "cc", "memory");
+
+       return ret;
+}
+
+static inline int vmptrst(uint64_t *value)
+{
+       uint64_t tmp;
+       uint8_t ret;
+
+       __asm__ __volatile__("vmptrst %[value]; setna %[ret]"
+               : [value]"=m"(tmp), [ret]"=rm"(ret)
+               : : "cc", "memory");
+
+       *value = tmp;
+       return ret;
+}
+
+/*
+ * A wrapper around vmptrst that ignores errors and returns zero if the
+ * vmptrst instruction fails.
+ */
+static inline uint64_t vmptrstz(void)
+{
+       uint64_t value = 0;
+       vmptrst(&value);
+       return value;
+}
+
+/*
+ * No guest state (e.g. GPRs) is established by this vmlaunch.
+ */
+static inline int vmlaunch(void)
+{
+       int ret;
+
+       __asm__ __volatile__("push %%rbp;"
+                            "push %%rcx;"
+                            "push %%rdx;"
+                            "push %%rsi;"
+                            "push %%rdi;"
+                            "push $0;"
+                            "vmwrite %%rsp, %[host_rsp];"
+                            "lea 1f(%%rip), %%rax;"
+                            "vmwrite %%rax, %[host_rip];"
+                            "vmlaunch;"
+                            "incq (%%rsp);"
+                            "1: pop %%rax;"
+                            "pop %%rdi;"
+                            "pop %%rsi;"
+                            "pop %%rdx;"
+                            "pop %%rcx;"
+                            "pop %%rbp;"
+                            : [ret]"=&a"(ret)
+                            : [host_rsp]"r"((uint64_t)HOST_RSP),
+                              [host_rip]"r"((uint64_t)HOST_RIP)
+                            : "memory", "cc", "rbx", "r8", "r9", "r10",
+                              "r11", "r12", "r13", "r14", "r15");
+       return ret;
+}
+
+/*
+ * No guest state (e.g. GPRs) is established by this vmresume.
+ */
+static inline int vmresume(void)
+{
+       int ret;
+
+       __asm__ __volatile__("push %%rbp;"
+                            "push %%rcx;"
+                            "push %%rdx;"
+                            "push %%rsi;"
+                            "push %%rdi;"
+                            "push $0;"
+                            "vmwrite %%rsp, %[host_rsp];"
+                            "lea 1f(%%rip), %%rax;"
+                            "vmwrite %%rax, %[host_rip];"
+                            "vmresume;"
+                            "incq (%%rsp);"
+                            "1: pop %%rax;"
+                            "pop %%rdi;"
+                            "pop %%rsi;"
+                            "pop %%rdx;"
+                            "pop %%rcx;"
+                            "pop %%rbp;"
+                            : [ret]"=&a"(ret)
+                            : [host_rsp]"r"((uint64_t)HOST_RSP),
+                              [host_rip]"r"((uint64_t)HOST_RIP)
+                            : "memory", "cc", "rbx", "r8", "r9", "r10",
+                              "r11", "r12", "r13", "r14", "r15");
+       return ret;
+}
+
+static inline void vmcall(void)
+{
+       /* Currently, L1 destroys our GPRs during vmexits.  */
+       __asm__ __volatile__("push %%rbp; vmcall; pop %%rbp" : : :
+                            "rax", "rbx", "rcx", "rdx",
+                            "rsi", "rdi", "r8", "r9", "r10", "r11", "r12",
+                            "r13", "r14", "r15");
+}
+
+static inline int vmread(uint64_t encoding, uint64_t *value)
+{
+       uint64_t tmp;
+       uint8_t ret;
+
+       __asm__ __volatile__("vmread %[encoding], %[value]; setna %[ret]"
+               : [value]"=rm"(tmp), [ret]"=rm"(ret)
+               : [encoding]"r"(encoding)
+               : "cc", "memory");
+
+       *value = tmp;
+       return ret;
+}
+
+/*
+ * A wrapper around vmread that ignores errors and returns zero if the
+ * vmread instruction fails.
+ */
+static inline uint64_t vmreadz(uint64_t encoding)
+{
+       uint64_t value = 0;
+       vmread(encoding, &value);
+       return value;
+}
+
+static inline int vmwrite(uint64_t encoding, uint64_t value)
+{
+       uint8_t ret;
+
+       __asm__ __volatile__ ("vmwrite %[value], %[encoding]; setna %[ret]"
+               : [ret]"=rm"(ret)
+               : [value]"rm"(value), [encoding]"r"(encoding)
+               : "cc", "memory");
+
+       return ret;
+}
+
+static inline uint32_t vmcs_revision(void)
+{
+       return rdmsr(MSR_IA32_VMX_BASIC);
+}
+
+struct vmx_pages {
+       void *vmxon_hva;
+       uint64_t vmxon_gpa;
+       void *vmxon;
+
+       void *vmcs_hva;
+       uint64_t vmcs_gpa;
+       void *vmcs;
+
+       void *msr_hva;
+       uint64_t msr_gpa;
+       void *msr;
+
+       void *shadow_vmcs_hva;
+       uint64_t shadow_vmcs_gpa;
+       void *shadow_vmcs;
+
+       void *vmread_hva;
+       uint64_t vmread_gpa;
+       void *vmread;
+
+       void *vmwrite_hva;
+       uint64_t vmwrite_gpa;
+       void *vmwrite;
+};
+
+struct vmx_pages *vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva);
+bool prepare_for_vmx_operation(struct vmx_pages *vmx);
+void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp);
+
+#endif /* SELFTEST_KVM_VMX_H */
index cd01144d27c8ddb027204c345c3f2aa5bb932c2e..6398efe678853de3117526c2db5fea92df59bf5f 100644 (file)
@@ -13,7 +13,7 @@
 #include <execinfo.h>
 #include <sys/syscall.h>
 
-#include "../../kselftest.h"
+#include "kselftest.h"
 
 /* Dumps the current stack trace to stderr. */
 static void __attribute__((noinline)) test_dump_stack(void);
index 8fa7c9f7567a19414d0628337f71674c2fe1b0f6..36367be0fe2624cb433140a7a63619eade10acbb 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * tools/testing/selftests/kvm/lib/kvm_util.c
+ * tools/testing/selftests/kvm/lib/kvm_util_internal.h
  *
  * Copyright (C) 2018, Google LLC.
  *
  * This work is licensed under the terms of the GNU GPL, version 2.
  */
 
-#ifndef KVM_UTIL_INTERNAL_H
-#define KVM_UTIL_INTERNAL_H 1
+#ifndef SELFTEST_KVM_UTIL_INTERNAL_H
+#define SELFTEST_KVM_UTIL_INTERNAL_H
 
 #include "sparsebit.h"
 
@@ -70,4 +70,4 @@ void regs_dump(FILE *stream, struct kvm_regs *regs,
 void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
        uint8_t indent);
 
-#endif
+#endif /* SELFTEST_KVM_UTIL_INTERNAL_H */
diff --git a/tools/testing/selftests/kvm/lib/vmx.c b/tools/testing/selftests/kvm/lib/vmx.c
deleted file mode 100644 (file)
index b987c3c..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * tools/testing/selftests/kvm/lib/x86.c
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- */
-
-#define _GNU_SOURCE /* for program_invocation_name */
-
-#include "test_util.h"
-#include "kvm_util.h"
-#include "x86.h"
-#include "vmx.h"
-
-/* Allocate memory regions for nested VMX tests.
- *
- * Input Args:
- *   vm - The VM to allocate guest-virtual addresses in.
- *
- * Output Args:
- *   p_vmx_gva - The guest virtual address for the struct vmx_pages.
- *
- * Return:
- *   Pointer to structure with the addresses of the VMX areas.
- */
-struct vmx_pages *
-vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva)
-{
-       vm_vaddr_t vmx_gva = vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       struct vmx_pages *vmx = addr_gva2hva(vm, vmx_gva);
-
-       /* Setup of a region of guest memory for the vmxon region. */
-       vmx->vmxon = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       vmx->vmxon_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmxon);
-       vmx->vmxon_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmxon);
-
-       /* Setup of a region of guest memory for a vmcs. */
-       vmx->vmcs = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       vmx->vmcs_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmcs);
-       vmx->vmcs_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmcs);
-
-       /* Setup of a region of guest memory for the MSR bitmap. */
-       vmx->msr = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       vmx->msr_hva = addr_gva2hva(vm, (uintptr_t)vmx->msr);
-       vmx->msr_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->msr);
-       memset(vmx->msr_hva, 0, getpagesize());
-
-       /* Setup of a region of guest memory for the shadow VMCS. */
-       vmx->shadow_vmcs = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       vmx->shadow_vmcs_hva = addr_gva2hva(vm, (uintptr_t)vmx->shadow_vmcs);
-       vmx->shadow_vmcs_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->shadow_vmcs);
-
-       /* Setup of a region of guest memory for the VMREAD and VMWRITE bitmaps. */
-       vmx->vmread = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       vmx->vmread_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmread);
-       vmx->vmread_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmread);
-       memset(vmx->vmread_hva, 0, getpagesize());
-
-       vmx->vmwrite = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
-       vmx->vmwrite_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmwrite);
-       vmx->vmwrite_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmwrite);
-       memset(vmx->vmwrite_hva, 0, getpagesize());
-
-       *p_vmx_gva = vmx_gva;
-       return vmx;
-}
-
-bool prepare_for_vmx_operation(struct vmx_pages *vmx)
-{
-       uint64_t feature_control;
-       uint64_t required;
-       unsigned long cr0;
-       unsigned long cr4;
-
-       /*
-        * Ensure bits in CR0 and CR4 are valid in VMX operation:
-        * - Bit X is 1 in _FIXED0: bit X is fixed to 1 in CRx.
-        * - Bit X is 0 in _FIXED1: bit X is fixed to 0 in CRx.
-        */
-       __asm__ __volatile__("mov %%cr0, %0" : "=r"(cr0) : : "memory");
-       cr0 &= rdmsr(MSR_IA32_VMX_CR0_FIXED1);
-       cr0 |= rdmsr(MSR_IA32_VMX_CR0_FIXED0);
-       __asm__ __volatile__("mov %0, %%cr0" : : "r"(cr0) : "memory");
-
-       __asm__ __volatile__("mov %%cr4, %0" : "=r"(cr4) : : "memory");
-       cr4 &= rdmsr(MSR_IA32_VMX_CR4_FIXED1);
-       cr4 |= rdmsr(MSR_IA32_VMX_CR4_FIXED0);
-       /* Enable VMX operation */
-       cr4 |= X86_CR4_VMXE;
-       __asm__ __volatile__("mov %0, %%cr4" : : "r"(cr4) : "memory");
-
-       /*
-        * Configure IA32_FEATURE_CONTROL MSR to allow VMXON:
-        *  Bit 0: Lock bit. If clear, VMXON causes a #GP.
-        *  Bit 2: Enables VMXON outside of SMX operation. If clear, VMXON
-        *    outside of SMX causes a #GP.
-        */
-       required = FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
-       required |= FEATURE_CONTROL_LOCKED;
-       feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
-       if ((feature_control & required) != required)
-               wrmsr(MSR_IA32_FEATURE_CONTROL, feature_control | required);
-
-       /* Enter VMX root operation. */
-       *(uint32_t *)(vmx->vmxon) = vmcs_revision();
-       if (vmxon(vmx->vmxon_gpa))
-               return false;
-
-       /* Load a VMCS. */
-       *(uint32_t *)(vmx->vmcs) = vmcs_revision();
-       if (vmclear(vmx->vmcs_gpa))
-               return false;
-
-       if (vmptrld(vmx->vmcs_gpa))
-               return false;
-
-       /* Setup shadow VMCS, do not load it yet. */
-       *(uint32_t *)(vmx->shadow_vmcs) = vmcs_revision() | 0x80000000ul;
-       if (vmclear(vmx->shadow_vmcs_gpa))
-               return false;
-
-       return true;
-}
-
-/*
- * Initialize the control fields to the most basic settings possible.
- */
-static inline void init_vmcs_control_fields(struct vmx_pages *vmx)
-{
-       vmwrite(VIRTUAL_PROCESSOR_ID, 0);
-       vmwrite(POSTED_INTR_NV, 0);
-
-       vmwrite(PIN_BASED_VM_EXEC_CONTROL, rdmsr(MSR_IA32_VMX_TRUE_PINBASED_CTLS));
-       if (!vmwrite(SECONDARY_VM_EXEC_CONTROL, 0))
-               vmwrite(CPU_BASED_VM_EXEC_CONTROL,
-                       rdmsr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS) | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
-       else
-               vmwrite(CPU_BASED_VM_EXEC_CONTROL, rdmsr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS));
-       vmwrite(EXCEPTION_BITMAP, 0);
-       vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0);
-       vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, -1); /* Never match */
-       vmwrite(CR3_TARGET_COUNT, 0);
-       vmwrite(VM_EXIT_CONTROLS, rdmsr(MSR_IA32_VMX_EXIT_CTLS) |
-               VM_EXIT_HOST_ADDR_SPACE_SIZE);    /* 64-bit host */
-       vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
-       vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
-       vmwrite(VM_ENTRY_CONTROLS, rdmsr(MSR_IA32_VMX_ENTRY_CTLS) |
-               VM_ENTRY_IA32E_MODE);             /* 64-bit guest */
-       vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
-       vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
-       vmwrite(TPR_THRESHOLD, 0);
-
-       vmwrite(CR0_GUEST_HOST_MASK, 0);
-       vmwrite(CR4_GUEST_HOST_MASK, 0);
-       vmwrite(CR0_READ_SHADOW, get_cr0());
-       vmwrite(CR4_READ_SHADOW, get_cr4());
-
-       vmwrite(MSR_BITMAP, vmx->msr_gpa);
-       vmwrite(VMREAD_BITMAP, vmx->vmread_gpa);
-       vmwrite(VMWRITE_BITMAP, vmx->vmwrite_gpa);
-}
-
-/*
- * Initialize the host state fields based on the current host state, with
- * the exception of HOST_RSP and HOST_RIP, which should be set by vmlaunch
- * or vmresume.
- */
-static inline void init_vmcs_host_state(void)
-{
-       uint32_t exit_controls = vmreadz(VM_EXIT_CONTROLS);
-
-       vmwrite(HOST_ES_SELECTOR, get_es());
-       vmwrite(HOST_CS_SELECTOR, get_cs());
-       vmwrite(HOST_SS_SELECTOR, get_ss());
-       vmwrite(HOST_DS_SELECTOR, get_ds());
-       vmwrite(HOST_FS_SELECTOR, get_fs());
-       vmwrite(HOST_GS_SELECTOR, get_gs());
-       vmwrite(HOST_TR_SELECTOR, get_tr());
-
-       if (exit_controls & VM_EXIT_LOAD_IA32_PAT)
-               vmwrite(HOST_IA32_PAT, rdmsr(MSR_IA32_CR_PAT));
-       if (exit_controls & VM_EXIT_LOAD_IA32_EFER)
-               vmwrite(HOST_IA32_EFER, rdmsr(MSR_EFER));
-       if (exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
-               vmwrite(HOST_IA32_PERF_GLOBAL_CTRL,
-                       rdmsr(MSR_CORE_PERF_GLOBAL_CTRL));
-
-       vmwrite(HOST_IA32_SYSENTER_CS, rdmsr(MSR_IA32_SYSENTER_CS));
-
-       vmwrite(HOST_CR0, get_cr0());
-       vmwrite(HOST_CR3, get_cr3());
-       vmwrite(HOST_CR4, get_cr4());
-       vmwrite(HOST_FS_BASE, rdmsr(MSR_FS_BASE));
-       vmwrite(HOST_GS_BASE, rdmsr(MSR_GS_BASE));
-       vmwrite(HOST_TR_BASE,
-               get_desc64_base((struct desc64 *)(get_gdt_base() + get_tr())));
-       vmwrite(HOST_GDTR_BASE, get_gdt_base());
-       vmwrite(HOST_IDTR_BASE, get_idt_base());
-       vmwrite(HOST_IA32_SYSENTER_ESP, rdmsr(MSR_IA32_SYSENTER_ESP));
-       vmwrite(HOST_IA32_SYSENTER_EIP, rdmsr(MSR_IA32_SYSENTER_EIP));
-}
-
-/*
- * Initialize the guest state fields essentially as a clone of
- * the host state fields. Some host state fields have fixed
- * values, and we set the corresponding guest state fields accordingly.
- */
-static inline void init_vmcs_guest_state(void *rip, void *rsp)
-{
-       vmwrite(GUEST_ES_SELECTOR, vmreadz(HOST_ES_SELECTOR));
-       vmwrite(GUEST_CS_SELECTOR, vmreadz(HOST_CS_SELECTOR));
-       vmwrite(GUEST_SS_SELECTOR, vmreadz(HOST_SS_SELECTOR));
-       vmwrite(GUEST_DS_SELECTOR, vmreadz(HOST_DS_SELECTOR));
-       vmwrite(GUEST_FS_SELECTOR, vmreadz(HOST_FS_SELECTOR));
-       vmwrite(GUEST_GS_SELECTOR, vmreadz(HOST_GS_SELECTOR));
-       vmwrite(GUEST_LDTR_SELECTOR, 0);
-       vmwrite(GUEST_TR_SELECTOR, vmreadz(HOST_TR_SELECTOR));
-       vmwrite(GUEST_INTR_STATUS, 0);
-       vmwrite(GUEST_PML_INDEX, 0);
-
-       vmwrite(VMCS_LINK_POINTER, -1ll);
-       vmwrite(GUEST_IA32_DEBUGCTL, 0);
-       vmwrite(GUEST_IA32_PAT, vmreadz(HOST_IA32_PAT));
-       vmwrite(GUEST_IA32_EFER, vmreadz(HOST_IA32_EFER));
-       vmwrite(GUEST_IA32_PERF_GLOBAL_CTRL,
-               vmreadz(HOST_IA32_PERF_GLOBAL_CTRL));
-
-       vmwrite(GUEST_ES_LIMIT, -1);
-       vmwrite(GUEST_CS_LIMIT, -1);
-       vmwrite(GUEST_SS_LIMIT, -1);
-       vmwrite(GUEST_DS_LIMIT, -1);
-       vmwrite(GUEST_FS_LIMIT, -1);
-       vmwrite(GUEST_GS_LIMIT, -1);
-       vmwrite(GUEST_LDTR_LIMIT, -1);
-       vmwrite(GUEST_TR_LIMIT, 0x67);
-       vmwrite(GUEST_GDTR_LIMIT, 0xffff);
-       vmwrite(GUEST_IDTR_LIMIT, 0xffff);
-       vmwrite(GUEST_ES_AR_BYTES,
-               vmreadz(GUEST_ES_SELECTOR) == 0 ? 0x10000 : 0xc093);
-       vmwrite(GUEST_CS_AR_BYTES, 0xa09b);
-       vmwrite(GUEST_SS_AR_BYTES, 0xc093);
-       vmwrite(GUEST_DS_AR_BYTES,
-               vmreadz(GUEST_DS_SELECTOR) == 0 ? 0x10000 : 0xc093);
-       vmwrite(GUEST_FS_AR_BYTES,
-               vmreadz(GUEST_FS_SELECTOR) == 0 ? 0x10000 : 0xc093);
-       vmwrite(GUEST_GS_AR_BYTES,
-               vmreadz(GUEST_GS_SELECTOR) == 0 ? 0x10000 : 0xc093);
-       vmwrite(GUEST_LDTR_AR_BYTES, 0x10000);
-       vmwrite(GUEST_TR_AR_BYTES, 0x8b);
-       vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
-       vmwrite(GUEST_ACTIVITY_STATE, 0);
-       vmwrite(GUEST_SYSENTER_CS, vmreadz(HOST_IA32_SYSENTER_CS));
-       vmwrite(VMX_PREEMPTION_TIMER_VALUE, 0);
-
-       vmwrite(GUEST_CR0, vmreadz(HOST_CR0));
-       vmwrite(GUEST_CR3, vmreadz(HOST_CR3));
-       vmwrite(GUEST_CR4, vmreadz(HOST_CR4));
-       vmwrite(GUEST_ES_BASE, 0);
-       vmwrite(GUEST_CS_BASE, 0);
-       vmwrite(GUEST_SS_BASE, 0);
-       vmwrite(GUEST_DS_BASE, 0);
-       vmwrite(GUEST_FS_BASE, vmreadz(HOST_FS_BASE));
-       vmwrite(GUEST_GS_BASE, vmreadz(HOST_GS_BASE));
-       vmwrite(GUEST_LDTR_BASE, 0);
-       vmwrite(GUEST_TR_BASE, vmreadz(HOST_TR_BASE));
-       vmwrite(GUEST_GDTR_BASE, vmreadz(HOST_GDTR_BASE));
-       vmwrite(GUEST_IDTR_BASE, vmreadz(HOST_IDTR_BASE));
-       vmwrite(GUEST_DR7, 0x400);
-       vmwrite(GUEST_RSP, (uint64_t)rsp);
-       vmwrite(GUEST_RIP, (uint64_t)rip);
-       vmwrite(GUEST_RFLAGS, 2);
-       vmwrite(GUEST_PENDING_DBG_EXCEPTIONS, 0);
-       vmwrite(GUEST_SYSENTER_ESP, vmreadz(HOST_IA32_SYSENTER_ESP));
-       vmwrite(GUEST_SYSENTER_EIP, vmreadz(HOST_IA32_SYSENTER_EIP));
-}
-
-void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp)
-{
-       init_vmcs_control_fields(vmx);
-       init_vmcs_host_state();
-       init_vmcs_guest_state(guest_rip, guest_rsp);
-}
diff --git a/tools/testing/selftests/kvm/lib/x86.c b/tools/testing/selftests/kvm/lib/x86.c
deleted file mode 100644 (file)
index bb6c65e..0000000
+++ /dev/null
@@ -1,888 +0,0 @@
-/*
- * tools/testing/selftests/kvm/lib/x86.c
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- */
-
-#define _GNU_SOURCE /* for program_invocation_name */
-
-#include "test_util.h"
-#include "kvm_util.h"
-#include "kvm_util_internal.h"
-#include "x86.h"
-
-/* Minimum physical address used for virtual translation tables. */
-#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
-
-/* Virtual translation table structure declarations */
-struct pageMapL4Entry {
-       uint64_t present:1;
-       uint64_t writable:1;
-       uint64_t user:1;
-       uint64_t write_through:1;
-       uint64_t cache_disable:1;
-       uint64_t accessed:1;
-       uint64_t ignored_06:1;
-       uint64_t page_size:1;
-       uint64_t ignored_11_08:4;
-       uint64_t address:40;
-       uint64_t ignored_62_52:11;
-       uint64_t execute_disable:1;
-};
-
-struct pageDirectoryPointerEntry {
-       uint64_t present:1;
-       uint64_t writable:1;
-       uint64_t user:1;
-       uint64_t write_through:1;
-       uint64_t cache_disable:1;
-       uint64_t accessed:1;
-       uint64_t ignored_06:1;
-       uint64_t page_size:1;
-       uint64_t ignored_11_08:4;
-       uint64_t address:40;
-       uint64_t ignored_62_52:11;
-       uint64_t execute_disable:1;
-};
-
-struct pageDirectoryEntry {
-       uint64_t present:1;
-       uint64_t writable:1;
-       uint64_t user:1;
-       uint64_t write_through:1;
-       uint64_t cache_disable:1;
-       uint64_t accessed:1;
-       uint64_t ignored_06:1;
-       uint64_t page_size:1;
-       uint64_t ignored_11_08:4;
-       uint64_t address:40;
-       uint64_t ignored_62_52:11;
-       uint64_t execute_disable:1;
-};
-
-struct pageTableEntry {
-       uint64_t present:1;
-       uint64_t writable:1;
-       uint64_t user:1;
-       uint64_t write_through:1;
-       uint64_t cache_disable:1;
-       uint64_t accessed:1;
-       uint64_t dirty:1;
-       uint64_t reserved_07:1;
-       uint64_t global:1;
-       uint64_t ignored_11_09:3;
-       uint64_t address:40;
-       uint64_t ignored_62_52:11;
-       uint64_t execute_disable:1;
-};
-
-/* Register Dump
- *
- * Input Args:
- *   indent - Left margin indent amount
- *   regs - register
- *
- * Output Args:
- *   stream - Output FILE stream
- *
- * Return: None
- *
- * Dumps the state of the registers given by regs, to the FILE stream
- * given by steam.
- */
-void regs_dump(FILE *stream, struct kvm_regs *regs,
-              uint8_t indent)
-{
-       fprintf(stream, "%*srax: 0x%.16llx rbx: 0x%.16llx "
-               "rcx: 0x%.16llx rdx: 0x%.16llx\n",
-               indent, "",
-               regs->rax, regs->rbx, regs->rcx, regs->rdx);
-       fprintf(stream, "%*srsi: 0x%.16llx rdi: 0x%.16llx "
-               "rsp: 0x%.16llx rbp: 0x%.16llx\n",
-               indent, "",
-               regs->rsi, regs->rdi, regs->rsp, regs->rbp);
-       fprintf(stream, "%*sr8:  0x%.16llx r9:  0x%.16llx "
-               "r10: 0x%.16llx r11: 0x%.16llx\n",
-               indent, "",
-               regs->r8, regs->r9, regs->r10, regs->r11);
-       fprintf(stream, "%*sr12: 0x%.16llx r13: 0x%.16llx "
-               "r14: 0x%.16llx r15: 0x%.16llx\n",
-               indent, "",
-               regs->r12, regs->r13, regs->r14, regs->r15);
-       fprintf(stream, "%*srip: 0x%.16llx rfl: 0x%.16llx\n",
-               indent, "",
-               regs->rip, regs->rflags);
-}
-
-/* Segment Dump
- *
- * Input Args:
- *   indent - Left margin indent amount
- *   segment - KVM segment
- *
- * Output Args:
- *   stream - Output FILE stream
- *
- * Return: None
- *
- * Dumps the state of the KVM segment given by segment, to the FILE stream
- * given by steam.
- */
-static void segment_dump(FILE *stream, struct kvm_segment *segment,
-                        uint8_t indent)
-{
-       fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.8x "
-               "selector: 0x%.4x type: 0x%.2x\n",
-               indent, "", segment->base, segment->limit,
-               segment->selector, segment->type);
-       fprintf(stream, "%*spresent: 0x%.2x dpl: 0x%.2x "
-               "db: 0x%.2x s: 0x%.2x l: 0x%.2x\n",
-               indent, "", segment->present, segment->dpl,
-               segment->db, segment->s, segment->l);
-       fprintf(stream, "%*sg: 0x%.2x avl: 0x%.2x "
-               "unusable: 0x%.2x padding: 0x%.2x\n",
-               indent, "", segment->g, segment->avl,
-               segment->unusable, segment->padding);
-}
-
-/* dtable Dump
- *
- * Input Args:
- *   indent - Left margin indent amount
- *   dtable - KVM dtable
- *
- * Output Args:
- *   stream - Output FILE stream
- *
- * Return: None
- *
- * Dumps the state of the KVM dtable given by dtable, to the FILE stream
- * given by steam.
- */
-static void dtable_dump(FILE *stream, struct kvm_dtable *dtable,
-                       uint8_t indent)
-{
-       fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.4x "
-               "padding: 0x%.4x 0x%.4x 0x%.4x\n",
-               indent, "", dtable->base, dtable->limit,
-               dtable->padding[0], dtable->padding[1], dtable->padding[2]);
-}
-
-/* System Register Dump
- *
- * Input Args:
- *   indent - Left margin indent amount
- *   sregs - System registers
- *
- * Output Args:
- *   stream - Output FILE stream
- *
- * Return: None
- *
- * Dumps the state of the system registers given by sregs, to the FILE stream
- * given by steam.
- */
-void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
-               uint8_t indent)
-{
-       unsigned int i;
-
-       fprintf(stream, "%*scs:\n", indent, "");
-       segment_dump(stream, &sregs->cs, indent + 2);
-       fprintf(stream, "%*sds:\n", indent, "");
-       segment_dump(stream, &sregs->ds, indent + 2);
-       fprintf(stream, "%*ses:\n", indent, "");
-       segment_dump(stream, &sregs->es, indent + 2);
-       fprintf(stream, "%*sfs:\n", indent, "");
-       segment_dump(stream, &sregs->fs, indent + 2);
-       fprintf(stream, "%*sgs:\n", indent, "");
-       segment_dump(stream, &sregs->gs, indent + 2);
-       fprintf(stream, "%*sss:\n", indent, "");
-       segment_dump(stream, &sregs->ss, indent + 2);
-       fprintf(stream, "%*str:\n", indent, "");
-       segment_dump(stream, &sregs->tr, indent + 2);
-       fprintf(stream, "%*sldt:\n", indent, "");
-       segment_dump(stream, &sregs->ldt, indent + 2);
-
-       fprintf(stream, "%*sgdt:\n", indent, "");
-       dtable_dump(stream, &sregs->gdt, indent + 2);
-       fprintf(stream, "%*sidt:\n", indent, "");
-       dtable_dump(stream, &sregs->idt, indent + 2);
-
-       fprintf(stream, "%*scr0: 0x%.16llx cr2: 0x%.16llx "
-               "cr3: 0x%.16llx cr4: 0x%.16llx\n",
-               indent, "",
-               sregs->cr0, sregs->cr2, sregs->cr3, sregs->cr4);
-       fprintf(stream, "%*scr8: 0x%.16llx efer: 0x%.16llx "
-               "apic_base: 0x%.16llx\n",
-               indent, "",
-               sregs->cr8, sregs->efer, sregs->apic_base);
-
-       fprintf(stream, "%*sinterrupt_bitmap:\n", indent, "");
-       for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++) {
-               fprintf(stream, "%*s%.16llx\n", indent + 2, "",
-                       sregs->interrupt_bitmap[i]);
-       }
-}
-
-void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
-{
-       int rc;
-
-       TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
-               "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
-
-       /* If needed, create page map l4 table. */
-       if (!vm->pgd_created) {
-               vm_paddr_t paddr = vm_phy_page_alloc(vm,
-                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
-               vm->pgd = paddr;
-               vm->pgd_created = true;
-       }
-}
-
-/* VM Virtual Page Map
- *
- * Input Args:
- *   vm - Virtual Machine
- *   vaddr - VM Virtual Address
- *   paddr - VM Physical Address
- *   pgd_memslot - Memory region slot for new virtual translation tables
- *
- * Output Args: None
- *
- * Return: None
- *
- * Within the VM given by vm, creates a virtual translation for the page
- * starting at vaddr to the page starting at paddr.
- */
-void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
-       uint32_t pgd_memslot)
-{
-       uint16_t index[4];
-       struct pageMapL4Entry *pml4e;
-
-       TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
-               "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
-
-       TEST_ASSERT((vaddr % vm->page_size) == 0,
-               "Virtual address not on page boundary,\n"
-               "  vaddr: 0x%lx vm->page_size: 0x%x",
-               vaddr, vm->page_size);
-       TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
-               (vaddr >> vm->page_shift)),
-               "Invalid virtual address, vaddr: 0x%lx",
-               vaddr);
-       TEST_ASSERT((paddr % vm->page_size) == 0,
-               "Physical address not on page boundary,\n"
-               "  paddr: 0x%lx vm->page_size: 0x%x",
-               paddr, vm->page_size);
-       TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
-               "Physical address beyond beyond maximum supported,\n"
-               "  paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
-               paddr, vm->max_gfn, vm->page_size);
-
-       index[0] = (vaddr >> 12) & 0x1ffu;
-       index[1] = (vaddr >> 21) & 0x1ffu;
-       index[2] = (vaddr >> 30) & 0x1ffu;
-       index[3] = (vaddr >> 39) & 0x1ffu;
-
-       /* Allocate page directory pointer table if not present. */
-       pml4e = addr_gpa2hva(vm, vm->pgd);
-       if (!pml4e[index[3]].present) {
-               pml4e[index[3]].address = vm_phy_page_alloc(vm,
-                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
-                       >> vm->page_shift;
-               pml4e[index[3]].writable = true;
-               pml4e[index[3]].present = true;
-       }
-
-       /* Allocate page directory table if not present. */
-       struct pageDirectoryPointerEntry *pdpe;
-       pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
-       if (!pdpe[index[2]].present) {
-               pdpe[index[2]].address = vm_phy_page_alloc(vm,
-                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
-                       >> vm->page_shift;
-               pdpe[index[2]].writable = true;
-               pdpe[index[2]].present = true;
-       }
-
-       /* Allocate page table if not present. */
-       struct pageDirectoryEntry *pde;
-       pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
-       if (!pde[index[1]].present) {
-               pde[index[1]].address = vm_phy_page_alloc(vm,
-                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
-                       >> vm->page_shift;
-               pde[index[1]].writable = true;
-               pde[index[1]].present = true;
-       }
-
-       /* Fill in page table entry. */
-       struct pageTableEntry *pte;
-       pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
-       pte[index[0]].address = paddr >> vm->page_shift;
-       pte[index[0]].writable = true;
-       pte[index[0]].present = 1;
-}
-
-/* Virtual Translation Tables Dump
- *
- * Input Args:
- *   vm - Virtual Machine
- *   indent - Left margin indent amount
- *
- * Output Args:
- *   stream - Output FILE stream
- *
- * Return: None
- *
- * Dumps to the FILE stream given by stream, the contents of all the
- * virtual translation tables for the VM given by vm.
- */
-void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
-{
-       struct pageMapL4Entry *pml4e, *pml4e_start;
-       struct pageDirectoryPointerEntry *pdpe, *pdpe_start;
-       struct pageDirectoryEntry *pde, *pde_start;
-       struct pageTableEntry *pte, *pte_start;
-
-       if (!vm->pgd_created)
-               return;
-
-       fprintf(stream, "%*s                                          "
-               "                no\n", indent, "");
-       fprintf(stream, "%*s      index hvaddr         gpaddr         "
-               "addr         w exec dirty\n",
-               indent, "");
-       pml4e_start = (struct pageMapL4Entry *) addr_gpa2hva(vm,
-               vm->pgd);
-       for (uint16_t n1 = 0; n1 <= 0x1ffu; n1++) {
-               pml4e = &pml4e_start[n1];
-               if (!pml4e->present)
-                       continue;
-               fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10lx %u "
-                       " %u\n",
-                       indent, "",
-                       pml4e - pml4e_start, pml4e,
-                       addr_hva2gpa(vm, pml4e), (uint64_t) pml4e->address,
-                       pml4e->writable, pml4e->execute_disable);
-
-               pdpe_start = addr_gpa2hva(vm, pml4e->address
-                       * vm->page_size);
-               for (uint16_t n2 = 0; n2 <= 0x1ffu; n2++) {
-                       pdpe = &pdpe_start[n2];
-                       if (!pdpe->present)
-                               continue;
-                       fprintf(stream, "%*spdpe  0x%-3zx %p 0x%-12lx 0x%-10lx "
-                               "%u  %u\n",
-                               indent, "",
-                               pdpe - pdpe_start, pdpe,
-                               addr_hva2gpa(vm, pdpe),
-                               (uint64_t) pdpe->address, pdpe->writable,
-                               pdpe->execute_disable);
-
-                       pde_start = addr_gpa2hva(vm,
-                               pdpe->address * vm->page_size);
-                       for (uint16_t n3 = 0; n3 <= 0x1ffu; n3++) {
-                               pde = &pde_start[n3];
-                               if (!pde->present)
-                                       continue;
-                               fprintf(stream, "%*spde   0x%-3zx %p "
-                                       "0x%-12lx 0x%-10lx %u  %u\n",
-                                       indent, "", pde - pde_start, pde,
-                                       addr_hva2gpa(vm, pde),
-                                       (uint64_t) pde->address, pde->writable,
-                                       pde->execute_disable);
-
-                               pte_start = addr_gpa2hva(vm,
-                                       pde->address * vm->page_size);
-                               for (uint16_t n4 = 0; n4 <= 0x1ffu; n4++) {
-                                       pte = &pte_start[n4];
-                                       if (!pte->present)
-                                               continue;
-                                       fprintf(stream, "%*spte   0x%-3zx %p "
-                                               "0x%-12lx 0x%-10lx %u  %u "
-                                               "    %u    0x%-10lx\n",
-                                               indent, "",
-                                               pte - pte_start, pte,
-                                               addr_hva2gpa(vm, pte),
-                                               (uint64_t) pte->address,
-                                               pte->writable,
-                                               pte->execute_disable,
-                                               pte->dirty,
-                                               ((uint64_t) n1 << 27)
-                                                       | ((uint64_t) n2 << 18)
-                                                       | ((uint64_t) n3 << 9)
-                                                       | ((uint64_t) n4));
-                               }
-                       }
-               }
-       }
-}
-
-/* Set Unusable Segment
- *
- * Input Args: None
- *
- * Output Args:
- *   segp - Pointer to segment register
- *
- * Return: None
- *
- * Sets the segment register pointed to by segp to an unusable state.
- */
-static void kvm_seg_set_unusable(struct kvm_segment *segp)
-{
-       memset(segp, 0, sizeof(*segp));
-       segp->unusable = true;
-}
-
-static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
-{
-       void *gdt = addr_gva2hva(vm, vm->gdt);
-       struct desc64 *desc = gdt + (segp->selector >> 3) * 8;
-
-       desc->limit0 = segp->limit & 0xFFFF;
-       desc->base0 = segp->base & 0xFFFF;
-       desc->base1 = segp->base >> 16;
-       desc->s = segp->s;
-       desc->type = segp->type;
-       desc->dpl = segp->dpl;
-       desc->p = segp->present;
-       desc->limit1 = segp->limit >> 16;
-       desc->l = segp->l;
-       desc->db = segp->db;
-       desc->g = segp->g;
-       desc->base2 = segp->base >> 24;
-       if (!segp->s)
-               desc->base3 = segp->base >> 32;
-}
-
-
-/* Set Long Mode Flat Kernel Code Segment
- *
- * Input Args:
- *   vm - VM whose GDT is being filled, or NULL to only write segp
- *   selector - selector value
- *
- * Output Args:
- *   segp - Pointer to KVM segment
- *
- * Return: None
- *
- * Sets up the KVM segment pointed to by segp, to be a code segment
- * with the selector value given by selector.
- */
-static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
-       struct kvm_segment *segp)
-{
-       memset(segp, 0, sizeof(*segp));
-       segp->selector = selector;
-       segp->limit = 0xFFFFFFFFu;
-       segp->s = 0x1; /* kTypeCodeData */
-       segp->type = 0x08 | 0x01 | 0x02; /* kFlagCode | kFlagCodeAccessed
-                                         * | kFlagCodeReadable
-                                         */
-       segp->g = true;
-       segp->l = true;
-       segp->present = 1;
-       if (vm)
-               kvm_seg_fill_gdt_64bit(vm, segp);
-}
-
-/* Set Long Mode Flat Kernel Data Segment
- *
- * Input Args:
- *   vm - VM whose GDT is being filled, or NULL to only write segp
- *   selector - selector value
- *
- * Output Args:
- *   segp - Pointer to KVM segment
- *
- * Return: None
- *
- * Sets up the KVM segment pointed to by segp, to be a data segment
- * with the selector value given by selector.
- */
-static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
-       struct kvm_segment *segp)
-{
-       memset(segp, 0, sizeof(*segp));
-       segp->selector = selector;
-       segp->limit = 0xFFFFFFFFu;
-       segp->s = 0x1; /* kTypeCodeData */
-       segp->type = 0x00 | 0x01 | 0x02; /* kFlagData | kFlagDataAccessed
-                                         * | kFlagDataWritable
-                                         */
-       segp->g = true;
-       segp->present = true;
-       if (vm)
-               kvm_seg_fill_gdt_64bit(vm, segp);
-}
-
-/* Address Guest Virtual to Guest Physical
- *
- * Input Args:
- *   vm - Virtual Machine
- *   gpa - VM virtual address
- *
- * Output Args: None
- *
- * Return:
- *   Equivalent VM physical address
- *
- * Translates the VM virtual address given by gva to a VM physical
- * address and then locates the memory region containing the VM
- * physical address, within the VM given by vm.  When found, the host
- * virtual address providing the memory to the vm physical address is returned.
- * A TEST_ASSERT failure occurs if no region containing translated
- * VM virtual address exists.
- */
-vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
-{
-       uint16_t index[4];
-       struct pageMapL4Entry *pml4e;
-       struct pageDirectoryPointerEntry *pdpe;
-       struct pageDirectoryEntry *pde;
-       struct pageTableEntry *pte;
-       void *hva;
-
-       TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
-               "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
-
-       index[0] = (gva >> 12) & 0x1ffu;
-       index[1] = (gva >> 21) & 0x1ffu;
-       index[2] = (gva >> 30) & 0x1ffu;
-       index[3] = (gva >> 39) & 0x1ffu;
-
-       if (!vm->pgd_created)
-               goto unmapped_gva;
-       pml4e = addr_gpa2hva(vm, vm->pgd);
-       if (!pml4e[index[3]].present)
-               goto unmapped_gva;
-
-       pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
-       if (!pdpe[index[2]].present)
-               goto unmapped_gva;
-
-       pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
-       if (!pde[index[1]].present)
-               goto unmapped_gva;
-
-       pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
-       if (!pte[index[0]].present)
-               goto unmapped_gva;
-
-       return (pte[index[0]].address * vm->page_size) + (gva & 0xfffu);
-
-unmapped_gva:
-       TEST_ASSERT(false, "No mapping for vm virtual address, "
-                   "gva: 0x%lx", gva);
-}
-
-static void kvm_setup_gdt(struct kvm_vm *vm, struct kvm_dtable *dt, int gdt_memslot,
-                         int pgd_memslot)
-{
-       if (!vm->gdt)
-               vm->gdt = vm_vaddr_alloc(vm, getpagesize(),
-                       KVM_UTIL_MIN_VADDR, gdt_memslot, pgd_memslot);
-
-       dt->base = vm->gdt;
-       dt->limit = getpagesize();
-}
-
-static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
-                               int selector, int gdt_memslot,
-                               int pgd_memslot)
-{
-       if (!vm->tss)
-               vm->tss = vm_vaddr_alloc(vm, getpagesize(),
-                       KVM_UTIL_MIN_VADDR, gdt_memslot, pgd_memslot);
-
-       memset(segp, 0, sizeof(*segp));
-       segp->base = vm->tss;
-       segp->limit = 0x67;
-       segp->selector = selector;
-       segp->type = 0xb;
-       segp->present = 1;
-       kvm_seg_fill_gdt_64bit(vm, segp);
-}
-
-void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
-{
-       struct kvm_sregs sregs;
-
-       /* Set mode specific system register values. */
-       vcpu_sregs_get(vm, vcpuid, &sregs);
-
-       sregs.idt.limit = 0;
-
-       kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
-
-       switch (vm->mode) {
-       case VM_MODE_FLAT48PG:
-               sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
-               sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
-               sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
-
-               kvm_seg_set_unusable(&sregs.ldt);
-               kvm_seg_set_kernel_code_64bit(vm, 0x8, &sregs.cs);
-               kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.ds);
-               kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.es);
-               kvm_setup_tss_64bit(vm, &sregs.tr, 0x18, gdt_memslot, pgd_memslot);
-               break;
-
-       default:
-               TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
-       }
-
-       sregs.cr3 = vm->pgd;
-       vcpu_sregs_set(vm, vcpuid, &sregs);
-}
-/* Adds a vCPU with reasonable defaults (i.e., a stack)
- *
- * Input Args:
- *   vcpuid - The id of the VCPU to add to the VM.
- *   guest_code - The vCPU's entry point
- */
-void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
-{
-       struct kvm_mp_state mp_state;
-       struct kvm_regs regs;
-       vm_vaddr_t stack_vaddr;
-       stack_vaddr = vm_vaddr_alloc(vm, DEFAULT_STACK_PGS * getpagesize(),
-                                    DEFAULT_GUEST_STACK_VADDR_MIN, 0, 0);
-
-       /* Create VCPU */
-       vm_vcpu_add(vm, vcpuid, 0, 0);
-
-       /* Setup guest general purpose registers */
-       vcpu_regs_get(vm, vcpuid, &regs);
-       regs.rflags = regs.rflags | 0x2;
-       regs.rsp = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize());
-       regs.rip = (unsigned long) guest_code;
-       vcpu_regs_set(vm, vcpuid, &regs);
-
-       /* Setup the MP state */
-       mp_state.mp_state = 0;
-       vcpu_set_mp_state(vm, vcpuid, &mp_state);
-}
-
-/* VM VCPU CPUID Set
- *
- * Input Args:
- *   vm - Virtual Machine
- *   vcpuid - VCPU id
- *   cpuid - The CPUID values to set.
- *
- * Output Args: None
- *
- * Return: void
- *
- * Set the VCPU's CPUID.
- */
-void vcpu_set_cpuid(struct kvm_vm *vm,
-               uint32_t vcpuid, struct kvm_cpuid2 *cpuid)
-{
-       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
-       int rc;
-
-       TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
-
-       rc = ioctl(vcpu->fd, KVM_SET_CPUID2, cpuid);
-       TEST_ASSERT(rc == 0, "KVM_SET_CPUID2 failed, rc: %i errno: %i",
-                   rc, errno);
-
-}
-/* Create a VM with reasonable defaults
- *
- * Input Args:
- *   vcpuid - The id of the single VCPU to add to the VM.
- *   extra_mem_pages - The size of extra memories to add (this will
- *                     decide how much extra space we will need to
- *                     setup the page tables using mem slot 0)
- *   guest_code - The vCPU's entry point
- *
- * Output Args: None
- *
- * Return:
- *   Pointer to opaque structure that describes the created VM.
- */
-struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
-                                void *guest_code)
-{
-       struct kvm_vm *vm;
-       /*
-        * For x86 the maximum page table size for a memory region
-        * will be when only 4K pages are used.  In that case the
-        * total extra size for page tables (for extra N pages) will
-        * be: N/512+N/512^2+N/512^3+... which is definitely smaller
-        * than N/512*2.
-        */
-       uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
-
-       /* Create VM */
-       vm = vm_create(VM_MODE_FLAT48PG,
-                      DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
-                      O_RDWR);
-
-       /* Setup guest code */
-       kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
-
-       /* Setup IRQ Chip */
-       vm_create_irqchip(vm);
-
-       /* Add the first vCPU. */
-       vm_vcpu_add_default(vm, vcpuid, guest_code);
-
-       return vm;
-}
-
-struct kvm_x86_state {
-       struct kvm_vcpu_events events;
-       struct kvm_mp_state mp_state;
-       struct kvm_regs regs;
-       struct kvm_xsave xsave;
-       struct kvm_xcrs xcrs;
-       struct kvm_sregs sregs;
-       struct kvm_debugregs debugregs;
-       union {
-               struct kvm_nested_state nested;
-               char nested_[16384];
-       };
-       struct kvm_msrs msrs;
-};
-
-static int kvm_get_num_msrs(struct kvm_vm *vm)
-{
-       struct kvm_msr_list nmsrs;
-       int r;
-
-       nmsrs.nmsrs = 0;
-       r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, &nmsrs);
-       TEST_ASSERT(r == -1 && errno == E2BIG, "Unexpected result from KVM_GET_MSR_INDEX_LIST probe, r: %i",
-               r);
-
-       return nmsrs.nmsrs;
-}
-
-struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
-{
-       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
-       struct kvm_msr_list *list;
-       struct kvm_x86_state *state;
-       int nmsrs, r, i;
-       static int nested_size = -1;
-
-       if (nested_size == -1) {
-               nested_size = kvm_check_cap(KVM_CAP_NESTED_STATE);
-               TEST_ASSERT(nested_size <= sizeof(state->nested_),
-                           "Nested state size too big, %i > %zi",
-                           nested_size, sizeof(state->nested_));
-       }
-
-       nmsrs = kvm_get_num_msrs(vm);
-       list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
-       list->nmsrs = nmsrs;
-       r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, list);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MSR_INDEX_LIST, r: %i",
-                r);
-
-       state = malloc(sizeof(*state) + nmsrs * sizeof(state->msrs.entries[0]));
-       r = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, &state->events);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_VCPU_EVENTS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_GET_MP_STATE, &state->mp_state);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MP_STATE, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_GET_REGS, &state->regs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_REGS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_GET_XSAVE, &state->xsave);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i",
-                r);
-
-       if (nested_size) {
-               state->nested.size = sizeof(state->nested_);
-               r = ioctl(vcpu->fd, KVM_GET_NESTED_STATE, &state->nested);
-               TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_NESTED_STATE, r: %i",
-                       r);
-               TEST_ASSERT(state->nested.size <= nested_size,
-                       "Nested state size too big, %i (KVM_CHECK_CAP gave %i)",
-                       state->nested.size, nested_size);
-       } else
-               state->nested.size = 0;
-
-       state->msrs.nmsrs = nmsrs;
-       for (i = 0; i < nmsrs; i++)
-               state->msrs.entries[i].index = list->indices[i];
-       r = ioctl(vcpu->fd, KVM_GET_MSRS, &state->msrs);
-        TEST_ASSERT(r == nmsrs, "Unexpected result from KVM_GET_MSRS, r: %i (failed at %x)",
-                r, r == nmsrs ? -1 : list->indices[r]);
-
-       r = ioctl(vcpu->fd, KVM_GET_DEBUGREGS, &state->debugregs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_DEBUGREGS, r: %i",
-                r);
-
-       free(list);
-       return state;
-}
-
-void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state)
-{
-       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
-       int r;
-
-       if (state->nested.size) {
-               r = ioctl(vcpu->fd, KVM_SET_NESTED_STATE, &state->nested);
-               TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_NESTED_STATE, r: %i",
-                       r);
-       }
-
-       r = ioctl(vcpu->fd, KVM_SET_XSAVE, &state->xsave);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_SET_MSRS, &state->msrs);
-        TEST_ASSERT(r == state->msrs.nmsrs, "Unexpected result from KVM_SET_MSRS, r: %i (failed at %x)",
-                r, r == state->msrs.nmsrs ? -1 : state->msrs.entries[r].index);
-
-       r = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, &state->events);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_VCPU_EVENTS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_SET_MP_STATE, &state->mp_state);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_MP_STATE, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_SET_DEBUGREGS, &state->debugregs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_DEBUGREGS, r: %i",
-                r);
-
-       r = ioctl(vcpu->fd, KVM_SET_REGS, &state->regs);
-        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_REGS, r: %i",
-                r);
-}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
new file mode 100644 (file)
index 0000000..79c2c5c
--- /dev/null
@@ -0,0 +1,888 @@
+/*
+ * tools/testing/selftests/kvm/lib/x86_64/processor.c
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_name */
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "../kvm_util_internal.h"
+#include "processor.h"
+
+/* Minimum physical address used for virtual translation tables. */
+#define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
+
+/* Virtual translation table structure declarations */
+struct pageMapL4Entry {
+       uint64_t present:1;
+       uint64_t writable:1;
+       uint64_t user:1;
+       uint64_t write_through:1;
+       uint64_t cache_disable:1;
+       uint64_t accessed:1;
+       uint64_t ignored_06:1;
+       uint64_t page_size:1;
+       uint64_t ignored_11_08:4;
+       uint64_t address:40;
+       uint64_t ignored_62_52:11;
+       uint64_t execute_disable:1;
+};
+
+struct pageDirectoryPointerEntry {
+       uint64_t present:1;
+       uint64_t writable:1;
+       uint64_t user:1;
+       uint64_t write_through:1;
+       uint64_t cache_disable:1;
+       uint64_t accessed:1;
+       uint64_t ignored_06:1;
+       uint64_t page_size:1;
+       uint64_t ignored_11_08:4;
+       uint64_t address:40;
+       uint64_t ignored_62_52:11;
+       uint64_t execute_disable:1;
+};
+
+struct pageDirectoryEntry {
+       uint64_t present:1;
+       uint64_t writable:1;
+       uint64_t user:1;
+       uint64_t write_through:1;
+       uint64_t cache_disable:1;
+       uint64_t accessed:1;
+       uint64_t ignored_06:1;
+       uint64_t page_size:1;
+       uint64_t ignored_11_08:4;
+       uint64_t address:40;
+       uint64_t ignored_62_52:11;
+       uint64_t execute_disable:1;
+};
+
+struct pageTableEntry {
+       uint64_t present:1;
+       uint64_t writable:1;
+       uint64_t user:1;
+       uint64_t write_through:1;
+       uint64_t cache_disable:1;
+       uint64_t accessed:1;
+       uint64_t dirty:1;
+       uint64_t reserved_07:1;
+       uint64_t global:1;
+       uint64_t ignored_11_09:3;
+       uint64_t address:40;
+       uint64_t ignored_62_52:11;
+       uint64_t execute_disable:1;
+};
+
+/* Register Dump
+ *
+ * Input Args:
+ *   indent - Left margin indent amount
+ *   regs - register
+ *
+ * Output Args:
+ *   stream - Output FILE stream
+ *
+ * Return: None
+ *
+ * Dumps the state of the registers given by regs, to the FILE stream
+ * given by steam.
+ */
+void regs_dump(FILE *stream, struct kvm_regs *regs,
+              uint8_t indent)
+{
+       fprintf(stream, "%*srax: 0x%.16llx rbx: 0x%.16llx "
+               "rcx: 0x%.16llx rdx: 0x%.16llx\n",
+               indent, "",
+               regs->rax, regs->rbx, regs->rcx, regs->rdx);
+       fprintf(stream, "%*srsi: 0x%.16llx rdi: 0x%.16llx "
+               "rsp: 0x%.16llx rbp: 0x%.16llx\n",
+               indent, "",
+               regs->rsi, regs->rdi, regs->rsp, regs->rbp);
+       fprintf(stream, "%*sr8:  0x%.16llx r9:  0x%.16llx "
+               "r10: 0x%.16llx r11: 0x%.16llx\n",
+               indent, "",
+               regs->r8, regs->r9, regs->r10, regs->r11);
+       fprintf(stream, "%*sr12: 0x%.16llx r13: 0x%.16llx "
+               "r14: 0x%.16llx r15: 0x%.16llx\n",
+               indent, "",
+               regs->r12, regs->r13, regs->r14, regs->r15);
+       fprintf(stream, "%*srip: 0x%.16llx rfl: 0x%.16llx\n",
+               indent, "",
+               regs->rip, regs->rflags);
+}
+
+/* Segment Dump
+ *
+ * Input Args:
+ *   indent - Left margin indent amount
+ *   segment - KVM segment
+ *
+ * Output Args:
+ *   stream - Output FILE stream
+ *
+ * Return: None
+ *
+ * Dumps the state of the KVM segment given by segment, to the FILE stream
+ * given by steam.
+ */
+static void segment_dump(FILE *stream, struct kvm_segment *segment,
+                        uint8_t indent)
+{
+       fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.8x "
+               "selector: 0x%.4x type: 0x%.2x\n",
+               indent, "", segment->base, segment->limit,
+               segment->selector, segment->type);
+       fprintf(stream, "%*spresent: 0x%.2x dpl: 0x%.2x "
+               "db: 0x%.2x s: 0x%.2x l: 0x%.2x\n",
+               indent, "", segment->present, segment->dpl,
+               segment->db, segment->s, segment->l);
+       fprintf(stream, "%*sg: 0x%.2x avl: 0x%.2x "
+               "unusable: 0x%.2x padding: 0x%.2x\n",
+               indent, "", segment->g, segment->avl,
+               segment->unusable, segment->padding);
+}
+
+/* dtable Dump
+ *
+ * Input Args:
+ *   indent - Left margin indent amount
+ *   dtable - KVM dtable
+ *
+ * Output Args:
+ *   stream - Output FILE stream
+ *
+ * Return: None
+ *
+ * Dumps the state of the KVM dtable given by dtable, to the FILE stream
+ * given by steam.
+ */
+static void dtable_dump(FILE *stream, struct kvm_dtable *dtable,
+                       uint8_t indent)
+{
+       fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.4x "
+               "padding: 0x%.4x 0x%.4x 0x%.4x\n",
+               indent, "", dtable->base, dtable->limit,
+               dtable->padding[0], dtable->padding[1], dtable->padding[2]);
+}
+
+/* System Register Dump
+ *
+ * Input Args:
+ *   indent - Left margin indent amount
+ *   sregs - System registers
+ *
+ * Output Args:
+ *   stream - Output FILE stream
+ *
+ * Return: None
+ *
+ * Dumps the state of the system registers given by sregs, to the FILE stream
+ * given by steam.
+ */
+void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
+               uint8_t indent)
+{
+       unsigned int i;
+
+       fprintf(stream, "%*scs:\n", indent, "");
+       segment_dump(stream, &sregs->cs, indent + 2);
+       fprintf(stream, "%*sds:\n", indent, "");
+       segment_dump(stream, &sregs->ds, indent + 2);
+       fprintf(stream, "%*ses:\n", indent, "");
+       segment_dump(stream, &sregs->es, indent + 2);
+       fprintf(stream, "%*sfs:\n", indent, "");
+       segment_dump(stream, &sregs->fs, indent + 2);
+       fprintf(stream, "%*sgs:\n", indent, "");
+       segment_dump(stream, &sregs->gs, indent + 2);
+       fprintf(stream, "%*sss:\n", indent, "");
+       segment_dump(stream, &sregs->ss, indent + 2);
+       fprintf(stream, "%*str:\n", indent, "");
+       segment_dump(stream, &sregs->tr, indent + 2);
+       fprintf(stream, "%*sldt:\n", indent, "");
+       segment_dump(stream, &sregs->ldt, indent + 2);
+
+       fprintf(stream, "%*sgdt:\n", indent, "");
+       dtable_dump(stream, &sregs->gdt, indent + 2);
+       fprintf(stream, "%*sidt:\n", indent, "");
+       dtable_dump(stream, &sregs->idt, indent + 2);
+
+       fprintf(stream, "%*scr0: 0x%.16llx cr2: 0x%.16llx "
+               "cr3: 0x%.16llx cr4: 0x%.16llx\n",
+               indent, "",
+               sregs->cr0, sregs->cr2, sregs->cr3, sregs->cr4);
+       fprintf(stream, "%*scr8: 0x%.16llx efer: 0x%.16llx "
+               "apic_base: 0x%.16llx\n",
+               indent, "",
+               sregs->cr8, sregs->efer, sregs->apic_base);
+
+       fprintf(stream, "%*sinterrupt_bitmap:\n", indent, "");
+       for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++) {
+               fprintf(stream, "%*s%.16llx\n", indent + 2, "",
+                       sregs->interrupt_bitmap[i]);
+       }
+}
+
+void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
+{
+       int rc;
+
+       TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
+               "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
+
+       /* If needed, create page map l4 table. */
+       if (!vm->pgd_created) {
+               vm_paddr_t paddr = vm_phy_page_alloc(vm,
+                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
+               vm->pgd = paddr;
+               vm->pgd_created = true;
+       }
+}
+
+/* VM Virtual Page Map
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   vaddr - VM Virtual Address
+ *   paddr - VM Physical Address
+ *   pgd_memslot - Memory region slot for new virtual translation tables
+ *
+ * Output Args: None
+ *
+ * Return: None
+ *
+ * Within the VM given by vm, creates a virtual translation for the page
+ * starting at vaddr to the page starting at paddr.
+ */
+void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
+       uint32_t pgd_memslot)
+{
+       uint16_t index[4];
+       struct pageMapL4Entry *pml4e;
+
+       TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
+               "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
+
+       TEST_ASSERT((vaddr % vm->page_size) == 0,
+               "Virtual address not on page boundary,\n"
+               "  vaddr: 0x%lx vm->page_size: 0x%x",
+               vaddr, vm->page_size);
+       TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
+               (vaddr >> vm->page_shift)),
+               "Invalid virtual address, vaddr: 0x%lx",
+               vaddr);
+       TEST_ASSERT((paddr % vm->page_size) == 0,
+               "Physical address not on page boundary,\n"
+               "  paddr: 0x%lx vm->page_size: 0x%x",
+               paddr, vm->page_size);
+       TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
+               "Physical address beyond beyond maximum supported,\n"
+               "  paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
+               paddr, vm->max_gfn, vm->page_size);
+
+       index[0] = (vaddr >> 12) & 0x1ffu;
+       index[1] = (vaddr >> 21) & 0x1ffu;
+       index[2] = (vaddr >> 30) & 0x1ffu;
+       index[3] = (vaddr >> 39) & 0x1ffu;
+
+       /* Allocate page directory pointer table if not present. */
+       pml4e = addr_gpa2hva(vm, vm->pgd);
+       if (!pml4e[index[3]].present) {
+               pml4e[index[3]].address = vm_phy_page_alloc(vm,
+                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
+                       >> vm->page_shift;
+               pml4e[index[3]].writable = true;
+               pml4e[index[3]].present = true;
+       }
+
+       /* Allocate page directory table if not present. */
+       struct pageDirectoryPointerEntry *pdpe;
+       pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
+       if (!pdpe[index[2]].present) {
+               pdpe[index[2]].address = vm_phy_page_alloc(vm,
+                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
+                       >> vm->page_shift;
+               pdpe[index[2]].writable = true;
+               pdpe[index[2]].present = true;
+       }
+
+       /* Allocate page table if not present. */
+       struct pageDirectoryEntry *pde;
+       pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
+       if (!pde[index[1]].present) {
+               pde[index[1]].address = vm_phy_page_alloc(vm,
+                       KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
+                       >> vm->page_shift;
+               pde[index[1]].writable = true;
+               pde[index[1]].present = true;
+       }
+
+       /* Fill in page table entry. */
+       struct pageTableEntry *pte;
+       pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
+       pte[index[0]].address = paddr >> vm->page_shift;
+       pte[index[0]].writable = true;
+       pte[index[0]].present = 1;
+}
+
+/* Virtual Translation Tables Dump
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   indent - Left margin indent amount
+ *
+ * Output Args:
+ *   stream - Output FILE stream
+ *
+ * Return: None
+ *
+ * Dumps to the FILE stream given by stream, the contents of all the
+ * virtual translation tables for the VM given by vm.
+ */
+void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
+{
+       struct pageMapL4Entry *pml4e, *pml4e_start;
+       struct pageDirectoryPointerEntry *pdpe, *pdpe_start;
+       struct pageDirectoryEntry *pde, *pde_start;
+       struct pageTableEntry *pte, *pte_start;
+
+       if (!vm->pgd_created)
+               return;
+
+       fprintf(stream, "%*s                                          "
+               "                no\n", indent, "");
+       fprintf(stream, "%*s      index hvaddr         gpaddr         "
+               "addr         w exec dirty\n",
+               indent, "");
+       pml4e_start = (struct pageMapL4Entry *) addr_gpa2hva(vm,
+               vm->pgd);
+       for (uint16_t n1 = 0; n1 <= 0x1ffu; n1++) {
+               pml4e = &pml4e_start[n1];
+               if (!pml4e->present)
+                       continue;
+               fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10lx %u "
+                       " %u\n",
+                       indent, "",
+                       pml4e - pml4e_start, pml4e,
+                       addr_hva2gpa(vm, pml4e), (uint64_t) pml4e->address,
+                       pml4e->writable, pml4e->execute_disable);
+
+               pdpe_start = addr_gpa2hva(vm, pml4e->address
+                       * vm->page_size);
+               for (uint16_t n2 = 0; n2 <= 0x1ffu; n2++) {
+                       pdpe = &pdpe_start[n2];
+                       if (!pdpe->present)
+                               continue;
+                       fprintf(stream, "%*spdpe  0x%-3zx %p 0x%-12lx 0x%-10lx "
+                               "%u  %u\n",
+                               indent, "",
+                               pdpe - pdpe_start, pdpe,
+                               addr_hva2gpa(vm, pdpe),
+                               (uint64_t) pdpe->address, pdpe->writable,
+                               pdpe->execute_disable);
+
+                       pde_start = addr_gpa2hva(vm,
+                               pdpe->address * vm->page_size);
+                       for (uint16_t n3 = 0; n3 <= 0x1ffu; n3++) {
+                               pde = &pde_start[n3];
+                               if (!pde->present)
+                                       continue;
+                               fprintf(stream, "%*spde   0x%-3zx %p "
+                                       "0x%-12lx 0x%-10lx %u  %u\n",
+                                       indent, "", pde - pde_start, pde,
+                                       addr_hva2gpa(vm, pde),
+                                       (uint64_t) pde->address, pde->writable,
+                                       pde->execute_disable);
+
+                               pte_start = addr_gpa2hva(vm,
+                                       pde->address * vm->page_size);
+                               for (uint16_t n4 = 0; n4 <= 0x1ffu; n4++) {
+                                       pte = &pte_start[n4];
+                                       if (!pte->present)
+                                               continue;
+                                       fprintf(stream, "%*spte   0x%-3zx %p "
+                                               "0x%-12lx 0x%-10lx %u  %u "
+                                               "    %u    0x%-10lx\n",
+                                               indent, "",
+                                               pte - pte_start, pte,
+                                               addr_hva2gpa(vm, pte),
+                                               (uint64_t) pte->address,
+                                               pte->writable,
+                                               pte->execute_disable,
+                                               pte->dirty,
+                                               ((uint64_t) n1 << 27)
+                                                       | ((uint64_t) n2 << 18)
+                                                       | ((uint64_t) n3 << 9)
+                                                       | ((uint64_t) n4));
+                               }
+                       }
+               }
+       }
+}
+
+/* Set Unusable Segment
+ *
+ * Input Args: None
+ *
+ * Output Args:
+ *   segp - Pointer to segment register
+ *
+ * Return: None
+ *
+ * Sets the segment register pointed to by segp to an unusable state.
+ */
+static void kvm_seg_set_unusable(struct kvm_segment *segp)
+{
+       memset(segp, 0, sizeof(*segp));
+       segp->unusable = true;
+}
+
+static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
+{
+       void *gdt = addr_gva2hva(vm, vm->gdt);
+       struct desc64 *desc = gdt + (segp->selector >> 3) * 8;
+
+       desc->limit0 = segp->limit & 0xFFFF;
+       desc->base0 = segp->base & 0xFFFF;
+       desc->base1 = segp->base >> 16;
+       desc->s = segp->s;
+       desc->type = segp->type;
+       desc->dpl = segp->dpl;
+       desc->p = segp->present;
+       desc->limit1 = segp->limit >> 16;
+       desc->l = segp->l;
+       desc->db = segp->db;
+       desc->g = segp->g;
+       desc->base2 = segp->base >> 24;
+       if (!segp->s)
+               desc->base3 = segp->base >> 32;
+}
+
+
+/* Set Long Mode Flat Kernel Code Segment
+ *
+ * Input Args:
+ *   vm - VM whose GDT is being filled, or NULL to only write segp
+ *   selector - selector value
+ *
+ * Output Args:
+ *   segp - Pointer to KVM segment
+ *
+ * Return: None
+ *
+ * Sets up the KVM segment pointed to by segp, to be a code segment
+ * with the selector value given by selector.
+ */
+static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
+       struct kvm_segment *segp)
+{
+       memset(segp, 0, sizeof(*segp));
+       segp->selector = selector;
+       segp->limit = 0xFFFFFFFFu;
+       segp->s = 0x1; /* kTypeCodeData */
+       segp->type = 0x08 | 0x01 | 0x02; /* kFlagCode | kFlagCodeAccessed
+                                         * | kFlagCodeReadable
+                                         */
+       segp->g = true;
+       segp->l = true;
+       segp->present = 1;
+       if (vm)
+               kvm_seg_fill_gdt_64bit(vm, segp);
+}
+
+/* Set Long Mode Flat Kernel Data Segment
+ *
+ * Input Args:
+ *   vm - VM whose GDT is being filled, or NULL to only write segp
+ *   selector - selector value
+ *
+ * Output Args:
+ *   segp - Pointer to KVM segment
+ *
+ * Return: None
+ *
+ * Sets up the KVM segment pointed to by segp, to be a data segment
+ * with the selector value given by selector.
+ */
+static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
+       struct kvm_segment *segp)
+{
+       memset(segp, 0, sizeof(*segp));
+       segp->selector = selector;
+       segp->limit = 0xFFFFFFFFu;
+       segp->s = 0x1; /* kTypeCodeData */
+       segp->type = 0x00 | 0x01 | 0x02; /* kFlagData | kFlagDataAccessed
+                                         * | kFlagDataWritable
+                                         */
+       segp->g = true;
+       segp->present = true;
+       if (vm)
+               kvm_seg_fill_gdt_64bit(vm, segp);
+}
+
+/* Address Guest Virtual to Guest Physical
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   gpa - VM virtual address
+ *
+ * Output Args: None
+ *
+ * Return:
+ *   Equivalent VM physical address
+ *
+ * Translates the VM virtual address given by gva to a VM physical
+ * address and then locates the memory region containing the VM
+ * physical address, within the VM given by vm.  When found, the host
+ * virtual address providing the memory to the vm physical address is returned.
+ * A TEST_ASSERT failure occurs if no region containing translated
+ * VM virtual address exists.
+ */
+vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
+{
+       uint16_t index[4];
+       struct pageMapL4Entry *pml4e;
+       struct pageDirectoryPointerEntry *pdpe;
+       struct pageDirectoryEntry *pde;
+       struct pageTableEntry *pte;
+       void *hva;
+
+       TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
+               "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
+
+       index[0] = (gva >> 12) & 0x1ffu;
+       index[1] = (gva >> 21) & 0x1ffu;
+       index[2] = (gva >> 30) & 0x1ffu;
+       index[3] = (gva >> 39) & 0x1ffu;
+
+       if (!vm->pgd_created)
+               goto unmapped_gva;
+       pml4e = addr_gpa2hva(vm, vm->pgd);
+       if (!pml4e[index[3]].present)
+               goto unmapped_gva;
+
+       pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
+       if (!pdpe[index[2]].present)
+               goto unmapped_gva;
+
+       pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
+       if (!pde[index[1]].present)
+               goto unmapped_gva;
+
+       pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
+       if (!pte[index[0]].present)
+               goto unmapped_gva;
+
+       return (pte[index[0]].address * vm->page_size) + (gva & 0xfffu);
+
+unmapped_gva:
+       TEST_ASSERT(false, "No mapping for vm virtual address, "
+                   "gva: 0x%lx", gva);
+}
+
+static void kvm_setup_gdt(struct kvm_vm *vm, struct kvm_dtable *dt, int gdt_memslot,
+                         int pgd_memslot)
+{
+       if (!vm->gdt)
+               vm->gdt = vm_vaddr_alloc(vm, getpagesize(),
+                       KVM_UTIL_MIN_VADDR, gdt_memslot, pgd_memslot);
+
+       dt->base = vm->gdt;
+       dt->limit = getpagesize();
+}
+
+static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
+                               int selector, int gdt_memslot,
+                               int pgd_memslot)
+{
+       if (!vm->tss)
+               vm->tss = vm_vaddr_alloc(vm, getpagesize(),
+                       KVM_UTIL_MIN_VADDR, gdt_memslot, pgd_memslot);
+
+       memset(segp, 0, sizeof(*segp));
+       segp->base = vm->tss;
+       segp->limit = 0x67;
+       segp->selector = selector;
+       segp->type = 0xb;
+       segp->present = 1;
+       kvm_seg_fill_gdt_64bit(vm, segp);
+}
+
+void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
+{
+       struct kvm_sregs sregs;
+
+       /* Set mode specific system register values. */
+       vcpu_sregs_get(vm, vcpuid, &sregs);
+
+       sregs.idt.limit = 0;
+
+       kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
+
+       switch (vm->mode) {
+       case VM_MODE_FLAT48PG:
+               sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
+               sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
+               sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
+
+               kvm_seg_set_unusable(&sregs.ldt);
+               kvm_seg_set_kernel_code_64bit(vm, 0x8, &sregs.cs);
+               kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.ds);
+               kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.es);
+               kvm_setup_tss_64bit(vm, &sregs.tr, 0x18, gdt_memslot, pgd_memslot);
+               break;
+
+       default:
+               TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
+       }
+
+       sregs.cr3 = vm->pgd;
+       vcpu_sregs_set(vm, vcpuid, &sregs);
+}
+/* Adds a vCPU with reasonable defaults (i.e., a stack)
+ *
+ * Input Args:
+ *   vcpuid - The id of the VCPU to add to the VM.
+ *   guest_code - The vCPU's entry point
+ */
+void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
+{
+       struct kvm_mp_state mp_state;
+       struct kvm_regs regs;
+       vm_vaddr_t stack_vaddr;
+       stack_vaddr = vm_vaddr_alloc(vm, DEFAULT_STACK_PGS * getpagesize(),
+                                    DEFAULT_GUEST_STACK_VADDR_MIN, 0, 0);
+
+       /* Create VCPU */
+       vm_vcpu_add(vm, vcpuid, 0, 0);
+
+       /* Setup guest general purpose registers */
+       vcpu_regs_get(vm, vcpuid, &regs);
+       regs.rflags = regs.rflags | 0x2;
+       regs.rsp = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize());
+       regs.rip = (unsigned long) guest_code;
+       vcpu_regs_set(vm, vcpuid, &regs);
+
+       /* Setup the MP state */
+       mp_state.mp_state = 0;
+       vcpu_set_mp_state(vm, vcpuid, &mp_state);
+}
+
+/* VM VCPU CPUID Set
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   vcpuid - VCPU id
+ *   cpuid - The CPUID values to set.
+ *
+ * Output Args: None
+ *
+ * Return: void
+ *
+ * Set the VCPU's CPUID.
+ */
+void vcpu_set_cpuid(struct kvm_vm *vm,
+               uint32_t vcpuid, struct kvm_cpuid2 *cpuid)
+{
+       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
+       int rc;
+
+       TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
+
+       rc = ioctl(vcpu->fd, KVM_SET_CPUID2, cpuid);
+       TEST_ASSERT(rc == 0, "KVM_SET_CPUID2 failed, rc: %i errno: %i",
+                   rc, errno);
+
+}
+/* Create a VM with reasonable defaults
+ *
+ * Input Args:
+ *   vcpuid - The id of the single VCPU to add to the VM.
+ *   extra_mem_pages - The size of extra memories to add (this will
+ *                     decide how much extra space we will need to
+ *                     setup the page tables using mem slot 0)
+ *   guest_code - The vCPU's entry point
+ *
+ * Output Args: None
+ *
+ * Return:
+ *   Pointer to opaque structure that describes the created VM.
+ */
+struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
+                                void *guest_code)
+{
+       struct kvm_vm *vm;
+       /*
+        * For x86 the maximum page table size for a memory region
+        * will be when only 4K pages are used.  In that case the
+        * total extra size for page tables (for extra N pages) will
+        * be: N/512+N/512^2+N/512^3+... which is definitely smaller
+        * than N/512*2.
+        */
+       uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
+
+       /* Create VM */
+       vm = vm_create(VM_MODE_FLAT48PG,
+                      DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
+                      O_RDWR);
+
+       /* Setup guest code */
+       kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
+
+       /* Setup IRQ Chip */
+       vm_create_irqchip(vm);
+
+       /* Add the first vCPU. */
+       vm_vcpu_add_default(vm, vcpuid, guest_code);
+
+       return vm;
+}
+
+struct kvm_x86_state {
+       struct kvm_vcpu_events events;
+       struct kvm_mp_state mp_state;
+       struct kvm_regs regs;
+       struct kvm_xsave xsave;
+       struct kvm_xcrs xcrs;
+       struct kvm_sregs sregs;
+       struct kvm_debugregs debugregs;
+       union {
+               struct kvm_nested_state nested;
+               char nested_[16384];
+       };
+       struct kvm_msrs msrs;
+};
+
+static int kvm_get_num_msrs(struct kvm_vm *vm)
+{
+       struct kvm_msr_list nmsrs;
+       int r;
+
+       nmsrs.nmsrs = 0;
+       r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, &nmsrs);
+       TEST_ASSERT(r == -1 && errno == E2BIG, "Unexpected result from KVM_GET_MSR_INDEX_LIST probe, r: %i",
+               r);
+
+       return nmsrs.nmsrs;
+}
+
+struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
+{
+       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
+       struct kvm_msr_list *list;
+       struct kvm_x86_state *state;
+       int nmsrs, r, i;
+       static int nested_size = -1;
+
+       if (nested_size == -1) {
+               nested_size = kvm_check_cap(KVM_CAP_NESTED_STATE);
+               TEST_ASSERT(nested_size <= sizeof(state->nested_),
+                           "Nested state size too big, %i > %zi",
+                           nested_size, sizeof(state->nested_));
+       }
+
+       nmsrs = kvm_get_num_msrs(vm);
+       list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
+       list->nmsrs = nmsrs;
+       r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, list);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MSR_INDEX_LIST, r: %i",
+                r);
+
+       state = malloc(sizeof(*state) + nmsrs * sizeof(state->msrs.entries[0]));
+       r = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, &state->events);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_VCPU_EVENTS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_GET_MP_STATE, &state->mp_state);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MP_STATE, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_GET_REGS, &state->regs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_REGS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_GET_XSAVE, &state->xsave);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i",
+                r);
+
+       if (nested_size) {
+               state->nested.size = sizeof(state->nested_);
+               r = ioctl(vcpu->fd, KVM_GET_NESTED_STATE, &state->nested);
+               TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_NESTED_STATE, r: %i",
+                       r);
+               TEST_ASSERT(state->nested.size <= nested_size,
+                       "Nested state size too big, %i (KVM_CHECK_CAP gave %i)",
+                       state->nested.size, nested_size);
+       } else
+               state->nested.size = 0;
+
+       state->msrs.nmsrs = nmsrs;
+       for (i = 0; i < nmsrs; i++)
+               state->msrs.entries[i].index = list->indices[i];
+       r = ioctl(vcpu->fd, KVM_GET_MSRS, &state->msrs);
+        TEST_ASSERT(r == nmsrs, "Unexpected result from KVM_GET_MSRS, r: %i (failed at %x)",
+                r, r == nmsrs ? -1 : list->indices[r]);
+
+       r = ioctl(vcpu->fd, KVM_GET_DEBUGREGS, &state->debugregs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_DEBUGREGS, r: %i",
+                r);
+
+       free(list);
+       return state;
+}
+
+void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state)
+{
+       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
+       int r;
+
+       if (state->nested.size) {
+               r = ioctl(vcpu->fd, KVM_SET_NESTED_STATE, &state->nested);
+               TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_NESTED_STATE, r: %i",
+                       r);
+       }
+
+       r = ioctl(vcpu->fd, KVM_SET_XSAVE, &state->xsave);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_SET_MSRS, &state->msrs);
+        TEST_ASSERT(r == state->msrs.nmsrs, "Unexpected result from KVM_SET_MSRS, r: %i (failed at %x)",
+                r, r == state->msrs.nmsrs ? -1 : state->msrs.entries[r].index);
+
+       r = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, &state->events);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_VCPU_EVENTS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_SET_MP_STATE, &state->mp_state);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_MP_STATE, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_SET_DEBUGREGS, &state->debugregs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_DEBUGREGS, r: %i",
+                r);
+
+       r = ioctl(vcpu->fd, KVM_SET_REGS, &state->regs);
+        TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_REGS, r: %i",
+                r);
+}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/vmx.c b/tools/testing/selftests/kvm/lib/x86_64/vmx.c
new file mode 100644 (file)
index 0000000..d7c4014
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * tools/testing/selftests/kvm/lib/x86_64/vmx.c
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_name */
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+#include "vmx.h"
+
+/* Allocate memory regions for nested VMX tests.
+ *
+ * Input Args:
+ *   vm - The VM to allocate guest-virtual addresses in.
+ *
+ * Output Args:
+ *   p_vmx_gva - The guest virtual address for the struct vmx_pages.
+ *
+ * Return:
+ *   Pointer to structure with the addresses of the VMX areas.
+ */
+struct vmx_pages *
+vcpu_alloc_vmx(struct kvm_vm *vm, vm_vaddr_t *p_vmx_gva)
+{
+       vm_vaddr_t vmx_gva = vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       struct vmx_pages *vmx = addr_gva2hva(vm, vmx_gva);
+
+       /* Setup of a region of guest memory for the vmxon region. */
+       vmx->vmxon = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       vmx->vmxon_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmxon);
+       vmx->vmxon_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmxon);
+
+       /* Setup of a region of guest memory for a vmcs. */
+       vmx->vmcs = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       vmx->vmcs_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmcs);
+       vmx->vmcs_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmcs);
+
+       /* Setup of a region of guest memory for the MSR bitmap. */
+       vmx->msr = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       vmx->msr_hva = addr_gva2hva(vm, (uintptr_t)vmx->msr);
+       vmx->msr_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->msr);
+       memset(vmx->msr_hva, 0, getpagesize());
+
+       /* Setup of a region of guest memory for the shadow VMCS. */
+       vmx->shadow_vmcs = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       vmx->shadow_vmcs_hva = addr_gva2hva(vm, (uintptr_t)vmx->shadow_vmcs);
+       vmx->shadow_vmcs_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->shadow_vmcs);
+
+       /* Setup of a region of guest memory for the VMREAD and VMWRITE bitmaps. */
+       vmx->vmread = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       vmx->vmread_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmread);
+       vmx->vmread_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmread);
+       memset(vmx->vmread_hva, 0, getpagesize());
+
+       vmx->vmwrite = (void *)vm_vaddr_alloc(vm, getpagesize(), 0x10000, 0, 0);
+       vmx->vmwrite_hva = addr_gva2hva(vm, (uintptr_t)vmx->vmwrite);
+       vmx->vmwrite_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->vmwrite);
+       memset(vmx->vmwrite_hva, 0, getpagesize());
+
+       *p_vmx_gva = vmx_gva;
+       return vmx;
+}
+
+bool prepare_for_vmx_operation(struct vmx_pages *vmx)
+{
+       uint64_t feature_control;
+       uint64_t required;
+       unsigned long cr0;
+       unsigned long cr4;
+
+       /*
+        * Ensure bits in CR0 and CR4 are valid in VMX operation:
+        * - Bit X is 1 in _FIXED0: bit X is fixed to 1 in CRx.
+        * - Bit X is 0 in _FIXED1: bit X is fixed to 0 in CRx.
+        */
+       __asm__ __volatile__("mov %%cr0, %0" : "=r"(cr0) : : "memory");
+       cr0 &= rdmsr(MSR_IA32_VMX_CR0_FIXED1);
+       cr0 |= rdmsr(MSR_IA32_VMX_CR0_FIXED0);
+       __asm__ __volatile__("mov %0, %%cr0" : : "r"(cr0) : "memory");
+
+       __asm__ __volatile__("mov %%cr4, %0" : "=r"(cr4) : : "memory");
+       cr4 &= rdmsr(MSR_IA32_VMX_CR4_FIXED1);
+       cr4 |= rdmsr(MSR_IA32_VMX_CR4_FIXED0);
+       /* Enable VMX operation */
+       cr4 |= X86_CR4_VMXE;
+       __asm__ __volatile__("mov %0, %%cr4" : : "r"(cr4) : "memory");
+
+       /*
+        * Configure IA32_FEATURE_CONTROL MSR to allow VMXON:
+        *  Bit 0: Lock bit. If clear, VMXON causes a #GP.
+        *  Bit 2: Enables VMXON outside of SMX operation. If clear, VMXON
+        *    outside of SMX causes a #GP.
+        */
+       required = FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+       required |= FEATURE_CONTROL_LOCKED;
+       feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
+       if ((feature_control & required) != required)
+               wrmsr(MSR_IA32_FEATURE_CONTROL, feature_control | required);
+
+       /* Enter VMX root operation. */
+       *(uint32_t *)(vmx->vmxon) = vmcs_revision();
+       if (vmxon(vmx->vmxon_gpa))
+               return false;
+
+       /* Load a VMCS. */
+       *(uint32_t *)(vmx->vmcs) = vmcs_revision();
+       if (vmclear(vmx->vmcs_gpa))
+               return false;
+
+       if (vmptrld(vmx->vmcs_gpa))
+               return false;
+
+       /* Setup shadow VMCS, do not load it yet. */
+       *(uint32_t *)(vmx->shadow_vmcs) = vmcs_revision() | 0x80000000ul;
+       if (vmclear(vmx->shadow_vmcs_gpa))
+               return false;
+
+       return true;
+}
+
+/*
+ * Initialize the control fields to the most basic settings possible.
+ */
+static inline void init_vmcs_control_fields(struct vmx_pages *vmx)
+{
+       vmwrite(VIRTUAL_PROCESSOR_ID, 0);
+       vmwrite(POSTED_INTR_NV, 0);
+
+       vmwrite(PIN_BASED_VM_EXEC_CONTROL, rdmsr(MSR_IA32_VMX_TRUE_PINBASED_CTLS));
+       if (!vmwrite(SECONDARY_VM_EXEC_CONTROL, 0))
+               vmwrite(CPU_BASED_VM_EXEC_CONTROL,
+                       rdmsr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS) | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
+       else
+               vmwrite(CPU_BASED_VM_EXEC_CONTROL, rdmsr(MSR_IA32_VMX_TRUE_PROCBASED_CTLS));
+       vmwrite(EXCEPTION_BITMAP, 0);
+       vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0);
+       vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, -1); /* Never match */
+       vmwrite(CR3_TARGET_COUNT, 0);
+       vmwrite(VM_EXIT_CONTROLS, rdmsr(MSR_IA32_VMX_EXIT_CTLS) |
+               VM_EXIT_HOST_ADDR_SPACE_SIZE);    /* 64-bit host */
+       vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
+       vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0);
+       vmwrite(VM_ENTRY_CONTROLS, rdmsr(MSR_IA32_VMX_ENTRY_CTLS) |
+               VM_ENTRY_IA32E_MODE);             /* 64-bit guest */
+       vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0);
+       vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0);
+       vmwrite(TPR_THRESHOLD, 0);
+
+       vmwrite(CR0_GUEST_HOST_MASK, 0);
+       vmwrite(CR4_GUEST_HOST_MASK, 0);
+       vmwrite(CR0_READ_SHADOW, get_cr0());
+       vmwrite(CR4_READ_SHADOW, get_cr4());
+
+       vmwrite(MSR_BITMAP, vmx->msr_gpa);
+       vmwrite(VMREAD_BITMAP, vmx->vmread_gpa);
+       vmwrite(VMWRITE_BITMAP, vmx->vmwrite_gpa);
+}
+
+/*
+ * Initialize the host state fields based on the current host state, with
+ * the exception of HOST_RSP and HOST_RIP, which should be set by vmlaunch
+ * or vmresume.
+ */
+static inline void init_vmcs_host_state(void)
+{
+       uint32_t exit_controls = vmreadz(VM_EXIT_CONTROLS);
+
+       vmwrite(HOST_ES_SELECTOR, get_es());
+       vmwrite(HOST_CS_SELECTOR, get_cs());
+       vmwrite(HOST_SS_SELECTOR, get_ss());
+       vmwrite(HOST_DS_SELECTOR, get_ds());
+       vmwrite(HOST_FS_SELECTOR, get_fs());
+       vmwrite(HOST_GS_SELECTOR, get_gs());
+       vmwrite(HOST_TR_SELECTOR, get_tr());
+
+       if (exit_controls & VM_EXIT_LOAD_IA32_PAT)
+               vmwrite(HOST_IA32_PAT, rdmsr(MSR_IA32_CR_PAT));
+       if (exit_controls & VM_EXIT_LOAD_IA32_EFER)
+               vmwrite(HOST_IA32_EFER, rdmsr(MSR_EFER));
+       if (exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
+               vmwrite(HOST_IA32_PERF_GLOBAL_CTRL,
+                       rdmsr(MSR_CORE_PERF_GLOBAL_CTRL));
+
+       vmwrite(HOST_IA32_SYSENTER_CS, rdmsr(MSR_IA32_SYSENTER_CS));
+
+       vmwrite(HOST_CR0, get_cr0());
+       vmwrite(HOST_CR3, get_cr3());
+       vmwrite(HOST_CR4, get_cr4());
+       vmwrite(HOST_FS_BASE, rdmsr(MSR_FS_BASE));
+       vmwrite(HOST_GS_BASE, rdmsr(MSR_GS_BASE));
+       vmwrite(HOST_TR_BASE,
+               get_desc64_base((struct desc64 *)(get_gdt_base() + get_tr())));
+       vmwrite(HOST_GDTR_BASE, get_gdt_base());
+       vmwrite(HOST_IDTR_BASE, get_idt_base());
+       vmwrite(HOST_IA32_SYSENTER_ESP, rdmsr(MSR_IA32_SYSENTER_ESP));
+       vmwrite(HOST_IA32_SYSENTER_EIP, rdmsr(MSR_IA32_SYSENTER_EIP));
+}
+
+/*
+ * Initialize the guest state fields essentially as a clone of
+ * the host state fields. Some host state fields have fixed
+ * values, and we set the corresponding guest state fields accordingly.
+ */
+static inline void init_vmcs_guest_state(void *rip, void *rsp)
+{
+       vmwrite(GUEST_ES_SELECTOR, vmreadz(HOST_ES_SELECTOR));
+       vmwrite(GUEST_CS_SELECTOR, vmreadz(HOST_CS_SELECTOR));
+       vmwrite(GUEST_SS_SELECTOR, vmreadz(HOST_SS_SELECTOR));
+       vmwrite(GUEST_DS_SELECTOR, vmreadz(HOST_DS_SELECTOR));
+       vmwrite(GUEST_FS_SELECTOR, vmreadz(HOST_FS_SELECTOR));
+       vmwrite(GUEST_GS_SELECTOR, vmreadz(HOST_GS_SELECTOR));
+       vmwrite(GUEST_LDTR_SELECTOR, 0);
+       vmwrite(GUEST_TR_SELECTOR, vmreadz(HOST_TR_SELECTOR));
+       vmwrite(GUEST_INTR_STATUS, 0);
+       vmwrite(GUEST_PML_INDEX, 0);
+
+       vmwrite(VMCS_LINK_POINTER, -1ll);
+       vmwrite(GUEST_IA32_DEBUGCTL, 0);
+       vmwrite(GUEST_IA32_PAT, vmreadz(HOST_IA32_PAT));
+       vmwrite(GUEST_IA32_EFER, vmreadz(HOST_IA32_EFER));
+       vmwrite(GUEST_IA32_PERF_GLOBAL_CTRL,
+               vmreadz(HOST_IA32_PERF_GLOBAL_CTRL));
+
+       vmwrite(GUEST_ES_LIMIT, -1);
+       vmwrite(GUEST_CS_LIMIT, -1);
+       vmwrite(GUEST_SS_LIMIT, -1);
+       vmwrite(GUEST_DS_LIMIT, -1);
+       vmwrite(GUEST_FS_LIMIT, -1);
+       vmwrite(GUEST_GS_LIMIT, -1);
+       vmwrite(GUEST_LDTR_LIMIT, -1);
+       vmwrite(GUEST_TR_LIMIT, 0x67);
+       vmwrite(GUEST_GDTR_LIMIT, 0xffff);
+       vmwrite(GUEST_IDTR_LIMIT, 0xffff);
+       vmwrite(GUEST_ES_AR_BYTES,
+               vmreadz(GUEST_ES_SELECTOR) == 0 ? 0x10000 : 0xc093);
+       vmwrite(GUEST_CS_AR_BYTES, 0xa09b);
+       vmwrite(GUEST_SS_AR_BYTES, 0xc093);
+       vmwrite(GUEST_DS_AR_BYTES,
+               vmreadz(GUEST_DS_SELECTOR) == 0 ? 0x10000 : 0xc093);
+       vmwrite(GUEST_FS_AR_BYTES,
+               vmreadz(GUEST_FS_SELECTOR) == 0 ? 0x10000 : 0xc093);
+       vmwrite(GUEST_GS_AR_BYTES,
+               vmreadz(GUEST_GS_SELECTOR) == 0 ? 0x10000 : 0xc093);
+       vmwrite(GUEST_LDTR_AR_BYTES, 0x10000);
+       vmwrite(GUEST_TR_AR_BYTES, 0x8b);
+       vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
+       vmwrite(GUEST_ACTIVITY_STATE, 0);
+       vmwrite(GUEST_SYSENTER_CS, vmreadz(HOST_IA32_SYSENTER_CS));
+       vmwrite(VMX_PREEMPTION_TIMER_VALUE, 0);
+
+       vmwrite(GUEST_CR0, vmreadz(HOST_CR0));
+       vmwrite(GUEST_CR3, vmreadz(HOST_CR3));
+       vmwrite(GUEST_CR4, vmreadz(HOST_CR4));
+       vmwrite(GUEST_ES_BASE, 0);
+       vmwrite(GUEST_CS_BASE, 0);
+       vmwrite(GUEST_SS_BASE, 0);
+       vmwrite(GUEST_DS_BASE, 0);
+       vmwrite(GUEST_FS_BASE, vmreadz(HOST_FS_BASE));
+       vmwrite(GUEST_GS_BASE, vmreadz(HOST_GS_BASE));
+       vmwrite(GUEST_LDTR_BASE, 0);
+       vmwrite(GUEST_TR_BASE, vmreadz(HOST_TR_BASE));
+       vmwrite(GUEST_GDTR_BASE, vmreadz(HOST_GDTR_BASE));
+       vmwrite(GUEST_IDTR_BASE, vmreadz(HOST_IDTR_BASE));
+       vmwrite(GUEST_DR7, 0x400);
+       vmwrite(GUEST_RSP, (uint64_t)rsp);
+       vmwrite(GUEST_RIP, (uint64_t)rip);
+       vmwrite(GUEST_RFLAGS, 2);
+       vmwrite(GUEST_PENDING_DBG_EXCEPTIONS, 0);
+       vmwrite(GUEST_SYSENTER_ESP, vmreadz(HOST_IA32_SYSENTER_ESP));
+       vmwrite(GUEST_SYSENTER_EIP, vmreadz(HOST_IA32_SYSENTER_EIP));
+}
+
+void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp)
+{
+       init_vmcs_control_fields(vmx);
+       init_vmcs_host_state();
+       init_vmcs_guest_state(guest_rip, guest_rsp);
+}
diff --git a/tools/testing/selftests/kvm/platform_info_test.c b/tools/testing/selftests/kvm/platform_info_test.c
deleted file mode 100644 (file)
index aa6a143..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test for x86 KVM_CAP_MSR_PLATFORM_INFO
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- * Verifies expected behavior of controlling guest access to
- * MSR_PLATFORM_INFO.
- */
-
-#define _GNU_SOURCE /* for program_invocation_short_name */
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "test_util.h"
-#include "kvm_util.h"
-#include "x86.h"
-
-#define VCPU_ID 0
-#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
-
-static void guest_code(void)
-{
-       uint64_t msr_platform_info;
-
-       for (;;) {
-               msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
-               GUEST_SYNC(msr_platform_info);
-               asm volatile ("inc %r11");
-       }
-}
-
-static void set_msr_platform_info_enabled(struct kvm_vm *vm, bool enable)
-{
-       struct kvm_enable_cap cap = {};
-
-       cap.cap = KVM_CAP_MSR_PLATFORM_INFO;
-       cap.flags = 0;
-       cap.args[0] = (int)enable;
-       vm_enable_cap(vm, &cap);
-}
-
-static void test_msr_platform_info_enabled(struct kvm_vm *vm)
-{
-       struct kvm_run *run = vcpu_state(vm, VCPU_ID);
-       struct ucall uc;
-
-       set_msr_platform_info_enabled(vm, true);
-       vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                       "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
-                       run->exit_reason,
-                       exit_reason_str(run->exit_reason));
-       get_ucall(vm, VCPU_ID, &uc);
-       TEST_ASSERT(uc.cmd == UCALL_SYNC,
-                       "Received ucall other than UCALL_SYNC: %u\n",
-                       ucall);
-       TEST_ASSERT((uc.args[1] & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
-               MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
-               "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
-               MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
-}
-
-static void test_msr_platform_info_disabled(struct kvm_vm *vm)
-{
-       struct kvm_run *run = vcpu_state(vm, VCPU_ID);
-
-       set_msr_platform_info_enabled(vm, false);
-       vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-                       "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
-                       run->exit_reason,
-                       exit_reason_str(run->exit_reason));
-}
-
-int main(int argc, char *argv[])
-{
-       struct kvm_vm *vm;
-       struct kvm_run *state;
-       int rv;
-       uint64_t msr_platform_info;
-
-       /* Tell stdout not to buffer its content */
-       setbuf(stdout, NULL);
-
-       rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
-       if (!rv) {
-               fprintf(stderr,
-                       "KVM_CAP_MSR_PLATFORM_INFO not supported, skip test\n");
-               exit(KSFT_SKIP);
-       }
-
-       vm = vm_create_default(VCPU_ID, 0, guest_code);
-
-       msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
-       vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
-               msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
-       test_msr_platform_info_disabled(vm);
-       test_msr_platform_info_enabled(vm);
-       vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
-
-       kvm_vm_free(vm);
-
-       return 0;
-}
diff --git a/tools/testing/selftests/kvm/set_sregs_test.c b/tools/testing/selftests/kvm/set_sregs_test.c
deleted file mode 100644 (file)
index 881419d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * KVM_SET_SREGS tests
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- * This is a regression test for the bug fixed by the following commit:
- * d3802286fa0f ("kvm: x86: Disallow illegal IA32_APIC_BASE MSR values")
- *
- * That bug allowed a user-mode program that called the KVM_SET_SREGS
- * ioctl to put a VCPU's local APIC into an invalid state.
- *
- */
-#define _GNU_SOURCE /* for program_invocation_short_name */
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "test_util.h"
-
-#include "kvm_util.h"
-#include "x86.h"
-
-#define VCPU_ID                  5
-
-int main(int argc, char *argv[])
-{
-       struct kvm_sregs sregs;
-       struct kvm_vm *vm;
-       int rc;
-
-       /* Tell stdout not to buffer its content */
-       setbuf(stdout, NULL);
-
-       /* Create VM */
-       vm = vm_create_default(VCPU_ID, 0, NULL);
-
-       vcpu_sregs_get(vm, VCPU_ID, &sregs);
-       sregs.apic_base = 1 << 10;
-       rc = _vcpu_sregs_set(vm, VCPU_ID, &sregs);
-       TEST_ASSERT(rc, "Set IA32_APIC_BASE to %llx (invalid)",
-                   sregs.apic_base);
-       sregs.apic_base = 1 << 11;
-       rc = _vcpu_sregs_set(vm, VCPU_ID, &sregs);
-       TEST_ASSERT(!rc, "Couldn't set IA32_APIC_BASE to %llx (valid)",
-                   sregs.apic_base);
-
-       kvm_vm_free(vm);
-
-       return 0;
-}
diff --git a/tools/testing/selftests/kvm/state_test.c b/tools/testing/selftests/kvm/state_test.c
deleted file mode 100644 (file)
index cdf8273..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * KVM_GET/SET_* tests
- *
- * Copyright (C) 2018, Red Hat, Inc.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- * Tests for vCPU state save/restore, including nested guest state.
- */
-#define _GNU_SOURCE /* for program_invocation_short_name */
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "test_util.h"
-
-#include "kvm_util.h"
-#include "x86.h"
-#include "vmx.h"
-
-#define VCPU_ID                5
-
-static bool have_nested_state;
-
-void l2_guest_code(void)
-{
-       GUEST_SYNC(5);
-
-        /* Exit to L1 */
-       vmcall();
-
-       /* L1 has now set up a shadow VMCS for us.  */
-       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
-       GUEST_SYNC(9);
-       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
-       GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0fffee));
-       GUEST_SYNC(10);
-       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0fffee);
-       GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0ffffee));
-       GUEST_SYNC(11);
-
-       /* Done, exit to L1 and never come back.  */
-       vmcall();
-}
-
-void l1_guest_code(struct vmx_pages *vmx_pages)
-{
-#define L2_GUEST_STACK_SIZE 64
-        unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
-
-       GUEST_ASSERT(vmx_pages->vmcs_gpa);
-       GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
-       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
-
-       GUEST_SYNC(3);
-       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
-
-       prepare_vmcs(vmx_pages, l2_guest_code,
-                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
-
-       GUEST_SYNC(4);
-       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
-       GUEST_ASSERT(!vmlaunch());
-       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
-
-       /* Check that the launched state is preserved.  */
-       GUEST_ASSERT(vmlaunch());
-
-       GUEST_ASSERT(!vmresume());
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
-
-       GUEST_SYNC(6);
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
-
-       GUEST_ASSERT(!vmresume());
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
-
-       vmwrite(GUEST_RIP, vmreadz(GUEST_RIP) + 3);
-
-       vmwrite(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_SHADOW_VMCS);
-       vmwrite(VMCS_LINK_POINTER, vmx_pages->shadow_vmcs_gpa);
-
-       GUEST_ASSERT(!vmptrld(vmx_pages->shadow_vmcs_gpa));
-       GUEST_ASSERT(vmlaunch());
-       GUEST_SYNC(7);
-       GUEST_ASSERT(vmlaunch());
-       GUEST_ASSERT(vmresume());
-
-       vmwrite(GUEST_RIP, 0xc0ffee);
-       GUEST_SYNC(8);
-       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
-
-       GUEST_ASSERT(!vmptrld(vmx_pages->vmcs_gpa));
-       GUEST_ASSERT(!vmresume());
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
-
-       GUEST_ASSERT(!vmptrld(vmx_pages->shadow_vmcs_gpa));
-       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee);
-       GUEST_ASSERT(vmlaunch());
-       GUEST_ASSERT(vmresume());
-       GUEST_SYNC(12);
-       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee);
-       GUEST_ASSERT(vmlaunch());
-       GUEST_ASSERT(vmresume());
-}
-
-void guest_code(struct vmx_pages *vmx_pages)
-{
-       GUEST_SYNC(1);
-       GUEST_SYNC(2);
-
-       if (vmx_pages)
-               l1_guest_code(vmx_pages);
-
-       GUEST_DONE();
-}
-
-int main(int argc, char *argv[])
-{
-       struct vmx_pages *vmx_pages = NULL;
-       vm_vaddr_t vmx_pages_gva = 0;
-
-       struct kvm_regs regs1, regs2;
-       struct kvm_vm *vm;
-       struct kvm_run *run;
-       struct kvm_x86_state *state;
-       struct ucall uc;
-       int stage;
-
-       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
-
-       /* Create VM */
-       vm = vm_create_default(VCPU_ID, 0, guest_code);
-       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-       run = vcpu_state(vm, VCPU_ID);
-
-       vcpu_regs_get(vm, VCPU_ID, &regs1);
-
-       if (kvm_check_cap(KVM_CAP_NESTED_STATE)) {
-               vmx_pages = vcpu_alloc_vmx(vm, &vmx_pages_gva);
-               vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_gva);
-       } else {
-               printf("will skip nested state checks\n");
-               vcpu_args_set(vm, VCPU_ID, 1, 0);
-       }
-
-       for (stage = 1;; stage++) {
-               _vcpu_run(vm, VCPU_ID);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Unexpected exit reason: %u (%s),\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
-
-               memset(&regs1, 0, sizeof(regs1));
-               vcpu_regs_get(vm, VCPU_ID, &regs1);
-               switch (get_ucall(vm, VCPU_ID, &uc)) {
-               case UCALL_ABORT:
-                       TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0],
-                                   __FILE__, uc.args[1]);
-                       /* NOT REACHED */
-               case UCALL_SYNC:
-                       break;
-               case UCALL_DONE:
-                       goto done;
-               default:
-                       TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
-               }
-
-               /* UCALL_SYNC is handled here.  */
-               TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
-                           uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx",
-                           stage, (ulong)uc.args[1]);
-
-               state = vcpu_save_state(vm, VCPU_ID);
-               kvm_vm_release(vm);
-
-               /* Restore state in a new VM.  */
-               kvm_vm_restart(vm, O_RDWR);
-               vm_vcpu_add(vm, VCPU_ID, 0, 0);
-               vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-               vcpu_load_state(vm, VCPU_ID, state);
-               run = vcpu_state(vm, VCPU_ID);
-               free(state);
-
-               memset(&regs2, 0, sizeof(regs2));
-               vcpu_regs_get(vm, VCPU_ID, &regs2);
-               TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
-                           "Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
-                           (ulong) regs2.rdi, (ulong) regs2.rsi);
-       }
-
-done:
-       kvm_vm_free(vm);
-}
diff --git a/tools/testing/selftests/kvm/sync_regs_test.c b/tools/testing/selftests/kvm/sync_regs_test.c
deleted file mode 100644 (file)
index 213343e..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Test for x86 KVM_CAP_SYNC_REGS
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- * Verifies expected behavior of x86 KVM_CAP_SYNC_REGS functionality,
- * including requesting an invalid register set, updates to/from values
- * in kvm_run.s.regs when kvm_valid_regs and kvm_dirty_regs are toggled.
- */
-
-#define _GNU_SOURCE /* for program_invocation_short_name */
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "test_util.h"
-#include "kvm_util.h"
-#include "x86.h"
-
-#define VCPU_ID 5
-
-void guest_code(void)
-{
-       for (;;) {
-               GUEST_SYNC(0);
-               asm volatile ("inc %r11");
-       }
-}
-
-static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
-{
-#define REG_COMPARE(reg) \
-       TEST_ASSERT(left->reg == right->reg, \
-                   "Register " #reg \
-                   " values did not match: 0x%llx, 0x%llx\n", \
-                   left->reg, right->reg)
-       REG_COMPARE(rax);
-       REG_COMPARE(rbx);
-       REG_COMPARE(rcx);
-       REG_COMPARE(rdx);
-       REG_COMPARE(rsi);
-       REG_COMPARE(rdi);
-       REG_COMPARE(rsp);
-       REG_COMPARE(rbp);
-       REG_COMPARE(r8);
-       REG_COMPARE(r9);
-       REG_COMPARE(r10);
-       REG_COMPARE(r11);
-       REG_COMPARE(r12);
-       REG_COMPARE(r13);
-       REG_COMPARE(r14);
-       REG_COMPARE(r15);
-       REG_COMPARE(rip);
-       REG_COMPARE(rflags);
-#undef REG_COMPARE
-}
-
-static void compare_sregs(struct kvm_sregs *left, struct kvm_sregs *right)
-{
-}
-
-static void compare_vcpu_events(struct kvm_vcpu_events *left,
-                               struct kvm_vcpu_events *right)
-{
-}
-
-#define TEST_SYNC_FIELDS   (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS)
-#define INVALID_SYNC_FIELD 0x80000000
-
-int main(int argc, char *argv[])
-{
-       struct kvm_vm *vm;
-       struct kvm_run *run;
-       struct kvm_regs regs;
-       struct kvm_sregs sregs;
-       struct kvm_vcpu_events events;
-       int rv, cap;
-
-       /* Tell stdout not to buffer its content */
-       setbuf(stdout, NULL);
-
-       cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
-       if ((cap & TEST_SYNC_FIELDS) != TEST_SYNC_FIELDS) {
-               fprintf(stderr, "KVM_CAP_SYNC_REGS not supported, skipping test\n");
-               exit(KSFT_SKIP);
-       }
-       if ((cap & INVALID_SYNC_FIELD) != 0) {
-               fprintf(stderr, "The \"invalid\" field is not invalid, skipping test\n");
-               exit(KSFT_SKIP);
-       }
-
-       /* Create VM */
-       vm = vm_create_default(VCPU_ID, 0, guest_code);
-
-       run = vcpu_state(vm, VCPU_ID);
-
-       /* Request reading invalid register set from VCPU. */
-       run->kvm_valid_regs = INVALID_SYNC_FIELD;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
-                   rv);
-       vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
-
-       run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
-                   rv);
-       vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
-
-       /* Request setting invalid register set into VCPU. */
-       run->kvm_dirty_regs = INVALID_SYNC_FIELD;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
-                   rv);
-       vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
-
-       run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(rv < 0 && errno == EINVAL,
-                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
-                   rv);
-       vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
-
-       /* Request and verify all valid register sets. */
-       /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
-       run->kvm_valid_regs = TEST_SYNC_FIELDS;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
-
-       vcpu_regs_get(vm, VCPU_ID, &regs);
-       compare_regs(&regs, &run->s.regs.regs);
-
-       vcpu_sregs_get(vm, VCPU_ID, &sregs);
-       compare_sregs(&sregs, &run->s.regs.sregs);
-
-       vcpu_events_get(vm, VCPU_ID, &events);
-       compare_vcpu_events(&events, &run->s.regs.events);
-
-       /* Set and verify various register values. */
-       run->s.regs.regs.r11 = 0xBAD1DEA;
-       run->s.regs.sregs.apic_base = 1 << 11;
-       /* TODO run->s.regs.events.XYZ = ABC; */
-
-       run->kvm_valid_regs = TEST_SYNC_FIELDS;
-       run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
-       TEST_ASSERT(run->s.regs.regs.r11 == 0xBAD1DEA + 1,
-                   "r11 sync regs value incorrect 0x%llx.",
-                   run->s.regs.regs.r11);
-       TEST_ASSERT(run->s.regs.sregs.apic_base == 1 << 11,
-                   "apic_base sync regs value incorrect 0x%llx.",
-                   run->s.regs.sregs.apic_base);
-
-       vcpu_regs_get(vm, VCPU_ID, &regs);
-       compare_regs(&regs, &run->s.regs.regs);
-
-       vcpu_sregs_get(vm, VCPU_ID, &sregs);
-       compare_sregs(&sregs, &run->s.regs.sregs);
-
-       vcpu_events_get(vm, VCPU_ID, &events);
-       compare_vcpu_events(&events, &run->s.regs.events);
-
-       /* Clear kvm_dirty_regs bits, verify new s.regs values are
-        * overwritten with existing guest values.
-        */
-       run->kvm_valid_regs = TEST_SYNC_FIELDS;
-       run->kvm_dirty_regs = 0;
-       run->s.regs.regs.r11 = 0xDEADBEEF;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
-       TEST_ASSERT(run->s.regs.regs.r11 != 0xDEADBEEF,
-                   "r11 sync regs value incorrect 0x%llx.",
-                   run->s.regs.regs.r11);
-
-       /* Clear kvm_valid_regs bits and kvm_dirty_bits.
-        * Verify s.regs values are not overwritten with existing guest values
-        * and that guest values are not overwritten with kvm_sync_regs values.
-        */
-       run->kvm_valid_regs = 0;
-       run->kvm_dirty_regs = 0;
-       run->s.regs.regs.r11 = 0xAAAA;
-       regs.r11 = 0xBAC0;
-       vcpu_regs_set(vm, VCPU_ID, &regs);
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
-       TEST_ASSERT(run->s.regs.regs.r11 == 0xAAAA,
-                   "r11 sync regs value incorrect 0x%llx.",
-                   run->s.regs.regs.r11);
-       vcpu_regs_get(vm, VCPU_ID, &regs);
-       TEST_ASSERT(regs.r11 == 0xBAC0 + 1,
-                   "r11 guest value incorrect 0x%llx.",
-                   regs.r11);
-
-       /* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
-        * with existing guest values but that guest values are overwritten
-        * with kvm_sync_regs values.
-        */
-       run->kvm_valid_regs = 0;
-       run->kvm_dirty_regs = TEST_SYNC_FIELDS;
-       run->s.regs.regs.r11 = 0xBBBB;
-       rv = _vcpu_run(vm, VCPU_ID);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
-       TEST_ASSERT(run->s.regs.regs.r11 == 0xBBBB,
-                   "r11 sync regs value incorrect 0x%llx.",
-                   run->s.regs.regs.r11);
-       vcpu_regs_get(vm, VCPU_ID, &regs);
-       TEST_ASSERT(regs.r11 == 0xBBBB + 1,
-                   "r11 guest value incorrect 0x%llx.",
-                   regs.r11);
-
-       kvm_vm_free(vm);
-
-       return 0;
-}
diff --git a/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
deleted file mode 100644 (file)
index 8d487c7..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * gtests/tests/vmx_tsc_adjust_test.c
- *
- * Copyright (C) 2018, Google LLC.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- *
- *
- * IA32_TSC_ADJUST test
- *
- * According to the SDM, "if an execution of WRMSR to the
- * IA32_TIME_STAMP_COUNTER MSR adds (or subtracts) value X from the TSC,
- * the logical processor also adds (or subtracts) value X from the
- * IA32_TSC_ADJUST MSR.
- *
- * Note that when L1 doesn't intercept writes to IA32_TSC, a
- * WRMSR(IA32_TSC) from L2 sets L1's TSC value, not L2's perceived TSC
- * value.
- *
- * This test verifies that this unusual case is handled correctly.
- */
-
-#include "test_util.h"
-#include "kvm_util.h"
-#include "x86.h"
-#include "vmx.h"
-
-#include <string.h>
-#include <sys/ioctl.h>
-
-#include "../kselftest.h"
-
-#ifndef MSR_IA32_TSC_ADJUST
-#define MSR_IA32_TSC_ADJUST 0x3b
-#endif
-
-#define PAGE_SIZE      4096
-#define VCPU_ID                5
-
-#define TSC_ADJUST_VALUE (1ll << 32)
-#define TSC_OFFSET_VALUE -(1ll << 48)
-
-enum {
-       PORT_ABORT = 0x1000,
-       PORT_REPORT,
-       PORT_DONE,
-};
-
-enum {
-       VMXON_PAGE = 0,
-       VMCS_PAGE,
-       MSR_BITMAP_PAGE,
-
-       NUM_VMX_PAGES,
-};
-
-struct kvm_single_msr {
-       struct kvm_msrs header;
-       struct kvm_msr_entry entry;
-} __attribute__((packed));
-
-/* The virtual machine object. */
-static struct kvm_vm *vm;
-
-static void check_ia32_tsc_adjust(int64_t max)
-{
-       int64_t adjust;
-
-       adjust = rdmsr(MSR_IA32_TSC_ADJUST);
-       GUEST_SYNC(adjust);
-       GUEST_ASSERT(adjust <= max);
-}
-
-static void l2_guest_code(void)
-{
-       uint64_t l1_tsc = rdtsc() - TSC_OFFSET_VALUE;
-
-       wrmsr(MSR_IA32_TSC, l1_tsc - TSC_ADJUST_VALUE);
-       check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
-
-       /* Exit to L1 */
-       __asm__ __volatile__("vmcall");
-}
-
-static void l1_guest_code(struct vmx_pages *vmx_pages)
-{
-#define L2_GUEST_STACK_SIZE 64
-       unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
-       uint32_t control;
-       uintptr_t save_cr3;
-
-       GUEST_ASSERT(rdtsc() < TSC_ADJUST_VALUE);
-       wrmsr(MSR_IA32_TSC, rdtsc() - TSC_ADJUST_VALUE);
-       check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
-
-       GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
-
-       /* Prepare the VMCS for L2 execution. */
-       prepare_vmcs(vmx_pages, l2_guest_code,
-                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
-       control = vmreadz(CPU_BASED_VM_EXEC_CONTROL);
-       control |= CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETING;
-       vmwrite(CPU_BASED_VM_EXEC_CONTROL, control);
-       vmwrite(TSC_OFFSET, TSC_OFFSET_VALUE);
-
-       /* Jump into L2.  First, test failure to load guest CR3.  */
-       save_cr3 = vmreadz(GUEST_CR3);
-       vmwrite(GUEST_CR3, -1ull);
-       GUEST_ASSERT(!vmlaunch());
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) ==
-                    (EXIT_REASON_FAILED_VMENTRY | EXIT_REASON_INVALID_STATE));
-       check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
-       vmwrite(GUEST_CR3, save_cr3);
-
-       GUEST_ASSERT(!vmlaunch());
-       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
-
-       check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
-
-       GUEST_DONE();
-}
-
-void report(int64_t val)
-{
-       printf("IA32_TSC_ADJUST is %ld (%lld * TSC_ADJUST_VALUE + %lld).\n",
-              val, val / TSC_ADJUST_VALUE, val % TSC_ADJUST_VALUE);
-}
-
-int main(int argc, char *argv[])
-{
-       struct vmx_pages *vmx_pages;
-       vm_vaddr_t vmx_pages_gva;
-       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
-
-       if (!(entry->ecx & CPUID_VMX)) {
-               fprintf(stderr, "nested VMX not enabled, skipping test\n");
-               exit(KSFT_SKIP);
-       }
-
-       vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
-       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
-
-       /* Allocate VMX pages and shared descriptors (vmx_pages). */
-       vmx_pages = vcpu_alloc_vmx(vm, &vmx_pages_gva);
-       vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_gva);
-
-       for (;;) {
-               volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
-               struct ucall uc;
-
-               vcpu_run(vm, VCPU_ID);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
-
-               switch (get_ucall(vm, VCPU_ID, &uc)) {
-               case UCALL_ABORT:
-                       TEST_ASSERT(false, "%s", (const char *)uc.args[0]);
-                       /* NOT REACHED */
-               case UCALL_SYNC:
-                       report(uc.args[1]);
-                       break;
-               case UCALL_DONE:
-                       goto done;
-               default:
-                       TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
-               }
-       }
-
-       kvm_vm_free(vm);
-done:
-       return 0;
-}
diff --git a/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c b/tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c
new file mode 100644 (file)
index 0000000..d503a51
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CR4 and CPUID sync test
+ *
+ * Copyright 2018, Red Hat, Inc. and/or its affiliates.
+ *
+ * Author:
+ *   Wei Huang <wei@redhat.com>
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+
+#include "kvm_util.h"
+#include "processor.h"
+
+#define X86_FEATURE_XSAVE      (1<<26)
+#define X86_FEATURE_OSXSAVE    (1<<27)
+#define VCPU_ID                        1
+
+static inline bool cr4_cpuid_is_sync(void)
+{
+       int func, subfunc;
+       uint32_t eax, ebx, ecx, edx;
+       uint64_t cr4;
+
+       func = 0x1;
+       subfunc = 0x0;
+       __asm__ __volatile__("cpuid"
+                            : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
+                            : "a"(func), "c"(subfunc));
+
+       cr4 = get_cr4();
+
+       return (!!(ecx & X86_FEATURE_OSXSAVE)) == (!!(cr4 & X86_CR4_OSXSAVE));
+}
+
+static void guest_code(void)
+{
+       uint64_t cr4;
+
+       /* turn on CR4.OSXSAVE */
+       cr4 = get_cr4();
+       cr4 |= X86_CR4_OSXSAVE;
+       set_cr4(cr4);
+
+       /* verify CR4.OSXSAVE == CPUID.OSXSAVE */
+       GUEST_ASSERT(cr4_cpuid_is_sync());
+
+       /* notify hypervisor to change CR4 */
+       GUEST_SYNC(0);
+
+       /* check again */
+       GUEST_ASSERT(cr4_cpuid_is_sync());
+
+       GUEST_DONE();
+}
+
+int main(int argc, char *argv[])
+{
+       struct kvm_run *run;
+       struct kvm_vm *vm;
+       struct kvm_sregs sregs;
+       struct kvm_cpuid_entry2 *entry;
+       struct ucall uc;
+       int rc;
+
+       entry = kvm_get_supported_cpuid_entry(1);
+       if (!(entry->ecx & X86_FEATURE_XSAVE)) {
+               printf("XSAVE feature not supported, skipping test\n");
+               return 0;
+       }
+
+       /* Tell stdout not to buffer its content */
+       setbuf(stdout, NULL);
+
+       /* Create VM */
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
+       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+       run = vcpu_state(vm, VCPU_ID);
+
+       while (1) {
+               rc = _vcpu_run(vm, VCPU_ID);
+
+               if (run->exit_reason == KVM_EXIT_IO) {
+                       switch (get_ucall(vm, VCPU_ID, &uc)) {
+                       case UCALL_SYNC:
+                               /* emulate hypervisor clearing CR4.OSXSAVE */
+                               vcpu_sregs_get(vm, VCPU_ID, &sregs);
+                               sregs.cr4 &= ~X86_CR4_OSXSAVE;
+                               vcpu_sregs_set(vm, VCPU_ID, &sregs);
+                               break;
+                       case UCALL_ABORT:
+                               TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
+                               break;
+                       case UCALL_DONE:
+                               goto done;
+                       default:
+                               TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
+                       }
+               }
+       }
+
+       kvm_vm_free(vm);
+
+done:
+       return 0;
+}
diff --git a/tools/testing/selftests/kvm/x86_64/dirty_log_test.c b/tools/testing/selftests/kvm/x86_64/dirty_log_test.c
new file mode 100644 (file)
index 0000000..7cf3e4a
--- /dev/null
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KVM dirty page logging test
+ *
+ * Copyright (C) 2018, Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+
+#define  DEBUG                 printf
+
+#define  VCPU_ID                        1
+/* The memory slot index to track dirty pages */
+#define  TEST_MEM_SLOT_INDEX            1
+/*
+ * GPA offset of the testing memory slot. Must be bigger than the
+ * default vm mem slot, which is DEFAULT_GUEST_PHY_PAGES.
+ */
+#define  TEST_MEM_OFFSET                (1ULL << 30) /* 1G */
+/* Size of the testing memory slot */
+#define  TEST_MEM_PAGES                 (1ULL << 18) /* 1G for 4K pages */
+/* How many pages to dirty for each guest loop */
+#define  TEST_PAGES_PER_LOOP            1024
+/* How many host loops to run (one KVM_GET_DIRTY_LOG for each loop) */
+#define  TEST_HOST_LOOP_N               32
+/* Interval for each host loop (ms) */
+#define  TEST_HOST_LOOP_INTERVAL        10
+
+/*
+ * Guest variables.  We use these variables to share data between host
+ * and guest.  There are two copies of the variables, one in host memory
+ * (which is unused) and one in guest memory.  When the host wants to
+ * access these variables, it needs to call addr_gva2hva() to access the
+ * guest copy.
+ */
+uint64_t guest_random_array[TEST_PAGES_PER_LOOP];
+uint64_t guest_iteration;
+uint64_t guest_page_size;
+
+/*
+ * Writes to the first byte of a random page within the testing memory
+ * region continuously.
+ */
+void guest_code(void)
+{
+       int i = 0;
+       uint64_t volatile *array = guest_random_array;
+       uint64_t volatile *guest_addr;
+
+       while (true) {
+               for (i = 0; i < TEST_PAGES_PER_LOOP; i++) {
+                       /*
+                        * Write to the first 8 bytes of a random page
+                        * on the testing memory region.
+                        */
+                       guest_addr = (uint64_t *)
+                           (TEST_MEM_OFFSET +
+                            (array[i] % TEST_MEM_PAGES) * guest_page_size);
+                       *guest_addr = guest_iteration;
+               }
+               /* Tell the host that we need more random numbers */
+               GUEST_SYNC(1);
+       }
+}
+
+/*
+ * Host variables.  These variables should only be used by the host
+ * rather than the guest.
+ */
+bool host_quit;
+
+/* Points to the test VM memory region on which we track dirty logs */
+void *host_test_mem;
+
+/* For statistics only */
+uint64_t host_dirty_count;
+uint64_t host_clear_count;
+uint64_t host_track_next_count;
+
+/*
+ * We use this bitmap to track some pages that should have its dirty
+ * bit set in the _next_ iteration.  For example, if we detected the
+ * page value changed to current iteration but at the same time the
+ * page bit is cleared in the latest bitmap, then the system must
+ * report that write in the next get dirty log call.
+ */
+unsigned long *host_bmap_track;
+
+void generate_random_array(uint64_t *guest_array, uint64_t size)
+{
+       uint64_t i;
+
+       for (i = 0; i < size; i++) {
+               guest_array[i] = random();
+       }
+}
+
+void *vcpu_worker(void *data)
+{
+       int ret;
+       uint64_t loops, *guest_array, pages_count = 0;
+       struct kvm_vm *vm = data;
+       struct kvm_run *run;
+       struct ucall uc;
+
+       run = vcpu_state(vm, VCPU_ID);
+
+       /* Retrieve the guest random array pointer and cache it */
+       guest_array = addr_gva2hva(vm, (vm_vaddr_t)guest_random_array);
+
+       DEBUG("VCPU starts\n");
+
+       generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
+
+       while (!READ_ONCE(host_quit)) {
+               /* Let the guest to dirty these random pages */
+               ret = _vcpu_run(vm, VCPU_ID);
+               if (run->exit_reason == KVM_EXIT_IO &&
+                   get_ucall(vm, VCPU_ID, &uc) == UCALL_SYNC) {
+                       pages_count += TEST_PAGES_PER_LOOP;
+                       generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
+               } else {
+                       TEST_ASSERT(false,
+                                   "Invalid guest sync status: "
+                                   "exit_reason=%s\n",
+                                   exit_reason_str(run->exit_reason));
+               }
+       }
+
+       DEBUG("VCPU exits, dirtied %"PRIu64" pages\n", pages_count);
+
+       return NULL;
+}
+
+void vm_dirty_log_verify(unsigned long *bmap, uint64_t iteration)
+{
+       uint64_t page;
+       uint64_t volatile *value_ptr;
+
+       for (page = 0; page < TEST_MEM_PAGES; page++) {
+               value_ptr = host_test_mem + page * getpagesize();
+
+               /* If this is a special page that we were tracking... */
+               if (test_and_clear_bit(page, host_bmap_track)) {
+                       host_track_next_count++;
+                       TEST_ASSERT(test_bit(page, bmap),
+                                   "Page %"PRIu64" should have its dirty bit "
+                                   "set in this iteration but it is missing",
+                                   page);
+               }
+
+               if (test_bit(page, bmap)) {
+                       host_dirty_count++;
+                       /*
+                        * If the bit is set, the value written onto
+                        * the corresponding page should be either the
+                        * previous iteration number or the current one.
+                        */
+                       TEST_ASSERT(*value_ptr == iteration ||
+                                   *value_ptr == iteration - 1,
+                                   "Set page %"PRIu64" value %"PRIu64
+                                   " incorrect (iteration=%"PRIu64")",
+                                   page, *value_ptr, iteration);
+               } else {
+                       host_clear_count++;
+                       /*
+                        * If cleared, the value written can be any
+                        * value smaller or equals to the iteration
+                        * number.  Note that the value can be exactly
+                        * (iteration-1) if that write can happen
+                        * like this:
+                        *
+                        * (1) increase loop count to "iteration-1"
+                        * (2) write to page P happens (with value
+                        *     "iteration-1")
+                        * (3) get dirty log for "iteration-1"; we'll
+                        *     see that page P bit is set (dirtied),
+                        *     and not set the bit in host_bmap_track
+                        * (4) increase loop count to "iteration"
+                        *     (which is current iteration)
+                        * (5) get dirty log for current iteration,
+                        *     we'll see that page P is cleared, with
+                        *     value "iteration-1".
+                        */
+                       TEST_ASSERT(*value_ptr <= iteration,
+                                   "Clear page %"PRIu64" value %"PRIu64
+                                   " incorrect (iteration=%"PRIu64")",
+                                   page, *value_ptr, iteration);
+                       if (*value_ptr == iteration) {
+                               /*
+                                * This page is _just_ modified; it
+                                * should report its dirtyness in the
+                                * next run
+                                */
+                               set_bit(page, host_bmap_track);
+                       }
+               }
+       }
+}
+
+void help(char *name)
+{
+       puts("");
+       printf("usage: %s [-i iterations] [-I interval] [-h]\n", name);
+       puts("");
+       printf(" -i: specify iteration counts (default: %"PRIu64")\n",
+              TEST_HOST_LOOP_N);
+       printf(" -I: specify interval in ms (default: %"PRIu64" ms)\n",
+              TEST_HOST_LOOP_INTERVAL);
+       puts("");
+       exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+       pthread_t vcpu_thread;
+       struct kvm_vm *vm;
+       uint64_t volatile *psize, *iteration;
+       unsigned long *bmap, iterations = TEST_HOST_LOOP_N,
+           interval = TEST_HOST_LOOP_INTERVAL;
+       int opt;
+
+       while ((opt = getopt(argc, argv, "hi:I:")) != -1) {
+               switch (opt) {
+               case 'i':
+                       iterations = strtol(optarg, NULL, 10);
+                       break;
+               case 'I':
+                       interval = strtol(optarg, NULL, 10);
+                       break;
+               case 'h':
+               default:
+                       help(argv[0]);
+                       break;
+               }
+       }
+
+       TEST_ASSERT(iterations > 2, "Iteration must be bigger than zero\n");
+       TEST_ASSERT(interval > 0, "Interval must be bigger than zero");
+
+       DEBUG("Test iterations: %"PRIu64", interval: %"PRIu64" (ms)\n",
+             iterations, interval);
+
+       srandom(time(0));
+
+       bmap = bitmap_alloc(TEST_MEM_PAGES);
+       host_bmap_track = bitmap_alloc(TEST_MEM_PAGES);
+
+       vm = vm_create_default(VCPU_ID, TEST_MEM_PAGES, guest_code);
+
+       /* Add an extra memory slot for testing dirty logging */
+       vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+                                   TEST_MEM_OFFSET,
+                                   TEST_MEM_SLOT_INDEX,
+                                   TEST_MEM_PAGES,
+                                   KVM_MEM_LOG_DIRTY_PAGES);
+       /* Cache the HVA pointer of the region */
+       host_test_mem = addr_gpa2hva(vm, (vm_paddr_t)TEST_MEM_OFFSET);
+
+       /* Do 1:1 mapping for the dirty track memory slot */
+       virt_map(vm, TEST_MEM_OFFSET, TEST_MEM_OFFSET,
+                TEST_MEM_PAGES * getpagesize(), 0);
+
+       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+
+       /* Tell the guest about the page size on the system */
+       psize = addr_gva2hva(vm, (vm_vaddr_t)&guest_page_size);
+       *psize = getpagesize();
+
+       /* Start the iterations */
+       iteration = addr_gva2hva(vm, (vm_vaddr_t)&guest_iteration);
+       *iteration = 1;
+
+       /* Start dirtying pages */
+       pthread_create(&vcpu_thread, NULL, vcpu_worker, vm);
+
+       while (*iteration < iterations) {
+               /* Give the vcpu thread some time to dirty some pages */
+               usleep(interval * 1000);
+               kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
+               vm_dirty_log_verify(bmap, *iteration);
+               (*iteration)++;
+       }
+
+       /* Tell the vcpu thread to quit */
+       host_quit = true;
+       pthread_join(vcpu_thread, NULL);
+
+       DEBUG("Total bits checked: dirty (%"PRIu64"), clear (%"PRIu64"), "
+             "track_next (%"PRIu64")\n", host_dirty_count, host_clear_count,
+             host_track_next_count);
+
+       free(bmap);
+       free(host_bmap_track);
+       kvm_vm_free(vm);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/kvm/x86_64/platform_info_test.c b/tools/testing/selftests/kvm/x86_64/platform_info_test.c
new file mode 100644 (file)
index 0000000..eb3e7a8
--- /dev/null
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test for x86 KVM_CAP_MSR_PLATFORM_INFO
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * Verifies expected behavior of controlling guest access to
+ * MSR_PLATFORM_INFO.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+
+#define VCPU_ID 0
+#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
+
+static void guest_code(void)
+{
+       uint64_t msr_platform_info;
+
+       for (;;) {
+               msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
+               GUEST_SYNC(msr_platform_info);
+               asm volatile ("inc %r11");
+       }
+}
+
+static void set_msr_platform_info_enabled(struct kvm_vm *vm, bool enable)
+{
+       struct kvm_enable_cap cap = {};
+
+       cap.cap = KVM_CAP_MSR_PLATFORM_INFO;
+       cap.flags = 0;
+       cap.args[0] = (int)enable;
+       vm_enable_cap(vm, &cap);
+}
+
+static void test_msr_platform_info_enabled(struct kvm_vm *vm)
+{
+       struct kvm_run *run = vcpu_state(vm, VCPU_ID);
+       struct ucall uc;
+
+       set_msr_platform_info_enabled(vm, true);
+       vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                       "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
+                       run->exit_reason,
+                       exit_reason_str(run->exit_reason));
+       get_ucall(vm, VCPU_ID, &uc);
+       TEST_ASSERT(uc.cmd == UCALL_SYNC,
+                       "Received ucall other than UCALL_SYNC: %u\n",
+                       ucall);
+       TEST_ASSERT((uc.args[1] & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
+               MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
+               "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
+               MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
+}
+
+static void test_msr_platform_info_disabled(struct kvm_vm *vm)
+{
+       struct kvm_run *run = vcpu_state(vm, VCPU_ID);
+
+       set_msr_platform_info_enabled(vm, false);
+       vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
+                       "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
+                       run->exit_reason,
+                       exit_reason_str(run->exit_reason));
+}
+
+int main(int argc, char *argv[])
+{
+       struct kvm_vm *vm;
+       struct kvm_run *state;
+       int rv;
+       uint64_t msr_platform_info;
+
+       /* Tell stdout not to buffer its content */
+       setbuf(stdout, NULL);
+
+       rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
+       if (!rv) {
+               fprintf(stderr,
+                       "KVM_CAP_MSR_PLATFORM_INFO not supported, skip test\n");
+               exit(KSFT_SKIP);
+       }
+
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
+
+       msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
+       vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
+               msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
+       test_msr_platform_info_disabled(vm);
+       test_msr_platform_info_enabled(vm);
+       vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
+
+       kvm_vm_free(vm);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/kvm/x86_64/set_sregs_test.c b/tools/testing/selftests/kvm/x86_64/set_sregs_test.c
new file mode 100644 (file)
index 0000000..35640e8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * KVM_SET_SREGS tests
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * This is a regression test for the bug fixed by the following commit:
+ * d3802286fa0f ("kvm: x86: Disallow illegal IA32_APIC_BASE MSR values")
+ *
+ * That bug allowed a user-mode program that called the KVM_SET_SREGS
+ * ioctl to put a VCPU's local APIC into an invalid state.
+ *
+ */
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+
+#include "kvm_util.h"
+#include "processor.h"
+
+#define VCPU_ID                  5
+
+int main(int argc, char *argv[])
+{
+       struct kvm_sregs sregs;
+       struct kvm_vm *vm;
+       int rc;
+
+       /* Tell stdout not to buffer its content */
+       setbuf(stdout, NULL);
+
+       /* Create VM */
+       vm = vm_create_default(VCPU_ID, 0, NULL);
+
+       vcpu_sregs_get(vm, VCPU_ID, &sregs);
+       sregs.apic_base = 1 << 10;
+       rc = _vcpu_sregs_set(vm, VCPU_ID, &sregs);
+       TEST_ASSERT(rc, "Set IA32_APIC_BASE to %llx (invalid)",
+                   sregs.apic_base);
+       sregs.apic_base = 1 << 11;
+       rc = _vcpu_sregs_set(vm, VCPU_ID, &sregs);
+       TEST_ASSERT(!rc, "Couldn't set IA32_APIC_BASE to %llx (valid)",
+                   sregs.apic_base);
+
+       kvm_vm_free(vm);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/kvm/x86_64/state_test.c b/tools/testing/selftests/kvm/x86_64/state_test.c
new file mode 100644 (file)
index 0000000..43df194
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * KVM_GET/SET_* tests
+ *
+ * Copyright (C) 2018, Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * Tests for vCPU state save/restore, including nested guest state.
+ */
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+
+#include "kvm_util.h"
+#include "processor.h"
+#include "vmx.h"
+
+#define VCPU_ID                5
+
+static bool have_nested_state;
+
+void l2_guest_code(void)
+{
+       GUEST_SYNC(5);
+
+        /* Exit to L1 */
+       vmcall();
+
+       /* L1 has now set up a shadow VMCS for us.  */
+       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
+       GUEST_SYNC(9);
+       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
+       GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0fffee));
+       GUEST_SYNC(10);
+       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0fffee);
+       GUEST_ASSERT(!vmwrite(GUEST_RIP, 0xc0ffffee));
+       GUEST_SYNC(11);
+
+       /* Done, exit to L1 and never come back.  */
+       vmcall();
+}
+
+void l1_guest_code(struct vmx_pages *vmx_pages)
+{
+#define L2_GUEST_STACK_SIZE 64
+        unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+
+       GUEST_ASSERT(vmx_pages->vmcs_gpa);
+       GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
+       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
+
+       GUEST_SYNC(3);
+       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
+
+       prepare_vmcs(vmx_pages, l2_guest_code,
+                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
+
+       GUEST_SYNC(4);
+       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
+       GUEST_ASSERT(!vmlaunch());
+       GUEST_ASSERT(vmptrstz() == vmx_pages->vmcs_gpa);
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       /* Check that the launched state is preserved.  */
+       GUEST_ASSERT(vmlaunch());
+
+       GUEST_ASSERT(!vmresume());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       GUEST_SYNC(6);
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       GUEST_ASSERT(!vmresume());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       vmwrite(GUEST_RIP, vmreadz(GUEST_RIP) + 3);
+
+       vmwrite(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_SHADOW_VMCS);
+       vmwrite(VMCS_LINK_POINTER, vmx_pages->shadow_vmcs_gpa);
+
+       GUEST_ASSERT(!vmptrld(vmx_pages->shadow_vmcs_gpa));
+       GUEST_ASSERT(vmlaunch());
+       GUEST_SYNC(7);
+       GUEST_ASSERT(vmlaunch());
+       GUEST_ASSERT(vmresume());
+
+       vmwrite(GUEST_RIP, 0xc0ffee);
+       GUEST_SYNC(8);
+       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffee);
+
+       GUEST_ASSERT(!vmptrld(vmx_pages->vmcs_gpa));
+       GUEST_ASSERT(!vmresume());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       GUEST_ASSERT(!vmptrld(vmx_pages->shadow_vmcs_gpa));
+       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee);
+       GUEST_ASSERT(vmlaunch());
+       GUEST_ASSERT(vmresume());
+       GUEST_SYNC(12);
+       GUEST_ASSERT(vmreadz(GUEST_RIP) == 0xc0ffffee);
+       GUEST_ASSERT(vmlaunch());
+       GUEST_ASSERT(vmresume());
+}
+
+void guest_code(struct vmx_pages *vmx_pages)
+{
+       GUEST_SYNC(1);
+       GUEST_SYNC(2);
+
+       if (vmx_pages)
+               l1_guest_code(vmx_pages);
+
+       GUEST_DONE();
+}
+
+int main(int argc, char *argv[])
+{
+       struct vmx_pages *vmx_pages = NULL;
+       vm_vaddr_t vmx_pages_gva = 0;
+
+       struct kvm_regs regs1, regs2;
+       struct kvm_vm *vm;
+       struct kvm_run *run;
+       struct kvm_x86_state *state;
+       struct ucall uc;
+       int stage;
+
+       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
+
+       /* Create VM */
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
+       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+       run = vcpu_state(vm, VCPU_ID);
+
+       vcpu_regs_get(vm, VCPU_ID, &regs1);
+
+       if (kvm_check_cap(KVM_CAP_NESTED_STATE)) {
+               vmx_pages = vcpu_alloc_vmx(vm, &vmx_pages_gva);
+               vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_gva);
+       } else {
+               printf("will skip nested state checks\n");
+               vcpu_args_set(vm, VCPU_ID, 1, 0);
+       }
+
+       for (stage = 1;; stage++) {
+               _vcpu_run(vm, VCPU_ID);
+               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                           "Unexpected exit reason: %u (%s),\n",
+                           run->exit_reason,
+                           exit_reason_str(run->exit_reason));
+
+               memset(&regs1, 0, sizeof(regs1));
+               vcpu_regs_get(vm, VCPU_ID, &regs1);
+               switch (get_ucall(vm, VCPU_ID, &uc)) {
+               case UCALL_ABORT:
+                       TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0],
+                                   __FILE__, uc.args[1]);
+                       /* NOT REACHED */
+               case UCALL_SYNC:
+                       break;
+               case UCALL_DONE:
+                       goto done;
+               default:
+                       TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
+               }
+
+               /* UCALL_SYNC is handled here.  */
+               TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
+                           uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx",
+                           stage, (ulong)uc.args[1]);
+
+               state = vcpu_save_state(vm, VCPU_ID);
+               kvm_vm_release(vm);
+
+               /* Restore state in a new VM.  */
+               kvm_vm_restart(vm, O_RDWR);
+               vm_vcpu_add(vm, VCPU_ID, 0, 0);
+               vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+               vcpu_load_state(vm, VCPU_ID, state);
+               run = vcpu_state(vm, VCPU_ID);
+               free(state);
+
+               memset(&regs2, 0, sizeof(regs2));
+               vcpu_regs_get(vm, VCPU_ID, &regs2);
+               TEST_ASSERT(!memcmp(&regs1, &regs2, sizeof(regs2)),
+                           "Unexpected register values after vcpu_load_state; rdi: %lx rsi: %lx",
+                           (ulong) regs2.rdi, (ulong) regs2.rsi);
+       }
+
+done:
+       kvm_vm_free(vm);
+}
diff --git a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c
new file mode 100644 (file)
index 0000000..c8478ce
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Test for x86 KVM_CAP_SYNC_REGS
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * Verifies expected behavior of x86 KVM_CAP_SYNC_REGS functionality,
+ * including requesting an invalid register set, updates to/from values
+ * in kvm_run.s.regs when kvm_valid_regs and kvm_dirty_regs are toggled.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+
+#define VCPU_ID 5
+
+void guest_code(void)
+{
+       for (;;) {
+               GUEST_SYNC(0);
+               asm volatile ("inc %r11");
+       }
+}
+
+static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
+{
+#define REG_COMPARE(reg) \
+       TEST_ASSERT(left->reg == right->reg, \
+                   "Register " #reg \
+                   " values did not match: 0x%llx, 0x%llx\n", \
+                   left->reg, right->reg)
+       REG_COMPARE(rax);
+       REG_COMPARE(rbx);
+       REG_COMPARE(rcx);
+       REG_COMPARE(rdx);
+       REG_COMPARE(rsi);
+       REG_COMPARE(rdi);
+       REG_COMPARE(rsp);
+       REG_COMPARE(rbp);
+       REG_COMPARE(r8);
+       REG_COMPARE(r9);
+       REG_COMPARE(r10);
+       REG_COMPARE(r11);
+       REG_COMPARE(r12);
+       REG_COMPARE(r13);
+       REG_COMPARE(r14);
+       REG_COMPARE(r15);
+       REG_COMPARE(rip);
+       REG_COMPARE(rflags);
+#undef REG_COMPARE
+}
+
+static void compare_sregs(struct kvm_sregs *left, struct kvm_sregs *right)
+{
+}
+
+static void compare_vcpu_events(struct kvm_vcpu_events *left,
+                               struct kvm_vcpu_events *right)
+{
+}
+
+#define TEST_SYNC_FIELDS   (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS)
+#define INVALID_SYNC_FIELD 0x80000000
+
+int main(int argc, char *argv[])
+{
+       struct kvm_vm *vm;
+       struct kvm_run *run;
+       struct kvm_regs regs;
+       struct kvm_sregs sregs;
+       struct kvm_vcpu_events events;
+       int rv, cap;
+
+       /* Tell stdout not to buffer its content */
+       setbuf(stdout, NULL);
+
+       cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
+       if ((cap & TEST_SYNC_FIELDS) != TEST_SYNC_FIELDS) {
+               fprintf(stderr, "KVM_CAP_SYNC_REGS not supported, skipping test\n");
+               exit(KSFT_SKIP);
+       }
+       if ((cap & INVALID_SYNC_FIELD) != 0) {
+               fprintf(stderr, "The \"invalid\" field is not invalid, skipping test\n");
+               exit(KSFT_SKIP);
+       }
+
+       /* Create VM */
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
+
+       run = vcpu_state(vm, VCPU_ID);
+
+       /* Request reading invalid register set from VCPU. */
+       run->kvm_valid_regs = INVALID_SYNC_FIELD;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(rv < 0 && errno == EINVAL,
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   rv);
+       vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
+
+       run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(rv < 0 && errno == EINVAL,
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   rv);
+       vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
+
+       /* Request setting invalid register set into VCPU. */
+       run->kvm_dirty_regs = INVALID_SYNC_FIELD;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(rv < 0 && errno == EINVAL,
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   rv);
+       vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
+
+       run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(rv < 0 && errno == EINVAL,
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   rv);
+       vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
+
+       /* Request and verify all valid register sets. */
+       /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
+       run->kvm_valid_regs = TEST_SYNC_FIELDS;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                   "Unexpected exit reason: %u (%s),\n",
+                   run->exit_reason,
+                   exit_reason_str(run->exit_reason));
+
+       vcpu_regs_get(vm, VCPU_ID, &regs);
+       compare_regs(&regs, &run->s.regs.regs);
+
+       vcpu_sregs_get(vm, VCPU_ID, &sregs);
+       compare_sregs(&sregs, &run->s.regs.sregs);
+
+       vcpu_events_get(vm, VCPU_ID, &events);
+       compare_vcpu_events(&events, &run->s.regs.events);
+
+       /* Set and verify various register values. */
+       run->s.regs.regs.r11 = 0xBAD1DEA;
+       run->s.regs.sregs.apic_base = 1 << 11;
+       /* TODO run->s.regs.events.XYZ = ABC; */
+
+       run->kvm_valid_regs = TEST_SYNC_FIELDS;
+       run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                   "Unexpected exit reason: %u (%s),\n",
+                   run->exit_reason,
+                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT(run->s.regs.regs.r11 == 0xBAD1DEA + 1,
+                   "r11 sync regs value incorrect 0x%llx.",
+                   run->s.regs.regs.r11);
+       TEST_ASSERT(run->s.regs.sregs.apic_base == 1 << 11,
+                   "apic_base sync regs value incorrect 0x%llx.",
+                   run->s.regs.sregs.apic_base);
+
+       vcpu_regs_get(vm, VCPU_ID, &regs);
+       compare_regs(&regs, &run->s.regs.regs);
+
+       vcpu_sregs_get(vm, VCPU_ID, &sregs);
+       compare_sregs(&sregs, &run->s.regs.sregs);
+
+       vcpu_events_get(vm, VCPU_ID, &events);
+       compare_vcpu_events(&events, &run->s.regs.events);
+
+       /* Clear kvm_dirty_regs bits, verify new s.regs values are
+        * overwritten with existing guest values.
+        */
+       run->kvm_valid_regs = TEST_SYNC_FIELDS;
+       run->kvm_dirty_regs = 0;
+       run->s.regs.regs.r11 = 0xDEADBEEF;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                   "Unexpected exit reason: %u (%s),\n",
+                   run->exit_reason,
+                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT(run->s.regs.regs.r11 != 0xDEADBEEF,
+                   "r11 sync regs value incorrect 0x%llx.",
+                   run->s.regs.regs.r11);
+
+       /* Clear kvm_valid_regs bits and kvm_dirty_bits.
+        * Verify s.regs values are not overwritten with existing guest values
+        * and that guest values are not overwritten with kvm_sync_regs values.
+        */
+       run->kvm_valid_regs = 0;
+       run->kvm_dirty_regs = 0;
+       run->s.regs.regs.r11 = 0xAAAA;
+       regs.r11 = 0xBAC0;
+       vcpu_regs_set(vm, VCPU_ID, &regs);
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                   "Unexpected exit reason: %u (%s),\n",
+                   run->exit_reason,
+                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT(run->s.regs.regs.r11 == 0xAAAA,
+                   "r11 sync regs value incorrect 0x%llx.",
+                   run->s.regs.regs.r11);
+       vcpu_regs_get(vm, VCPU_ID, &regs);
+       TEST_ASSERT(regs.r11 == 0xBAC0 + 1,
+                   "r11 guest value incorrect 0x%llx.",
+                   regs.r11);
+
+       /* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
+        * with existing guest values but that guest values are overwritten
+        * with kvm_sync_regs values.
+        */
+       run->kvm_valid_regs = 0;
+       run->kvm_dirty_regs = TEST_SYNC_FIELDS;
+       run->s.regs.regs.r11 = 0xBBBB;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                   "Unexpected exit reason: %u (%s),\n",
+                   run->exit_reason,
+                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT(run->s.regs.regs.r11 == 0xBBBB,
+                   "r11 sync regs value incorrect 0x%llx.",
+                   run->s.regs.regs.r11);
+       vcpu_regs_get(vm, VCPU_ID, &regs);
+       TEST_ASSERT(regs.r11 == 0xBBBB + 1,
+                   "r11 guest value incorrect 0x%llx.",
+                   regs.r11);
+
+       kvm_vm_free(vm);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c b/tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c
new file mode 100644 (file)
index 0000000..38a91a5
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * vmx_tsc_adjust_test
+ *
+ * Copyright (C) 2018, Google LLC.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ *
+ * IA32_TSC_ADJUST test
+ *
+ * According to the SDM, "if an execution of WRMSR to the
+ * IA32_TIME_STAMP_COUNTER MSR adds (or subtracts) value X from the TSC,
+ * the logical processor also adds (or subtracts) value X from the
+ * IA32_TSC_ADJUST MSR.
+ *
+ * Note that when L1 doesn't intercept writes to IA32_TSC, a
+ * WRMSR(IA32_TSC) from L2 sets L1's TSC value, not L2's perceived TSC
+ * value.
+ *
+ * This test verifies that this unusual case is handled correctly.
+ */
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "processor.h"
+#include "vmx.h"
+
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "kselftest.h"
+
+#ifndef MSR_IA32_TSC_ADJUST
+#define MSR_IA32_TSC_ADJUST 0x3b
+#endif
+
+#define PAGE_SIZE      4096
+#define VCPU_ID                5
+
+#define TSC_ADJUST_VALUE (1ll << 32)
+#define TSC_OFFSET_VALUE -(1ll << 48)
+
+enum {
+       PORT_ABORT = 0x1000,
+       PORT_REPORT,
+       PORT_DONE,
+};
+
+enum {
+       VMXON_PAGE = 0,
+       VMCS_PAGE,
+       MSR_BITMAP_PAGE,
+
+       NUM_VMX_PAGES,
+};
+
+struct kvm_single_msr {
+       struct kvm_msrs header;
+       struct kvm_msr_entry entry;
+} __attribute__((packed));
+
+/* The virtual machine object. */
+static struct kvm_vm *vm;
+
+static void check_ia32_tsc_adjust(int64_t max)
+{
+       int64_t adjust;
+
+       adjust = rdmsr(MSR_IA32_TSC_ADJUST);
+       GUEST_SYNC(adjust);
+       GUEST_ASSERT(adjust <= max);
+}
+
+static void l2_guest_code(void)
+{
+       uint64_t l1_tsc = rdtsc() - TSC_OFFSET_VALUE;
+
+       wrmsr(MSR_IA32_TSC, l1_tsc - TSC_ADJUST_VALUE);
+       check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
+
+       /* Exit to L1 */
+       __asm__ __volatile__("vmcall");
+}
+
+static void l1_guest_code(struct vmx_pages *vmx_pages)
+{
+#define L2_GUEST_STACK_SIZE 64
+       unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+       uint32_t control;
+       uintptr_t save_cr3;
+
+       GUEST_ASSERT(rdtsc() < TSC_ADJUST_VALUE);
+       wrmsr(MSR_IA32_TSC, rdtsc() - TSC_ADJUST_VALUE);
+       check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
+
+       GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
+
+       /* Prepare the VMCS for L2 execution. */
+       prepare_vmcs(vmx_pages, l2_guest_code,
+                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
+       control = vmreadz(CPU_BASED_VM_EXEC_CONTROL);
+       control |= CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETING;
+       vmwrite(CPU_BASED_VM_EXEC_CONTROL, control);
+       vmwrite(TSC_OFFSET, TSC_OFFSET_VALUE);
+
+       /* Jump into L2.  First, test failure to load guest CR3.  */
+       save_cr3 = vmreadz(GUEST_CR3);
+       vmwrite(GUEST_CR3, -1ull);
+       GUEST_ASSERT(!vmlaunch());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) ==
+                    (EXIT_REASON_FAILED_VMENTRY | EXIT_REASON_INVALID_STATE));
+       check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE);
+       vmwrite(GUEST_CR3, save_cr3);
+
+       GUEST_ASSERT(!vmlaunch());
+       GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
+
+       check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
+
+       GUEST_DONE();
+}
+
+void report(int64_t val)
+{
+       printf("IA32_TSC_ADJUST is %ld (%lld * TSC_ADJUST_VALUE + %lld).\n",
+              val, val / TSC_ADJUST_VALUE, val % TSC_ADJUST_VALUE);
+}
+
+int main(int argc, char *argv[])
+{
+       struct vmx_pages *vmx_pages;
+       vm_vaddr_t vmx_pages_gva;
+       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
+
+       if (!(entry->ecx & CPUID_VMX)) {
+               fprintf(stderr, "nested VMX not enabled, skipping test\n");
+               exit(KSFT_SKIP);
+       }
+
+       vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
+       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+
+       /* Allocate VMX pages and shared descriptors (vmx_pages). */
+       vmx_pages = vcpu_alloc_vmx(vm, &vmx_pages_gva);
+       vcpu_args_set(vm, VCPU_ID, 1, vmx_pages_gva);
+
+       for (;;) {
+               volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
+               struct ucall uc;
+
+               vcpu_run(vm, VCPU_ID);
+               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
+                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
+                           run->exit_reason,
+                           exit_reason_str(run->exit_reason));
+
+               switch (get_ucall(vm, VCPU_ID, &uc)) {
+               case UCALL_ABORT:
+                       TEST_ASSERT(false, "%s", (const char *)uc.args[0]);
+                       /* NOT REACHED */
+               case UCALL_SYNC:
+                       report(uc.args[1]);
+                       break;
+               case UCALL_DONE:
+                       goto done;
+               default:
+                       TEST_ASSERT(false, "Unknown ucall 0x%x.", uc.cmd);
+               }
+       }
+
+       kvm_vm_free(vm);
+done:
+       return 0;
+}