From: Dave Voutila Subject: declutter vmd/vmctl by pulling vmm structs out of vmd structs To: tech@openbsd.org Date: Sat, 27 Dec 2025 10:31:23 -0500 This looks like deck chair shuffling, but this is to set up for switching vmm(4) from using magic identifiers (a monotonically incrementing uint32_t) passed in ioctl's to files[1] to not only clean up the vmm api a bit, but make virtual machine lifetime management simpler. This diff: - cleans up how vm identifiers are used, specifically vmm(4) vs. vmd(8), making use of explcit naming (vmm_id for kernel ids vs. vm_id for vmd ids) to prevent future confusion. - makes vmctl(8) not depend on any vmm(4) kernel structs and only on the vmd(8)-defined structs by removing the vmm structs embedded in vmd structs. - is net-negative!? Right now I'm mostly looking for testers to check for any regressions. No behavioral change is expected from this diff. I don't have an AMD SEV machine, so testing on that would be appreciated. *You need to also rebuild vmctl to test this.* If trying to review, I recommend looking at the header file changes as they better describe the change to the data types. [1]: KVM has had this file-based API design from the beginning, IIRC, but KVM also creates files for each vcpu. The KVM ioctls for running a vcpu or reading/writing registers are made against these files. There's no value to go that wild with vmm, but this would allow a vm process to only need a file open to the vm itself, not /dev/vmm, and process exits would make the vm process "clean up" the vm state. Today, vmd's "vmm" process does this cleanup via VMM_IOC_TERM ioctls after the child vm processes exit. Another bonus would be not doing some hacky pid-based filtering in vmm based on the ioctl being called since nothing currently prevents a process from "guessing" another vm's identifier (or accidentally using one if there's a bug in vmd). diffstat refs/heads/master refs/heads/vmd-vmctl-cleanup M usr.sbin/vmctl/vmctl.c | 49+ 64- M usr.sbin/vmd/arm64_vm.c | 2+ 2- M usr.sbin/vmd/config.c | 14+ 15- M usr.sbin/vmd/dhcp.c | 5+ 5- M usr.sbin/vmd/fw_cfg.c | 2+ 2- M usr.sbin/vmd/loadfile_elf.c | 6+ 7- M usr.sbin/vmd/parse.y | 11+ 13- M usr.sbin/vmd/priv.c | 1+ 2- M usr.sbin/vmd/sev.c | 10+ 18- M usr.sbin/vmd/vioblk.c | 4+ 5- M usr.sbin/vmd/vionet.c | 4+ 5- M usr.sbin/vmd/virtio.c | 38+ 40- M usr.sbin/vmd/virtio.h | 2+ 2- M usr.sbin/vmd/vm.c | 70+ 68- M usr.sbin/vmd/vm_agentx.c | 9+ 10- M usr.sbin/vmd/vmd.c | 86+ 104- M usr.sbin/vmd/vmd.h | 54+ 23- M usr.sbin/vmd/vmm.c | 24+ 18- M usr.sbin/vmd/x86_vm.c | 56+ 63- 19 files changed, 447 insertions(+), 466 deletions(-) diff refs/heads/master refs/heads/vmd-vmctl-cleanup commit - a39b2115abef8adc9cc601a81bdf809c4a8dc51e commit + f59376db8c369968041b61dfc8bd7cd9f3cc52f9 blob - eae1a9cb191f08f6bba2cb8d6243cf70d765fcc8 blob + f6a44b6219a58aa0aa56c1f4684777df2edf2ded --- usr.sbin/vmctl/vmctl.c +++ usr.sbin/vmctl/vmctl.c @@ -75,8 +75,7 @@ vm_start(uint32_t start_id, const char *name, size_t m char **nics, int ndisks, char **disks, int *disktypes, char *kernel, char *iso, char *instance, unsigned int bootdevice) { - struct vmop_create_params *vmc; - struct vm_create_params *vcp; + struct vmop_create_params vmc; struct stat sb; unsigned int flags = 0; int i; @@ -120,47 +119,43 @@ vm_start(uint32_t start_id, const char *name, size_t m warnx("starting without network interfaces"); } - if ((vmc = calloc(1, sizeof(struct vmop_create_params))) == NULL) - return (ENOMEM); - vmc->vmc_kernel = -1; - vmc->vmc_flags = flags; + memset(&vmc, 0, sizeof(vmc)); + vmc.vmc_kernel = -1; + vmc.vmc_flags = flags; - /* vcp includes configuration that is shared with the kernel */ - vcp = &vmc->vmc_params; - /* * XXX: vmd(8) fills in the actual memory ranges. vmctl(8) * just passes in the actual memory size here. */ - vcp->vcp_nmemranges = 1; - vcp->vcp_memranges[0].vmr_size = memsize; + vmc.vmc_nmemranges = 1; + vmc.vmc_memranges[0].vmr_size = memsize; - vcp->vcp_ncpus = 1; - vcp->vcp_id = start_id; + vmc.vmc_ncpus = 1; + vmc.vmc_id = start_id; - vmc->vmc_ndisks = ndisks; - vmc->vmc_nnics = nnics; + vmc.vmc_ndisks = ndisks; + vmc.vmc_nnics = nnics; for (i = 0 ; i < ndisks; i++) { - if (strlcpy(vmc->vmc_disks[i], disks[i], - sizeof(vmc->vmc_disks[i])) >= - sizeof(vmc->vmc_disks[i])) + if (strlcpy(vmc.vmc_disks[i], disks[i], + sizeof(vmc.vmc_disks[i])) >= + sizeof(vmc.vmc_disks[i])) errx(1, "disk path too long"); - vmc->vmc_disktypes[i] = disktypes[i]; + vmc.vmc_disktypes[i] = disktypes[i]; } for (i = 0 ; i < nnics; i++) { - vmc->vmc_ifflags[i] = VMIFF_UP; + vmc.vmc_ifflags[i] = VMIFF_UP; if (strcmp(".", nics[i]) == 0) { /* Add a "local" interface */ - (void)strlcpy(vmc->vmc_ifswitch[i], "", - sizeof(vmc->vmc_ifswitch[i])); - vmc->vmc_ifflags[i] |= VMIFF_LOCAL; + (void)strlcpy(vmc.vmc_ifswitch[i], "", + sizeof(vmc.vmc_ifswitch[i])); + vmc.vmc_ifflags[i] |= VMIFF_LOCAL; } else { /* Add an interface to a switch */ - if (strlcpy(vmc->vmc_ifswitch[i], nics[i], - sizeof(vmc->vmc_ifswitch[i])) >= - sizeof(vmc->vmc_ifswitch[i])) + if (strlcpy(vmc.vmc_ifswitch[i], nics[i], + sizeof(vmc.vmc_ifswitch[i])) >= + sizeof(vmc.vmc_ifswitch[i])) errx(1, "interface name too long"); } } @@ -179,36 +174,35 @@ vm_start(uint32_t start_id, const char *name, size_t m errx(1, "invalid VM name"); } - if (strlcpy(vcp->vcp_name, name, - sizeof(vcp->vcp_name)) >= sizeof(vcp->vcp_name)) + if (strlcpy(vmc.vmc_name, name, + sizeof(vmc.vmc_name)) >= sizeof(vmc.vmc_name)) errx(1, "vm name too long"); } if (kernel != NULL) { if (strnlen(kernel, PATH_MAX) == PATH_MAX) errx(1, "kernel name too long"); - vmc->vmc_kernel = open(kernel, O_RDONLY); - if (vmc->vmc_kernel == -1) + vmc.vmc_kernel = open(kernel, O_RDONLY); + if (vmc.vmc_kernel == -1) err(1, "cannot open kernel '%s'", kernel); memset(&sb, 0, sizeof(sb)); - if (fstat(vmc->vmc_kernel, &sb) == -1) + if (fstat(vmc.vmc_kernel, &sb) == -1) err(1, "fstat kernel"); if (!S_ISREG(sb.st_mode)) errx(1, "kernel must be a regular file"); } if (iso != NULL) - if (strlcpy(vmc->vmc_cdrom, iso, - sizeof(vmc->vmc_cdrom)) >= sizeof(vmc->vmc_cdrom)) + if (strlcpy(vmc.vmc_cdrom, iso, + sizeof(vmc.vmc_cdrom)) >= sizeof(vmc.vmc_cdrom)) errx(1, "cdrom name too long"); if (instance != NULL) - if (strlcpy(vmc->vmc_instance, instance, - sizeof(vmc->vmc_instance)) >= sizeof(vmc->vmc_instance)) + if (strlcpy(vmc.vmc_instance, instance, + sizeof(vmc.vmc_instance)) >= sizeof(vmc.vmc_instance)) errx(1, "instance vm name too long"); - vmc->vmc_bootdevice = bootdevice; + vmc.vmc_bootdevice = bootdevice; - imsg_compose(ibuf, IMSG_VMDOP_START_VM_REQUEST, 0, 0, vmc->vmc_kernel, - vmc, sizeof(struct vmop_create_params)); + imsg_compose(ibuf, IMSG_VMDOP_START_VM_REQUEST, 0, 0, vmc.vmc_kernel, + &vmc, sizeof(vmc)); - free(vmc); return (0); } @@ -495,14 +489,12 @@ terminate_vm_complete(struct imsg *imsg, int *ret, uns void terminate_all(struct vmop_info_result *list, size_t ct, unsigned int flags) { - struct vm_info_result *vir; - struct vmop_info_result *vmi; + struct vmop_info_result *vir; struct parse_result res; size_t i; for (i = 0; i < ct; i++) { - vmi = &list[i]; - vir = &vmi->vir_info; + vir = &list[i]; /* The VM is already stopped */ if (vir->vir_creator_pid == 0 || vir->vir_id == 0) @@ -705,8 +697,7 @@ vm_state(unsigned int mask) int print_vm_info(struct vmop_info_result *list, size_t ct) { - struct vm_info_result *vir; - struct vmop_info_result *vmi; + struct vmop_info_result *vir; size_t i; char *tty; char curmem[FMT_SCALED_STRSIZE]; @@ -722,8 +713,7 @@ print_vm_info(struct vmop_info_result *list, size_t ct "MAXMEM", "CURMEM", "TTY", "OWNER", "STATE", "NAME"); for (i = 0; i < ct; i++) { - vmi = &list[i]; - vir = &vmi->vir_info; + vir = &list[i]; running = (vir->vir_creator_pid != 0 && vir->vir_id != 0); if (!running && stat_rflag) continue; @@ -732,18 +722,18 @@ print_vm_info(struct vmop_info_result *list, size_t ct if (check_info_id(vir->vir_name, vir->vir_id)) { /* get user name */ - name = user_from_uid(vmi->vir_uid, 1); + name = user_from_uid(vir->vir_uid, 1); if (name == NULL) (void)snprintf(user, sizeof(user), - "%d", vmi->vir_uid); + "%d", vir->vir_uid); else (void)strlcpy(user, name, sizeof(user)); /* get group name */ - if (vmi->vir_gid != -1) { - name = group_from_gid(vmi->vir_gid, 1); + if (vir->vir_gid != -1) { + name = group_from_gid(vir->vir_gid, 1); if (name == NULL) (void)snprintf(group, sizeof(group), - ":%lld", vmi->vir_gid); + ":%lld", vir->vir_gid); else (void)snprintf(group, sizeof(group), ":%s", name); @@ -756,10 +746,10 @@ print_vm_info(struct vmop_info_result *list, size_t ct (void)fmt_scaled(vir->vir_memory_size, maxmem); if (running) { - if (*vmi->vir_ttyname == '\0') + if (*vir->vir_ttyname == '\0') tty = "-"; /* get tty - skip /dev/ path */ - else if ((tty = strrchr(vmi->vir_ttyname, + else if ((tty = strrchr(vir->vir_ttyname, '/')) == NULL || *++tty == '\0') tty = list[i].vir_ttyname; @@ -769,14 +759,14 @@ print_vm_info(struct vmop_info_result *list, size_t ct printf("%5u %5u %5zd %7s %7s %7s %12s %8s %s\n", vir->vir_id, vir->vir_creator_pid, vir->vir_ncpus, maxmem, curmem, - tty, user, vm_state(vmi->vir_state), + tty, user, vm_state(vir->vir_state), vir->vir_name); } else { /* disabled vm */ printf("%5u %5s %5zd %7s %7s %7s %12s %8s %s\n", vir->vir_id, "-", vir->vir_ncpus, maxmem, curmem, - "-", user, vm_state(vmi->vir_state), + "-", user, vm_state(vir->vir_state), vir->vir_name); } } @@ -805,9 +795,8 @@ vm_console(struct vmop_info_result *list, size_t ct) for (i = 0; i < ct; i++) { vir = &list[i]; - if ((check_info_id(vir->vir_info.vir_name, - vir->vir_info.vir_id) > 0) && - (vir->vir_ttyname[0] != '\0')) { + if ((check_info_id(vir->vir_name, vir->vir_id) > 0) && + (vir->vir_ttyname[0] != '\0')) { /* does not return */ ctl_openconsole(vir->vir_ttyname); } @@ -930,14 +919,10 @@ vmop_result_read(struct imsg *imsg, struct vmop_result void vmop_info_result_read(struct imsg *imsg, struct vmop_info_result *vir) { - struct vm_info_result *r; - if (imsg_get_data(imsg, vir, sizeof(*vir))) fatal("%s", __func__); - r = &vir->vir_info; - r->vir_name[sizeof(r->vir_name) - 1] = '\0'; - + vir->vir_name[sizeof(vir->vir_name) - 1] = '\0'; vir->vir_ttyname[sizeof(vir->vir_ttyname) - 1] = '\0'; } blob - bb3eb114e83c6a2c1cedbd159911543b1a0cb6b2 blob + 89b19e74b702e71e2a09265d69fc3c4f3c61c776 --- usr.sbin/vmd/arm64_vm.c +++ usr.sbin/vmd/arm64_vm.c @@ -20,7 +20,7 @@ #include "vmm.h" void -create_memory_map(struct vm_create_params *vcp) +create_memory_map(struct vmd_vm *vm) { fatalx("%s: unimplemented", __func__); /* NOTREACHED */ @@ -35,7 +35,7 @@ load_firmware(struct vmd_vm *vm, struct vcpu_reg_state } int -init_emulated_hw(struct vmop_create_params *vcp, int child_cdrom, +init_emulated_hw(struct vmd_vm *vm, int child_cdrom, int child_disks[][VM_MAX_BASE_PER_DISK], int *child_taps) { fatalx("%s: unimplemented", __func__); blob - 069c05608cc842bc9604504698bfb453d62ce475 blob + 24f1c7fe8bd6edc255d5360ed6d12e56c53cf517 --- usr.sbin/vmd/config.c +++ usr.sbin/vmd/config.c @@ -190,7 +190,6 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui int diskfds[VM_MAX_DISKS_PER_VM][VM_MAX_BASE_PER_DISK]; struct vmd_if *vif; struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; unsigned int i, j; int fd = -1, cdromfd = -1, kernfd = -1; int *tapfds = NULL; @@ -227,13 +226,13 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui } log_debug("%s: vm %u restarted after %lld.%ld seconds," - " limit %d/%d", __func__, vcp->vcp_id, since_last.tv_sec, + " limit %d/%d", __func__, vm->vm_vmid, since_last.tv_sec, since_last.tv_usec, vm->vm_start_limit, VM_START_RATE_LIMIT); if (vm->vm_start_limit >= VM_START_RATE_LIMIT) { - log_warnx("%s: vm %u restarted too quickly", - __func__, vcp->vcp_id); + log_warnx("%s: vm %u restarted too quickly", __func__, + vm->vm_vmid); return (EPERM); } } @@ -290,7 +289,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui vmc->vmc_checkaccess & VMOP_CREATE_KERNEL, uid, R_OK) == -1) { log_warnx("vm \"%s\" no read access to kernel " - "%s", vcp->vcp_name, vm->vm_kernel_path); + "%s", vmc->vmc_name, vm->vm_kernel_path); ret = EPERM; goto fail; } @@ -313,7 +312,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui vmc->vmc_checkaccess & VMOP_CREATE_CDROM, uid, R_OK) == -1) { log_warnx("vm \"%s\" no read access to cdrom %s", - vcp->vcp_name, vmc->vmc_cdrom); + vmc->vmc_name, vmc->vmc_cdrom); ret = EPERM; goto fail; } @@ -343,7 +342,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui vmc->vmc_checkaccess & VMOP_CREATE_DISK, uid, aflags) == -1) { log_warnx("vm \"%s\" unable to access " - "disk %s", vcp->vcp_name, path); + "disk %s", vmc->vmc_name, path); errno = EPERM; goto fail; } @@ -361,7 +360,7 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui break; if (n == -1) { log_warnx("vm \"%s\" unable to read " - "base for disk %s", vcp->vcp_name, + "base for disk %s", vmc->vmc_name, vmc->vmc_disks[i]); goto fail; } @@ -488,18 +487,18 @@ config_setvm(struct privsep *ps, struct vmd_vm *vm, ui free(tapfds); /* Collapse any memranges after the vm was sent to PROC_VMM */ - if (vcp->vcp_nmemranges > 0) { - for (i = 0; i < vcp->vcp_nmemranges; i++) - bytes += vcp->vcp_memranges[i].vmr_size; - memset(&vcp->vcp_memranges, 0, sizeof(vcp->vcp_memranges)); - vcp->vcp_nmemranges = 0; - vcp->vcp_memranges[0].vmr_size = bytes; + if (vmc->vmc_nmemranges > 0) { + for (i = 0; i < vmc->vmc_nmemranges; i++) + bytes += vmc->vmc_memranges[i].vmr_size; + memset(&vmc->vmc_memranges, 0, sizeof(vmc->vmc_memranges)); + vmc->vmc_nmemranges = 0; + vmc->vmc_memranges[0].vmr_size = bytes; } vm->vm_state |= VM_STATE_RUNNING; return (0); fail: - log_warnx("failed to start vm %s", vcp->vcp_name); + log_warnx("failed to start vm %s", vmc->vmc_name); if (vm->vm_kernel != -1) close(kernfd); blob - 256a29f51260e7af51977b4ea16676e056376943 blob + 03cdcb269dcc3f8560c2d35299c1226da5fdea26 --- usr.sbin/vmd/dhcp.c +++ usr.sbin/vmd/dhcp.c @@ -139,13 +139,13 @@ dhcp_request(struct virtio_dev *dev, char *buf, size_t if (vionet->pxeboot) { strlcpy(resp.file, "auto_install", sizeof resp.file); - vm = vm_getbyvmid(dev->vm_vmid); - if (vm && res_hnok(vm->vm_params.vmc_params.vcp_name)) - hostname = vm->vm_params.vmc_params.vcp_name; + vm = vm_getbyid(dev->vmm_id); + if (vm && res_hnok(vm->vm_params.vmc_name)) + hostname = vm->vm_params.vmc_name; } if ((client_addr.s_addr = vm_priv_addr(&vionet->local_prefix, - dev->vm_vmid, vionet->idx, 1)) == 0) + dev->vm_id, vionet->idx, 1)) == 0) return (-1); memcpy(&resp.yiaddr, &client_addr, sizeof(client_addr)); @@ -154,7 +154,7 @@ dhcp_request(struct virtio_dev *dev, char *buf, size_t ss2sin(&pc.pc_dst)->sin_port = htons(CLIENT_PORT); if ((server_addr.s_addr = vm_priv_addr(&vionet->local_prefix, - dev->vm_vmid, vionet->idx, 0)) == 0) + dev->vm_id, vionet->idx, 0)) == 0) return (-1); memcpy(&resp.siaddr, &server_addr, sizeof(server_addr)); memcpy(&ss2sin(&pc.pc_src)->sin_addr, &server_addr, blob - 44bc7bd58fbf956168c8adb8731def6e14a076eb blob + ce6b6cc2187ed3c983ed324bd1054b7cbc3b46cb --- usr.sbin/vmd/fw_cfg.c +++ usr.sbin/vmd/fw_cfg.c @@ -79,8 +79,8 @@ fw_cfg_init(struct vmop_create_params *vmc) /* Define e820 memory ranges. */ memset(&e820, 0, sizeof(e820)); - for (i = 0; i < vmc->vmc_params.vcp_nmemranges; i++) { - struct vm_mem_range *range = &vmc->vmc_params.vcp_memranges[i]; + for (i = 0; i < vmc->vmc_nmemranges; i++) { + struct vm_mem_range *range = &vmc->vmc_memranges[i]; bios_memmap_t *entry = &e820[i]; entry->addr = range->vmr_gpa; entry->size = range->vmr_size; blob - 875287d8c7a856d34efd730603e1d9a9c692daa4 blob + 36a94208ee400e3831878be04feb910dec913f09 --- usr.sbin/vmd/loadfile_elf.c +++ usr.sbin/vmd/loadfile_elf.c @@ -113,7 +113,7 @@ static void setsegment(struct mem_segment_descriptor * size_t, int, int, int, int); static int elf32_exec(gzFile, Elf32_Ehdr *, u_long *, int); static int elf64_exec(gzFile, Elf64_Ehdr *, u_long *, int); -static size_t create_bios_memmap(struct vm_create_params *, bios_memmap_t *); +static size_t create_bios_memmap(struct vmop_create_params *, bios_memmap_t *); static uint32_t push_bootargs(bios_memmap_t *, size_t, bios_bootmac_t *); static size_t push_stack(uint32_t, uint32_t); static void push_gdt(void); @@ -217,7 +217,6 @@ loadfile_elf(gzFile fp, struct vmd_vm *vm, struct vcpu u_long marks[MARK_MAX]; bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1]; bios_bootmac_t bm, *bootmac = NULL; - struct vm_create_params *vcp = &vm->vm_params.vmc_params; if ((r = gzread(fp, &hdr, sizeof(hdr))) != sizeof(hdr)) return 1; @@ -251,7 +250,7 @@ loadfile_elf(gzFile fp, struct vmd_vm *vm, struct vcpu bootmac = &bm; memcpy(bootmac, vm->vm_params.vmc_macs[0], ETHER_ADDR_LEN); } - n = create_bios_memmap(vcp, memmap); + n = create_bios_memmap(&vm->vm_params, memmap); bootargsz = push_bootargs(memmap, n, bootmac); stacksize = push_stack(bootargsz, marks[MARK_END]); @@ -270,20 +269,20 @@ loadfile_elf(gzFile fp, struct vmd_vm *vm, struct vcpu * Construct a memory map as returned by the BIOS INT 0x15, e820 routine. * * Parameters: - * vcp: the VM create parameters, containing the memory map passed to vmm(4) + * vmc: the VM create parameters, containing the memory map passed to vmm(4) * memmap (out): the BIOS memory map * * Return values: * Number of bios_memmap_t entries, including the terminating nul-entry. */ static size_t -create_bios_memmap(struct vm_create_params *vcp, bios_memmap_t *memmap) +create_bios_memmap(struct vmop_create_params *vmc, bios_memmap_t *memmap) { size_t i, n = 0; struct vm_mem_range *vmr; - for (i = 0; i < vcp->vcp_nmemranges; i++, n++) { - vmr = &vcp->vcp_memranges[i]; + for (i = 0; i < vmc->vmc_nmemranges; i++, n++) { + vmr = &vmc->vmc_memranges[i]; memmap[n].addr = vmr->vmr_gpa; memmap[n].size = vmr->vmr_size; if (vmr->vmr_type == VM_MEM_RAM) blob - 967583ea5fa26da4f30fe4e6b6c7e9377782621a blob + 4a8e2d2166784330be19cbb0c9dedbffa0dd5574 --- usr.sbin/vmd/parse.y +++ usr.sbin/vmd/parse.y @@ -92,7 +92,6 @@ int parse_disk(char *, int); unsigned int parse_format(const char *); static struct vmop_create_params vmc; -static struct vm_create_params *vcp; static struct vmd_switch *vsw; static char *kernel = NULL; static char vsw_type[IF_NAMESIZE]; @@ -323,7 +322,6 @@ vm : VM string vm_instance { memset(&vmc, 0, sizeof(vmc)); vmc.vmc_kernel = -1; - vcp = &vmc.vmc_params; vmc_disable = 0; vmc_nnics = 0; @@ -349,8 +347,8 @@ vm : VM string vm_instance { vmc.vmc_ifflags[i] |= IFF_UP; } - if (strlcpy(vcp->vcp_name, name, - sizeof(vcp->vcp_name)) >= sizeof(vcp->vcp_name)) { + if (strlcpy(vmc.vmc_name, name, + sizeof(vmc.vmc_name)) >= sizeof(vmc.vmc_name)) { yyerror("vm name too long"); free($2); free($3); @@ -375,12 +373,12 @@ vm : VM string vm_instance { log_debug("%s:%d: vm \"%s\"" " skipped (%s)", file->name, yylval.lineno, - vcp->vcp_name, + vmc.vmc_name, (vm->vm_state & VM_STATE_RUNNING) ? "running" : "already exists"); } else if (ret == -1) { yyerror("vm \"%s\" failed: %s", - vcp->vcp_name, strerror(errno)); + vmc.vmc_name, strerror(errno)); YYERROR; } else { if (vmc_disable) @@ -390,7 +388,7 @@ vm : VM string vm_instance { log_debug("%s:%d: vm \"%s\" " "registered (%s)", file->name, yylval.lineno, - vcp->vcp_name, + vmc.vmc_name, vmc_disable ? "disabled" : "enabled"); } @@ -414,10 +412,10 @@ vm_opts : disable { vmc_disable = $1; } | sev { - vcp->vcp_sev = 1; + vmc.vmc_sev = 1; } | seves { - vcp->vcp_sev = vcp->vcp_seves = 1; + vmc.vmc_sev = vmc.vmc_seves = 1; } | DISK string image_format { if (parse_disk($2, $3) != 0) { @@ -518,7 +516,7 @@ vm_opts : disable { } | MEMORY NUMBER { ssize_t res; - if (vcp->vcp_memranges[0].vmr_size != 0) { + if (vmc.vmc_memranges[0].vmr_size != 0) { yyerror("memory specified more than once"); YYERROR; } @@ -526,12 +524,12 @@ vm_opts : disable { yyerror("failed to parse size: %lld", $2); YYERROR; } - vcp->vcp_memranges[0].vmr_size = (size_t)res; + vmc.vmc_memranges[0].vmr_size = (size_t)res; vmc.vmc_flags |= VMOP_CREATE_MEMORY; } | MEMORY STRING { ssize_t res; - if (vcp->vcp_memranges[0].vmr_size != 0) { + if (vmc.vmc_memranges[0].vmr_size != 0) { yyerror("argument specified more than once"); free($2); YYERROR; @@ -541,7 +539,7 @@ vm_opts : disable { free($2); YYERROR; } - vcp->vcp_memranges[0].vmr_size = (size_t)res; + vmc.vmc_memranges[0].vmr_size = (size_t)res; vmc.vmc_flags |= VMOP_CREATE_MEMORY; } | OWNER owner_id { blob - 196e905aa98f0a31c0108505015c4adca947a8a6 blob + 100454da36c65a5d70e7f7421abb121038a00b38 --- usr.sbin/vmd/priv.c +++ usr.sbin/vmd/priv.c @@ -326,7 +326,6 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm { char name[64]; struct vmd *env = ps->ps_env; - struct vm_create_params *vcp = &vm->vm_params.vmc_params; struct vmd_if *vif; struct vmd_switch *vsw; unsigned int i; @@ -347,7 +346,7 @@ vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm /* Description can be truncated */ (void)snprintf(vfr.vfr_value, sizeof(vfr.vfr_value), - "vm%u-if%u-%s", vm->vm_vmid, i, vcp->vcp_name); + "vm%u-if%u-%s", vm->vm_vmid, i, vm->vm_params.vmc_name); log_debug("%s: interface %s description %s", __func__, vfr.vfr_name, vfr.vfr_value); blob - 77964c495de4f5042c305208a2e79aa172b95803 blob + eef693d6e863e25f4887c33dca0a8c1fb9b85e42 --- usr.sbin/vmd/sev.c +++ usr.sbin/vmd/sev.c @@ -41,12 +41,11 @@ int sev_init(struct vmd_vm *vm) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; uint32_t handle; uint16_t pstate; uint8_t gstate; - if (!vcp->vcp_sev) + if (!vmc->vmc_sev) return (0); if (psp_get_pstate(&pstate, NULL, NULL, NULL, NULL)) { @@ -58,7 +57,7 @@ sev_init(struct vmd_vm *vm) return (-1); } - if (psp_launch_start(&handle, vcp->vcp_seves) < 0) { + if (psp_launch_start(&handle, vmc->vmc_seves) < 0) { log_warnx("%s: launch failed", __func__); return (-1); } @@ -83,15 +82,13 @@ int sev_register_encryption(vaddr_t addr, size_t size) { struct vmop_create_params *vmc; - struct vm_create_params *vcp; struct vm_mem_range *vmr; size_t off; int i; vmc = ¤t_vm->vm_params; - vcp = &vmc->vmc_params; - if (!vcp->vcp_sev) + if (!vmc->vmc_sev) return (0); if (size == 0) @@ -103,7 +100,7 @@ sev_register_encryption(vaddr_t addr, size_t size) addr &= ~(AES_XTS_BLOCKSIZE - 1); } - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, addr, size); + vmr = find_gpa_range(¤t_vm->vm_params, addr, size); if (vmr == NULL) { log_warnx("%s: failed - invalid memory range addr = 0x%lx, " "len = 0x%zx", __func__, addr, size); @@ -145,11 +142,10 @@ int sev_encrypt_memory(struct vmd_vm *vm) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; struct vm_mem_range *vmr; size_t i; - if (!vcp->vcp_sev) + if (!vmc->vmc_sev) return (0); for (i = 0; i < vm->vm_sev_nmemsegments; i++) { @@ -178,10 +174,9 @@ int sev_activate(struct vmd_vm *vm, int vcpu_id) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; uint8_t gstate; - if (!vcp->vcp_sev) + if (!vmc->vmc_sev) return (0); if (psp_df_flush() || @@ -208,13 +203,12 @@ int sev_encrypt_state(struct vmd_vm *vm, int vcpu_id) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; - if (!vcp->vcp_seves) + if (!vmc->vmc_seves) return (0); if (psp_encrypt_state(vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id], - vcp->vcp_id, vcpu_id)) { + vm->vm_vmmid, vcpu_id)) { log_warnx("%s: failed to encrypt state: 0x%x 0x%x 0x%0x 0x%0x", __func__, vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id], vm->vm_vmid, vcpu_id); @@ -228,10 +222,9 @@ int sev_launch_finalize(struct vmd_vm *vm) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; uint8_t gstate; - if (!vcp->vcp_sev) + if (!vmc->vmc_sev) return (0); if (psp_launch_measure(vm->vm_sev_handle)) { @@ -262,9 +255,8 @@ int sev_shutdown(struct vmd_vm *vm) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; - if (!vcp->vcp_sev) + if (!vmc->vmc_sev) return (0); if (psp_guest_shutdown(vm->vm_sev_handle)) { blob - dbebb76e022433696a5894ef63ad3ddd9b6f0adf blob + 97b69ab11c6c8dd3311610a560f2c363fec4d695 --- usr.sbin/vmd/vioblk.c +++ usr.sbin/vmd/vioblk.c @@ -65,7 +65,6 @@ vioblk_main(int fd, int fd_vmm) struct vioblk_dev *vioblk = NULL; struct viodev_msg msg; struct vmd_vm vm; - struct vm_create_params *vcp; ssize_t sz; off_t szp = 0; int i, ret, type; @@ -109,11 +108,10 @@ vioblk_main(int fd, int fd_vmm) log_warnx("failed to receive vm details"); goto fail; } - vcp = &vm.vm_params.vmc_params; current_vm = &vm; - setproctitle("%s/vioblk%d", vcp->vcp_name, vioblk->idx); - log_procinit("vm/%s/vioblk%d", vcp->vcp_name, vioblk->idx); + setproctitle("%s/vioblk%d", vm.vm_params.vmc_name, vioblk->idx); + log_procinit("vm/%s/vioblk%d", vm.vm_params.vmc_name, vioblk->idx); /* Now that we have our vm information, we can remap memory. */ ret = remap_guest_mem(&vm, fd_vmm); @@ -178,7 +176,8 @@ vioblk_main(int fd, int fd_vmm) imsg_event_add(&dev.sync_iev); /* Send a ready message over the sync channel. */ - log_debug("%s: telling vm %s device is ready", __func__, vcp->vcp_name); + log_debug("%s: telling vm %s device is ready", __func__, + vm.vm_params.vmc_name); memset(&msg, 0, sizeof(msg)); msg.type = VIODEV_MSG_READY; imsg_compose_event(&dev.sync_iev, IMSG_DEVOP_MSG, 0, 0, -1, &msg, blob - 7435db9f8ad7d22fe61ab35f986b03e9652547d7 blob + 8e50229938b143626337676554a63c4080648cb4 --- usr.sbin/vmd/vionet.c +++ usr.sbin/vmd/vionet.c @@ -112,7 +112,6 @@ vionet_main(int fd, int fd_vmm) struct vionet_dev *vionet = NULL; struct viodev_msg msg; struct vmd_vm vm; - struct vm_create_params *vcp; ssize_t sz; int ret; @@ -154,10 +153,9 @@ vionet_main(int fd, int fd_vmm) log_warnx("failed to receive vm details"); goto fail; } - vcp = &vm.vm_params.vmc_params; current_vm = &vm; - setproctitle("%s/vionet%d", vcp->vcp_name, vionet->idx); - log_procinit("vm/%s/vionet%d", vcp->vcp_name, vionet->idx); + setproctitle("%s/vionet%d", vm.vm_params.vmc_name, vionet->idx); + log_procinit("vm/%s/vionet%d", vm.vm_params.vmc_name, vionet->idx); /* Now that we have our vm information, we can remap memory. */ ret = remap_guest_mem(&vm, fd_vmm); @@ -238,7 +236,8 @@ vionet_main(int fd, int fd_vmm) imsg_event_add2(&dev.sync_iev, ev_base_main); /* Send a ready message over the sync channel. */ - log_debug("%s: telling vm %s device is ready", __func__, vcp->vcp_name); + log_debug("%s: telling vm %s device is ready", __func__, + vm.vm_params.vmc_name); memset(&msg, 0, sizeof(msg)); msg.type = VIODEV_MSG_READY; imsg_compose_event2(&dev.sync_iev, IMSG_DEVOP_MSG, 0, 0, -1, &msg, blob - ecd033cc7ac0e397936b6d2b1e18dbfbed2aa15f blob + 9a1f0ad93de15f1048289c46a7436879e05a6096 --- usr.sbin/vmd/virtio.c +++ usr.sbin/vmd/virtio.c @@ -73,8 +73,8 @@ SLIST_HEAD(virtio_dev_head, virtio_dev) virtio_devs; #define RXQ 0 #define TXQ 1 -static void virtio_dev_init(struct virtio_dev *, uint8_t, uint16_t, uint16_t, - uint64_t, uint32_t); +static void virtio_dev_init(struct vmd_vm *, struct virtio_dev *, uint8_t, + uint16_t, uint16_t, uint64_t); static int virtio_dev_launch(struct vmd_vm *, struct virtio_dev *); static void virtio_dispatch_dev(int, short, void *); static int handle_dev_msg(struct viodev_msg *, struct virtio_dev *); @@ -649,7 +649,7 @@ virtio_io_isr(int dir, uint16_t reg, uint32_t *data, u if (dir == VEI_DIR_IN) { *data = dev->isr; dev->isr = 0; - vcpu_deassert_irq(dev->vm_id, 0, dev->irq); + vcpu_deassert_irq(dev->vmm_id, 0, dev->irq); } return (0); @@ -750,7 +750,7 @@ vmmci_ctl(struct virtio_dev *dev, unsigned int cmd) /* Trigger interrupt */ dev->isr = VIRTIO_CONFIG_ISR_CONFIG_CHANGE; - vcpu_assert_irq(dev->vm_id, 0, dev->irq); + vcpu_assert_irq(dev->vmm_id, 0, dev->irq); /* Add ACK timeout */ tv.tv_sec = VMMCI_TIMEOUT_SHORT; @@ -762,7 +762,7 @@ vmmci_ctl(struct virtio_dev *dev, unsigned int cmd) v->cmd = cmd; dev->isr = VIRTIO_CONFIG_ISR_CONFIG_CHANGE; - vcpu_assert_irq(dev->vm_id, 0, dev->irq); + vcpu_assert_irq(dev->vmm_id, 0, dev->irq); } else { log_debug("%s: RTC sync skipped (guest does not " "support RTC sync)\n", __func__); @@ -806,7 +806,7 @@ vmmci_ack(struct virtio_dev *dev, unsigned int cmd) */ if (v->cmd == 0) { log_debug("%s: vm %u requested shutdown", __func__, - dev->vm_id); + dev->vmm_id); vm_pipe_send(&v->dev_pipe, VMMCI_SET_TIMEOUT_SHORT); return; } @@ -821,13 +821,13 @@ vmmci_ack(struct virtio_dev *dev, unsigned int cmd) */ if (cmd == v->cmd) { log_debug("%s: vm %u acknowledged shutdown request", - __func__, dev->vm_id); + __func__, dev->vmm_id); vm_pipe_send(&v->dev_pipe, VMMCI_SET_TIMEOUT_LONG); } break; case VMMCI_SYNCRTC: log_debug("%s: vm %u acknowledged RTC sync request", - __func__, dev->vm_id); + __func__, dev->vmm_id); v->cmd = VMMCI_NONE; break; default: @@ -846,7 +846,7 @@ vmmci_timeout(int fd, short type, void *arg) fatalx("%s: device is not a vmmci device", __func__); v = &dev->vmmci; - log_debug("vm %u shutdown", dev->vm_id); + log_debug("vm %u shutdown", dev->vmm_id); vm_shutdown(v->cmd == VMMCI_REBOOT ? VMMCI_REBOOT : VMMCI_SHUTDOWN); } @@ -935,7 +935,7 @@ vmmci_io(int dir, uint16_t reg, uint32_t *data, uint8_ case VIRTIO_CONFIG_ISR_STATUS: *data = dev->isr; dev->isr = 0; - vcpu_deassert_irq(dev->vm_id, 0, dev->irq); + vcpu_deassert_irq(dev->vmm_id, 0, dev->irq); break; } } @@ -990,7 +990,6 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int child_disks[][VM_MAX_BASE_PER_DISK], int *child_taps) { struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; struct virtio_dev *dev; uint8_t id, i, j; int bar_id, ret = 0; @@ -1005,8 +1004,8 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, log_warnx("can't add PCI virtio rng device"); return (1); } - virtio_dev_init(&viornd, id, VIORND_QUEUE_SIZE_DEFAULT, - VIRTIO_RND_QUEUES, VIRTIO_F_VERSION_1, vcp->vcp_id); + virtio_dev_init(vm, &viornd, id, VIORND_QUEUE_SIZE_DEFAULT, + VIRTIO_RND_QUEUES, VIRTIO_F_VERSION_1); bar_id = pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_io_dispatch, &viornd); @@ -1033,10 +1032,9 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, log_warnx("can't add PCI virtio net device"); return (1); } - virtio_dev_init(dev, id, VIONET_QUEUE_SIZE_DEFAULT, + virtio_dev_init(vm, dev, id, VIONET_QUEUE_SIZE_DEFAULT, VIRTIO_NET_QUEUES, - (VIRTIO_NET_F_MAC | VIRTIO_F_VERSION_1), - vcp->vcp_id); + (VIRTIO_NET_F_MAC | VIRTIO_F_VERSION_1)); if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_pci_io, dev) == -1) { @@ -1055,7 +1053,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, /* Device specific initializiation. */ dev->dev_type = VMD_DEVTYPE_NET; - dev->vm_vmid = vm->vm_vmid; + dev->vmm_id = vm->vm_vmmid; dev->vionet.data_fd = child_taps[i]; /* MAC address has been assigned by the parent */ @@ -1070,7 +1068,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, &env->vmd_cfg.cfg_localprefix, sizeof(dev->vionet.local_prefix)); log_debug("%s: vm \"%s\" vio%u lladdr %s%s%s%s", - __func__, vcp->vcp_name, i, + __func__, vm->vm_params.vmc_name, i, ether_ntoa((void *)dev->vionet.mac), dev->vionet.lockedmac ? ", locked" : "", dev->vionet.local ? ", local" : "", @@ -1100,10 +1098,9 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, "device"); return (1); } - virtio_dev_init(dev, id, VIOBLK_QUEUE_SIZE_DEFAULT, + virtio_dev_init(vm, dev, id, VIOBLK_QUEUE_SIZE_DEFAULT, VIRTIO_BLK_QUEUES, - (VIRTIO_F_VERSION_1 | VIRTIO_BLK_F_SEG_MAX), - vcp->vcp_id); + (VIRTIO_F_VERSION_1 | VIRTIO_BLK_F_SEG_MAX)); bar_id = pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_pci_io, dev); @@ -1123,7 +1120,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, /* Device specific initialization. */ dev->dev_type = VMD_DEVTYPE_DISK; - dev->vm_vmid = vm->vm_vmid; + dev->vmm_id = vm->vm_vmmid; dev->vioblk.seg_max = VIOBLK_SEG_MAX_DEFAULT; /* @@ -1165,8 +1162,8 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, log_warnx("can't add PCI vioscsi device"); return (1); } - virtio_dev_init(dev, id, VIOSCSI_QUEUE_SIZE_DEFAULT, - VIRTIO_SCSI_QUEUES, VIRTIO_F_VERSION_1, vcp->vcp_id); + virtio_dev_init(vm, dev, id, VIOSCSI_QUEUE_SIZE_DEFAULT, + VIRTIO_SCSI_QUEUES, VIRTIO_F_VERSION_1); if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, virtio_io_dispatch, dev) == -1) { log_warnx("can't add bar for vioscsi device"); @@ -1199,8 +1196,8 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, log_warnx("can't add PCI vmm control device"); return (1); } - virtio_dev_init(dev, id, 0, 0, - VMMCI_F_TIMESYNC | VMMCI_F_ACK | VMMCI_F_SYNCRTC, vcp->vcp_id); + virtio_dev_init(vm, dev, id, 0, 0, + VMMCI_F_TIMESYNC | VMMCI_F_ACK | VMMCI_F_SYNCRTC); if (pci_add_bar(id, PCI_MAPREG_TYPE_IO, vmmci_io, dev) == -1) { log_warnx("can't add bar for vmm control device"); return (1); @@ -1346,8 +1343,8 @@ virtio_start(struct vmd_vm *vm) * Initialize a new virtio device structure. */ static void -virtio_dev_init(struct virtio_dev *dev, uint8_t pci_id, uint16_t queue_size, - uint16_t num_queues, uint64_t features, uint32_t vm_id) +virtio_dev_init(struct vmd_vm *vm, struct virtio_dev *dev, uint8_t pci_id, + uint16_t queue_size, uint16_t num_queues, uint64_t features) { size_t i; uint16_t device_id; @@ -1365,7 +1362,8 @@ virtio_dev_init(struct virtio_dev *dev, uint8_t pci_id dev->device_id = device_id; dev->irq = pci_get_dev_irq(pci_id); dev->isr = 0; - dev->vm_id = vm_id; + dev->vm_id = vm->vm_vmid; + dev->vmm_id = vm->vm_vmmid; dev->device_feature = features; @@ -1478,12 +1476,12 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev switch (dev->dev_type) { case VMD_DEVTYPE_NET: - log_debug("%s: launching vionet%d", - vm->vm_params.vmc_params.vcp_name, dev->vionet.idx); + log_debug("%s: launching vionet%d", vm->vm_params.vmc_name, + dev->vionet.idx); break; case VMD_DEVTYPE_DISK: - log_debug("%s: launching vioblk%d", - vm->vm_params.vmc_params.vcp_name, dev->vioblk.idx); + log_debug("%s: launching vioblk%d", vm->vm_params.vmc_name, + dev->vioblk.idx); break; /* NOTREACHED */ default: @@ -1542,7 +1540,7 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev /* 2. Send over details on the VM (including memory fds). */ log_debug("%s: sending vm message for '%s'", __func__, - vm->vm_params.vmc_params.vcp_name); + vm->vm_params.vmc_name); sz = atomicio(vwrite, sync_fds[0], vm, sizeof(*vm)); if (sz != sizeof(*vm)) { log_warnx("%s: failed to send vm details", __func__); @@ -1616,7 +1614,7 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev snprintf(vmm_fd, sizeof(vmm_fd), "%d", env->vmd_fd); memset(vm_name, 0, sizeof(vm_name)); snprintf(vm_name, sizeof(vm_name), "%s", - vm->vm_params.vmc_params.vcp_name); + vm->vm_params.vmc_name); t[0] = dev->dev_type; t[1] = '\0'; @@ -1745,14 +1743,14 @@ virtio_dispatch_dev(int fd, short event, void *arg) static int handle_dev_msg(struct viodev_msg *msg, struct virtio_dev *gdev) { - uint32_t vm_id = gdev->vm_id; + uint32_t vmm_id = gdev->vmm_id; switch (msg->type) { case VIODEV_MSG_KICK: if (msg->state == INTR_STATE_ASSERT) - vcpu_assert_irq(vm_id, msg->vcpu, msg->irq); + vcpu_assert_irq(vmm_id, msg->vcpu, msg->irq); else if (msg->state == INTR_STATE_DEASSERT) - vcpu_deassert_irq(vm_id, msg->vcpu, msg->irq); + vcpu_deassert_irq(vmm_id, msg->vcpu, msg->irq); break; case VIODEV_MSG_READY: log_debug("%s: device reports ready", __func__); @@ -1851,9 +1849,9 @@ virtio_pci_io(int dir, uint16_t reg, uint32_t *data, u * device performs a register read. */ if (msg.state == INTR_STATE_ASSERT) - vcpu_assert_irq(dev->vm_id, msg.vcpu, msg.irq); + vcpu_assert_irq(dev->vmm_id, msg.vcpu, msg.irq); else if (msg.state == INTR_STATE_DEASSERT) - vcpu_deassert_irq(dev->vm_id, msg.vcpu, msg.irq); + vcpu_deassert_irq(dev->vmm_id, msg.vcpu, msg.irq); } else { log_warnx("%s: expected IO_READ, got %d", __func__, msg.type); blob - b7a49b40e0b1255139a130f554d2363eb33d99d1 blob + 1d7f1d45c684400b5c95c2b70f2cb6a474332c96 --- usr.sbin/vmd/virtio.h +++ usr.sbin/vmd/virtio.h @@ -358,7 +358,6 @@ struct virtio_dev { uint64_t driver_feature; /* driver features [rw] */ uint8_t pci_id; /* pci device id [r] */ - uint32_t vm_id; /* vmm(4) vm identifier [r] */ int irq; /* assigned irq [r] */ /* Multi-process emulation fields. */ @@ -368,7 +367,8 @@ struct virtio_dev { int sync_fd; /* fd for synchronous channel */ int async_fd; /* fd for async channel */ - uint32_t vm_vmid; /* vmd(8) vm identifier [r] */ + uint32_t vm_id; /* vmd(8) vm identifier [r] */ + uint32_t vmm_id; /* vmm(4) vm identifier [r] */ pid_t dev_pid; /* pid of emulator process */ char dev_type; /* device type (as char) */ SLIST_ENTRY(virtio_dev) dev_next; blob - b971c4688b4e47fc5bfe4ad8a26b1cdf2834a8af blob + 58bafe332a92f318fec6e82289dd4205fb46b5bc --- usr.sbin/vmd/vm.c +++ usr.sbin/vmd/vm.c @@ -44,7 +44,7 @@ #define MMIO_NOTYET 0 -static int run_vm(struct vmop_create_params *, struct vcpu_reg_state *); +static int run_vm(struct vmd_vm *, struct vcpu_reg_state *); static void vm_dispatch_vmm(int, short, void *); static void *event_thread(void *); static void *vcpu_run_loop(void *); @@ -82,7 +82,6 @@ uint8_t vcpu_done[VMM_MAX_VCPUS_PER_VM]; void vm_main(int fd, int fd_vmm) { - struct vm_create_params *vcp = NULL; struct vmd_vm vm; size_t sz = 0; int ret = 0; @@ -118,9 +117,8 @@ vm_main(int fd, int fd_vmm) } /* Update process with the vm name. */ - vcp = &vm.vm_params.vmc_params; - setproctitle("%s", vcp->vcp_name); - log_procinit("vm/%s", vcp->vcp_name); + setproctitle("%s", vm.vm_params.vmc_name); + log_procinit("vm/%s", vm.vm_params.vmc_name); /* Receive the local prefix settings. */ sz = atomicio(read, fd, &env->vmd_cfg.cfg_localprefix, @@ -135,11 +133,11 @@ vm_main(int fd, int fd_vmm) * kernel or a BIOS image. */ if (vm.vm_kernel == -1) { - log_warnx("%s: failed to receive boot fd", vcp->vcp_name); + log_warnx("failed to receive boot fd"); _exit(EINVAL); } - if (vcp->vcp_sev && env->vmd_psp_fd < 0) { + if (vm.vm_params.vmc_sev && env->vmd_psp_fd < 0) { log_warnx("%s not available", PSP_NODE); _exit(EINVAL); } @@ -173,18 +171,15 @@ vm_main(int fd, int fd_vmm) int start_vm(struct vmd_vm *vm, int fd) { - struct vmop_create_params *vmc = &vm->vm_params; - struct vm_create_params *vcp = &vmc->vmc_params; struct vcpu_reg_state vrs; - int nicfds[VM_MAX_NICS_PER_VM]; - int ret; + int ret, nicfds[VM_MAX_NICS_PER_VM]; size_t i; /* * We first try to initialize and allocate memory before bothering * vmm(4) with a request to create a new vm. */ - create_memory_map(vcp); + create_memory_map(vm); /* Create the vm in vmm(4). */ ret = vmm_create_vm(vm); @@ -201,8 +196,8 @@ start_vm(struct vmd_vm *vm, int fd) } /* Let the vmm process know we failed by sending a 0 vm id. */ - vcp->vcp_id = 0; - atomicio(vwrite, fd, &vcp->vcp_id, sizeof(vcp->vcp_id)); + vm->vm_vmmid = 0; + atomicio(vwrite, fd, &vm->vm_vmmid, sizeof(vm->vm_vmmid)); return (ret); } @@ -227,8 +222,8 @@ start_vm(struct vmd_vm *vm, int fd) * We now let the vmm process know we were successful by sending it our * vmm(4) assigned vm id. */ - if (atomicio(vwrite, fd, &vcp->vcp_id, sizeof(vcp->vcp_id)) != - sizeof(vcp->vcp_id)) { + if (atomicio(vwrite, fd, &vm->vm_vmmid, sizeof(vm->vm_vmmid)) != + sizeof(vm->vm_vmmid)) { log_warn("failed to send created vm id to vmm process"); return (1); } @@ -276,7 +271,7 @@ start_vm(struct vmd_vm *vm, int fd) */ for (i = 0; i < VMM_MAX_NICS_PER_VM; i++) nicfds[i] = vm->vm_ifs[i].vif_fd; - ret = init_emulated_hw(vmc, vm->vm_cdrom, vm->vm_disks, nicfds); + ret = init_emulated_hw(vm, vm->vm_cdrom, vm->vm_disks, nicfds); if (ret) { virtio_shutdown(vm); return (ret); @@ -289,7 +284,7 @@ start_vm(struct vmd_vm *vm, int fd) /* * Execute the vcpu run loop(s) for this VM. */ - ret = run_vm(&vm->vm_params, &vrs); + ret = run_vm(vm, &vrs); /* Shutdown SEV. */ if (sev_shutdown(vm)) @@ -383,14 +378,14 @@ vm_dispatch_vmm(int fd, short event, void *arg) case IMSG_VMDOP_PRIV_GET_ADDR_RESPONSE: vmop_addr_result_read(&imsg, &var); log_debug("%s: received tap addr %s for nic %d", - vm->vm_params.vmc_params.vcp_name, + vm->vm_params.vmc_name, ether_ntoa((void *)var.var_addr), var.var_nic_idx); vionet_set_hostmac(vm, var.var_nic_idx, var.var_addr); break; default: fatalx("%s: got invalid imsg %d from %s", __func__, - type, vm->vm_params.vmc_params.vcp_name); + type, vm->vm_params.vmc_name); } imsg_free(&imsg); } @@ -440,7 +435,7 @@ pause_vm(struct vmd_vm *vm) current_vm->vm_state |= VM_STATE_PAUSED; mutex_unlock(&vm_mtx); - for (n = 0; n < vm->vm_params.vmc_params.vcp_ncpus; n++) { + for (n = 0; n < vm->vm_params.vmc_ncpus; n++) { ret = pthread_cond_broadcast(&vcpu_run_cond[n]); if (ret) { log_warnx("%s: can't broadcast vcpu run cond (%d)", @@ -472,7 +467,7 @@ unpause_vm(struct vmd_vm *vm) current_vm->vm_state &= ~VM_STATE_PAUSED; mutex_unlock(&vm_mtx); - for (n = 0; n < vm->vm_params.vmc_params.vcp_ncpus; n++) { + for (n = 0; n < vm->vm_params.vmc_ncpus; n++) { ret = pthread_cond_broadcast(&vcpu_unpause_cond[n]); if (ret) { log_warnx("%s: can't broadcast vcpu unpause cond (%d)", @@ -535,44 +530,54 @@ vcpu_reset(uint32_t vmid, uint32_t vcpu_id, struct vcp static int vmm_create_vm(struct vmd_vm *vm) { - struct vm_create_params *vcp = &vm->vm_params.vmc_params; - size_t i; + struct vm_create_params vcp; + struct vmop_create_params *vmc = &vm->vm_params; + size_t i; /* Sanity check arguments */ - if (vcp->vcp_ncpus > VMM_MAX_VCPUS_PER_VM) + if (vmc->vmc_ncpus > VMM_MAX_VCPUS_PER_VM) return (EINVAL); - if (vcp->vcp_nmemranges == 0 || - vcp->vcp_nmemranges > VMM_MAX_MEM_RANGES) + if (vmc->vmc_nmemranges == 0 || + vmc->vmc_nmemranges > VMM_MAX_MEM_RANGES) return (EINVAL); - if (vm->vm_params.vmc_ndisks > VM_MAX_DISKS_PER_VM) + if (vmc->vmc_ndisks > VM_MAX_DISKS_PER_VM) return (EINVAL); - if (vm->vm_params.vmc_nnics > VM_MAX_NICS_PER_VM) + if (vmc->vmc_nnics > VM_MAX_NICS_PER_VM) return (EINVAL); - if (ioctl(env->vmd_fd, VMM_IOC_CREATE, vcp) == -1) + memset(&vcp, 0, sizeof(vcp)); + vcp.vcp_nmemranges = vmc->vmc_nmemranges; + vcp.vcp_ncpus = vmc->vmc_ncpus; + memcpy(vcp.vcp_memranges, vmc->vmc_memranges, + sizeof(vcp.vcp_memranges)); + memcpy(vcp.vcp_name, vmc->vmc_name, sizeof(vcp.vcp_name)); + vcp.vcp_sev = vmc->vmc_sev; + vcp.vcp_seves = vmc->vmc_seves; + + if (ioctl(env->vmd_fd, VMM_IOC_CREATE, &vcp) == -1) return (errno); - for (i = 0; i < vcp->vcp_ncpus; i++) - vm->vm_sev_asid[i] = vcp->vcp_asid[i]; + vm->vm_vmmid = vcp.vcp_id; + for (i = 0; i < vcp.vcp_ncpus; i++) + vm->vm_sev_asid[i] = vcp.vcp_asid[i]; + for (i = 0; i < vmc->vmc_nmemranges; i++) + vmc->vmc_memranges[i].vmr_va = vcp.vcp_memranges[i].vmr_va; + vm->vm_poscbit = vcp.vcp_poscbit; return (0); } - /* +/* * run_vm * * Runs the VM whose creation parameters are specified in vcp * * Parameters: - * child_cdrom: previously-opened child ISO disk file descriptor - * child_disks: previously-opened child VM disk file file descriptors - * child_taps: previously-opened child tap file descriptors - * vmc: vmop_create_params struct containing the VM's desired creation - * configuration + * vm: vm to begin emulating * vrs: VCPU register state to initialize * * Return values: @@ -580,9 +585,9 @@ vmm_create_vm(struct vmd_vm *vm) * !0 : the VM exited abnormally or failed to start */ static int -run_vm(struct vmop_create_params *vmc, struct vcpu_reg_state *vrs) +run_vm(struct vmd_vm *vm, struct vcpu_reg_state *vrs) { - struct vm_create_params *vcp = &vmc->vmc_params; + struct vmop_create_params *vmc; uint8_t evdone = 0; size_t i; int ret; @@ -591,32 +596,31 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg struct vm_run_params **vrp; void *exit_status; - if (vcp == NULL) - return (EINVAL); + vmc = &vm->vm_params; - if (vcp->vcp_nmemranges == 0 || - vcp->vcp_nmemranges > VMM_MAX_MEM_RANGES) + if (vmc->vmc_nmemranges == 0 || + vmc->vmc_nmemranges > VMM_MAX_MEM_RANGES) return (EINVAL); - tid = calloc(vcp->vcp_ncpus, sizeof(pthread_t)); + tid = calloc(vmc->vmc_ncpus, sizeof(pthread_t)); if (tid == NULL) { log_warn("failed to allocate pthread structures"); return (ENOMEM); } - vrp = calloc(vcp->vcp_ncpus, sizeof(struct vm_run_params *)); + vrp = calloc(vmc->vmc_ncpus, sizeof(struct vm_run_params *)); if (vrp == NULL) { log_warn("failed to allocate vm run params array"); return (ENOMEM); } - ret = pthread_barrier_init(&vm_pause_barrier, NULL, vcp->vcp_ncpus + 1); + ret = pthread_barrier_init(&vm_pause_barrier, NULL, vmc->vmc_ncpus + 1); if (ret) { log_warnx("cannot initialize pause barrier (%d)", ret); return (ret); } log_debug("%s: starting %zu vcpu thread(s) for vm %s", __func__, - vcp->vcp_ncpus, vcp->vcp_name); + vmc->vmc_ncpus, vmc->vmc_name); /* * Create and launch one thread for each VCPU. These threads may @@ -624,7 +628,7 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg * in such situations is detected and performed by vmm(4) in the * kernel. */ - for (i = 0 ; i < vcp->vcp_ncpus; i++) { + for (i = 0 ; i < vmc->vmc_ncpus; i++) { vrp[i] = malloc(sizeof(struct vm_run_params)); if (vrp[i] == NULL) { log_warn("failed to allocate vm run parameters"); @@ -637,30 +641,30 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg /* caller will exit, so skip freeing */ return (ENOMEM); } - vrp[i]->vrp_vm_id = vcp->vcp_id; + vrp[i]->vrp_vm_id = vm->vm_vmmid; vrp[i]->vrp_vcpu_id = i; - if (vcpu_reset(vcp->vcp_id, i, vrs)) { + if (vcpu_reset(vm->vm_vmmid, i, vrs)) { log_warnx("cannot reset vcpu %zu", i); return (EIO); } - if (sev_activate(current_vm, i)) { + if (sev_activate(vm, i)) { log_warnx("SEV activatation failed for vcpu %zu", i); return (EIO); } - if (sev_encrypt_memory(current_vm)) { + if (sev_encrypt_memory(vm)) { log_warnx("memory encryption failed for vcpu %zu", i); return (EIO); } - if (sev_encrypt_state(current_vm, i)) { + if (sev_encrypt_state(vm, i)) { log_warnx("state encryption failed for vcpu %zu", i); return (EIO); } - if (sev_launch_finalize(current_vm)) { + if (sev_launch_finalize(vm)) { log_warnx("encryption failed for vcpu %zu", i); return (EIO); } @@ -705,7 +709,7 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg pthread_set_name_np(tid[i], tname); } - log_debug("%s: waiting on events for VM %s", __func__, vcp->vcp_name); + log_debug("%s: waiting on events for VM %s", __func__, vmc->vmc_name); ret = pthread_create(&evtid, NULL, event_thread, &evdone); if (ret) { errno = ret; @@ -726,7 +730,7 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg * Did a VCPU thread exit with an error? => return the first one */ mutex_lock(&vm_mtx); - for (i = 0; i < vcp->vcp_ncpus; i++) { + for (i = 0; i < vmc->vmc_ncpus; i++) { if (vcpu_done[i] == 0) continue; @@ -747,19 +751,18 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg return (EIO); } - log_warnx("vm %d event thread exited unexpectedly", - vcp->vcp_id); + log_warnx("event thread exited unexpectedly"); return (EIO); } /* Did all VCPU threads exit successfully? => return */ mutex_lock(&vm_mtx); - for (i = 0; i < vcp->vcp_ncpus; i++) { + for (i = 0; i < vmc->vmc_ncpus; i++) { if (vcpu_done[i] == 0) break; } mutex_unlock(&vm_mtx); - if (i == vcp->vcp_ncpus) + if (i == vmc->vmc_ncpus) break; /* Some more threads to wait for, start over */ @@ -928,13 +931,13 @@ vcpu_run_loop(void *arg) } int -vcpu_intr(uint32_t vm_id, uint32_t vcpu_id, uint8_t intr) +vcpu_intr(uint32_t vmm_id, uint32_t vcpu_id, uint8_t intr) { struct vm_intr_params vip; memset(&vip, 0, sizeof(vip)); - vip.vip_vm_id = vm_id; + vip.vip_vm_id = vmm_id; vip.vip_vcpu_id = vcpu_id; /* XXX always 0? */ vip.vip_intr = intr; @@ -1096,7 +1099,6 @@ int remap_guest_mem(struct vmd_vm *vm, int vmm_fd) { size_t i; - struct vm_create_params *vcp = &vm->vm_params.vmc_params; struct vm_sharemem_params vsp; if (vm == NULL) @@ -1104,9 +1106,9 @@ remap_guest_mem(struct vmd_vm *vm, int vmm_fd) /* Initialize using our original creation parameters. */ memset(&vsp, 0, sizeof(vsp)); - vsp.vsp_nmemranges = vcp->vcp_nmemranges; - vsp.vsp_vm_id = vcp->vcp_id; - memcpy(&vsp.vsp_memranges, &vcp->vcp_memranges, + vsp.vsp_nmemranges = vm->vm_params.vmc_nmemranges; + vsp.vsp_vm_id = vm->vm_vmmid; + memcpy(&vsp.vsp_memranges, &vm->vm_params.vmc_memranges, sizeof(vsp.vsp_memranges)); /* Ask vmm(4) to enter a shared mapping to guest memory. */ @@ -1115,7 +1117,7 @@ remap_guest_mem(struct vmd_vm *vm, int vmm_fd) /* Update with the location of the new mappings. */ for (i = 0; i < vsp.vsp_nmemranges; i++) - vcp->vcp_memranges[i].vmr_va = vsp.vsp_va[i]; + vm->vm_params.vmc_memranges[i].vmr_va = vsp.vsp_va[i]; return (0); } blob - 13b7ccf9ef324f6e99f85974d6e51024b8fee28d blob + 9b6f58ded8cd0c8c41f993255f677cde2094e771 --- usr.sbin/vmd/vm_agentx.c +++ usr.sbin/vmd/vm_agentx.c @@ -183,14 +183,14 @@ vm_agentx_dispatch_parent(int fd, struct privsep_proc vmIndex); rtype = agentx_varbind_request(vminfo[i]); for (j = 0; j < nvir; j++) { - if (vir[j].vir_info.vir_id < index) + if (vir[j].vir_id < index) continue; - if (vir[j].vir_info.vir_id == index && + if (vir[j].vir_id == index && (rtype == AGENTX_REQUEST_TYPE_GET || rtype == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)) break; - if (vir[j].vir_info.vir_id > index && + if (vir[j].vir_id > index && (rtype == AGENTX_REQUEST_TYPE_GETNEXT || rtype == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)) @@ -202,10 +202,10 @@ vm_agentx_dispatch_parent(int fd, struct privsep_proc } mvir = &(vir[j]); agentx_varbind_set_index_integer(vminfo[i], vmIndex, - mvir->vir_info.vir_id); + mvir->vir_id); if (reqObject == vmName) agentx_varbind_string(vminfo[i], - mvir->vir_info.vir_name); + mvir->vir_name); else if (reqObject == vmUUID) agentx_varbind_string(vminfo[i], ""); else if (reqObject == vmOSType) @@ -228,17 +228,17 @@ vm_agentx_dispatch_parent(int fd, struct privsep_proc reqObject == vmMinCpuNumber || reqObject == vmMaxCpuNumber) agentx_varbind_integer(vminfo[i], - mvir->vir_info.vir_ncpus); + mvir->vir_ncpus); else if (reqObject == vmMemUnit) agentx_varbind_integer(vminfo[i], MEM_SCALE); else if (reqObject == vmCurMem) agentx_varbind_integer(vminfo[i], - mvir->vir_info.vir_used_size / MEM_SCALE); + mvir->vir_used_size / MEM_SCALE); else if (reqObject == vmMinMem) agentx_varbind_integer(vminfo[i], -1); else if (reqObject == vmMaxMem) agentx_varbind_integer(vminfo[i], - mvir->vir_info.vir_memory_size / MEM_SCALE); + mvir->vir_memory_size / MEM_SCALE); /* We probably had a reload */ else agentx_varbind_notfound(vminfo[i]); @@ -433,8 +433,7 @@ vm_agentx_sortvir(const void *c1, const void *c2) { const struct vmop_info_result *v1 = c1, *v2 = c2; - return (v1->vir_info.vir_id < v2->vir_info.vir_id ? -1 : - v1->vir_info.vir_id > v2->vir_info.vir_id); + return (v1->vir_id < v2->vir_id ? -1 : v1->vir_id > v2->vir_id); } static int blob - f69738bbe98955b73c542519f0d822d527101a26 blob + de3cfa7cf57999ad863e939dd93fb73138ed6a89 --- usr.sbin/vmd/vmd.c +++ usr.sbin/vmd/vmd.c @@ -283,8 +283,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc { struct vmop_result vmr; struct privsep *ps = p->p_ps; - struct vmd_vm *vm; - struct vm_create_params *vcp; + struct vmd_vm *vm = NULL; struct vmop_info_result vir; uint32_t peer_id, type; @@ -299,7 +298,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc proc_compose_imsg(ps, PROC_CONTROL, type, vm->vm_peerid, -1, &vmr, sizeof(vmr)); log_info("%s: paused vm %d successfully", - vm->vm_params.vmc_params.vcp_name, vm->vm_vmid); + vm->vm_params.vmc_name, vm->vm_vmid); vm->vm_state |= VM_STATE_PAUSED; break; case IMSG_VMDOP_UNPAUSE_VM_RESPONSE: @@ -309,7 +308,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc proc_compose_imsg(ps, PROC_CONTROL, type, vm->vm_peerid, -1, &vmr, sizeof(vmr)); log_info("%s: unpaused vm %d successfully.", - vm->vm_params.vmc_params.vcp_name, vm->vm_vmid); + vm->vm_params.vmc_name, vm->vm_vmid); vm->vm_state &= ~VM_STATE_PAUSED; break; case IMSG_VMDOP_START_VM_RESPONSE: @@ -317,8 +316,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc if ((vm = vm_getbyvmid(vmr.vmr_id)) == NULL) break; vm->vm_pid = vmr.vmr_pid; - vcp = &vm->vm_params.vmc_params; - vcp->vcp_id = vmr.vmr_id; + vm->vm_vmmid = vmr.vmr_id; /* * If the peerid is not -1, forward the response back to the @@ -332,14 +330,15 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc vm->vm_peerid, -1, &vmr, sizeof(vmr)) == -1) { errno = vmr.vmr_result; log_warn("%s: failed to forward vm result", - vcp->vcp_name); + vm->vm_params.vmc_name); vm_terminate(vm, __func__); return (-1); } } if (vmr.vmr_result) { - log_warnx("%s: failed to start vm", vcp->vcp_name); + log_warnx("%s: failed to start vm", + vm->vm_params.vmc_name); vm_terminate(vm, __func__); errno = vmr.vmr_result; break; @@ -347,13 +346,14 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc /* Now configure all the interfaces */ if (vm_priv_ifconfig(ps, vm) == -1) { - log_warn("%s: failed to configure vm", vcp->vcp_name); + log_warn("%s: failed to configure vm", + vm->vm_params.vmc_name); vm_terminate(vm, __func__); break; } log_info("started %s (vm %d) successfully, tty %s", - vcp->vcp_name, vm->vm_vmid, vm->vm_ttyname); + vm->vm_params.vmc_name, vm->vm_vmid, vm->vm_ttyname); break; case IMSG_VMDOP_TERMINATE_VM_RESPONSE: vmop_result_read(imsg, &vmr); @@ -397,7 +397,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc break; case IMSG_VMDOP_GET_INFO_VM_DATA: vmop_info_result_read(imsg, &vir); - if ((vm = vm_getbyvmid(vir.vir_info.vir_id)) != NULL) { + if ((vm = vm_getbyvmid(vir.vir_id)) != NULL) { memset(vir.vir_ttyname, 0, sizeof(vir.vir_ttyname)); if (vm->vm_ttyname[0] != '\0') strlcpy(vir.vir_ttyname, vm->vm_ttyname, @@ -426,15 +426,12 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) { if (!(vm->vm_state & VM_STATE_RUNNING)) { memset(&vir, 0, sizeof(vir)); - vir.vir_info.vir_id = vm->vm_vmid; - strlcpy(vir.vir_info.vir_name, - vm->vm_params.vmc_params.vcp_name, - VMM_MAX_NAME_LEN); - vir.vir_info.vir_memory_size = - vm->vm_params.vmc_params. - vcp_memranges[0].vmr_size; - vir.vir_info.vir_ncpus = - vm->vm_params.vmc_params.vcp_ncpus; + vir.vir_id = vm->vm_vmid; + strlcpy(vir.vir_name, vm->vm_params.vmc_name, + sizeof(vir.vir_name)); + vir.vir_memory_size = + vm->vm_params.vmc_memranges[0].vmr_size; + vir.vir_ncpus = vm->vm_params.vmc_ncpus; /* get the configured user id for this vm */ vir.vir_uid = vm->vm_params.vmc_owner.uid; vir.vir_gid = vm->vm_params.vmc_owner.gid; @@ -748,8 +745,7 @@ start_vm_batch(int fd, short type, void *args) TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) { if (!(vm->vm_state & VM_STATE_WAITING)) { log_debug("%s: not starting vm %s (disabled)", - __func__, - vm->vm_params.vmc_params.vcp_name); + __func__, vm->vm_params.vmc_name); continue; } i++; @@ -944,13 +940,14 @@ vm_getbyvmid(uint32_t vmid) if (vmid == 0) return (NULL); TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) { - if (vm->vm_vmid == vmid) + if (vm->vm_vmid == vmid) // XXX check this return (vm); } return (NULL); } +/* Find a vm in the list by it's vmm(4) id. */ struct vmd_vm * vm_getbyid(uint32_t id) { @@ -959,13 +956,14 @@ vm_getbyid(uint32_t id) if (id == 0) return (NULL); TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) { - if (vm->vm_params.vmc_params.vcp_id == id) + if (vm->vm_vmmid == id) // XXX check this return (vm); } return (NULL); } +/* Translate a kernel/vmm(4) vm id to a vmd(8) id. */ uint32_t vm_id2vmid(uint32_t id, struct vmd_vm *vm) { @@ -981,9 +979,8 @@ vm_vmid2id(uint32_t vmid, struct vmd_vm *vm) { if (vm == NULL && (vm = vm_getbyvmid(vmid)) == NULL) return (0); - DPRINTF("%s: vmid %u is vmm id %u", __func__, - vmid, vm->vm_params.vmc_params.vcp_id); - return (vm->vm_params.vmc_params.vcp_id); + DPRINTF("%s: vmid %u is vmm id %u", __func__, vmid, vm->vm_vmmid); + return (vm->vm_vmmid); } struct vmd_vm * @@ -994,7 +991,7 @@ vm_getbyname(const char *name) if (name == NULL) return (NULL); TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) { - if (strcmp(vm->vm_params.vmc_params.vcp_name, name) == 0) + if (strcmp(vm->vm_params.vmc_name, name) == 0) return (vm); } @@ -1123,7 +1120,6 @@ vm_register(struct privsep *ps, struct vmop_create_par struct vmd_vm **ret_vm, uint32_t id, uid_t uid) { struct vmd_vm *vm = NULL, *vm_parent = NULL; - struct vm_create_params *vcp = &vmc->vmc_params; struct vmop_owner *vmo = NULL; uint32_t nid, rng; unsigned int i, j; @@ -1140,8 +1136,8 @@ vm_register(struct privsep *ps, struct vmop_create_par errno = 0; *ret_vm = NULL; - if ((vm = vm_getbyname(vcp->vcp_name)) != NULL || - (vm = vm_getbyvmid(vcp->vcp_id)) != NULL) { + if ((vm = vm_getbyname(vmc->vmc_name)) != NULL || + (vm = vm_getbyvmid(vmc->vmc_id)) != NULL) { if (vm_checkperm(vm, &vm->vm_params.vmc_owner, uid) != 0) { errno = EPERM; @@ -1167,11 +1163,11 @@ vm_register(struct privsep *ps, struct vmop_create_par errno = VMD_DISK_MISSING; goto fail; } - if (vcp->vcp_ncpus == 0) - vcp->vcp_ncpus = 1; - if (vcp->vcp_memranges[0].vmr_size == 0) - vcp->vcp_memranges[0].vmr_size = VM_DEFAULT_MEMORY; - if (vcp->vcp_ncpus > VMM_MAX_VCPUS_PER_VM) { + if (vmc->vmc_ncpus == 0) + vmc->vmc_ncpus = 1; + if (vmc->vmc_memranges[0].vmr_size == 0) + vmc->vmc_memranges[0].vmr_size = VM_DEFAULT_MEMORY; + if (vmc->vmc_ncpus > VMM_MAX_VCPUS_PER_VM) { log_warnx("invalid number of CPUs"); goto fail; } else if (vmc->vmc_ndisks > VM_MAX_DISKS_PER_VM) { @@ -1184,15 +1180,15 @@ vm_register(struct privsep *ps, struct vmop_create_par && strlen(vmc->vmc_cdrom) == 0) { log_warnx("no kernel or disk/cdrom specified"); goto fail; - } else if (strlen(vcp->vcp_name) == 0) { + } else if (strlen(vmc->vmc_name) == 0) { log_warnx("invalid VM name"); goto fail; - } else if (*vcp->vcp_name == '-' || *vcp->vcp_name == '.' || - *vcp->vcp_name == '_') { + } else if (*vmc->vmc_name == '-' || *vmc->vmc_name == '.' || + *vmc->vmc_name == '_') { log_warnx("invalid VM name"); goto fail; } else { - for (s = vcp->vcp_name; *s != '\0'; ++s) { + for (s = vmc->vmc_name; *s != '\0'; ++s) { if (!(isalnum((unsigned char)*s) || *s == '.' || \ *s == '-' || *s == '_')) { log_warnx("invalid VM name"); @@ -1206,7 +1202,6 @@ vm_register(struct privsep *ps, struct vmop_create_par memcpy(&vm->vm_params, vmc, sizeof(vm->vm_params)); vmc = &vm->vm_params; - vcp = &vmc->vmc_params; vm->vm_pid = -1; vm->vm_tty = -1; vm->vm_kernel = -1; @@ -1252,7 +1247,7 @@ vm_register(struct privsep *ps, struct vmop_create_par */ if (id != 0) vm->vm_vmid = id; - else if (vm_claimid(vcp->vcp_name, uid, &nid) == -1) + else if (vm_claimid(vmc->vmc_name, uid, &nid) == -1) goto fail; else vm->vm_vmid = nid; @@ -1272,69 +1267,63 @@ int vm_instance(struct privsep *ps, struct vmd_vm **vm_parent, struct vmop_create_params *vmc, uid_t uid) { - char *name; - struct vm_create_params *vcp = &vmc->vmc_params; - struct vmop_create_params *vmcp; - struct vm_create_params *vcpp; - unsigned int i, j; + char *name; + struct vmop_create_params *vmc_parent; + unsigned int i, j; /* return without error if the parent is NULL (nothing to inherit) */ if ((vmc->vmc_flags & VMOP_CREATE_INSTANCE) == 0 || vmc->vmc_instance[0] == '\0') return (0); - if ((*vm_parent = vm_getbyname(vmc->vmc_instance)) == NULL) { + if ((*vm_parent = vm_getbyname(vmc->vmc_instance)) == NULL) return (VMD_PARENT_INVALID); - } - vmcp = &(*vm_parent)->vm_params; - vcpp = &vmcp->vmc_params; + vmc_parent = &(*vm_parent)->vm_params; /* Are we allowed to create an instance from this VM? */ - if (vm_checkperm(NULL, &vmcp->vmc_insowner, uid) != 0) { + if (vm_checkperm(NULL, &vmc_parent->vmc_insowner, uid) != 0) { log_warnx("vm \"%s\" no permission to create vm instance", - vcpp->vcp_name); + vmc->vmc_name); return (ENAMETOOLONG); } - name = vcp->vcp_name; + name = vmc->vmc_name; - if (vm_getbyname(vcp->vcp_name) != NULL || - vm_getbyvmid(vcp->vcp_id) != NULL) { + if (vm_getbyname(name) != NULL || vm_getbyvmid(vmc->vmc_id) != NULL) return (EPROCLIM); - } /* CPU */ - if (vcp->vcp_ncpus == 0) - vcp->vcp_ncpus = vcpp->vcp_ncpus; - if (vm_checkinsflag(vmcp, VMOP_CREATE_CPU, uid) != 0 && - vcp->vcp_ncpus != vcpp->vcp_ncpus) { + if (vmc->vmc_ncpus == 0) + vmc->vmc_ncpus = vmc_parent->vmc_ncpus; + if (vm_checkinsflag(vmc_parent, VMOP_CREATE_CPU, uid) != 0 && + vmc->vmc_ncpus != vmc_parent->vmc_ncpus) { log_warnx("vm \"%s\" no permission to set cpus", name); return (EPERM); } /* memory */ - if (vcp->vcp_memranges[0].vmr_size == 0) - vcp->vcp_memranges[0].vmr_size = - vcpp->vcp_memranges[0].vmr_size; - if (vm_checkinsflag(vmcp, VMOP_CREATE_MEMORY, uid) != 0 && - vcp->vcp_memranges[0].vmr_size != - vcpp->vcp_memranges[0].vmr_size) { + if (vmc->vmc_memranges[0].vmr_size == 0) + vmc->vmc_memranges[0].vmr_size = + vmc_parent->vmc_memranges[0].vmr_size; + if (vm_checkinsflag(vmc_parent, VMOP_CREATE_MEMORY, uid) != 0 && + vmc->vmc_memranges[0].vmr_size != + vmc_parent->vmc_memranges[0].vmr_size) { log_warnx("vm \"%s\" no permission to set memory", name); return (EPERM); } /* disks cannot be inherited */ - if (vm_checkinsflag(vmcp, VMOP_CREATE_DISK, uid) != 0 && + if (vm_checkinsflag(vmc_parent, VMOP_CREATE_DISK, uid) != 0 && vmc->vmc_ndisks) { log_warnx("vm \"%s\" no permission to set disks", name); return (EPERM); } for (i = 0; i < vmc->vmc_ndisks; i++) { /* Check if this disk is already used in the parent */ - for (j = 0; j < vmcp->vmc_ndisks; j++) { + for (j = 0; j < vmc_parent->vmc_ndisks; j++) { if (strcmp(vmc->vmc_disks[i], - vmcp->vmc_disks[j]) == 0) { + vmc_parent->vmc_disks[j]) == 0) { log_warnx("vm \"%s\" disk %s cannot be reused", name, vmc->vmc_disks[i]); return (EBUSY); @@ -1345,34 +1334,34 @@ vm_instance(struct privsep *ps, struct vmd_vm **vm_par /* interfaces */ if (vmc->vmc_nnics > 0 && - vm_checkinsflag(vmcp, VMOP_CREATE_NETWORK, uid) != 0 && - vmc->vmc_nnics != vmcp->vmc_nnics) { + vm_checkinsflag(vmc_parent, VMOP_CREATE_NETWORK, uid) != 0 && + vmc->vmc_nnics != vmc_parent->vmc_nnics) { log_warnx("vm \"%s\" no permission to set interfaces", name); return (EPERM); } - for (i = 0; i < vmcp->vmc_nnics; i++) { + for (i = 0; i < vmc_parent->vmc_nnics; i++) { /* Interface got overwritten */ if (i < vmc->vmc_nnics) continue; /* Copy interface from parent */ - vmc->vmc_ifflags[i] = vmcp->vmc_ifflags[i]; - (void)strlcpy(vmc->vmc_ifnames[i], vmcp->vmc_ifnames[i], + vmc->vmc_ifflags[i] = vmc_parent->vmc_ifflags[i]; + (void)strlcpy(vmc->vmc_ifnames[i], vmc_parent->vmc_ifnames[i], sizeof(vmc->vmc_ifnames[i])); - (void)strlcpy(vmc->vmc_ifswitch[i], vmcp->vmc_ifswitch[i], + (void)strlcpy(vmc->vmc_ifswitch[i], vmc_parent->vmc_ifswitch[i], sizeof(vmc->vmc_ifswitch[i])); - (void)strlcpy(vmc->vmc_ifgroup[i], vmcp->vmc_ifgroup[i], + (void)strlcpy(vmc->vmc_ifgroup[i], vmc_parent->vmc_ifgroup[i], sizeof(vmc->vmc_ifgroup[i])); - memcpy(vmc->vmc_macs[i], vmcp->vmc_macs[i], + memcpy(vmc->vmc_macs[i], vmc_parent->vmc_macs[i], sizeof(vmc->vmc_macs[i])); - vmc->vmc_ifrdomain[i] = vmcp->vmc_ifrdomain[i]; + vmc->vmc_ifrdomain[i] = vmc_parent->vmc_ifrdomain[i]; vmc->vmc_nnics++; } for (i = 0; i < vmc->vmc_nnics; i++) { - for (j = 0; j < vmcp->vmc_nnics; j++) { + for (j = 0; j < vmc_parent->vmc_nnics; j++) { if (memcmp(zero_mac, vmc->vmc_macs[i], sizeof(vmc->vmc_macs[i])) != 0 && - memcmp(vmcp->vmc_macs[i], vmc->vmc_macs[i], + memcmp(vmc_parent->vmc_macs[i], vmc->vmc_macs[i], sizeof(vmc->vmc_macs[i])) != 0) { log_warnx("vm \"%s\" lladdr cannot be reused", name); @@ -1380,7 +1369,7 @@ vm_instance(struct privsep *ps, struct vmd_vm **vm_par } if (strlen(vmc->vmc_ifnames[i]) && strcmp(vmc->vmc_ifnames[i], - vmcp->vmc_ifnames[j]) == 0) { + vmc_parent->vmc_ifnames[j]) == 0) { log_warnx("vm \"%s\" %s cannot be reused", vmc->vmc_ifnames[i], name); return (EBUSY); @@ -1391,7 +1380,7 @@ vm_instance(struct privsep *ps, struct vmd_vm **vm_par /* kernel */ if (vmc->vmc_kernel > -1 || ((*vm_parent)->vm_kernel_path != NULL && strnlen((*vm_parent)->vm_kernel_path, PATH_MAX) < PATH_MAX)) { - if (vm_checkinsflag(vmcp, VMOP_CREATE_KERNEL, uid) != 0) { + if (vm_checkinsflag(vmc_parent, VMOP_CREATE_KERNEL, uid) != 0) { log_warnx("vm \"%s\" no permission to set boot image", name); return (EPERM); @@ -1401,12 +1390,12 @@ vm_instance(struct privsep *ps, struct vmd_vm **vm_par /* cdrom */ if (strlen(vmc->vmc_cdrom) > 0) { - if (vm_checkinsflag(vmcp, VMOP_CREATE_CDROM, uid) != 0) { + if (vm_checkinsflag(vmc_parent, VMOP_CREATE_CDROM, uid) != 0) { log_warnx("vm \"%s\" no permission to set cdrom", name); return (EPERM); } vmc->vmc_checkaccess |= VMOP_CREATE_CDROM; - } else if (strlcpy(vmc->vmc_cdrom, vmcp->vmc_cdrom, + } else if (strlcpy(vmc->vmc_cdrom, vmc_parent->vmc_cdrom, sizeof(vmc->vmc_cdrom)) >= sizeof(vmc->vmc_cdrom)) { log_warnx("vm \"%s\" cdrom name too long", name); return (EINVAL); @@ -1414,17 +1403,17 @@ vm_instance(struct privsep *ps, struct vmd_vm **vm_par /* user */ if (vmc->vmc_owner.uid == 0) - vmc->vmc_owner.uid = vmcp->vmc_owner.uid; + vmc->vmc_owner.uid = vmc_parent->vmc_owner.uid; else if (vmc->vmc_owner.uid != uid && - vmc->vmc_owner.uid != vmcp->vmc_owner.uid) { + vmc->vmc_owner.uid != vmc_parent->vmc_owner.uid) { log_warnx("vm \"%s\" user mismatch", name); return (EPERM); } /* group */ if (vmc->vmc_owner.gid == 0) - vmc->vmc_owner.gid = vmcp->vmc_owner.gid; - else if (vmc->vmc_owner.gid != vmcp->vmc_owner.gid) { + vmc->vmc_owner.gid = vmc_parent->vmc_owner.gid; + else if (vmc->vmc_owner.gid != vmc_parent->vmc_owner.gid) { log_warnx("vm \"%s\" group mismatch", name); return (EPERM); } @@ -1434,10 +1423,10 @@ vm_instance(struct privsep *ps, struct vmd_vm **vm_par log_warnx("vm \"%s\" cannot change instance permissions", name); return (EPERM); } - if (vmcp->vmc_insflags & VMOP_CREATE_INSTANCE) { - vmc->vmc_insowner.gid = vmcp->vmc_insowner.gid; - vmc->vmc_insowner.uid = vmcp->vmc_insowner.gid; - vmc->vmc_insflags = vmcp->vmc_insflags; + if (vmc_parent->vmc_insflags & VMOP_CREATE_INSTANCE) { + vmc->vmc_insowner.gid = vmc_parent->vmc_insowner.gid; + vmc->vmc_insowner.uid = vmc_parent->vmc_insowner.gid; + vmc->vmc_insflags = vmc_parent->vmc_insflags; } else { vmc->vmc_insowner.gid = 0; vmc->vmc_insowner.uid = 0; @@ -1647,9 +1636,8 @@ vm_opentty(struct vmd_vm *vm) gid = 0; } - log_debug("%s: vm %s tty %s uid %d gid %d mode %o", - __func__, vm->vm_params.vmc_params.vcp_name, - vm->vm_ttyname, uid, gid, mode); + log_debug("%s: vm %s tty %s uid %d gid %d mode %o", __func__, + vm->vm_params.vmc_name, vm->vm_ttyname, uid, gid, mode); /* * Change ownership and mode of the tty as required. @@ -1825,14 +1813,10 @@ vmop_result_read(struct imsg *imsg, struct vmop_result void vmop_info_result_read(struct imsg *imsg, struct vmop_info_result *vir) { - struct vm_info_result *r; - if (imsg_get_data(imsg, vir, sizeof(*vir))) fatal("%s", __func__); - r = &vir->vir_info; - r->vir_name[sizeof(r->vir_name) - 1] = '\0'; - + vir->vir_name[sizeof(vir->vir_name) - 1] = '\0'; vir->vir_ttyname[sizeof(vir->vir_ttyname) - 1] = '\0'; } @@ -1879,14 +1863,12 @@ vmop_owner_read(struct imsg *imsg, struct vmop_owner * void vmop_create_params_read(struct imsg *imsg, struct vmop_create_params *vmc) { - struct vm_create_params *vcp; size_t i, n; if (imsg_get_data(imsg, vmc, sizeof(*vmc))) fatal("%s", __func__); - vcp = &vmc->vmc_params; - vcp->vcp_name[sizeof(vcp->vcp_name) - 1] = '\0'; + vmc->vmc_name[sizeof(vmc->vmc_name) - 1] = '\0'; n = sizeof(vmc->vmc_disks) / sizeof(vmc->vmc_disks[0]); for (i = 0; i < n; i++) blob - f0f5a9bccf9fc12a2ebb55c4fe31efd0a00f8105 blob + 37bdefb911c61464e11f6119ea2519ef777b1a8e --- usr.sbin/vmd/vmd.h +++ usr.sbin/vmd/vmd.h @@ -159,7 +159,14 @@ struct vmop_result { }; struct vmop_info_result { - struct vm_info_result vir_info; + size_t vir_memory_size; + size_t vir_used_size; + size_t vir_ncpus; + uint8_t vir_vcpu_state[VMM_MAX_VCPUS_PER_VM]; + pid_t vir_creator_pid; + uint32_t vir_id; + char vir_name[VMM_MAX_NAME_LEN]; + char vir_ttyname[VM_TTYNAME_MAX]; uid_t vir_uid; int64_t vir_gid; @@ -200,7 +207,11 @@ struct vmop_owner { }; struct vmop_create_params { - struct vm_create_params vmc_params; + /* vm identifying information */ + uint32_t vmc_id; + char vmc_name[VMM_MAX_NAME_LEN]; + struct vmop_owner vmc_owner; + unsigned int vmc_flags; #define VMOP_CREATE_CPU 0x01 #define VMOP_CREATE_KERNEL 0x02 @@ -209,42 +220,53 @@ struct vmop_create_params { #define VMOP_CREATE_DISK 0x10 #define VMOP_CREATE_CDROM 0x20 #define VMOP_CREATE_INSTANCE 0x40 - - /* same flags; check for access to these resources */ + /* same flags as vmc_flags; check for access to these resources */ unsigned int vmc_checkaccess; - /* userland-only part of the create params */ + /* vcpu count and features */ + size_t vmc_ncpus; + uint32_t vmc_asid[VMM_MAX_VCPUS]; + + /* AMD SEV support */ + uint32_t vmc_poscbit; + int vmc_sev; + int vmc_seves; + + /* guest memory */ + size_t vmc_nmemranges; + struct vm_mem_range vmc_memranges[VMM_MAX_MEM_RANGES]; + + /* Boot device and firmware */ + int vmc_kernel; unsigned int vmc_bootdevice; #define VMBOOTDEV_AUTO 0 #define VMBOOTDEV_DISK 1 #define VMBOOTDEV_CDROM 2 #define VMBOOTDEV_NET 3 - unsigned int vmc_ifflags[VM_MAX_NICS_PER_VM]; -#define VMIFF_UP 0x01 -#define VMIFF_LOCKED 0x02 -#define VMIFF_LOCAL 0x04 -#define VMIFF_RDOMAIN 0x08 -#define VMIFF_OPTMASK (VMIFF_LOCKED|VMIFF_LOCAL|VMIFF_RDOMAIN) + /* Emulated disk and cdrom drives */ size_t vmc_ndisks; char vmc_disks[VM_MAX_DISKS_PER_VM][PATH_MAX]; unsigned int vmc_disktypes[VM_MAX_DISKS_PER_VM]; unsigned int vmc_diskbases[VM_MAX_DISKS_PER_VM]; #define VMDF_RAW 0x01 #define VMDF_QCOW2 0x02 - char vmc_cdrom[PATH_MAX]; - int vmc_kernel; + /* Emulated network devices */ size_t vmc_nnics; char vmc_ifnames[VM_MAX_NICS_PER_VM][IF_NAMESIZE]; char vmc_ifswitch[VM_MAX_NICS_PER_VM][VM_NAME_MAX]; char vmc_ifgroup[VM_MAX_NICS_PER_VM][IF_NAMESIZE]; unsigned int vmc_ifrdomain[VM_MAX_NICS_PER_VM]; uint8_t vmc_macs[VM_MAX_NICS_PER_VM][6]; + unsigned int vmc_ifflags[VM_MAX_NICS_PER_VM]; +#define VMIFF_UP 0x01 +#define VMIFF_LOCKED 0x02 +#define VMIFF_LOCAL 0x04 +#define VMIFF_RDOMAIN 0x08 +#define VMIFF_OPTMASK (VMIFF_LOCKED|VMIFF_LOCAL|VMIFF_RDOMAIN) - struct vmop_owner vmc_owner; - /* instance template params */ char vmc_instance[VMM_MAX_NAME_LEN]; struct vmop_owner vmc_insowner; @@ -275,11 +297,18 @@ TAILQ_HEAD(switchlist, vmd_switch); struct vmd_vm { struct vmop_create_params vm_params; + + /* Owner and identifier information */ pid_t vm_pid; - uint32_t vm_vmid; + uid_t vm_uid; + uint32_t vm_vmid; /* vmd(8) identifier */ + uint32_t vm_vmmid; /* vmm(4) identifier */ + uint32_t vm_peerid; + + /* AMD SEV features */ uint32_t vm_sev_handle; uint32_t vm_sev_asid[VMM_MAX_VCPUS_PER_VM]; - + uint32_t vm_poscbit; #define VM_SEV_NSEGMENTS 128 size_t vm_sev_nmemsegments; struct vm_mem_range vm_sev_memsegments[VM_SEV_NSEGMENTS]; @@ -287,16 +316,18 @@ struct vmd_vm { int vm_kernel; char *vm_kernel_path; /* Used by vm.conf. */ + /* Device and disk image file descriptors */ int vm_cdrom; int vm_disks[VM_MAX_DISKS_PER_VM][VM_MAX_BASE_PER_DISK]; struct vmd_if vm_ifs[VM_MAX_NICS_PER_VM]; + + /* Serial port */ char vm_ttyname[VM_TTYNAME_MAX]; int vm_tty; - uint32_t vm_peerid; + /* When set, VM was defined in a config file */ int vm_from_config; struct imsgev vm_iev; - uid_t vm_uid; unsigned int vm_state; /* When set, VM is running now (PROC_PARENT only) */ #define VM_STATE_RUNNING 0x01 @@ -484,16 +515,16 @@ int fd_hasdata(int); int vmm_pipe(struct vmd_vm *, int, void (*)(int, short, void *)); /* {mach}_vm.c (md interface) */ -void create_memory_map(struct vm_create_params *); +void create_memory_map(struct vmd_vm *); int load_firmware(struct vmd_vm *, struct vcpu_reg_state *); -int init_emulated_hw(struct vmop_create_params *, int, - int[][VM_MAX_BASE_PER_DISK], int *); +int init_emulated_hw(struct vmd_vm *, int, int[][VM_MAX_BASE_PER_DISK], + int *); int vcpu_reset(uint32_t, uint32_t, struct vcpu_reg_state *); void pause_vm_md(struct vmd_vm *); void unpause_vm_md(struct vmd_vm *); void *hvaddr_mem(paddr_t, size_t); struct vm_mem_range * - find_gpa_range(struct vm_create_params *, paddr_t, size_t); + find_gpa_range(struct vmop_create_params *, paddr_t, size_t); int write_mem(paddr_t, const void *, size_t); int read_mem(paddr_t, void *, size_t); int intr_ack(struct vmd_vm *); blob - 51d6e406d1d924a3750f4aa62bd12fdeba2c2e50 blob + 5892156f831aa8d6cb03c981cb32e51cede4b6b1 --- usr.sbin/vmd/vmm.c +++ usr.sbin/vmd/vmm.c @@ -317,7 +317,6 @@ vmm_sighdlr(int sig, short event, void *arg) { struct privsep *ps = arg; int status, ret = 0; - uint32_t vmid; pid_t pid; struct vmop_result vmr; struct vmd_vm *vm; @@ -350,18 +349,18 @@ vmm_sighdlr(int sig, short event, void *arg) (vm->vm_state & VM_STATE_SHUTDOWN)) ret = 0; - vmid = vm->vm_params.vmc_params.vcp_id; - vtp.vtp_vm_id = vmid; + /* XXX check this */ + vtp.vtp_vm_id = vm->vm_vmmid; if (terminate_vm(&vtp) == 0) log_debug("%s: terminated vm %s" " (id %d)", __func__, - vm->vm_params.vmc_params.vcp_name, + vm->vm_params.vmc_name, vm->vm_vmid); memset(&vmr, 0, sizeof(vmr)); vmr.vmr_result = ret; - vmr.vmr_id = vm_id2vmid(vmid, vm); + vmr.vmr_id = vm_id2vmid(vm->vm_vmmid, vm); if (proc_compose_imsg(ps, PROC_PARENT, IMSG_VMDOP_TERMINATE_VM_EVENT, vm->vm_peerid, -1, &vmr, sizeof(vmr)) == -1) @@ -497,7 +496,7 @@ vmm_dispatch_vm(int fd, short event, void *arg) default: fatalx("%s: got invalid imsg %d from %s", __func__, - type, vm->vm_params.vmc_params.vcp_name); + type, vm->vm_params.vmc_name); } imsg_free(&imsg); } @@ -588,7 +587,6 @@ opentap(char *ifname) int vmm_start_vm(struct imsg *imsg, uint32_t *id, pid_t *pid) { - struct vm_create_params *vcp; struct vmd_vm *vm; char *nargv[10], num[32], vmm_fd[32], psp_fd[32]; int fd, ret = EINVAL; @@ -602,14 +600,12 @@ vmm_start_vm(struct imsg *imsg, uint32_t *id, pid_t *p log_warnx("%s: can't find vm", __func__); return (ENOENT); } - vcp = &vm->vm_params.vmc_params; if ((vm->vm_tty = imsg_get_fd(imsg)) == -1) { log_warnx("%s: can't get tty", __func__); goto err; } - if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC, fds) == -1) fatal("socketpair"); @@ -631,7 +627,7 @@ vmm_start_vm(struct imsg *imsg, uint32_t *id, pid_t *p sz = atomicio(vwrite, fds[0], vm, sizeof(*vm)); if (sz != sizeof(*vm)) { log_warnx("%s: failed to send config for vm '%s'", - __func__, vcp->vcp_name); + __func__, vm->vm_params.vmc_name); ret = EIO; /* Defer error handling until after fd closing. */ } @@ -663,26 +659,27 @@ vmm_start_vm(struct imsg *imsg, uint32_t *id, pid_t *p sizeof(env->vmd_cfg.cfg_localprefix)); if (sz != sizeof(env->vmd_cfg.cfg_localprefix)) { log_warnx("%s: failed to send local prefix for vm '%s'", - __func__, vcp->vcp_name); + __func__, vm->vm_params.vmc_name); ret = EIO; goto err; } /* Read back the kernel-generated vm id from the child */ - sz = atomicio(read, fds[0], &vcp->vcp_id, sizeof(vcp->vcp_id)); - if (sz != sizeof(vcp->vcp_id)) { + sz = atomicio(read, fds[0], &vm->vm_vmmid, + sizeof(vm->vm_vmmid)); + if (sz != sizeof(vm->vm_vmmid)) { log_debug("%s: failed to receive vm id from vm %s", - __func__, vcp->vcp_name); + __func__, vm->vm_params.vmc_name); /* vmd could not allocate memory for the vm. */ ret = ENOMEM; goto err; } /* Check for an invalid id. This indicates child failure. */ - if (vcp->vcp_id == 0) + if (vm->vm_vmmid == 0) goto err; - *id = vcp->vcp_id; + *id = vm->vm_vmmid; *pid = vm->vm_pid; /* Wire up our pipe into the event handling. */ @@ -828,8 +825,17 @@ get_info_vm(struct privsep *ps, struct imsg *imsg, int info[i].vir_name, info[i].vir_id); continue; } - memcpy(&vir.vir_info, &info[i], sizeof(vir.vir_info)); - vir.vir_info.vir_id = vm_id2vmid(info[i].vir_id, NULL); + + /* XXX */ + vir.vir_memory_size = info[i].vir_memory_size; + vir.vir_used_size = info[i].vir_used_size; + vir.vir_ncpus = info[i].vir_ncpus; + memcpy(vir.vir_vcpu_state, info[i].vir_vcpu_state, + sizeof(vir.vir_vcpu_state)); + vir.vir_creator_pid = info[i].vir_creator_pid; + vir.vir_id = vm_id2vmid(info[i].vir_id, NULL); + memcpy(vir.vir_name, info[i].vir_name, sizeof(vir.vir_name)); + peer_id = imsg_get_id(imsg); if (proc_compose_imsg(ps, PROC_PARENT, blob - ff02fd9a3515d05cfd468280230c3731e687bbbb blob + 403f0b1ec4a58ffeb7b65ee32fa2cb4a5e7f6a8a --- usr.sbin/vmd/x86_vm.c +++ usr.sbin/vmd/x86_vm.c @@ -47,7 +47,6 @@ typedef uint8_t (*io_fn_t)(struct vm_run_params *); io_fn_t ioports_map[MAX_PORTS]; -void create_memory_map(struct vm_create_params *); int translate_gva(struct vm_exit*, uint64_t, uint64_t *, int); static int loadfile_bios(gzFile, off_t, struct vcpu_reg_state *); @@ -148,30 +147,24 @@ static const struct vcpu_reg_state vcpu_init_flat16 = * create_memory_map * * Sets up the guest physical memory ranges that the VM can access. - * - * Parameters: - * vcp: VM create parameters describing the VM whose memory map - * is being created - * - * Return values: - * nothing */ void -create_memory_map(struct vm_create_params *vcp) +create_memory_map(struct vmd_vm *vm) { + struct vmop_create_params *vmc = &vm->vm_params; size_t len, mem_bytes; size_t above_1m = 0, above_4g = 0; - mem_bytes = vcp->vcp_memranges[0].vmr_size; - vcp->vcp_nmemranges = 0; + mem_bytes = vmc->vmc_memranges[0].vmr_size; + vmc->vmc_nmemranges = 0; if (mem_bytes == 0 || mem_bytes > VMM_MAX_VM_MEM_SIZE) return; /* First memory region: 0 - LOWMEM_KB (DOS low mem) */ len = LOWMEM_KB * 1024; - vcp->vcp_memranges[0].vmr_gpa = 0x0; - vcp->vcp_memranges[0].vmr_size = len; - vcp->vcp_memranges[0].vmr_type = VM_MEM_RAM; + vmc->vmc_memranges[0].vmr_gpa = 0x0; + vmc->vmc_memranges[0].vmr_size = len; + vmc->vmc_memranges[0].vmr_type = VM_MEM_RAM; mem_bytes -= len; /* @@ -184,9 +177,9 @@ create_memory_map(struct vm_create_params *vcp) * to it. So allocate guest memory for it. */ len = MB(1) - (LOWMEM_KB * 1024); - vcp->vcp_memranges[1].vmr_gpa = LOWMEM_KB * 1024; - vcp->vcp_memranges[1].vmr_size = len; - vcp->vcp_memranges[1].vmr_type = VM_MEM_RESERVED; + vmc->vmc_memranges[1].vmr_gpa = LOWMEM_KB * 1024; + vmc->vmc_memranges[1].vmr_size = len; + vmc->vmc_memranges[1].vmr_type = VM_MEM_RESERVED; mem_bytes -= len; /* @@ -194,10 +187,10 @@ create_memory_map(struct vm_create_params *vcp) * BIOS area. */ if (mem_bytes <= MB(4)) { - vcp->vcp_memranges[2].vmr_gpa = PCI_MMIO_BAR_END; - vcp->vcp_memranges[2].vmr_size = MB(4); - vcp->vcp_memranges[2].vmr_type = VM_MEM_RESERVED; - vcp->vcp_nmemranges = 3; + vmc->vmc_memranges[2].vmr_gpa = PCI_MMIO_BAR_END; + vmc->vmc_memranges[2].vmr_size = MB(4); + vmc->vmc_memranges[2].vmr_type = VM_MEM_RESERVED; + vmc->vmc_nmemranges = 3; return; } @@ -215,29 +208,29 @@ create_memory_map(struct vm_create_params *vcp) } /* Third memory region: area above 1MB to MMIO region */ - vcp->vcp_memranges[2].vmr_gpa = MB(1); - vcp->vcp_memranges[2].vmr_size = above_1m; - vcp->vcp_memranges[2].vmr_type = VM_MEM_RAM; + vmc->vmc_memranges[2].vmr_gpa = MB(1); + vmc->vmc_memranges[2].vmr_size = above_1m; + vmc->vmc_memranges[2].vmr_type = VM_MEM_RAM; /* Fourth region: PCI MMIO range */ - vcp->vcp_memranges[3].vmr_gpa = PCI_MMIO_BAR_BASE; - vcp->vcp_memranges[3].vmr_size = PCI_MMIO_BAR_END - + vmc->vmc_memranges[3].vmr_gpa = PCI_MMIO_BAR_BASE; + vmc->vmc_memranges[3].vmr_size = PCI_MMIO_BAR_END - PCI_MMIO_BAR_BASE + 1; - vcp->vcp_memranges[3].vmr_type = VM_MEM_MMIO; + vmc->vmc_memranges[3].vmr_type = VM_MEM_MMIO; /* Fifth region: 2nd copy of BIOS above MMIO ending at 4GB */ - vcp->vcp_memranges[4].vmr_gpa = PCI_MMIO_BAR_END + 1; - vcp->vcp_memranges[4].vmr_size = MB(4); - vcp->vcp_memranges[4].vmr_type = VM_MEM_RESERVED; + vmc->vmc_memranges[4].vmr_gpa = PCI_MMIO_BAR_END + 1; + vmc->vmc_memranges[4].vmr_size = MB(4); + vmc->vmc_memranges[4].vmr_type = VM_MEM_RESERVED; /* Sixth region: any remainder above 4GB */ if (above_4g > 0) { - vcp->vcp_memranges[5].vmr_gpa = GB(4); - vcp->vcp_memranges[5].vmr_size = above_4g; - vcp->vcp_memranges[5].vmr_type = VM_MEM_RAM; - vcp->vcp_nmemranges = 6; + vmc->vmc_memranges[5].vmr_gpa = GB(4); + vmc->vmc_memranges[5].vmr_size = above_4g; + vmc->vmc_memranges[5].vmr_type = VM_MEM_RAM; + vmc->vmc_nmemranges = 6; } else - vcp->vcp_nmemranges = 5; + vmc->vmc_nmemranges = 5; } int @@ -353,28 +346,28 @@ loadfile_bios(gzFile fp, off_t size, struct vcpu_reg_s * Returns 0 on success, 1 on failure. */ int -init_emulated_hw(struct vmop_create_params *vmc, int child_cdrom, +init_emulated_hw(struct vmd_vm *vm, int child_cdrom, int child_disks[][VM_MAX_BASE_PER_DISK], int *child_taps) { - struct vm_create_params *vcp = &vmc->vmc_params; + struct vmop_create_params *vmc = &vm->vm_params; size_t i; uint64_t memlo, memhi; /* Calculate memory size for NVRAM registers */ memlo = memhi = 0; - for (i = 0; i < vcp->vcp_nmemranges; i++) { - if (vcp->vcp_memranges[i].vmr_gpa == MB(1) && - vcp->vcp_memranges[i].vmr_size > (15 * MB(1))) - memlo = vcp->vcp_memranges[i].vmr_size - (15 * MB(1)); - else if (vcp->vcp_memranges[i].vmr_gpa == GB(4)) - memhi = vcp->vcp_memranges[i].vmr_size; + for (i = 0; i < vmc->vmc_nmemranges; i++) { + if (vmc->vmc_memranges[i].vmr_gpa == MB(1) && + vmc->vmc_memranges[i].vmr_size > (15 * MB(1))) + memlo = vmc->vmc_memranges[i].vmr_size - (15 * MB(1)); + else if (vmc->vmc_memranges[i].vmr_gpa == GB(4)) + memhi = vmc->vmc_memranges[i].vmr_size; } /* Reset the IO port map */ memset(&ioports_map, 0, sizeof(io_fn_t) * MAX_PORTS); /* Init i8253 PIT */ - i8253_init(vcp->vcp_id); + i8253_init(vm->vm_vmmid); ioports_map[TIMER_CTRL] = vcpu_exit_i8253; ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253; ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253; @@ -382,7 +375,7 @@ init_emulated_hw(struct vmop_create_params *vmc, int c ioports_map[PCKBC_AUX] = vcpu_exit_i8253_misc; /* Init mc146818 RTC */ - mc146818_init(vcp->vcp_id, memlo, memhi); + mc146818_init(vm->vm_vmmid, memlo, memhi); ioports_map[IO_RTC] = vcpu_exit_mc146818; ioports_map[IO_RTC + 1] = vcpu_exit_mc146818; @@ -396,7 +389,7 @@ init_emulated_hw(struct vmop_create_params *vmc, int c ioports_map[ELCR1] = vcpu_exit_elcr; /* Init ns8250 UART */ - ns8250_init(con_fd, vcp->vcp_id); + ns8250_init(con_fd, vm->vm_vmmid); for (i = COM1_DATA; i <= COM1_SCR; i++) ioports_map[i] = vcpu_exit_com; @@ -697,20 +690,20 @@ vcpu_exit_pci(struct vm_run_params *vrp) * Pointer to vm_mem_range that contains the start of the range otherwise. */ struct vm_mem_range * -find_gpa_range(struct vm_create_params *vcp, paddr_t gpa, size_t len) +find_gpa_range(struct vmop_create_params *vmc, paddr_t gpa, size_t len) { size_t i, n; struct vm_mem_range *vmr; /* Find the first vm_mem_range that contains gpa */ - for (i = 0; i < vcp->vcp_nmemranges; i++) { - vmr = &vcp->vcp_memranges[i]; + for (i = 0; i < vmc->vmc_nmemranges; i++) { + vmr = &vmc->vmc_memranges[i]; if (gpa < vmr->vmr_gpa + vmr->vmr_size) break; } /* No range found. */ - if (i == vcp->vcp_nmemranges) + if (i == vmc->vmc_nmemranges) return (NULL); /* @@ -724,8 +717,8 @@ find_gpa_range(struct vm_create_params *vcp, paddr_t g else len -= n; gpa = vmr->vmr_gpa + vmr->vmr_size; - for (i = i + 1; len != 0 && i < vcp->vcp_nmemranges; i++) { - vmr = &vcp->vcp_memranges[i]; + for (i = i + 1; len != 0 && i < vmc->vmc_nmemranges; i++) { + vmr = &vmc->vmc_memranges[i]; if (gpa != vmr->vmr_gpa) return (NULL); if (len <= vmr->vmr_size) @@ -764,7 +757,7 @@ write_mem(paddr_t dst, const void *buf, size_t len) size_t n, off; struct vm_mem_range *vmr; - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, dst, len); + vmr = find_gpa_range(¤t_vm->vm_params, dst, len); if (vmr == NULL) { errno = EINVAL; log_warn("%s: failed - invalid memory range dst = 0x%lx, " @@ -815,7 +808,7 @@ read_mem(paddr_t src, void *buf, size_t len) size_t n, off; struct vm_mem_range *vmr; - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, src, len); + vmr = find_gpa_range(¤t_vm->vm_params, src, len); if (vmr == NULL) { errno = EINVAL; log_warn("%s: failed - invalid memory range src = 0x%lx, " @@ -864,7 +857,7 @@ hvaddr_mem(paddr_t gpa, size_t len) struct vm_mem_range *vmr; size_t off; - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, gpa, len); + vmr = find_gpa_range(¤t_vm->vm_params, gpa, len); if (vmr == NULL) { log_warnx("%s: failed - invalid gpa: 0x%lx\n", __func__, gpa); errno = EFAULT; @@ -888,17 +881,17 @@ hvaddr_mem(paddr_t gpa, size_t len) * Injects the specified IRQ on the supplied vcpu/vm * * Parameters: - * vm_id: VM ID to inject to + * vm_id: VMM vm ID to inject to * vcpu_id: VCPU ID to inject to * irq: IRQ to inject */ void -vcpu_assert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) +vcpu_assert_irq(uint32_t vmm_id, uint32_t vcpu_id, int irq) { i8259_assert_irq(irq); if (i8259_is_pending()) { - if (vcpu_intr(vm_id, vcpu_id, 1)) + if (vcpu_intr(vmm_id, vcpu_id, 1)) fatalx("%s: can't assert INTR", __func__); vcpu_unhalt(vcpu_id); @@ -912,19 +905,19 @@ vcpu_assert_irq(uint32_t vm_id, uint32_t vcpu_id, int * Clears the specified IRQ on the supplied vcpu/vm * * Parameters: - * vm_id: VM ID to clear in + * vm_id: VMM vm ID to clear in * vcpu_id: VCPU ID to clear in * irq: IRQ to clear */ void -vcpu_deassert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) +vcpu_deassert_irq(uint32_t vmm_id, uint32_t vcpu_id, int irq) { i8259_deassert_irq(irq); if (!i8259_is_pending()) { - if (vcpu_intr(vm_id, vcpu_id, 0)) - fatalx("%s: can't deassert INTR for vm_id %d, " - "vcpu_id %d", __func__, vm_id, vcpu_id); + if (vcpu_intr(vmm_id, vcpu_id, 0)) + fatalx("%s: can't deassert INTR for vmm_id %d, " + "vcpu_id %d", __func__, vmm_id, vcpu_id); } }