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