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 /lib/libvmmapi | |
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 'lib/libvmmapi')
-rw-r--r-- | lib/libvmmapi/vmmapi.c | 86 | ||||
-rw-r--r-- | lib/libvmmapi/vmmapi.h | 5 |
2 files changed, 91 insertions, 0 deletions
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 5e630f8..45fffcf 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mman.h> #include <machine/specialreg.h> +#include <machine/param.h> #include <stdio.h> #include <stdlib.h> @@ -937,3 +938,88 @@ vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities) *capabilities = cap.capabilities; return (error); } + +static int +vm_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging, + uint64_t gla, int prot, int *fault, uint64_t *gpa) +{ + struct vm_gla2gpa gg; + int error; + + bzero(&gg, sizeof(struct vm_gla2gpa)); + gg.vcpuid = vcpu; + gg.prot = prot; + gg.gla = gla; + gg.paging = *paging; + + error = ioctl(ctx->fd, VM_GLA2GPA, &gg); + if (error == 0) { + *fault = gg.fault; + *gpa = gg.gpa; + } + return (error); +} + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +int +vm_copyin(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging, + uint64_t gla, void *vp, size_t len) +{ + char *dst; + const char *src; + uint64_t gpa; + int error, fault, n, off; + + dst = vp; + while (len) { + error = vm_gla2gpa(ctx, vcpu, paging, gla, PROT_READ, + &fault, &gpa); + if (error) + return (-1); + if (fault) + return (1); + + off = gpa & PAGE_MASK; + n = min(len, PAGE_SIZE - off); + src = vm_map_gpa(ctx, gpa, n); + bcopy(src, dst, n); + + gla += n; + dst += n; + len -= n; + } + return (0); +} + +int +vm_copyout(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging, + const void *vp, uint64_t gla, size_t len) +{ + uint64_t gpa; + char *dst; + const char *src; + int error, fault, n, off; + + src = vp; + while (len) { + error = vm_gla2gpa(ctx, vcpu, paging, gla, PROT_WRITE, + &fault, &gpa); + if (error) + return (-1); + if (fault) + return (1); + + off = gpa & PAGE_MASK; + n = min(len, PAGE_SIZE - off); + dst = vm_map_gpa(ctx, gpa, n); + bcopy(src, dst, n); + + gla += n; + src += n; + len -= n; + } + return (0); +} diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index 88e9947..cad41c8 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -109,6 +109,11 @@ int vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state s); int vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities); +int vm_copyin(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging, + uint64_t gla_src, void *dst, size_t len); +int vm_copyout(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging, + const void *src, uint64_t gla_dst, size_t len); + /* Reset vcpu register state */ int vcpu_reset(struct vmctx *ctx, int vcpu); |