diff options
author | neel <neel@FreeBSD.org> | 2014-05-24 23:12:30 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-05-24 23:12:30 +0000 |
commit | 51a05acc08355b84ae16b193ccb7037691f8ba90 (patch) | |
tree | 6d3c6dd2e08177b036c0a323543c552eea67411c /sys/amd64 | |
parent | 75eadcdacf2b5f0dc80b3adb8f91fc71cb1c62cc (diff) | |
download | FreeBSD-src-51a05acc08355b84ae16b193ccb7037691f8ba90.zip FreeBSD-src-51a05acc08355b84ae16b193ccb7037691f8ba90.tar.gz |
Add libvmmapi functions vm_copyin() and vm_copyout() to copy into and out
of the guest linear address space. These APIs in turn use a new ioctl
'VM_GLA2GPA' to convert the guest linear address to guest physical.
Use the new copyin/copyout APIs when emulating ins/outs instruction in
bhyve(8).
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/include/vmm.h | 1 | ||||
-rw-r--r-- | sys/amd64/include/vmm_dev.h | 12 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_dev.c | 24 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_ioport.c | 16 |
4 files changed, 39 insertions, 14 deletions
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index 021efaf..28e2808 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -427,7 +427,6 @@ struct vm_inout_str { enum vm_reg_name seg_name; struct seg_desc seg_desc; uint64_t gla; /* may be set to VIE_INVALID_GLA */ - uint64_t gpa; }; struct vm_exit { diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h index ecafa9c..f094d51 100644 --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -168,6 +168,15 @@ struct vm_suspend { enum vm_suspend_how how; }; +struct vm_gla2gpa { + int vcpuid; /* inputs */ + int prot; /* PROT_READ or PROT_WRITE */ + uint64_t gla; + struct vm_guest_paging paging; + int fault; /* outputs */ + uint64_t gpa; +}; + enum { /* general routines */ IOCNUM_ABIVERS = 0, @@ -180,6 +189,7 @@ enum { IOCNUM_MAP_MEMORY = 10, IOCNUM_GET_MEMORY_SEG = 11, IOCNUM_GET_GPA_PMAP = 12, + IOCNUM_GLA2GPA = 13, /* register/state accessors */ IOCNUM_SET_REGISTER = 20, @@ -289,4 +299,6 @@ enum { _IOR('v', IOCNUM_GET_HPET_CAPABILITIES, struct vm_hpet_cap) #define VM_GET_GPA_PMAP \ _IOWR('v', IOCNUM_GET_GPA_PMAP, struct vm_gpa_pte) +#define VM_GLA2GPA \ + _IOWR('v', IOCNUM_GLA2GPA, struct vm_gla2gpa) #endif diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index f1d5795..0561785 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <machine/vmparam.h> #include <machine/vmm.h> +#include <machine/vmm_instruction_emul.h> #include <machine/vmm_dev.h> #include "vmm_lapic.h" @@ -168,6 +169,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, struct vm_x2apic *x2apic; struct vm_gpa_pte *gpapte; struct vm_suspend *vmsuspend; + struct vm_gla2gpa *gg; sc = vmmdev_lookup2(cdev); if (sc == NULL) @@ -192,6 +194,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, case VM_PPTDEV_MSI: case VM_PPTDEV_MSIX: case VM_SET_X2APIC_STATE: + case VM_GLA2GPA: /* * XXX fragile, handle with care * Assumes that the first field of the ioctl data is the vcpu. @@ -415,6 +418,27 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, case VM_GET_HPET_CAPABILITIES: error = vhpet_getcap((struct vm_hpet_cap *)data); break; + case VM_GLA2GPA: { + CTASSERT(PROT_READ == VM_PROT_READ); + CTASSERT(PROT_WRITE == VM_PROT_WRITE); + CTASSERT(PROT_EXEC == VM_PROT_EXECUTE); + gg = (struct vm_gla2gpa *)data; + error = vmm_gla2gpa(sc->vm, gg->vcpuid, &gg->paging, gg->gla, + gg->prot, &gg->gpa); + KASSERT(error == 0 || error == 1 || error == -1, + ("%s: vmm_gla2gpa unknown error %d", __func__, error)); + if (error >= 0) { + /* + * error = 0: the translation was successful + * error = 1: a fault was injected into the guest + */ + gg->fault = error; + error = 0; + } else { + error = EFAULT; + } + break; + } default: error = ENOTTY; break; diff --git a/sys/amd64/vmm/vmm_ioport.c b/sys/amd64/vmm/vmm_ioport.c index f9fda2d..96f2418 100644 --- a/sys/amd64/vmm/vmm_ioport.c +++ b/sys/amd64/vmm/vmm_ioport.c @@ -145,7 +145,7 @@ emulate_inout_str(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu) { struct vm_inout_str *vis; uint64_t gla, index, segbase; - int error, in; + int in; vis = &vmexit->u.inout_str; in = vis->inout.in; @@ -197,18 +197,8 @@ emulate_inout_str(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu) } vis->gla = gla; - error = vmm_gla2gpa(vm, vcpuid, &vis->paging, gla, - in ? VM_PROT_WRITE : VM_PROT_READ, &vis->gpa); - KASSERT(error == 0 || error == 1 || error == -1, - ("%s: vmm_gla2gpa unexpected error %d", __func__, error)); - if (error == -1) { - return (EFAULT); - } else if (error == 1) { - return (0); /* Resume guest to handle page fault */ - } else { - *retu = true; - return (0); /* Return to userspace to finish emulation */ - } + *retu = true; + return (0); /* Return to userspace to finish emulation */ } int |