Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Feb 2018 00:39:25 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r329768 - in head: lib/libvmmapi sys/amd64/include sys/amd64/vmm
Message-ID:  <201802220039.w1M0dP8d011632@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Feb 22 00:39:25 2018
New Revision: 329768
URL: https://svnweb.freebsd.org/changeset/base/329768

Log:
  Add two new ioctls to bhyve for batch register fetch/store operations.
  
  These are a convenience for bhyve's debug server to use a single
  ioctl for 'g' and 'G' rather than a loop of individual get/set
  ioctl requests.
  
  Reviewed by:	grehan
  MFC after:	2 months
  Differential Revision:	https://reviews.freebsd.org/D14074

Modified:
  head/lib/libvmmapi/vmmapi.c
  head/lib/libvmmapi/vmmapi.h
  head/sys/amd64/include/vmm_dev.h
  head/sys/amd64/vmm/vmm_dev.c

Modified: head/lib/libvmmapi/vmmapi.c
==============================================================================
--- head/lib/libvmmapi/vmmapi.c	Thu Feb 22 00:36:12 2018	(r329767)
+++ head/lib/libvmmapi/vmmapi.c	Thu Feb 22 00:39:25 2018	(r329768)
@@ -588,6 +588,40 @@ vm_get_register(struct vmctx *ctx, int vcpu, int reg, 
 }
 
 int
+vm_set_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
+    const int *regnums, uint64_t *regvals)
+{
+	int error;
+	struct vm_register_set vmregset;
+
+	bzero(&vmregset, sizeof(vmregset));
+	vmregset.cpuid = vcpu;
+	vmregset.count = count;
+	vmregset.regnums = regnums;
+	vmregset.regvals = regvals;
+
+	error = ioctl(ctx->fd, VM_SET_REGISTER_SET, &vmregset);
+	return (error);
+}
+
+int
+vm_get_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
+    const int *regnums, uint64_t *regvals)
+{
+	int error;
+	struct vm_register_set vmregset;
+
+	bzero(&vmregset, sizeof(vmregset));
+	vmregset.cpuid = vcpu;
+	vmregset.count = count;
+	vmregset.regnums = regnums;
+	vmregset.regvals = regvals;
+
+	error = ioctl(ctx->fd, VM_GET_REGISTER_SET, &vmregset);
+	return (error);
+}
+
+int
 vm_run(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit)
 {
 	int error;
@@ -1435,6 +1469,7 @@ vm_get_ioctls(size_t *len)
 	    VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
 	    VM_MMAP_GETNEXT, VM_SET_REGISTER, VM_GET_REGISTER,
 	    VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
+	    VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
 	    VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
 	    VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
 	    VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,

Modified: head/lib/libvmmapi/vmmapi.h
==============================================================================
--- head/lib/libvmmapi/vmmapi.h	Thu Feb 22 00:36:12 2018	(r329767)
+++ head/lib/libvmmapi/vmmapi.h	Thu Feb 22 00:39:25 2018	(r329768)
@@ -127,6 +127,10 @@ int	vm_get_seg_desc(struct vmctx *ctx, int vcpu, int r
 			struct seg_desc *seg_desc);
 int	vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val);
 int	vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *retval);
+int	vm_set_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
+    const int *regnums, uint64_t *regvals);
+int	vm_get_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
+    const int *regnums, uint64_t *regvals);
 int	vm_run(struct vmctx *ctx, int vcpu, struct vm_exit *ret_vmexit);
 int	vm_suspend(struct vmctx *ctx, enum vm_suspend_how how);
 int	vm_reinit(struct vmctx *ctx);

Modified: head/sys/amd64/include/vmm_dev.h
==============================================================================
--- head/sys/amd64/include/vmm_dev.h	Thu Feb 22 00:36:12 2018	(r329767)
+++ head/sys/amd64/include/vmm_dev.h	Thu Feb 22 00:39:25 2018	(r329768)
@@ -66,6 +66,13 @@ struct vm_seg_desc {			/* data or code segment */
 	struct seg_desc desc;
 };
 
