Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Several improvements and fixes:



details:   https://anonhg.NetBSD.org/src/rev/cb8c850fe438
branches:  trunk
changeset: 446971:cb8c850fe438
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu Dec 27 07:22:31 2018 +0000

description:
Several improvements and fixes:

 * Change the Assist API. Rather than passing callbacks in each call, the
   callbacks are now registered beforehand. Then change the I/O Assist to
   fetch MMIO data via the Mem callback. This allows a guest to perform an
   I/O string operation on a memory that is itself an MMIO.

 * Introduce two new functions internal to libnvmm, read_guest_memory and
   write_guest_memory. They can handle mapped memory, MMIO memory and
   cross-page transactions.

 * Allow nvmm_gva_to_gpa and nvmm_gpa_to_hva to take non-page-aligned
   addresses. This simplifies a lot of things.

 * Support the MOVS instruction, and add a test for it. This instruction
   is special, in that it takes two implicit memory operands. In
   particular, it means that the two buffers can both be in MMIO memory,
   and we handle this case.

 * Fix gross copy-pasto in nvmm_hva_unmap. Also fix a few things here and
   there.

diffstat:

 lib/libnvmm/libnvmm.3                |   23 +-
 lib/libnvmm/libnvmm.c                |   25 +-
 lib/libnvmm/libnvmm_x86.c            |  747 ++++++++++++++++++++++------------
 lib/libnvmm/nvmm.h                   |   16 +-
 tests/lib/libnvmm/h_mem_assist.c     |   15 +-
 tests/lib/libnvmm/h_mem_assist_asm.S |   20 +
 6 files changed, 547 insertions(+), 299 deletions(-)

diffs (truncated from 1267 to 300 lines):

diff -r 23b65877f501 -r cb8c850fe438 lib/libnvmm/libnvmm.3
--- a/lib/libnvmm/libnvmm.3     Thu Dec 27 04:54:03 2018 +0000
+++ b/lib/libnvmm/libnvmm.3     Thu Dec 27 07:22:31 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: libnvmm.3,v 1.5 2018/12/15 13:39:43 maxv Exp $
+.\"    $NetBSD: libnvmm.3,v 1.6 2018/12/27 07:22:31 maxv Exp $
 .\"
 .\" Copyright (c) 2018 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 14, 2018
+.Dd December 26, 2018
 .Dt LIBNVMM 3
 .Os
 .Sh NAME
@@ -78,12 +78,14 @@
 .Ft int
 .Fn nvmm_gpa_to_hva "struct nvmm_machine *mach" "gpaddr_t gpa" \
     "uintptr_t *hva"
+.Ft void
+.Fn nvmm_callbacks_register "const struct nvmm_callbacks *cbs"
 .Ft int
 .Fn nvmm_assist_io "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \
-    "struct nvmm_exit *exit" "void (*cb)(struct nvmm_io *)"
+    "struct nvmm_exit *exit"
 .Ft int
 .Fn nvmm_assist_mem "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \
-    "struct nvmm_exit *exit" "void (*cb)(struct nvmm_mem *)"
+    "struct nvmm_exit *exit"
 .Sh DESCRIPTION
 .Nm
 provides a library for VMM software to handle hardware-accelerated virtual
@@ -228,6 +230,11 @@
 .Fa gpa
 must be page-aligned.
 .Pp
+.Fn nvmm_callbacks_register
+registers in
+.Nm
+the callbacks descriptor passed as argument.
+.Pp
 .Fn nvmm_assist_io
 emulates the I/O operation described in
 .Fa exit
@@ -397,8 +404,8 @@
 provides an easy way for VMM software to perform that.
 .Pp
 .Fn nvmm_assist_io
-will call the
-.Fa cb
+will call the registered
+.Fa io
 callback function and give it a
 .Cd nvmm_io
 structure as argument.
@@ -444,8 +451,8 @@
 Assist.
 .Pp
 .Fn nvmm_assist_mem
-will call the
-.Fa cb
+will call the registered
+.Fa mem
 callback function and give it a
 .Cd nvmm_mem
 structure as argument.
