]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
kvm: tests: Add test to verify MSR_IA32_XSS
authorAaron Lewis <aaronlewis@google.com>
Mon, 21 Oct 2019 23:30:28 +0000 (16:30 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 22 Oct 2019 13:48:15 +0000 (15:48 +0200)
Ensure that IA32_XSS appears in KVM_GET_MSR_INDEX_LIST if it can be set
to a non-zero value.

Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Aaron Lewis <aaronlewis@google.com>
Change-Id: Ia2d644f69e2d6d8c27d7e0a7a45c2bf9c42bf5ff
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/x86_64/xss_msr_test.c [new file with mode: 0644]

index 409c1fa75e03575c2c04736b325b0484ae8fd65a..30072c3f52fbee7155511a59139c592ffeaf12be 100644 (file)
@@ -13,6 +13,7 @@
 /x86_64/vmx_dirty_log_test
 /x86_64/vmx_set_nested_state_test
 /x86_64/vmx_tsc_adjust_test
+/x86_64/xss_msr_test
 /clear_dirty_log_test
 /dirty_log_test
 /kvm_create_max_vcpus
index c5ec868fa1e523fc36419ef008722afb469349c8..3138a916574a9468835a4ec9a4be28fd0d69ff2a 100644 (file)
@@ -25,6 +25,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/vmx_close_while_nested_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_dirty_log_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_set_nested_state_test
 TEST_GEN_PROGS_x86_64 += x86_64/vmx_tsc_adjust_test
+TEST_GEN_PROGS_x86_64 += x86_64/xss_msr_test
 TEST_GEN_PROGS_x86_64 += clear_dirty_log_test
 TEST_GEN_PROGS_x86_64 += dirty_log_test
 TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus
index ff234018219cfcf883e020d86f4c4306c2591e5a..635ee6c33ad250909941843952bb633daf7bb259 100644 (file)
@@ -308,6 +308,8 @@ 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);
 
+struct kvm_msr_list *kvm_get_msr_index_list(void);
+
 struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
 void vcpu_set_cpuid(struct kvm_vm *vm, uint32_t vcpuid,
                    struct kvm_cpuid2 *cpuid);
@@ -322,10 +324,13 @@ kvm_get_supported_cpuid_entry(uint32_t function)
 }
 
 uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
+int _vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
+                 uint64_t msr_value);
 void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
                  uint64_t msr_value);
 
-uint32_t kvm_get_cpuid_max(void);
+uint32_t kvm_get_cpuid_max_basic(void);
+uint32_t kvm_get_cpuid_max_extended(void);
 void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits);
 
 /*
index 6698cb741e10a47afad23e92d22490ed46ade598..683d3bdb8f6af236bb3bd2526225522a909766d8 100644 (file)
@@ -869,7 +869,7 @@ uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
        return buffer.entry.data;
 }
 
-/* VCPU Set MSR
+/* _VCPU Set MSR
  *
  * Input Args:
  *   vm - Virtual Machine
@@ -879,12 +879,12 @@ uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
  *
  * Output Args: None
  *
- * Return: On success, nothing. On failure a TEST_ASSERT is produced.
+ * Return: The result of KVM_SET_MSRS.
  *
- * Set value of MSR for VCPU.
+ * Sets the value of an MSR for the given VCPU.
  */
-void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
-       uint64_t msr_value)
+int _vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
+                 uint64_t msr_value)
 {
        struct vcpu *vcpu = vcpu_find(vm, vcpuid);
        struct {
@@ -899,6 +899,29 @@ void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
        buffer.entry.index = msr_index;
        buffer.entry.data = msr_value;
        r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
+       return r;
+}
+
+/* VCPU Set MSR
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   vcpuid - VCPU ID
+ *   msr_index - Index of MSR
+ *   msr_value - New value of MSR
+ *
+ * Output Args: None
+ *
+ * Return: On success, nothing. On failure a TEST_ASSERT is produced.
+ *
+ * Set value of MSR for VCPU.
+ */
+void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
+       uint64_t msr_value)
+{
+       int r;
+
+       r = _vcpu_set_msr(vm, vcpuid, msr_index, msr_value);
        TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
                "  rc: %i errno: %i", r, errno);
 }
@@ -1000,19 +1023,45 @@ struct kvm_x86_state {
        struct kvm_msrs msrs;
 };
 
-static int kvm_get_num_msrs(struct kvm_vm *vm)
+static int kvm_get_num_msrs_fd(int kvm_fd)
 {
        struct kvm_msr_list nmsrs;
        int r;
 
        nmsrs.nmsrs = 0;
-       r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, &nmsrs);
+       r = ioctl(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;
 }
 