+struct vm_register_set {
+	int		cpuid;
+	unsigned int	count;
+	const int	*regnums;	/* enum vm_reg_name */
+	uint64_t	*regvals;
+};
+
 struct vm_run {
 	int		cpuid;
 	struct vm_exit	vm_exit;
@@ -242,6 +249,8 @@ enum {
 	IOCNUM_GET_REGISTER = 21,
 	IOCNUM_SET_SEGMENT_DESCRIPTOR = 22,
 	IOCNUM_GET_SEGMENT_DESCRIPTOR = 23,
+	IOCNUM_SET_REGISTER_SET = 24,
+	IOCNUM_GET_REGISTER_SET = 25,
 
 	/* interrupt injection */
 	IOCNUM_GET_INTINFO = 28,
@@ -312,6 +321,10 @@ enum {
 	_IOW('v', IOCNUM_SET_SEGMENT_DESCRIPTOR, struct vm_seg_desc)
 #define	VM_GET_SEGMENT_DESCRIPTOR \
 	_IOWR('v', IOCNUM_GET_SEGMENT_DESCRIPTOR, struct vm_seg_desc)
+#define	VM_SET_REGISTER_SET \
+	_IOW('v', IOCNUM_SET_REGISTER_SET, struct vm_register_set)
+#define	VM_GET_REGISTER_SET \
+	_IOWR('v', IOCNUM_GET_REGISTER_SET, struct vm_register_set)
 #define	VM_INJECT_EXCEPTION	\
 	_IOW('v', IOCNUM_INJECT_EXCEPTION, struct vm_exception)
 #define	VM_LAPIC_IRQ 		\

Modified: head/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- head/sys/amd64/vmm/vmm_dev.c	Thu Feb 22 00:36:12 2018	(r329767)
+++ head/sys/amd64/vmm/vmm_dev.c	Thu Feb 22 00:39:25 2018	(r329768)
@@ -282,6 +282,36 @@ done:
 }
 
 static int
+vm_get_register_set(struct vm *vm, int vcpu, unsigned int count, int *regnum,
+    uint64_t *regval)
+{
+	int error, i;
+
+	error = 0;
+	for (i = 0; i < count; i++) {
+		error = vm_get_register(vm, vcpu, regnum[i], &regval[i]);
+		if (error)
+			break;
+	}
+	return (error);
+}
+
+static int
+vm_set_register_set(struct vm *vm, int vcpu, unsigned int count, int *regnum,
+    uint64_t *regval)
+{
+	int error, i;
+
+	error = 0;
+	for (i = 0; i < count; i++) {
+		error = vm_set_register(vm, vcpu, regnum[i], regval[i]);
+		if (error)
+			break;
+	}
+	return (error);
+}
+
+static int
 vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
 	     struct thread *td)
 {
@@ -290,6 +320,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t da
 	struct vmmdev_softc *sc;
 	struct vm_register *vmreg;
 	struct vm_seg_desc *vmsegdesc;
+	struct vm_register_set *vmregset;
 	struct vm_run *vmrun;
 	struct vm_exception *vmexc;
 	struct vm_lapic_irq *vmirq;
@@ -315,6 +346,8 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t da
 	struct vm_rtc_time *rtctime;
 	struct vm_rtc_data *rtcdata;
 	struct vm_memmap *mm;
+	uint64_t *regvals;
+	int *regnums;
 
 	sc = vmmdev_lookup2(cdev);
 	if (sc == NULL)
@@ -333,6 +366,8 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t da
 	case VM_SET_REGISTER:
 	case VM_GET_SEGMENT_DESCRIPTOR:
 	case VM_SET_SEGMENT_DESCRIPTOR:
+	case VM_GET_REGISTER_SET:
+	case VM_SET_REGISTER_SET:
 	case VM_INJECT_EXCEPTION:
 	case VM_GET_CAPABILITY:
 	case VM_SET_CAPABILITY:
@@ -545,6 +580,48 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t da
 		error = vm_get_seg_desc(sc->vm, vmsegdesc->cpuid,
 					vmsegdesc->regnum,
 					&vmsegdesc->desc);
+		break;
+	case VM_GET_REGISTER_SET:
+		vmregset = (struct vm_register_set *)data;
+		if (vmregset->count > VM_REG_LAST) {
+			error = EINVAL;
+			break;
+		}
+		regvals = malloc(sizeof(regvals[0]) * vmregset->count, M_VMMDEV,
+		    M_WAITOK);
+		regnums = malloc(sizeof(regnums[0]) * vmregset->count, M_VMMDEV,
+		    M_WAITOK);
+		error = copyin(vmregset->regnums, regnums, sizeof(regnums[0]) *
+		    vmregset->count);
+		if (error == 0)
+			error = vm_get_register_set(sc->vm, vmregset->cpuid,
+			    vmregset->count, regnums, regvals);
+		if (error == 0)
+			error = copyout(regvals, vmregset->regvals,
+			    sizeof(regvals[0]) * vmregset->count);
+		free(regvals, M_VMMDEV);
+		free(regnums, M_VMMDEV);
+		break;
+	case VM_SET_REGISTER_SET:
+		vmregset = (struct vm_register_set *)data;
+		if (vmregset->count > VM_REG_LAST) {
+			error = EINVAL;
+			break;
+		}
+		regvals = malloc(sizeof(regvals[0]) * vmregset->count, M_VMMDEV,
+		    M_WAITOK);
+		regnums = malloc(sizeof(regnums[0]) * vmregset->count, M_VMMDEV,
+		    M_WAITOK);
+		error = copyin(vmregset->regnums, regnums, sizeof(regnums[0]) *
+		    vmregset->count);
+		if (error == 0)
+			error = copyin(vmregset->regvals, regvals,
+			    sizeof(regvals[0]) * vmregset->count);
+		if (error == 0)
+			error = vm_set_register_set(sc->vm, vmregset->cpuid,
+			    vmregset->count, regnums, regvals);
+		free(regvals, M_VMMDEV);
+		free(regnums, M_VMMDEV);
 		break;
 	case VM_GET_CAPABILITY:
 		vmcap = (struct vm_capability *)data;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802220039.w1M0dP8d011632>