diff options
author | pd <pd@cvs.openbsd.org> | 2019-07-17 05:51:08 +0000 |
---|---|---|
committer | pd <pd@cvs.openbsd.org> | 2019-07-17 05:51:08 +0000 |
commit | b0fbf84b4b14aca5456de8ec175f740b26aa6ad4 (patch) | |
tree | 8817f23d489071b6014567888f2db3653e2cbd2e | |
parent | eb035a8d91662acbd8d08a8c195ea92714cf46bc (diff) |
vmm/vmd: Fix migration with pvclock
Implement VMM_IOC_READVMPARAMS and VMM_IOC_WRITEVMPARAMS ioctls to read and
write pvclock state.
reads ok mlarkin@
-rw-r--r-- | sys/arch/amd64/amd64/vmm.c | 72 | ||||
-rw-r--r-- | sys/arch/amd64/include/vmmvar.h | 20 | ||||
-rw-r--r-- | usr.sbin/vmd/vm.c | 44 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.h | 4 |
4 files changed, 135 insertions, 5 deletions
diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index 3c5e45e6409..4dadb04bbf6 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.248 2019/07/08 19:57:11 mlarkin Exp $ */ +/* $OpenBSD: vmm.c,v 1.249 2019/07/17 05:51:07 pd Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> * @@ -124,6 +124,7 @@ int vm_get_info(struct vm_info_params *); int vm_resetcpu(struct vm_resetcpu_params *); int vm_intr_pending(struct vm_intr_params *); int vm_rwregs(struct vm_rwregs_params *, int); +int vm_rwvmparams(struct vm_rwvmparams_params *, int); int vm_find(uint32_t, struct vm **); int vcpu_readregs_vmx(struct vcpu *, uint64_t, struct vcpu_reg_state *); int vcpu_readregs_svm(struct vcpu *, uint64_t, struct vcpu_reg_state *); @@ -485,6 +486,13 @@ vmmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case VMM_IOC_WRITEREGS: ret = vm_rwregs((struct vm_rwregs_params *)data, 1); break; + case VMM_IOC_READVMPARAMS: + ret = vm_rwvmparams((struct vm_rwvmparams_params *)data, 0); + break; + case VMM_IOC_WRITEVMPARAMS: + ret = vm_rwvmparams((struct vm_rwvmparams_params *)data, 1); + break; + default: DPRINTF("%s: unknown ioctl code 0x%lx\n", __func__, cmd); ret = ENOTTY; @@ -516,6 +524,8 @@ pledge_ioctl_vmm(struct proc *p, long com) case VMM_IOC_INTR: case VMM_IOC_READREGS: case VMM_IOC_WRITEREGS: + case VMM_IOC_READVMPARAMS: + case VMM_IOC_WRITEVMPARAMS: return (0); } @@ -667,6 +677,66 @@ vm_intr_pending(struct vm_intr_params *vip) } /* + * vm_rwvmparams + * + * IOCTL handler to read/write the current vmm params like pvclock gpa, pvclock + * version, etc. + * + * Parameters: + * vrwp: Describes the VM and VCPU to get/set the params from + * dir: 0 for reading, 1 for writing + * + * Return values: + * 0: if successful + * ENOENT: if the VM/VCPU defined by 'vpp' cannot be found + * EINVAL: if an error occured reading the registers of the guest + */ +int +vm_rwvmparams(struct vm_rwvmparams_params *vpp, int dir) { + struct vm *vm; + struct vcpu *vcpu; + int error; + + /* Find the desired VM */ + rw_enter_read(&vmm_softc->vm_lock); + error = vm_find(vpp->vpp_vm_id, &vm); + + /* Not found? exit. */ + if (error != 0) { + rw_exit_read(&vmm_softc->vm_lock); + return (error); + } + + rw_enter_read(&vm->vm_vcpu_lock); + SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { + if (vcpu->vc_id == vpp->vpp_vcpu_id) + break; + } + rw_exit_read(&vm->vm_vcpu_lock); + rw_exit_read(&vmm_softc->vm_lock); + + if (vcpu == NULL) + return (ENOENT); + + if (dir == 0) { + if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_VERSION) + vpp->vpp_pvclock_version = vcpu->vc_pvclock_version; + if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA) + vpp->vpp_pvclock_system_gpa = \ + vcpu->vc_pvclock_system_gpa; + return (0); + } + + if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_VERSION) + vcpu->vc_pvclock_version = vpp->vpp_pvclock_version; + if (vpp->vpp_mask & VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA) { + vmm_init_pvclock(vcpu, vpp->vpp_pvclock_system_gpa); + } + return (0); + +} + +/* * vm_readregs * * IOCTL handler to read/write the current register values of a guest VCPU. diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h index e4df09f6f92..78c477291f2 100644 --- a/sys/arch/amd64/include/vmmvar.h +++ b/sys/arch/amd64/include/vmmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmmvar.h,v 1.66 2019/05/17 19:07:16 guenther Exp $ */ +/* $OpenBSD: vmmvar.h,v 1.67 2019/07/17 05:51:07 pd Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> * @@ -525,6 +525,20 @@ struct vm_intr_params { uint16_t vip_intr; }; +#define VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA 0x1 /* read/write pvclock gpa */ +#define VM_RWVMPARAMS_PVCLOCK_VERSION 0x2 /* read/write pvclock version */ +#define VM_RWVMPARAMS_ALL (VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA | \ + VM_RWVMPARAMS_PVCLOCK_VERSION) + +struct vm_rwvmparams_params { + /* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */ + uint32_t vpp_vm_id; + uint32_t vpp_vcpu_id; + uint32_t vpp_mask; + paddr_t vpp_pvclock_system_gpa; + uint32_t vpp_pvclock_version; +}; + #define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ #define VM_RWREGS_SREGS 0x2 /* read/write segment registers */ #define VM_RWREGS_CRS 0x4 /* read/write CRs */ @@ -553,6 +567,10 @@ struct vm_rwregs_params { #define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ #define VMM_IOC_READREGS _IOWR('V', 7, struct vm_rwregs_params) /* Get regs */ #define VMM_IOC_WRITEREGS _IOW('V', 8, struct vm_rwregs_params) /* Set regs */ +/* Get VM params */ +#define VMM_IOC_READVMPARAMS _IOWR('V', 9, struct vm_rwvmparams_params) +/* Set VM params */ +#define VMM_IOC_WRITEVMPARAMS _IOW('V', 10, struct vm_rwvmparams_params) /* CPUID masks */ diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index 16683af31cb..48776a74971 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm.c,v 1.50 2019/06/28 13:32:51 deraadt Exp $ */ +/* $OpenBSD: vm.c,v 1.51 2019/07/17 05:51:07 pd Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -90,6 +90,7 @@ int dump_vmr(int , struct vm_mem_range *); int dump_mem(int, struct vm_create_params *); void restore_vmr(int, struct vm_mem_range *); void restore_mem(int, struct vm_create_params *); +int restore_vm_params(int, struct vm_create_params *); void pause_vm(struct vm_create_params *); void unpause_vm(struct vm_create_params *); @@ -366,6 +367,8 @@ start_vm(struct vmd_vm *vm, int fd) vm->vm_disks, vm->vm_cdrom); mc146818_start(); restore_mem(vm->vm_receive_fd, vcp); + if (restore_vm_params(vm->vm_receive_fd, vcp)) + fatal("restore vm params failed"); } if (vmm_pipe(vm, fd, vm_dispatch_vmm) == -1) @@ -503,6 +506,7 @@ int send_vm(int fd, struct vm_create_params *vcp) { struct vm_rwregs_params vrp; + struct vm_rwvmparams_params vpp; struct vmop_create_params *vmc; struct vm_terminate_params vtp; unsigned int flags = 0; @@ -530,6 +534,8 @@ send_vm(int fd, struct vm_create_params *vcp) vmc->vmc_flags = flags; vrp.vrwp_vm_id = vcp->vcp_id; vrp.vrwp_mask = VM_RWREGS_ALL; + vpp.vpp_mask = VM_RWVMPARAMS_ALL; + vpp.vpp_vm_id = vcp->vcp_id; sz = atomicio(vwrite, fd, vmc,sizeof(struct vmop_create_params)); if (sz != sizeof(struct vmop_create_params)) { @@ -570,6 +576,22 @@ send_vm(int fd, struct vm_create_params *vcp) if ((ret = dump_mem(fd, vcp))) goto err; + for (i = 0; i < vcp->vcp_ncpus; i++) { + vpp.vpp_vcpu_id = i; + if ((ret = ioctl(env->vmd_fd, VMM_IOC_READVMPARAMS, &vpp))) { + log_warn("%s: readvmparams failed", __func__); + goto err; + } + + sz = atomicio(vwrite, fd, &vpp, + sizeof(struct vm_rwvmparams_params)); + if (sz != sizeof(struct vm_rwvmparams_params)) { + log_warn("%s: dumping vm params failed", __func__); + ret = -1; + goto err; + } + } + vtp.vtp_vm_id = vcp->vcp_id; if (ioctl(env->vmd_fd, VMM_IOC_TERM, &vtp) == -1) { log_warnx("%s: term IOC error: %d, %d", __func__, @@ -638,6 +660,26 @@ dump_mem(int fd, struct vm_create_params *vcp) return (0); } +int +restore_vm_params(int fd, struct vm_create_params *vcp) { + unsigned int i; + struct vm_rwvmparams_params vpp; + + for (i = 0; i < vcp->vcp_ncpus; i++) { + if (atomicio(read, fd, &vpp, sizeof(vpp)) != sizeof(vpp)) { + log_warn("%s: error restoring vm params", __func__); + return (-1); + } + vpp.vpp_vm_id = vcp->vcp_id; + vpp.vpp_vcpu_id = i; + if (ioctl(env->vmd_fd, VMM_IOC_WRITEVMPARAMS, &vpp) < 0) { + log_debug("%s: writing vm params failed", __func__); + return (-1); + } + } + return (0); +} + void restore_mem(int fd, struct vm_create_params *vcp) { diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 7e40b38f51d..2d848e5d37e 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.94 2019/05/11 23:07:46 jasper Exp $ */ +/* $OpenBSD: vmd.h,v 1.95 2019/07/17 05:51:07 pd Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -215,7 +215,7 @@ struct vm_dump_header { #define VM_DUMP_SIGNATURE VMM_HV_SIGNATURE uint8_t vmh_pad[3]; uint8_t vmh_version; -#define VM_DUMP_VERSION 6 +#define VM_DUMP_VERSION 7 struct vm_dump_header_cpuid vmh_cpuids[VM_DUMP_HEADER_CPUID_COUNT]; } __packed; |