123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- // 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;
- 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 (run->io.port) {
- case GUEST_PORT_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 GUEST_PORT_ABORT:
- TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
- break;
- case GUEST_PORT_DONE:
- goto done;
- default:
- TEST_ASSERT(false, "Unknown port 0x%x.",
- run->io.port);
- }
- }
- }
- kvm_vm_free(vm);
- done:
- return 0;
- }
|