summaryrefslogtreecommitdiffstats
path: root/lib/libvmmapi
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2014-07-22 04:39:16 +0000
committerjhb <jhb@FreeBSD.org>2014-07-22 04:39:16 +0000
commitce450da4301f9fcfa34afaa8d4e1b69a4877a2f7 (patch)
treee884913964691296030a1dcf7a5ec58905d567c2 /lib/libvmmapi
parentc1fe945ebd0d209b238eb98b47c40c115576f2e4 (diff)
downloadFreeBSD-src-ce450da4301f9fcfa34afaa8d4e1b69a4877a2f7.zip
FreeBSD-src-ce450da4301f9fcfa34afaa8d4e1b69a4877a2f7.tar.gz
MFC 266424,266476,266524,266573,266595,266626,266627,266633,266641,266642,
266708,266724,266934,266935,268521: Emulation of the "ins" and "outs" instructions. Various fixes for translating guest linear addresses to guest physical addresses.
Diffstat (limited to 'lib/libvmmapi')
-rw-r--r--lib/libvmmapi/vmmapi.c106
-rw-r--r--lib/libvmmapi/vmmapi.h13
2 files changed, 119 insertions, 0 deletions
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
index 5e630f8..ba2904c 100644
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -33,8 +33,10 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/_iovec.h>
#include <machine/specialreg.h>
+#include <machine/param.h>
#include <stdio.h>
#include <stdlib.h>
@@ -937,3 +939,107 @@ vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
*capabilities = cap.capabilities;
return (error);
}
+
+static int
+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_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
+ uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt)
+{
+ uint64_t gpa;
+ int error, fault, i, n, off;
+
+ for (i = 0; i < iovcnt; i++) {
+ iov[i].iov_base = 0;
+ iov[i].iov_len = 0;
+ }
+
+ while (len) {
+ assert(iovcnt > 0);
+ error = gla2gpa(ctx, vcpu, paging, gla, prot, &fault, &gpa);
+ if (error)
+ return (-1);
+ if (fault)
+ return (1);
+
+ off = gpa & PAGE_MASK;
+ n = min(len, PAGE_SIZE - off);
+
+ iov->iov_base = (void *)gpa;
+ iov->iov_len = n;
+ iov++;
+ iovcnt--;
+
+ gla += n;
+ len -= n;
+ }
+ return (0);
+}
+
+void
+vm_copyin(struct vmctx *ctx, int vcpu, struct iovec *iov, void *vp, size_t len)
+{
+ const char *src;
+ char *dst;
+ uint64_t gpa;
+ size_t n;
+
+ dst = vp;
+ while (len) {
+ assert(iov->iov_len);
+ gpa = (uint64_t)iov->iov_base;
+ n = min(len, iov->iov_len);
+ src = vm_map_gpa(ctx, gpa, n);
+ bcopy(src, dst, n);
+
+ iov++;
+ dst += n;
+ len -= n;
+ }
+}
+
+void
+vm_copyout(struct vmctx *ctx, int vcpu, const void *vp, struct iovec *iov,
+ size_t len)
+{
+ const char *src;
+ char *dst;
+ uint64_t gpa;
+ size_t n;
+
+ src = vp;
+ while (len) {
+ assert(iov->iov_len);
+ gpa = (uint64_t)iov->iov_base;
+ n = min(len, iov->iov_len);
+ dst = vm_map_gpa(ctx, gpa, n);
+ bcopy(src, dst, n);
+
+ iov++;
+ src += n;
+ len -= n;
+ }
+}
diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
index 88e9947..bab41da 100644
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -29,6 +29,7 @@
#ifndef _VMMAPI_H_
#define _VMMAPI_H_
+struct iovec;
struct vmctx;
enum x2apic_state;
@@ -109,6 +110,18 @@ 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);
+/*
+ * Translate the GLA range [gla,gla+len) into GPA segments in 'iov'.
+ * The 'iovcnt' should be big enough to accomodate all GPA segments.
+ * Returns 0 on success, 1 on a guest fault condition and -1 otherwise.
+ */
+int vm_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
+ uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt);
+void vm_copyin(struct vmctx *ctx, int vcpu, struct iovec *guest_iov,
+ void *host_dst, size_t len);
+void vm_copyout(struct vmctx *ctx, int vcpu, const void *host_src,
+ struct iovec *guest_iov, size_t len);
+
/* Reset vcpu register state */
int vcpu_reset(struct vmctx *ctx, int vcpu);
OpenPOWER on IntegriCloud