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