diff -r 23b65877f501 -r cb8c850fe438 lib/libnvmm/libnvmm.c
--- a/lib/libnvmm/libnvmm.c     Thu Dec 27 04:54:03 2018 +0000
+++ b/lib/libnvmm/libnvmm.c     Thu Dec 27 07:22:31 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: libnvmm.c,v 1.5 2018/12/15 13:39:43 maxv Exp $ */
+/*     $NetBSD: libnvmm.c,v 1.6 2018/12/27 07:22:31 maxv Exp $ */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -43,6 +43,8 @@
 
 #include "nvmm.h"
 
+struct nvmm_callbacks __callbacks;
+
 typedef struct __area {
        LIST_ENTRY(__area) list;
        gpaddr_t gpa;
@@ -53,7 +55,6 @@
 typedef LIST_HEAD(, __area) area_list_t;
 
 static int nvmm_fd = -1;
-static size_t nvmm_page_size = 0;
 
 /* -------------------------------------------------------------------------- */
 
@@ -146,7 +147,6 @@
        nvmm_fd = open("/dev/nvmm", O_RDWR);
        if (nvmm_fd == -1)
                return -1;
-       nvmm_page_size = sysconf(_SC_PAGESIZE);
        return 0;
 }
 
@@ -454,7 +454,7 @@
 int
 nvmm_hva_unmap(struct nvmm_machine *mach, uintptr_t hva, size_t size)
 {
-       struct nvmm_ioc_hva_map args;
+       struct nvmm_ioc_hva_unmap args;
        int ret;
 
        if (nvmm_init() == -1) {
@@ -465,7 +465,7 @@
        args.hva = hva;
        args.size = size;
 
-       ret = ioctl(nvmm_fd, NVMM_IOC_HVA_MAP, &args);
+       ret = ioctl(nvmm_fd, NVMM_IOC_HVA_UNMAP, &args);
        if (ret == -1)
                return -1;
 
@@ -482,11 +482,6 @@
        area_list_t *areas = mach->areas;
        area_t *ent;
 
-       if (gpa % nvmm_page_size != 0) {
-               errno = EINVAL;
-               return -1;
-       }
-
        LIST_FOREACH(ent, areas, list) {
                if (gpa >= ent->gpa && gpa < ent->gpa + ent->size) {
                        *hva = ent->hva + (gpa - ent->gpa);
@@ -501,3 +496,13 @@
 /*
  * nvmm_assist_io(): architecture-specific.
  */
+
+/*
+ * nvmm_assist_mem(): architecture-specific.
+ */
+
+void
+nvmm_callbacks_register(const struct nvmm_callbacks *cbs)
+{
+       memcpy(&__callbacks, cbs, sizeof(__callbacks));
+}
diff -r 23b65877f501 -r cb8c850fe438 lib/libnvmm/libnvmm_x86.c
--- a/lib/libnvmm/libnvmm_x86.c Thu Dec 27 04:54:03 2018 +0000
+++ b/lib/libnvmm/libnvmm_x86.c Thu Dec 27 07:22:31 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: libnvmm_x86.c,v 1.5 2018/12/15 13:09:02 maxv Exp $     */
+/*     $NetBSD: libnvmm_x86.c,v 1.6 2018/12/27 07:22:31 maxv Exp $     */
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -47,6 +47,46 @@
 
 #include <x86/specialreg.h>
 
+extern struct nvmm_callbacks __callbacks;
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * Undocumented debugging function. Helpful.
+ */
+int
+nvmm_vcpu_dump(struct nvmm_machine *mach, nvmm_cpuid_t cpuid)
+{
+       struct nvmm_x64_state state;
+       size_t i;
+       int ret;
+
+       const char *segnames[] = {
+               "CS", "DS", "ES", "FS", "GS", "SS", "GDT", "IDT", "LDT", "TR"
+       };
+
+       ret = nvmm_vcpu_getstate(mach, cpuid, &state, NVMM_X64_STATE_ALL);
+       if (ret == -1)
+               return -1;
+
+       printf("+ VCPU id=%d\n", (int)cpuid);
+       printf("| -> RIP=%p\n", (void *)state.gprs[NVMM_X64_GPR_RIP]);
+       printf("| -> RSP=%p\n", (void *)state.gprs[NVMM_X64_GPR_RSP]);
+       printf("| -> RAX=%p\n", (void *)state.gprs[NVMM_X64_GPR_RAX]);
+       printf("| -> RBX=%p\n", (void *)state.gprs[NVMM_X64_GPR_RBX]);
+       printf("| -> RCX=%p\n", (void *)state.gprs[NVMM_X64_GPR_RCX]);
+       for (i = 0; i < NVMM_X64_NSEG; i++) {
+               printf("| -> %s: sel=0x%lx base=%p, limit=%p, P=%d\n",
+                   segnames[i],
+                   state.segs[i].selector,
+                   (void *)state.segs[i].base,
+                   (void *)state.segs[i].limit,
+                   state.segs[i].attrib.p);
+       }
+
+       return 0;
+}
+
 /* -------------------------------------------------------------------------- */
 
 #define PTE32_L1_SHIFT 12
@@ -330,6 +370,7 @@
 {
        bool is_pae, is_lng, has_pse;
        uint64_t cr3;
+       size_t off;
        int ret;
 
        if ((state->crs[NVMM_X64_CR_CR0] & CR0_PG) == 0) {
@@ -339,6 +380,9 @@
                return 0;
        }
 
+       off = (gva & PAGE_MASK);
+       gva &= ~PAGE_MASK;
+
        is_pae = (state->crs[NVMM_X64_CR_CR4] & CR4_PAE) != 0;
        is_lng = (state->msrs[NVMM_X64_MSR_EFER] & EFER_LME) != 0;
        has_pse = (state->crs[NVMM_X64_CR_CR4] & CR4_PSE) != 0;
@@ -362,6 +406,8 @@
                errno = EFAULT;
        }
 
+       *gpa = *gpa + off;
+
        return ret;
 }
 
@@ -372,11 +418,6 @@
        struct nvmm_x64_state state;
        int ret;
 
-       if (gva & PAGE_MASK) {
-               errno = EINVAL;
-               return -1;
-       }
-
        ret = nvmm_vcpu_getstate(mach, cpuid, &state,
            NVMM_X64_STATE_CRS | NVMM_X64_STATE_MSRS);
        if (ret == -1)
@@ -413,12 +454,6 @@
        return (state->msrs[NVMM_X64_MSR_EFER] & EFER_LME) != 0;
 }
 
-static inline bool
-is_illegal(struct nvmm_io *io, nvmm_prot_t prot)
-{
-       return (io->in && !(prot & NVMM_PROT_WRITE));
-}
-
 static int
 segment_apply(struct nvmm_x64_state_seg *seg, gvaddr_t *gva, size_t size)
 {
@@ -449,21 +484,150 @@
        return -1;
 }
 
+static uint64_t
+mask_from_adsize(size_t adsize)
+{
+       switch (adsize) {
+       case 8:
+               return 0xFFFFFFFFFFFFFFFF;
+       case 4:
+               return 0x00000000FFFFFFFF;
+       case 2:
+       default: /* impossible */
+               return 0x000000000000FFFF;
+       }
+}
+
+static uint64_t
+rep_dec_apply(struct nvmm_x64_state *state, size_t adsize)
+{
+       uint64_t mask, cnt;
+
+       mask = mask_from_adsize(adsize);
+
+       cnt = state->gprs[NVMM_X64_GPR_RCX] & mask; 
+       cnt -= 1;
+       cnt &= mask;
+
+       state->gprs[NVMM_X64_GPR_RCX] &= ~mask;
+       state->gprs[NVMM_X64_GPR_RCX] |= cnt;
+
+       return cnt;
+}
+
+static int
+read_guest_memory(struct nvmm_machine *mach, struct nvmm_x64_state *state,
+    gvaddr_t gva, uint8_t *data, size_t size)
+{
+       struct nvmm_mem mem;
+       nvmm_prot_t prot;
+       gpaddr_t gpa;
+       uintptr_t hva;
+       bool is_mmio;
+       int ret, remain;



Home | Main Index | Thread Index | Old Index