1 /*
2 * Copyright (c) 2019-2021 Maxime Villard, m00nbsd.net
3 * All rights reserved.
4 *
5 * This code is part of the NVMM hypervisor.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30
31 #include <err.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <stdbool.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <time.h>
41 #include <util.h>
42 #include <nvmm.h>
43
44 __dead2 static void usage(void);
45 static void nvmm_identify(char **);
46 static void nvmm_list(char **);
47
48 static struct cmdtab {
49 const char *label;
50 bool takesargs;
51 bool argsoptional;
52 void (*func)(char **);
53 } const nvmm_cmdtab[] = {
54 { "identify", false, false, nvmm_identify },
55 { "list", false, false, nvmm_list },
56 { NULL, false, false, NULL },
57 };
58
59 static struct nvmm_capability cap;
60
61 int
main(int argc,char ** argv)62 main(int argc, char **argv)
63 {
64 const struct cmdtab *ct;
65
66 argc -= 1;
67 argv += 1;
68 if (argc < 1)
69 usage();
70
71 for (ct = nvmm_cmdtab; ct->label != NULL; ct++) {
72 if (strcmp(argv[0], ct->label) == 0) {
73 if (!ct->argsoptional &&
74 ((ct->takesargs == 0) ^ (argv[1] == NULL)))
75 {
76 usage();
77 }
78 (*ct->func)(argv + 1);
79 break;
80 }
81 }
82
83 if (ct->label == NULL)
84 errx(EXIT_FAILURE, "unknown command ``%s''", argv[0]);
85
86 exit(EXIT_SUCCESS);
87 /* NOTREACHED */
88 }
89
90 static void
usage(void)91 usage(void)
92 {
93 const char *progname = getprogname();
94
95 fprintf(stderr, "usage: %s identify\n", progname);
96 fprintf(stderr, " %s list\n", progname);
97 exit(EXIT_FAILURE);
98 /* NOTREACHED */
99 }
100
101 #define MACH_CONF_FLAGS "\20"
102 #define VCPU_CONF_FLAGS "\20" "\1" "CPUID" "\2" "TPR"
103 #define XCR0_FLAGS1 "\20" \
104 "\1" "x87" "\2" "SSE" "\3" "AVX" \
105 "\4" "BNDREGS" "\5" "BNDCSR" "\6" "Opmask" \
106 "\7" "ZMM_Hi256" "\10" "Hi16_ZMM" "\11" "PT" \
107 "\12" "PKRU" "\14" "CET_U" "\15" "CET_S" \
108 "\16" "HDC" "\21" "HWP"
109
110 static void
nvmm_identify(char ** argv __unused)111 nvmm_identify(char **argv __unused)
112 {
113 char buf[256], ram[4+1];
114
115 if (nvmm_init() == -1)
116 err(EXIT_FAILURE, "nvmm_init failed");
117 if (nvmm_capability(&cap) == -1)
118 err(EXIT_FAILURE, "nvmm_capability failed");
119
120 printf("nvmm: Kernel API version %u\n", cap.version);
121 printf("nvmm: State size %u\n", cap.state_size);
122 printf("nvmm: Comm size %u\n", cap.comm_size);
123 printf("nvmm: Max machines %u\n", cap.max_machines);
124 printf("nvmm: Max VCPUs per machine %u\n", cap.max_vcpus);
125
126 if (humanize_number(ram, sizeof(ram), cap.max_ram, NULL, HN_AUTOSCALE,
127 (HN_DECIMAL | HN_B | HN_NOSPACE)) == -1)
128 err(EXIT_FAILURE, "humanize_number");
129 printf("nvmm: Max RAM per machine %s\n", ram);
130
131 snprintb(buf, sizeof(buf), MACH_CONF_FLAGS, cap.arch.mach_conf_support);
132 printf("nvmm: Arch Mach conf %s\n", buf);
133
134 snprintb(buf, sizeof(buf), VCPU_CONF_FLAGS, cap.arch.vcpu_conf_support);
135 printf("nvmm: Arch VCPU conf %s\n", buf);
136
137 snprintb(buf, sizeof(buf), XCR0_FLAGS1, cap.arch.xcr0_mask);
138 printf("nvmm: Guest FPU states %s\n", buf);
139 }
140
141 static void
nvmm_list(char ** argv __unused)142 nvmm_list(char **argv __unused)
143 {
144 struct nvmm_ctl_mach_info machinfo;
145 char ram[4+1], *ts;
146 size_t i;
147 int ret;
148
149 if (nvmm_root_init() == -1)
150 err(EXIT_FAILURE, "nvmm_root_init failed");
151 if (nvmm_capability(&cap) == -1)
152 err(EXIT_FAILURE, "nvmm_capability failed");
153
154 printf(
155 "Machine ID VCPUs RAM Owner PID Creation Time \n"
156 "---------- ----- ---- --------- ------------------------\n");
157
158 for (i = 0; i < cap.max_machines; i++) {
159 machinfo.machid = i;
160 ret = nvmm_ctl(NVMM_CTL_MACH_INFO, &machinfo, sizeof(machinfo));
161 if (ret == -1) {
162 if (errno == ENOENT)
163 continue;
164 err(EXIT_FAILURE, "nvmm_ctl failed");
165 }
166
167 ts = asctime(localtime(&machinfo.time));
168 ts[strlen(ts) - 1] = '\0';
169
170 if (humanize_number(ram, sizeof(ram), machinfo.nram, NULL,
171 HN_AUTOSCALE, (HN_DECIMAL | HN_B | HN_NOSPACE)) == -1)
172 err(EXIT_FAILURE, "humanize_number");
173
174 printf("%-10zu %-5u %-4s %-9d %s\n", i, machinfo.nvcpus, ram,
175 machinfo.pid, ts);
176 }
177 }
178