xref: /dflybsd-src/usr.sbin/nvmmctl/nvmmctl.c (revision cca384e4794b145c2db2c13903239d9c019de498)
137de577aSAaron LI /*
27a511437SAaron LI  * Copyright (c) 2019-2021 Maxime Villard, m00nbsd.net
337de577aSAaron LI  * All rights reserved.
437de577aSAaron LI  *
57f0e1ce2SAaron LI  * This code is part of the NVMM hypervisor.
637de577aSAaron LI  *
737de577aSAaron LI  * Redistribution and use in source and binary forms, with or without
837de577aSAaron LI  * modification, are permitted provided that the following conditions
937de577aSAaron LI  * are met:
1037de577aSAaron LI  * 1. Redistributions of source code must retain the above copyright
1137de577aSAaron LI  *    notice, this list of conditions and the following disclaimer.
1237de577aSAaron LI  * 2. Redistributions in binary form must reproduce the above copyright
1337de577aSAaron LI  *    notice, this list of conditions and the following disclaimer in the
1437de577aSAaron LI  *    documentation and/or other materials provided with the distribution.
1537de577aSAaron LI  *
167f0e1ce2SAaron LI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
177f0e1ce2SAaron LI  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
187f0e1ce2SAaron LI  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
197f0e1ce2SAaron LI  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
207f0e1ce2SAaron LI  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
217f0e1ce2SAaron LI  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
227f0e1ce2SAaron LI  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
237f0e1ce2SAaron LI  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
247f0e1ce2SAaron LI  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257f0e1ce2SAaron LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267f0e1ce2SAaron LI  * SUCH DAMAGE.
2737de577aSAaron LI  */
2837de577aSAaron LI 
2937de577aSAaron LI #include <sys/param.h>
3037de577aSAaron LI 
3137de577aSAaron LI #include <err.h>
3237de577aSAaron LI #include <errno.h>
3337de577aSAaron LI #include <fcntl.h>
3437de577aSAaron LI #include <stdio.h>
3537de577aSAaron LI #include <stdlib.h>
3637de577aSAaron LI #include <stdarg.h>
3737de577aSAaron LI #include <stdbool.h>
3837de577aSAaron LI #include <string.h>
3937de577aSAaron LI #include <unistd.h>
4037de577aSAaron LI #include <time.h>
4137de577aSAaron LI #include <util.h>
4237de577aSAaron LI #include <nvmm.h>
4337de577aSAaron LI 
44e1cb903eSAaron LI __dead2 static void usage(void);
4537de577aSAaron LI static void nvmm_identify(char **);
4637de577aSAaron LI static void nvmm_list(char **);
4737de577aSAaron LI 
4837de577aSAaron LI static struct cmdtab {
4937de577aSAaron LI 	const char *label;
5037de577aSAaron LI 	bool takesargs;
5137de577aSAaron LI 	bool argsoptional;
5237de577aSAaron LI 	void (*func)(char **);
5337de577aSAaron LI } const nvmm_cmdtab[] = {
5437de577aSAaron LI 	{ "identify",	false, false, nvmm_identify },
5537de577aSAaron LI 	{ "list",	false, false, nvmm_list },
5637de577aSAaron LI 	{ NULL,		false, false, NULL },
5737de577aSAaron LI };
5837de577aSAaron LI 
5937de577aSAaron LI static struct nvmm_capability cap;
6037de577aSAaron LI 
6137de577aSAaron LI int
main(int argc,char ** argv)6237de577aSAaron LI main(int argc, char **argv)
6337de577aSAaron LI {
6437de577aSAaron LI 	const struct cmdtab *ct;
6537de577aSAaron LI 
6637de577aSAaron LI 	argc -= 1;
6737de577aSAaron LI 	argv += 1;
6837de577aSAaron LI 	if (argc < 1)
6937de577aSAaron LI 		usage();
7037de577aSAaron LI 
7137de577aSAaron LI 	for (ct = nvmm_cmdtab; ct->label != NULL; ct++) {
7237de577aSAaron LI 		if (strcmp(argv[0], ct->label) == 0) {
7337de577aSAaron LI 			if (!ct->argsoptional &&
7437de577aSAaron LI 			    ((ct->takesargs == 0) ^ (argv[1] == NULL)))
7537de577aSAaron LI 			{
7637de577aSAaron LI 				usage();
7737de577aSAaron LI 			}
7837de577aSAaron LI 			(*ct->func)(argv + 1);
7937de577aSAaron LI 			break;
8037de577aSAaron LI 		}
8137de577aSAaron LI 	}
8237de577aSAaron LI 
8337de577aSAaron LI 	if (ct->label == NULL)
8437de577aSAaron LI 		errx(EXIT_FAILURE, "unknown command ``%s''", argv[0]);
8537de577aSAaron LI 
8637de577aSAaron LI 	exit(EXIT_SUCCESS);
8737de577aSAaron LI 	/* NOTREACHED */
8837de577aSAaron LI }
8937de577aSAaron LI 
9037de577aSAaron LI static void
usage(void)9137de577aSAaron LI usage(void)
9237de577aSAaron LI {
9337de577aSAaron LI 	const char *progname = getprogname();
9437de577aSAaron LI 
9537de577aSAaron LI 	fprintf(stderr, "usage: %s identify\n", progname);
9637de577aSAaron LI 	fprintf(stderr, "       %s list\n", progname);
9737de577aSAaron LI 	exit(EXIT_FAILURE);
9837de577aSAaron LI 	/* NOTREACHED */
9937de577aSAaron LI }
10037de577aSAaron LI 
10137de577aSAaron LI #define MACH_CONF_FLAGS		"\20"
10237de577aSAaron LI #define VCPU_CONF_FLAGS		"\20" "\1" "CPUID" "\2" "TPR"
103e1cb903eSAaron LI #define XCR0_FLAGS1		"\20" \
104e1cb903eSAaron LI 	"\1" "x87"		"\2" "SSE"		"\3" "AVX"	\
105e1cb903eSAaron LI 	"\4" "BNDREGS"		"\5" "BNDCSR"		"\6" "Opmask"	\
106e1cb903eSAaron LI 	"\7" "ZMM_Hi256"	"\10" "Hi16_ZMM"	"\11" "PT"	\
107e1cb903eSAaron LI 	"\12" "PKRU"		"\14" "CET_U"		"\15" "CET_S"	\
108e1cb903eSAaron LI 	"\16" "HDC"		"\21" "HWP"
10937de577aSAaron LI 
11037de577aSAaron LI static void
nvmm_identify(char ** argv __unused)111e1cb903eSAaron LI nvmm_identify(char **argv __unused)
11237de577aSAaron LI {
11337de577aSAaron LI 	char buf[256], ram[4+1];
11437de577aSAaron LI 
11537de577aSAaron LI 	if (nvmm_init() == -1)
11637de577aSAaron LI 		err(EXIT_FAILURE, "nvmm_init failed");
11737de577aSAaron LI 	if (nvmm_capability(&cap) == -1)
11837de577aSAaron LI 		err(EXIT_FAILURE, "nvmm_capability failed");
11937de577aSAaron LI 
12037de577aSAaron LI 	printf("nvmm: Kernel API version %u\n", cap.version);
12137de577aSAaron LI 	printf("nvmm: State size %u\n", cap.state_size);
122*cca384e4SAaron LI 	printf("nvmm: Comm size %u\n", cap.comm_size);
12337de577aSAaron LI 	printf("nvmm: Max machines %u\n", cap.max_machines);
12437de577aSAaron LI 	printf("nvmm: Max VCPUs per machine %u\n", cap.max_vcpus);
12537de577aSAaron LI 
12637de577aSAaron LI 	if (humanize_number(ram, sizeof(ram), cap.max_ram, NULL, HN_AUTOSCALE,
12737de577aSAaron LI 	    (HN_DECIMAL | HN_B | HN_NOSPACE)) == -1)
12837de577aSAaron LI 		err(EXIT_FAILURE, "humanize_number");
12937de577aSAaron LI 	printf("nvmm: Max RAM per machine %s\n", ram);
13037de577aSAaron LI 
13137de577aSAaron LI 	snprintb(buf, sizeof(buf), MACH_CONF_FLAGS, cap.arch.mach_conf_support);
13237de577aSAaron LI 	printf("nvmm: Arch Mach conf %s\n", buf);
13337de577aSAaron LI 
13437de577aSAaron LI 	snprintb(buf, sizeof(buf), VCPU_CONF_FLAGS, cap.arch.vcpu_conf_support);
13537de577aSAaron LI 	printf("nvmm: Arch VCPU conf %s\n", buf);
13637de577aSAaron LI 
13737de577aSAaron LI 	snprintb(buf, sizeof(buf), XCR0_FLAGS1, cap.arch.xcr0_mask);
13837de577aSAaron LI 	printf("nvmm: Guest FPU states %s\n", buf);
13937de577aSAaron LI }
14037de577aSAaron LI 
14137de577aSAaron LI static void
nvmm_list(char ** argv __unused)142e1cb903eSAaron LI nvmm_list(char **argv __unused)
14337de577aSAaron LI {
14437de577aSAaron LI 	struct nvmm_ctl_mach_info machinfo;
14537de577aSAaron LI 	char ram[4+1], *ts;
14637de577aSAaron LI 	size_t i;
14737de577aSAaron LI 	int ret;
14837de577aSAaron LI 
14937de577aSAaron LI 	if (nvmm_root_init() == -1)
15037de577aSAaron LI 		err(EXIT_FAILURE, "nvmm_root_init failed");
15137de577aSAaron LI 	if (nvmm_capability(&cap) == -1)
15237de577aSAaron LI 		err(EXIT_FAILURE, "nvmm_capability failed");
15337de577aSAaron LI 
15437de577aSAaron LI 	printf(
15537de577aSAaron LI 	    "Machine ID VCPUs RAM  Owner PID Creation Time           \n"
15637de577aSAaron LI 	    "---------- ----- ---- --------- ------------------------\n");
15737de577aSAaron LI 
15837de577aSAaron LI 	for (i = 0; i < cap.max_machines; i++) {
15937de577aSAaron LI 		machinfo.machid = i;
16037de577aSAaron LI 		ret = nvmm_ctl(NVMM_CTL_MACH_INFO, &machinfo, sizeof(machinfo));
16137de577aSAaron LI 		if (ret == -1) {
16237de577aSAaron LI 			if (errno == ENOENT)
16337de577aSAaron LI 				continue;
16437de577aSAaron LI 			err(EXIT_FAILURE, "nvmm_ctl failed");
16537de577aSAaron LI 		}
16637de577aSAaron LI 
16737de577aSAaron LI 		ts = asctime(localtime(&machinfo.time));
16837de577aSAaron LI 		ts[strlen(ts) - 1] = '\0';
16937de577aSAaron LI 
17037de577aSAaron LI 		if (humanize_number(ram, sizeof(ram), machinfo.nram, NULL,
17137de577aSAaron LI 		    HN_AUTOSCALE, (HN_DECIMAL | HN_B | HN_NOSPACE)) == -1)
17237de577aSAaron LI 			err(EXIT_FAILURE, "humanize_number");
17337de577aSAaron LI 
17437de577aSAaron LI 		printf("%-10zu %-5u %-4s %-9d %s\n", i, machinfo.nvcpus, ram,
17537de577aSAaron LI 		    machinfo.pid, ts);
17637de577aSAaron LI 	}
17737de577aSAaron LI }
178