xref: /aosp_15_r20/external/crosvm/tests/plugin_supported_cpuid.c (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker /*
2*bb4ee6a4SAndroid Build Coastguard Worker  * Copyright 2018 The ChromiumOS Authors
3*bb4ee6a4SAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
4*bb4ee6a4SAndroid Build Coastguard Worker  * found in the LICENSE file.
5*bb4ee6a4SAndroid Build Coastguard Worker  */
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker #include <errno.h>
8*bb4ee6a4SAndroid Build Coastguard Worker #include <stdint.h>
9*bb4ee6a4SAndroid Build Coastguard Worker #include <stdio.h>
10*bb4ee6a4SAndroid Build Coastguard Worker #include <stdlib.h>
11*bb4ee6a4SAndroid Build Coastguard Worker #include <string.h>
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker #include "crosvm.h"
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker typedef int (*crosvm_function)(struct crosvm*, uint32_t,
16*bb4ee6a4SAndroid Build Coastguard Worker                                struct kvm_cpuid_entry2*, uint32_t*);
17*bb4ee6a4SAndroid Build Coastguard Worker typedef int (*vcpu_function)(struct crosvm_vcpu*, uint32_t,
18*bb4ee6a4SAndroid Build Coastguard Worker                              struct kvm_cpuid_entry2*, uint32_t*);
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker // Members of union should only differ by the pointer type of 1st arg.
21*bb4ee6a4SAndroid Build Coastguard Worker union cpuid_function {
22*bb4ee6a4SAndroid Build Coastguard Worker     crosvm_function crosvm;
23*bb4ee6a4SAndroid Build Coastguard Worker     vcpu_function vcpu;
24*bb4ee6a4SAndroid Build Coastguard Worker };
25*bb4ee6a4SAndroid Build Coastguard Worker 
test_cpuid(void * crosvm,union cpuid_function funct,const char * name)26*bb4ee6a4SAndroid Build Coastguard Worker int test_cpuid(void* crosvm, union cpuid_function funct, const char* name) {
27*bb4ee6a4SAndroid Build Coastguard Worker     struct kvm_cpuid_entry2 cpuids[100];
28*bb4ee6a4SAndroid Build Coastguard Worker     int n_entries = 0;
29*bb4ee6a4SAndroid Build Coastguard Worker     int ret = funct.crosvm(crosvm, 1, cpuids, &n_entries);
30*bb4ee6a4SAndroid Build Coastguard Worker     if (ret >= 0) {
31*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr,
32*bb4ee6a4SAndroid Build Coastguard Worker                 "expected %s to fail with E2BIG\n", name);
33*bb4ee6a4SAndroid Build Coastguard Worker         return ret;
34*bb4ee6a4SAndroid Build Coastguard Worker     }
35*bb4ee6a4SAndroid Build Coastguard Worker 
36*bb4ee6a4SAndroid Build Coastguard Worker     ret = funct.crosvm(crosvm, 100, cpuids, &n_entries);
37*bb4ee6a4SAndroid Build Coastguard Worker     if (ret < 0) {
38*bb4ee6a4SAndroid Build Coastguard Worker         if (ret != -EINVAL) {
39*bb4ee6a4SAndroid Build Coastguard Worker             fprintf(stderr, "unexpected failure of %s: %d\n", name, ret);
40*bb4ee6a4SAndroid Build Coastguard Worker         } else {
41*bb4ee6a4SAndroid Build Coastguard Worker             fprintf(stderr,
42*bb4ee6a4SAndroid Build Coastguard Worker                     "Query of %s failed with EINVAL (may be expected)\n",
43*bb4ee6a4SAndroid Build Coastguard Worker                     name, ret);
44*bb4ee6a4SAndroid Build Coastguard Worker         }
45*bb4ee6a4SAndroid Build Coastguard Worker         return ret;
46*bb4ee6a4SAndroid Build Coastguard Worker     }
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker     if (n_entries <= 1) {
49*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr,
50*bb4ee6a4SAndroid Build Coastguard Worker                 "unexpected number of cpuid entries from %s: %d\n",
51*bb4ee6a4SAndroid Build Coastguard Worker                 name, n_entries);
52*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
53*bb4ee6a4SAndroid Build Coastguard Worker     }
54*bb4ee6a4SAndroid Build Coastguard Worker     return 0;
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
main(int argc,char ** argv)57*bb4ee6a4SAndroid Build Coastguard Worker int main(int argc, char** argv) {
58*bb4ee6a4SAndroid Build Coastguard Worker     struct crosvm* crosvm = NULL;
59*bb4ee6a4SAndroid Build Coastguard Worker     int ret = crosvm_connect(&crosvm);
60*bb4ee6a4SAndroid Build Coastguard Worker     if (ret) {
61*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr, "failed to connect to crosvm: %d\n", ret);
62*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
63*bb4ee6a4SAndroid Build Coastguard Worker     }
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker     struct crosvm_vcpu* vcpu = NULL;
66*bb4ee6a4SAndroid Build Coastguard Worker     ret = crosvm_get_vcpu(crosvm, 0, &vcpu);
67*bb4ee6a4SAndroid Build Coastguard Worker     if (ret) {
68*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr, "failed to get vcpu #0: %d\n", ret);
69*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
70*bb4ee6a4SAndroid Build Coastguard Worker     }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker     union cpuid_function funct;
73*bb4ee6a4SAndroid Build Coastguard Worker     funct.crosvm = crosvm_get_supported_cpuid;
74*bb4ee6a4SAndroid Build Coastguard Worker     if (test_cpuid(crosvm, funct, "crosvm_get_supported_cpuid")) {
75*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
76*bb4ee6a4SAndroid Build Coastguard Worker     }
77*bb4ee6a4SAndroid Build Coastguard Worker     funct.crosvm = crosvm_get_emulated_cpuid;
78*bb4ee6a4SAndroid Build Coastguard Worker     if (test_cpuid(crosvm, funct, "crosvm_get_emulated_cpuid")) {
79*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
80*bb4ee6a4SAndroid Build Coastguard Worker     }
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker     ret = crosvm_start(crosvm);
83*bb4ee6a4SAndroid Build Coastguard Worker     if (ret) {
84*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr, "failed to start vm: %d\n", ret);
85*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
86*bb4ee6a4SAndroid Build Coastguard Worker     }
87*bb4ee6a4SAndroid Build Coastguard Worker 
88*bb4ee6a4SAndroid Build Coastguard Worker     struct crosvm_vcpu_event evt = {0};
89*bb4ee6a4SAndroid Build Coastguard Worker     ret = crosvm_vcpu_wait(vcpu, &evt);
90*bb4ee6a4SAndroid Build Coastguard Worker     if (ret) {
91*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr, "failed to wait for vm start: %d\n", ret);
92*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
93*bb4ee6a4SAndroid Build Coastguard Worker     }
94*bb4ee6a4SAndroid Build Coastguard Worker     if (evt.kind != CROSVM_VCPU_EVENT_KIND_INIT) {
95*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr, "Got unexpected exit type: %d\n", evt.kind);
96*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
97*bb4ee6a4SAndroid Build Coastguard Worker     }
98*bb4ee6a4SAndroid Build Coastguard Worker 
99*bb4ee6a4SAndroid Build Coastguard Worker     funct.vcpu = crosvm_get_hyperv_cpuid;
100*bb4ee6a4SAndroid Build Coastguard Worker     ret = test_cpuid(vcpu, funct, "crosvm_get_hyperv_cpuid");
101*bb4ee6a4SAndroid Build Coastguard Worker     // Older kernels don't support and return EINVAL, so allow this for now.
102*bb4ee6a4SAndroid Build Coastguard Worker     if (ret && ret != -EINVAL) {
103*bb4ee6a4SAndroid Build Coastguard Worker         fprintf(stderr, "Ignoring failure of crosvm_get_hyperv_cpuid\n");
104*bb4ee6a4SAndroid Build Coastguard Worker         return 1;
105*bb4ee6a4SAndroid Build Coastguard Worker     }
106*bb4ee6a4SAndroid Build Coastguard Worker     return 0;
107*bb4ee6a4SAndroid Build Coastguard Worker }
108