diff options
Diffstat (limited to 'tools/testing/selftests/kvm/x86_64/cpuid_test.c')
| -rw-r--r-- | tools/testing/selftests/kvm/x86_64/cpuid_test.c | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/tools/testing/selftests/kvm/x86_64/cpuid_test.c b/tools/testing/selftests/kvm/x86_64/cpuid_test.c deleted file mode 100644 index d3c3aa93f090..000000000000 --- a/tools/testing/selftests/kvm/x86_64/cpuid_test.c +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2021, Red Hat Inc. - * - * Generic tests for KVM CPUID set/get ioctls - */ -#include <asm/kvm_para.h> -#include <linux/kvm_para.h> -#include <stdint.h> - -#include "test_util.h" -#include "kvm_util.h" -#include "processor.h" - -/* CPUIDs known to differ */ -struct { - u32 function; - u32 index; -} mangled_cpuids[] = { - /* - * These entries depend on the vCPU's XCR0 register and IA32_XSS MSR, - * which are not controlled for by this test. - */ - {.function = 0xd, .index = 0}, - {.function = 0xd, .index = 1}, -}; - -static void test_guest_cpuids(struct kvm_cpuid2 *guest_cpuid) -{ - int i; - u32 eax, ebx, ecx, edx; - - for (i = 0; i < guest_cpuid->nent; i++) { - __cpuid(guest_cpuid->entries[i].function, - guest_cpuid->entries[i].index, - &eax, &ebx, &ecx, &edx); - - GUEST_ASSERT(eax == guest_cpuid->entries[i].eax && - ebx == guest_cpuid->entries[i].ebx && - ecx == guest_cpuid->entries[i].ecx && - edx == guest_cpuid->entries[i].edx); - } - -} - -static void guest_main(struct kvm_cpuid2 *guest_cpuid) -{ - GUEST_SYNC(1); - - test_guest_cpuids(guest_cpuid); - - GUEST_SYNC(2); - - GUEST_ASSERT(this_cpu_property(X86_PROPERTY_MAX_KVM_LEAF) == 0x40000001); - - GUEST_DONE(); -} - -static bool is_cpuid_mangled(const struct kvm_cpuid_entry2 *entrie) -{ - int i; - - for (i = 0; i < sizeof(mangled_cpuids); i++) { - if (mangled_cpuids[i].function == entrie->function && - mangled_cpuids[i].index == entrie->index) - return true; - } - - return false; -} - -static void compare_cpuids(const struct kvm_cpuid2 *cpuid1, - const struct kvm_cpuid2 *cpuid2) -{ - const struct kvm_cpuid_entry2 *e1, *e2; - int i; - - TEST_ASSERT(cpuid1->nent == cpuid2->nent, - "CPUID nent mismatch: %d vs. %d", cpuid1->nent, cpuid2->nent); - - for (i = 0; i < cpuid1->nent; i++) { - e1 = &cpuid1->entries[i]; - e2 = &cpuid2->entries[i]; - - TEST_ASSERT(e1->function == e2->function && - e1->index == e2->index && e1->flags == e2->flags, - "CPUID entries[%d] mismtach: 0x%x.%d.%x vs. 0x%x.%d.%x\n", - i, e1->function, e1->index, e1->flags, - e2->function, e2->index, e2->flags); - - if (is_cpuid_mangled(e1)) - continue; - - TEST_ASSERT(e1->eax == e2->eax && e1->ebx == e2->ebx && - e1->ecx == e2->ecx && e1->edx == e2->edx, - "CPUID 0x%x.%x differ: 0x%x:0x%x:0x%x:0x%x vs 0x%x:0x%x:0x%x:0x%x", - e1->function, e1->index, - e1->eax, e1->ebx, e1->ecx, e1->edx, - e2->eax, e2->ebx, e2->ecx, e2->edx); - } -} - -static void run_vcpu(struct kvm_vcpu *vcpu, int stage) -{ - struct ucall uc; - - vcpu_run(vcpu); - - switch (get_ucall(vcpu, &uc)) { - case UCALL_SYNC: - TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") && - uc.args[1] == stage + 1, - "Stage %d: Unexpected register values vmexit, got %lx", - stage + 1, (ulong)uc.args[1]); - return; - case UCALL_DONE: - return; - case UCALL_ABORT: - REPORT_GUEST_ASSERT_2(uc, "values: %#lx, %#lx"); - default: - TEST_ASSERT(false, "Unexpected exit: %s", - exit_reason_str(vcpu->run->exit_reason)); - } -} - -struct kvm_cpuid2 *vcpu_alloc_cpuid(struct kvm_vm *vm, vm_vaddr_t *p_gva, struct kvm_cpuid2 *cpuid) -{ - int size = sizeof(*cpuid) + cpuid->nent * sizeof(cpuid->entries[0]); - vm_vaddr_t gva = vm_vaddr_alloc(vm, size, KVM_UTIL_MIN_VADDR); - struct kvm_cpuid2 *guest_cpuids = addr_gva2hva(vm, gva); - - memcpy(guest_cpuids, cpuid, size); - - *p_gva = gva; - return guest_cpuids; -} - -static void set_cpuid_after_run(struct kvm_vcpu *vcpu) -{ - struct kvm_cpuid_entry2 *ent; - int rc; - u32 eax, ebx, x; - - /* Setting unmodified CPUID is allowed */ - rc = __vcpu_set_cpuid(vcpu); - TEST_ASSERT(!rc, "Setting unmodified CPUID after KVM_RUN failed: %d", rc); - - /* Changing CPU features is forbidden */ - ent = vcpu_get_cpuid_entry(vcpu, 0x7); - ebx = ent->ebx; - ent->ebx--; - rc = __vcpu_set_cpuid(vcpu); - TEST_ASSERT(rc, "Changing CPU features should fail"); - ent->ebx = ebx; - - /* Changing MAXPHYADDR is forbidden */ - ent = vcpu_get_cpuid_entry(vcpu, 0x80000008); - eax = ent->eax; - x = eax & 0xff; - ent->eax = (eax & ~0xffu) | (x - 1); - rc = __vcpu_set_cpuid(vcpu); - TEST_ASSERT(rc, "Changing MAXPHYADDR should fail"); - ent->eax = eax; -} - -static void test_get_cpuid2(struct kvm_vcpu *vcpu) -{ - struct kvm_cpuid2 *cpuid = allocate_kvm_cpuid2(vcpu->cpuid->nent + 1); - int i, r; - - vcpu_ioctl(vcpu, KVM_GET_CPUID2, cpuid); - TEST_ASSERT(cpuid->nent == vcpu->cpuid->nent, - "KVM didn't update nent on success, wanted %u, got %u\n", - vcpu->cpuid->nent, cpuid->nent); - - for (i = 0; i < vcpu->cpuid->nent; i++) { - cpuid->nent = i; - r = __vcpu_ioctl(vcpu, KVM_GET_CPUID2, cpuid); - TEST_ASSERT(r && errno == E2BIG, KVM_IOCTL_ERROR(KVM_GET_CPUID2, r)); - TEST_ASSERT(cpuid->nent == i, "KVM modified nent on failure"); - } - free(cpuid); -} - -int main(void) -{ - struct kvm_vcpu *vcpu; - vm_vaddr_t cpuid_gva; - struct kvm_vm *vm; - int stage; - - vm = vm_create_with_one_vcpu(&vcpu, guest_main); - - compare_cpuids(kvm_get_supported_cpuid(), vcpu->cpuid); - - vcpu_alloc_cpuid(vm, &cpuid_gva, vcpu->cpuid); - - vcpu_args_set(vcpu, 1, cpuid_gva); - - for (stage = 0; stage < 3; stage++) - run_vcpu(vcpu, stage); - - set_cpuid_after_run(vcpu); - - test_get_cpuid2(vcpu); - - kvm_vm_free(vm); -} |
