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