svn commit: r329768 - in head: lib/libvmmapi sys/amd64/include sys/amd64/vmm
John Baldwin
jhb at FreeBSD.org
Thu Feb 22 00:39:27 UTC 2018
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], ®val[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;
More information about the svn-src-all
mailing list