0001
0002
0003
0004
0005
0006
0007
0008
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
0034 cr4 = get_cr4();
0035 cr4 |= X86_CR4_OSXSAVE;
0036 set_cr4(cr4);
0037
0038
0039 GUEST_ASSERT(cr4_cpuid_is_sync());
0040
0041
0042 GUEST_SYNC(0);
0043
0044
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
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
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 }