mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-22 07:20:00 +00:00
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
This commit is contained in:
parent
fa607d017d
commit
4f8666989a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329768
@ -587,6 +587,40 @@ vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
|
||||
return (error);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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,
|
||||
|
@ -127,6 +127,10 @@ int vm_get_seg_desc(struct vmctx *ctx, int vcpu, int reg,
|
||||
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);
|
||||
|
@ -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 \
|
||||
|
@ -281,6 +281,36 @@ alloc_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg)
|
||||
return (error);
|
||||
}
|
||||
|
||||
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 data, int fflag,
|
||||
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 data, int fflag,
|
||||
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 data, int fflag,
|
||||
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:
|
||||
@ -546,6 +581,48 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
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;
|
||||
error = vm_get_capability(sc->vm, vmcap->cpuid,
|
||||
|
Loading…
Reference in New Issue
Block a user