Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * CR4 and CPUID sync test
0004  *
0005  * Copyright 2018, Red Hat, Inc. and/or its affiliates.
0006  *
0007  * Author:
0008  *   Wei Huang <wei@redhat.com>
0009  */
0010 
0011 #include <fcntl.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 #include <sys/ioctl.h>
0016 
0017 #include "test_util.h"
0018 
0019 #include "kvm_util.h"
0020 #include "processor.h"
0021 
0022 static inline bool cr4_cpuid_is_sync(void)
0023 {
0024     uint64_t cr4 = get_cr4();
0025 
0026     return (this_cpu_has(X86_FEATURE_OSXSAVE) == !!(cr4 & X86_CR4_OSXSAVE));
0027 }
0028 
0029 static void guest_code(void)
0030 {
0031     uint64_t cr4;
0032 
0033     /* turn on CR4.OSXSAVE */
0034     cr4 = get_cr4();
0035     cr4 |= X86_CR4_OSXSAVE;
0036     set_cr4(cr4);
0037 
0038     /* verify CR4.OSXSAVE == CPUID.OSXSAVE */
0039     GUEST_ASSERT(cr4_cpuid_is_sync());
0040 
0041     /* notify hypervisor to change CR4 */
0042     GUEST_SYNC(0);
0043 
0044     /* check again */
0045     GUEST_ASSERT(cr4_cpuid_is_sync());
0046 
0047     GUEST_DONE();
0048 }
0049 
0050 int main(int argc, char *argv[])
0051 {
0052     struct kvm_vcpu *vcpu;
0053     struct kvm_run *run;
0054     struct kvm_vm *vm;
0055     struct kvm_sregs sregs;
0056     struct ucall uc;
0057 
0058     TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE));
0059 
0060     /* Tell stdout not to buffer its content */
0061     setbuf(stdout, NULL);
0062 
0063     vm = vm_create_with_one_vcpu(&vcpu, guest_code);
0064     run = vcpu->run;
0065 
0066     while (1) {
0067         vcpu_run(vcpu);
0068 
0069         TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
0070                 "Unexpected exit reason: %u (%s),\n",
0071                 run->exit_reason,
0072                 exit_reason_str(run->exit_reason));
0073 
0074         switch (get_ucall(vcpu, &uc)) {
0075         case UCALL_SYNC:
0076             /* emulate hypervisor clearing CR4.OSXSAVE */
0077             vcpu_sregs_get(vcpu, &sregs);
0078             sregs.cr4 &= ~X86_CR4_OSXSAVE;
0079             vcpu_sregs_set(vcpu, &sregs);
0080             break;
0081         case UCALL_ABORT:
0082             REPORT_GUEST_ASSERT(uc);
0083             break;
0084         case UCALL_DONE:
0085             goto done;
0086         default:
0087             TEST_FAIL("Unknown ucall %lu", uc.cmd);
0088         }
0089     }
0090 
0091 done:
0092     kvm_vm_free(vm);
0093     return 0;
0094 }