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