+static int kvm_get_num_msrs(struct kvm_vm *vm)
+{
+       return kvm_get_num_msrs_fd(vm->kvm_fd);
+}
+
+struct kvm_msr_list *kvm_get_msr_index_list(void)
+{
+       struct kvm_msr_list *list;
+       int nmsrs, r, kvm_fd;
+
+       kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
+       if (kvm_fd < 0)
+               exit(KSFT_SKIP);
+
+       nmsrs = kvm_get_num_msrs_fd(kvm_fd);
+       list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
+       list->nmsrs = nmsrs;
+       r = ioctl(kvm_fd, KVM_GET_MSR_INDEX_LIST, list);
+       close(kvm_fd);
+
+       TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MSR_INDEX_LIST, r: %i",
+               r);
+
+       return list;
+}
+
 struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
 {
        struct vcpu *vcpu = vcpu_find(vm, vcpuid);
@@ -1158,7 +1207,12 @@ bool is_intel_cpu(void)
        return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]);
 }
 
-uint32_t kvm_get_cpuid_max(void)
+uint32_t kvm_get_cpuid_max_basic(void)
+{
+       return kvm_get_supported_cpuid_entry(0)->eax;
+}
+
+uint32_t kvm_get_cpuid_max_extended(void)
 {
        return kvm_get_supported_cpuid_entry(0x80000000)->eax;
 }
@@ -1169,7 +1223,7 @@ void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits)
        bool pae;
 
        /* SDM 4.1.4 */
-       if (kvm_get_cpuid_max() < 0x80000008) {
+       if (kvm_get_cpuid_max_extended() < 0x80000008) {
                pae = kvm_get_supported_cpuid_entry(1)->edx & (1 << 6);
                *pa_bits = pae ? 36 : 32;
                *va_bits = 32;
diff --git a/tools/testing/selftests/kvm/x86_64/xss_msr_test.c b/tools/testing/selftests/kvm/x86_64/xss_msr_test.c
new file mode 100644 (file)
index 0000000..851ea81
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019, Google LLC.
+ *
+ * Tests for the IA32_XSS MSR.
+ */
+
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "vmx.h"
+
+#define VCPU_ID              1
+#define MSR_BITS      64
+
+#define X86_FEATURE_XSAVES     (1<<3)
+
+bool is_supported_msr(u32 msr_index)
+{
+       struct kvm_msr_list *list;
+       bool found = false;
+       int i;
+
+       list = kvm_get_msr_index_list();
+       for (i = 0; i < list->nmsrs; ++i) {
+               if (list->indices[i] == msr_index) {
+                       found = true;
+                       break;
+               }
+       }
+
+       free(list);
+       return found;
+}
+
+int main(int argc, char *argv[])
+{
+       struct kvm_cpuid_entry2 *entry;
+       bool xss_supported = false;
+       struct kvm_vm *vm;
+       uint64_t xss_val;
+       int i, r;
+
+       /* Create VM */
+       vm = vm_create_default(VCPU_ID, 0, 0);
+
+       if (kvm_get_cpuid_max_basic() >= 0xd) {
+               entry = kvm_get_supported_cpuid_index(0xd, 1);
+               xss_supported = entry && !!(entry->eax & X86_FEATURE_XSAVES);
+       }
+       if (!xss_supported) {
+               printf("IA32_XSS is not supported by the vCPU.\n");
+               exit(KSFT_SKIP);
+       }
+
+       xss_val = vcpu_get_msr(vm, VCPU_ID, MSR_IA32_XSS);
+       TEST_ASSERT(xss_val == 0,
+                   "MSR_IA32_XSS should be initialized to zero\n");
+
+       vcpu_set_msr(vm, VCPU_ID, MSR_IA32_XSS, xss_val);
+       /*
+        * At present, KVM only supports a guest IA32_XSS value of 0. Verify
+        * that trying to set the guest IA32_XSS to an unsupported value fails.
+        * Also, in the future when a non-zero value succeeds check that
+        * IA32_XSS is in the KVM_GET_MSR_INDEX_LIST.
+        */
+       for (i = 0; i < MSR_BITS; ++i) {
+               r = _vcpu_set_msr(vm, VCPU_ID, MSR_IA32_XSS, 1ull << i);
+               TEST_ASSERT(r == 0 || is_supported_msr(MSR_IA32_XSS),
+                           "IA32_XSS was able to be set, but was not found in KVM_GET_MSR_INDEX_LIST.\n");
+       }
+
+       kvm_vm_free(vm);
+}