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/aa060426a98e
branches: trunk
changeset: 995538:aa060426a98e
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 170b6b193a87 -r aa060426a98e 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 170b6b193a87 -r aa060426a98e 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 170b6b193a87 -r aa060426a98e 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