86 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * CR4 and CPUID sync test4 *5 * Copyright 2018, Red Hat, Inc. and/or its affiliates.6 *7 * Author:8 * Wei Huang <wei@redhat.com>9 */10 11#include <fcntl.h>12#include <stdio.h>13#include <stdlib.h>14#include <string.h>15#include <sys/ioctl.h>16 17#include "test_util.h"18 19#include "kvm_util.h"20#include "processor.h"21 22static inline bool cr4_cpuid_is_sync(void)23{24 uint64_t cr4 = get_cr4();25 26 return (this_cpu_has(X86_FEATURE_OSXSAVE) == !!(cr4 & X86_CR4_OSXSAVE));27}28 29static void guest_code(void)30{31 uint64_t cr4;32 33 /* turn on CR4.OSXSAVE */34 cr4 = get_cr4();35 cr4 |= X86_CR4_OSXSAVE;36 set_cr4(cr4);37 38 /* verify CR4.OSXSAVE == CPUID.OSXSAVE */39 GUEST_ASSERT(cr4_cpuid_is_sync());40 41 /* notify hypervisor to change CR4 */42 GUEST_SYNC(0);43 44 /* check again */45 GUEST_ASSERT(cr4_cpuid_is_sync());46 47 GUEST_DONE();48}49 50int main(int argc, char *argv[])51{52 struct kvm_vcpu *vcpu;53 struct kvm_vm *vm;54 struct kvm_sregs sregs;55 struct ucall uc;56 57 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE));58 59 vm = vm_create_with_one_vcpu(&vcpu, guest_code);60 61 while (1) {62 vcpu_run(vcpu);63 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);64 65 switch (get_ucall(vcpu, &uc)) {66 case UCALL_SYNC:67 /* emulate hypervisor clearing CR4.OSXSAVE */68 vcpu_sregs_get(vcpu, &sregs);69 sregs.cr4 &= ~X86_CR4_OSXSAVE;70 vcpu_sregs_set(vcpu, &sregs);71 break;72 case UCALL_ABORT:73 REPORT_GUEST_ASSERT(uc);74 break;75 case UCALL_DONE:76 goto done;77 default:78 TEST_FAIL("Unknown ucall %lu", uc.cmd);79 }80 }81 82done:83 kvm_vm_free(vm);84 return 0;85}86