xref: /dragonfly/usr.sbin/nvmmctl/nvmmctl.c (revision 655933d6)
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
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
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
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
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