summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpd <pd@cvs.openbsd.org>2019-07-17 05:51:08 +0000
committerpd <pd@cvs.openbsd.org>2019-07-17 05:51:08 +0000
commitb0fbf84b4b14aca5456de8ec175f740b26aa6ad4 (patch)
tree8817f23d489071b6014567888f2db3653e2cbd2e
parenteb035a8d91662acbd8d08a8c195ea92714cf46bc (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.c72
-rw-r--r--sys/arch/amd64/include/vmmvar.h20
-rw-r--r--usr.sbin/vmd/vm.c44
-rw-r--r--usr.sbin/vmd/vmd.h4
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;