1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2024 Oxide Computer Company
14 */
15
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <libgen.h>
21 #include <sys/stat.h>
22 #include <errno.h>
23 #include <err.h>
24 #include <assert.h>
25 #include <sys/sysmacros.h>
26 #include <stdbool.h>
27
28 #include <sys/vmm.h>
29 #include <sys/vmm_dev.h>
30 #include <sys/vmm_data.h>
31 #include <vmmapi.h>
32
33 #include "common.h"
34
35 int
main(int argc,char * argv[])36 main(int argc, char *argv[])
37 {
38 const char *suite_name = basename(argv[0]);
39 struct vmctx *ctx;
40
41 ctx = create_test_vm(suite_name);
42 if (ctx == NULL) {
43 errx(EXIT_FAILURE, "could not open test VM");
44 }
45
46 /* Query VM_MAXCPU equivalent via VM topology */
47 uint16_t sockets, cores, threads, maxcpus;
48 if (vm_get_topology(ctx, &sockets, &cores, &threads, &maxcpus) != 0) {
49 err(EXIT_FAILURE,
50 "could not query maxcpu via vm_get_topology()");
51 }
52
53 for (int i = 0; i < maxcpus; i++) {
54 struct vcpu *vcpu;
55 uint64_t val = 0;
56
57 if ((vcpu = vm_vcpu_open(ctx, i)) == NULL) {
58 err(EXIT_FAILURE, "could not open vcpu %d", i);
59 }
60
61 /* Check that all valid vCPUs can be activated... */
62 if (vm_activate_cpu(vcpu) != 0) {
63 err(EXIT_FAILURE, "could not activate vcpu %d", i);
64 }
65
66 /* and that we can do something basic (like read a register) */
67 if (vm_get_register(vcpu, VM_REG_GUEST_RAX, &val) != 0) {
68 err(EXIT_FAILURE, "could not read %%rax on vcpu %d", i);
69 }
70
71 vm_vcpu_close(vcpu);
72 }
73
74 /* Check some bogus inputs as well */
75 const int bad_inputs[] = {-1, maxcpus, maxcpus + 1};
76 for (uint_t i = 0; i < ARRAY_SIZE(bad_inputs); i++) {
77 const int vcpuid = bad_inputs[i];
78
79 /*
80 * There is no logic (currently) in vm_vcpu_open() checking
81 * vcpuid for validity, so we must use a further operation to
82 * perform a useful test.
83 */
84 struct vcpu *vcpu = vm_vcpu_open(ctx, vcpuid);
85 if (vcpu == NULL) {
86 errx(EXIT_FAILURE,
87 "unexpected failure from vm_vcpu_open()");
88 }
89
90 if (vm_activate_cpu(vcpu) == 0) {
91 err(EXIT_FAILURE,
92 "unexpected VM_ACTIVATE success for bad vcpuid %d",
93 vcpuid);
94 }
95 vm_vcpu_close(vcpu);
96 }
97
98 vm_destroy(ctx);
99 (void) printf("%s\tPASS\n", suite_name);
100 return (EXIT_SUCCESS);
101 }
102