gpio: Fix irqchip initialization order
[linux-2.6-block.git] / tools / testing / selftests / kvm / x86_64 / hyperv_cpuid.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test for x86 KVM_CAP_HYPERV_CPUID
4  *
5  * Copyright (C) 2018, Red Hat, Inc.
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2.
8  *
9  */
10
11 #define _GNU_SOURCE /* for program_invocation_short_name */
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17
18 #include "test_util.h"
19 #include "kvm_util.h"
20 #include "processor.h"
21
22 #define VCPU_ID 0
23
24 static void guest_code(void)
25 {
26 }
27
28 static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
29                           int evmcs_enabled)
30 {
31         int i;
32
33         if (!evmcs_enabled)
34                 TEST_ASSERT(hv_cpuid_entries->nent == 6,
35                             "KVM_GET_SUPPORTED_HV_CPUID should return 6 entries"
36                             " when Enlightened VMCS is disabled (returned %d)",
37                             hv_cpuid_entries->nent);
38         else
39                 TEST_ASSERT(hv_cpuid_entries->nent == 7,
40                             "KVM_GET_SUPPORTED_HV_CPUID should return 7 entries"
41                             " when Enlightened VMCS is enabled (returned %d)",
42                             hv_cpuid_entries->nent);
43
44         for (i = 0; i < hv_cpuid_entries->nent; i++) {
45                 struct kvm_cpuid_entry2 *entry = &hv_cpuid_entries->entries[i];
46
47                 TEST_ASSERT((entry->function >= 0x40000000) &&
48                             (entry->function <= 0x4000000A),
49                             "function %lx is our of supported range",
50                             entry->function);
51
52                 TEST_ASSERT(entry->index == 0,
53                             ".index field should be zero");
54
55                 TEST_ASSERT(entry->flags == 0,
56                             ".flags field should be zero");
57
58                 TEST_ASSERT(!entry->padding[0] && !entry->padding[1] &&
59                             !entry->padding[2], "padding should be zero");
60
61                 /*
62                  * If needed for debug:
63                  * fprintf(stdout,
64                  *      "CPUID%lx EAX=0x%lx EBX=0x%lx ECX=0x%lx EDX=0x%lx\n",
65                  *      entry->function, entry->eax, entry->ebx, entry->ecx,
66                  *      entry->edx);
67                  */
68         }
69
70 }
71
72 void test_hv_cpuid_e2big(struct kvm_vm *vm)
73 {
74         static struct kvm_cpuid2 cpuid = {.nent = 0};
75         int ret;
76
77         ret = _vcpu_ioctl(vm, VCPU_ID, KVM_GET_SUPPORTED_HV_CPUID, &cpuid);
78
79         TEST_ASSERT(ret == -1 && errno == E2BIG,
80                     "KVM_GET_SUPPORTED_HV_CPUID didn't fail with -E2BIG when"
81                     " it should have: %d %d", ret, errno);
82 }
83
84
85 struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(struct kvm_vm *vm)
86 {
87         int nent = 20; /* should be enough */
88         static struct kvm_cpuid2 *cpuid;
89
90         cpuid = malloc(sizeof(*cpuid) + nent * sizeof(struct kvm_cpuid_entry2));
91
92         if (!cpuid) {
93                 perror("malloc");
94                 abort();
95         }
96
97         cpuid->nent = nent;
98
99         vcpu_ioctl(vm, VCPU_ID, KVM_GET_SUPPORTED_HV_CPUID, cpuid);
100
101         return cpuid;
102 }
103
104
105 int main(int argc, char *argv[])
106 {
107         struct kvm_vm *vm;
108         int rv;
109         uint16_t evmcs_ver;
110         struct kvm_cpuid2 *hv_cpuid_entries;
111         struct kvm_enable_cap enable_evmcs_cap = {
112                 .cap = KVM_CAP_HYPERV_ENLIGHTENED_VMCS,
113                  .args[0] = (unsigned long)&evmcs_ver
114         };
115
116         /* Tell stdout not to buffer its content */
117         setbuf(stdout, NULL);
118
119         rv = kvm_check_cap(KVM_CAP_HYPERV_CPUID);
120         if (!rv) {
121                 fprintf(stderr,
122                         "KVM_CAP_HYPERV_CPUID not supported, skip test\n");
123                 exit(KSFT_SKIP);
124         }
125
126         /* Create VM */
127         vm = vm_create_default(VCPU_ID, 0, guest_code);
128
129         test_hv_cpuid_e2big(vm);
130
131         hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
132         if (!hv_cpuid_entries)
133                 return 1;
134
135         test_hv_cpuid(hv_cpuid_entries, 0);
136
137         free(hv_cpuid_entries);
138
139         rv = _vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
140
141         if (rv) {
142                 fprintf(stderr,
143                         "Enlightened VMCS is unsupported, skip related test\n");
144                 goto vm_free;
145         }
146
147         hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
148         if (!hv_cpuid_entries)
149                 return 1;
150
151         test_hv_cpuid(hv_cpuid_entries, 1);
152
153         free(hv_cpuid_entries);
154
155 vm_free:
156         kvm_vm_free(vm);
157
158         return 0;
159 }