0001
0002
0003
0004
0005
0006
0007 #include <asm/kvm_para.h>
0008 #include <linux/kvm_para.h>
0009 #include <stdint.h>
0010
0011 #include "test_util.h"
0012 #include "kvm_util.h"
0013 #include "processor.h"
0014
0015
0016 struct {
0017 u32 function;
0018 u32 index;
0019 } mangled_cpuids[] = {
0020
0021
0022
0023
0024 {.function = 0xd, .index = 0},
0025 {.function = 0xd, .index = 1},
0026 };
0027
0028 static void test_guest_cpuids(struct kvm_cpuid2 *guest_cpuid)
0029 {
0030 int i;
0031 u32 eax, ebx, ecx, edx;
0032
0033 for (i = 0; i < guest_cpuid->nent; i++) {
0034 __cpuid(guest_cpuid->entries[i].function,
0035 guest_cpuid->entries[i].index,
0036 &eax, &ebx, &ecx, &edx);
0037
0038 GUEST_ASSERT(eax == guest_cpuid->entries[i].eax &&
0039 ebx == guest_cpuid->entries[i].ebx &&
0040 ecx == guest_cpuid->entries[i].ecx &&
0041 edx == guest_cpuid->entries[i].edx);
0042 }
0043
0044 }
0045
0046 static void test_cpuid_40000000(struct kvm_cpuid2 *guest_cpuid)
0047 {
0048 u32 eax, ebx, ecx, edx;
0049
0050 cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
0051
0052 GUEST_ASSERT(eax == 0x40000001);
0053 }
0054
0055 static void guest_main(struct kvm_cpuid2 *guest_cpuid)
0056 {
0057 GUEST_SYNC(1);
0058
0059 test_guest_cpuids(guest_cpuid);
0060
0061 GUEST_SYNC(2);
0062
0063 test_cpuid_40000000(guest_cpuid);
0064
0065 GUEST_DONE();
0066 }
0067
0068 static bool is_cpuid_mangled(const struct kvm_cpuid_entry2 *entrie)
0069 {
0070 int i;
0071
0072 for (i = 0; i < sizeof(mangled_cpuids); i++) {
0073 if (mangled_cpuids[i].function == entrie->function &&
0074 mangled_cpuids[i].index == entrie->index)
0075 return true;
0076 }
0077
0078 return false;
0079 }
0080
0081 static void compare_cpuids(const struct kvm_cpuid2 *cpuid1,
0082 const struct kvm_cpuid2 *cpuid2)
0083 {
0084 const struct kvm_cpuid_entry2 *e1, *e2;
0085 int i;
0086
0087 TEST_ASSERT(cpuid1->nent == cpuid2->nent,
0088 "CPUID nent mismatch: %d vs. %d", cpuid1->nent, cpuid2->nent);
0089
0090 for (i = 0; i < cpuid1->nent; i++) {
0091 e1 = &cpuid1->entries[i];
0092 e2 = &cpuid2->entries[i];
0093
0094 TEST_ASSERT(e1->function == e2->function &&
0095 e1->index == e2->index && e1->flags == e2->flags,
0096 "CPUID entries[%d] mismtach: 0x%x.%d.%x vs. 0x%x.%d.%x\n",
0097 i, e1->function, e1->index, e1->flags,
0098 e2->function, e2->index, e2->flags);
0099
0100 if (is_cpuid_mangled(e1))
0101 continue;
0102
0103 TEST_ASSERT(e1->eax == e2->eax && e1->ebx == e2->ebx &&
0104 e1->ecx == e2->ecx && e1->edx == e2->edx,
0105 "CPUID 0x%x.%x differ: 0x%x:0x%x:0x%x:0x%x vs 0x%x:0x%x:0x%x:0x%x",
0106 e1->function, e1->index,
0107 e1->eax, e1->ebx, e1->ecx, e1->edx,
0108 e2->eax, e2->ebx, e2->ecx, e2->edx);
0109 }
0110 }
0111
0112 static void run_vcpu(struct kvm_vcpu *vcpu, int stage)
0113 {
0114 struct ucall uc;
0115
0116 vcpu_run(vcpu);
0117
0118 switch (get_ucall(vcpu, &uc)) {
0119 case UCALL_SYNC:
0120 TEST_ASSERT(!strcmp((const char *)uc.args[0], "hello") &&
0121 uc.args[1] == stage + 1,
0122 "Stage %d: Unexpected register values vmexit, got %lx",
0123 stage + 1, (ulong)uc.args[1]);
0124 return;
0125 case UCALL_DONE:
0126 return;
0127 case UCALL_ABORT:
0128 REPORT_GUEST_ASSERT_2(uc, "values: %#lx, %#lx");
0129 default:
0130 TEST_ASSERT(false, "Unexpected exit: %s",
0131 exit_reason_str(vcpu->run->exit_reason));
0132 }
0133 }
0134
0135 struct kvm_cpuid2 *vcpu_alloc_cpuid(struct kvm_vm *vm, vm_vaddr_t *p_gva, struct kvm_cpuid2 *cpuid)
0136 {
0137 int size = sizeof(*cpuid) + cpuid->nent * sizeof(cpuid->entries[0]);
0138 vm_vaddr_t gva = vm_vaddr_alloc(vm, size, KVM_UTIL_MIN_VADDR);
0139 struct kvm_cpuid2 *guest_cpuids = addr_gva2hva(vm, gva);
0140
0141 memcpy(guest_cpuids, cpuid, size);
0142
0143 *p_gva = gva;
0144 return guest_cpuids;
0145 }
0146
0147 static void set_cpuid_after_run(struct kvm_vcpu *vcpu)
0148 {
0149 struct kvm_cpuid_entry2 *ent;
0150 int rc;
0151 u32 eax, ebx, x;
0152
0153
0154 rc = __vcpu_set_cpuid(vcpu);
0155 TEST_ASSERT(!rc, "Setting unmodified CPUID after KVM_RUN failed: %d", rc);
0156
0157
0158 ent = vcpu_get_cpuid_entry(vcpu, 0x7);
0159 ebx = ent->ebx;
0160 ent->ebx--;
0161 rc = __vcpu_set_cpuid(vcpu);
0162 TEST_ASSERT(rc, "Changing CPU features should fail");
0163 ent->ebx = ebx;
0164
0165
0166 ent = vcpu_get_cpuid_entry(vcpu, 0x80000008);
0167 eax = ent->eax;
0168 x = eax & 0xff;
0169 ent->eax = (eax & ~0xffu) | (x - 1);
0170 rc = __vcpu_set_cpuid(vcpu);
0171 TEST_ASSERT(rc, "Changing MAXPHYADDR should fail");
0172 ent->eax = eax;
0173 }
0174
0175 int main(void)
0176 {
0177 struct kvm_vcpu *vcpu;
0178 vm_vaddr_t cpuid_gva;
0179 struct kvm_vm *vm;
0180 int stage;
0181
0182 vm = vm_create_with_one_vcpu(&vcpu, guest_main);
0183
0184 compare_cpuids(kvm_get_supported_cpuid(), vcpu->cpuid);
0185
0186 vcpu_alloc_cpuid(vm, &cpuid_gva, vcpu->cpuid);
0187
0188 vcpu_args_set(vcpu, 1, cpuid_gva);
0189
0190 for (stage = 0; stage < 3; stage++)
0191 run_vcpu(vcpu, stage);
0192
0193 set_cpuid_after_run(vcpu);
0194
0195 kvm_vm_free(vm);
0196 }