Hi, I've added the 'vmctl status' view to systat(1). I am not sure if this is of general interest.
Any opinions about it? Index: usr.bin/systat/Makefile =================================================================== RCS file: /cvs/src/usr.bin/systat/Makefile,v retrieving revision 1.27 diff -u -p -r1.27 Makefile --- usr.bin/systat/Makefile 12 Mar 2015 01:03:00 -0000 1.27 +++ usr.bin/systat/Makefile 26 Feb 2017 11:21:16 -0000 @@ -5,13 +5,14 @@ PROG= systat .PATH: ${.CURDIR}/../../usr.bin/vmstat CFLAGS+=-DNOKVM +CPPFLAGS+=-I${.CURDIR}/../../usr.sbin/vmd/ CPPFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat CPPFLAGS+=-I${.CURDIR}/../../sbin/pfctl SRCS= dkstats.c engine.c if.c inetname.c iostat.c main.c mbufs.c netstat.c \ nfs.c pigs.c sensors.c swap.c vmstat.c pftop.c cache.c pf.c \ - pool.c malloc.c cpu.c + pool.c malloc.c cpu.c vmm.c DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM} -LDADD= -lcurses -lm -lkvm +LDADD= -lcurses -lm -lkvm -lutil .include <bsd.prog.mk> Index: usr.bin/systat/engine.c =================================================================== RCS file: /cvs/src/usr.bin/systat/engine.c,v retrieving revision 1.19 diff -u -p -r1.19 engine.c --- usr.bin/systat/engine.c 2 Jan 2016 20:01:48 -0000 1.19 +++ usr.bin/systat/engine.c 26 Feb 2017 11:21:17 -0000 @@ -1320,6 +1320,7 @@ engine_initialize(void) signal(SIGQUIT, sig_close); signal(SIGWINCH, sig_resize); signal(SIGALRM, sig_alarm); + signal(SIGPIPE, SIG_IGN); } void Index: usr.bin/systat/main.c =================================================================== RCS file: /cvs/src/usr.bin/systat/main.c,v retrieving revision 1.66 diff -u -p -r1.66 main.c --- usr.bin/systat/main.c 13 Oct 2016 11:22:46 -0000 1.66 +++ usr.bin/systat/main.c 26 Feb 2017 11:21:17 -0000 @@ -362,6 +362,7 @@ initialize(void) initmalloc(); initnfs(); initcpu(); + initvmm(); } void Index: usr.bin/systat/vmm.c =================================================================== RCS file: usr.bin/systat/vmm.c diff -N usr.bin/systat/vmm.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.bin/systat/vmm.c 26 Feb 2017 11:21:25 -0000 @@ -0,0 +1,239 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/signal.h> +#include <sys/queue.h> +#include <sys/un.h> +#include <sys/uio.h> +#include <machine/vmmvar.h> + +#include <imsg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <err.h> +#include <unistd.h> + +#include "systat.h" +#include "vmd.h" + +#define VMM_IDENT 256 + +int initvmm(void); +void print_vmm(void); +int read_vmm(void); +int vmm_keyboard_callback(int ch); + +static void connect_vmd(void); +static void get_info_vm(uint32_t id, const char *name, int console); +static int add_info(struct imsg *imsg, int *ret); + +static struct vmop_info_result* vir = NULL; +static struct imsgbuf *ibuf; +static const char *socket_name = SOCKET_NAME; +static int is_connected = 0; +static int ctl_sock = -1; +static size_t ct = 0; /* counter for number of VM's */ + +field_def fields_vmm[] = { + {"ID", 6, 10, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, + {"PID", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"VCPUS", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"MAXMEM", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"CURMEM", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, + {"TTY", 5, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, + {"NAME", 5, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, +}; + +#define FLD_VMM_ID FIELD_ADDR(fields_vmm,0) +#define FLD_VMM_PID FIELD_ADDR(fields_vmm,1) +#define FLD_VMM_VCPUS FIELD_ADDR(fields_vmm,2) +#define FLD_VMM_MAXMEM FIELD_ADDR(fields_vmm,3) +#define FLD_VMM_CURMEM FIELD_ADDR(fields_vmm,4) +#define FLD_VMM_TTYNAME FIELD_ADDR(fields_vmm,5) +#define FLD_VMM_NAME FIELD_ADDR(fields_vmm,6) + +/* Define views */ +field_def *view_vmm_0[] = { + FLD_VMM_ID, FLD_VMM_PID, FLD_VMM_VCPUS, FLD_VMM_MAXMEM, + FLD_VMM_CURMEM, FLD_VMM_TTYNAME, FLD_VMM_NAME, NULL +}; + +/* Define view managers */ +struct view_manager vmm_mgr = { + "VMM", NULL, read_vmm, NULL, print_header, + print_vmm, vmm_keyboard_callback, NULL, NULL +}; + +field_view views_vmm[] = { + {view_vmm_0, "vmm", '6', &vmm_mgr}, + {NULL, NULL, 0, NULL} +}; + +static void +connect_vmd(void) +{ + struct sockaddr_un sun; + + if (ctl_sock != -1) { + close(ibuf->fd); + free(ibuf); + } + + if ((ctl_sock = socket(AF_UNIX, + SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1) + err(1, "socket"); + + bzero(&sun, sizeof(sun)); + sun.sun_family = AF_UNIX; + strlcpy(sun.sun_path, socket_name, sizeof(sun.sun_path)); + + if (connect(ctl_sock, + (struct sockaddr *)&sun, sizeof(sun)) == -1) + is_connected = 0; + else + is_connected = 1; + + if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) + err(1, "malloc"); + imsg_init(ibuf, ctl_sock); +} + +static void +get_info_vm(uint32_t id, const char *name, int console) +{ + if (imsg_compose(ibuf, IMSG_VMDOP_GET_INFO_VM_REQUEST, + 0, 0, -1, NULL, 0) < 0) + errx(1, "imsg_compose"); +} + + +static int +add_info(struct imsg *imsg, int *ret) +{ + if (imsg->hdr.type == IMSG_VMDOP_GET_INFO_VM_DATA) { + if ((vir = reallocarray(vir, ct + 1, + sizeof(struct vmop_info_result))) == NULL) { + *ret = ENOMEM; + return (1); + } + memcpy(&vir[ct], imsg->data, sizeof(struct vmop_info_result)); + ct++; + *ret = 0; + return (0); + } else if (imsg->hdr.type == IMSG_VMDOP_GET_INFO_VM_END_DATA) { + *ret = 0; + return (1); + } else { + *ret = EINVAL; + return (1); + } +} + +int +read_vmm(void) +{ + int n; + struct imsg imsg; + int ret, done = 0; + + if (!is_connected) + connect_vmd(); + + get_info_vm(0, NULL, 0); + while (is_connected && ibuf->w.queued) + if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) + is_connected = 0; + ct = 0; + + while (is_connected && !done) { + if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) + errx(1, "imsg_read error"); + if (n == 0) + errx(1, "pipe closed"); + + while (is_connected && !done) { + if ((n = imsg_get(ibuf, &imsg)) == -1) + errx(1, "imsg_get error"); + if (n == 0) + break; + + if (imsg.hdr.type == IMSG_CTL_FAIL) { + if (IMSG_DATA_SIZE(&imsg) == sizeof(ret)) { + memcpy(&ret, imsg.data, sizeof(ret)); + errno = ret; + warn("command failed"); + } else + warn("command failed"); + done = 1; + break; + } + + ret = 0; + done = add_info(&imsg, &ret); + + imsg_free(&imsg); + } + } + + return 0; +} + +void +print_vmm(void) +{ + char mem[VMM_IDENT]; + char cmem[VMM_IDENT]; + char tty[VMM_IDENT]; + char name[VMM_MAX_NAME_LEN]; + struct vm_info_result *v; + int i; + + for (i = 0; vir != NULL && i < ct; i++) { + v = &vir[i].vir_info; + if (v != NULL) { + print_fld_uint(FLD_VMM_ID, v->vir_id); + print_fld_uint(FLD_VMM_PID, v->vir_creator_pid); + print_fld_uint(FLD_VMM_VCPUS, v->vir_ncpus); + + snprintf(mem, sizeof(mem), "%7zdMB", v->vir_memory_size); + print_fld_str(FLD_VMM_MAXMEM, mem); + snprintf(cmem, sizeof(cmem), "%7zdMB", v->vir_used_size/1024/1024); + print_fld_str(FLD_VMM_CURMEM, cmem); + snprintf(tty, sizeof(tty), "%s", vir[i].vir_ttyname); + print_fld_str(FLD_VMM_TTYNAME, tty); + snprintf(name, VMM_MAX_NAME_LEN, "%s", v->vir_name); + print_fld_str(FLD_VMM_NAME, name); + + end_line(); + } + } + end_line(); + print_fld_str(FLD_VMM_ID, "Total:"); + print_fld_uint(FLD_VMM_PID, ct); + print_fld_str(FLD_VMM_NAME, + (is_connected) ? "connected" : "disconnected"); + + if (vir != NULL) + free(vir); + vir = NULL; +} + +int +vmm_keyboard_callback(int ch) +{ + keyboard_callback(ch); + read_vmm(); +} + +int +initvmm(void) +{ + field_view *v; + + connect_vmd(); + for (v = views_vmm; v->name != NULL; v++) + add_view(v); + + return(1); +}