Page MenuHomeFreeBSD

D15348.1790890437.diff
No OneTemporary

Size
17 KB
Referenced Files
None
Subscribers
None

D15348.1790890437.diff

Index: sys/amd64/include/vmm.h
===================================================================
--- sys/amd64/include/vmm.h
+++ sys/amd64/include/vmm.h
@@ -215,6 +215,7 @@
void *vm_gpa_hold(struct vm *, int vcpuid, vm_paddr_t gpa, size_t len,
int prot, void **cookie);
void vm_gpa_release(void *cookie);
+vm_offset_t vm_gpa_to_kva(struct vm *vm, vm_paddr_t gpa, int len, uint16_t *hint);
bool vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa);
int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
@@ -343,6 +344,8 @@
struct vatpit *vm_atpit(struct vm *vm);
struct vpmtmr *vm_pmtmr(struct vm *vm);
struct vrtc *vm_rtc(struct vm *vm);
+struct vtnet_be *vm_vtnet_be(struct vm *vm);
+void *vm_ioport(struct vm *vm);
/*
* Inject exception 'vector' into the guest vcpu. This function returns 0 on
Index: sys/amd64/include/vmm_dev.h
===================================================================
--- sys/amd64/include/vmm_dev.h
+++ sys/amd64/include/vmm_dev.h
@@ -46,6 +46,7 @@
};
#define VM_MEMMAP_F_WIRED 0x01
#define VM_MEMMAP_F_IOMMU 0x02
+#define VM_MEMMAP_F_WIRED_KERNEL 0x04
#define VM_MEMSEG_NAME(m) ((m)->name[0] != '\0' ? (m)->name : NULL)
struct vm_memseg {
Index: sys/amd64/vmm/io/vatpic.h
===================================================================
--- sys/amd64/vmm/io/vatpic.h
+++ sys/amd64/vmm/io/vatpic.h
@@ -40,11 +40,11 @@
void vatpic_cleanup(struct vatpic *vatpic);
int vatpic_master_handler(struct vm *vm, int vcpuid, bool in, int port,
- int bytes, uint32_t *eax);
+ int bytes, uint32_t *eax, void *arg);
int vatpic_slave_handler(struct vm *vm, int vcpuid, bool in, int port,
- int bytes, uint32_t *eax);
+ int bytes, uint32_t *eax, void *arg);
int vatpic_elc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax);
+ uint32_t *eax, void *arg);
int vatpic_assert_irq(struct vm *vm, int irq);
int vatpic_deassert_irq(struct vm *vm, int irq);
Index: sys/amd64/vmm/io/vatpic.c
===================================================================
--- sys/amd64/vmm/io/vatpic.c
+++ sys/amd64/vmm/io/vatpic.c
@@ -708,7 +708,7 @@
int
vatpic_master_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax)
+ uint32_t *eax, void *arg)
{
struct vatpic *vatpic;
struct atpic *atpic;
@@ -728,7 +728,7 @@
int
vatpic_slave_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax)
+ uint32_t *eax, void *arg)
{
struct vatpic *vatpic;
struct atpic *atpic;
@@ -748,7 +748,7 @@
int
vatpic_elc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax)
+ uint32_t *eax, void *arg)
{
struct vatpic *vatpic;
bool is_master;
Index: sys/amd64/vmm/io/vatpit.h
===================================================================
--- sys/amd64/vmm/io/vatpit.h
+++ sys/amd64/vmm/io/vatpit.h
@@ -38,8 +38,8 @@
void vatpit_cleanup(struct vatpit *vatpit);
int vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax);
+ uint32_t *eax, void *arg);
int vatpit_nmisc_handler(struct vm *vm, int vcpuid, bool in, int port,
- int bytes, uint32_t *eax);
+ int bytes, uint32_t *eax, void *arg);
#endif /* _VATPIT_H_ */
Index: sys/amd64/vmm/io/vatpit.c
===================================================================
--- sys/amd64/vmm/io/vatpit.c
+++ sys/amd64/vmm/io/vatpit.c
@@ -317,7 +317,7 @@
int
vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax)
+ uint32_t *eax, void *arg)
{
struct vatpit *vatpit;
struct channel *c;
@@ -400,7 +400,7 @@
int
vatpit_nmisc_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *eax)
+ uint32_t *eax, void *arg)
{
struct vatpit *vatpit;
Index: sys/amd64/vmm/io/vpmtmr.h
===================================================================
--- sys/amd64/vmm/io/vpmtmr.h
+++ sys/amd64/vmm/io/vpmtmr.h
@@ -37,6 +37,6 @@
void vpmtmr_cleanup(struct vpmtmr *pmtmr);
int vpmtmr_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *val);
+ uint32_t *eax, void *arg);
#endif
Index: sys/amd64/vmm/io/vpmtmr.c
===================================================================
--- sys/amd64/vmm/io/vpmtmr.c
+++ sys/amd64/vmm/io/vpmtmr.c
@@ -79,7 +79,7 @@
int
vpmtmr_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *val)
+ uint32_t *val, void *arg)
{
struct vpmtmr *vpmtmr;
sbintime_t now, delta;
Index: sys/amd64/vmm/io/vrtc.h
===================================================================
--- sys/amd64/vmm/io/vrtc.h
+++ sys/amd64/vmm/io/vrtc.h
@@ -43,8 +43,8 @@
int vrtc_nvram_read(struct vm *vm, int offset, uint8_t *retval);
int vrtc_addr_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *val);
+ uint32_t *eax, void *arg);
int vrtc_data_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *val);
+ uint32_t *eax, void *arg);
#endif
Index: sys/amd64/vmm/io/vrtc.c
===================================================================
--- sys/amd64/vmm/io/vrtc.c
+++ sys/amd64/vmm/io/vrtc.c
@@ -840,7 +840,7 @@
int
vrtc_addr_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *val)
+ uint32_t *val, void *arg)
{
struct vrtc *vrtc;
@@ -863,7 +863,7 @@
int
vrtc_data_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
- uint32_t *val)
+ uint32_t *val, void *arg)
{
struct vrtc *vrtc;
struct rtcdev *rtc;
Index: sys/amd64/vmm/net/if_vmnic.h
===================================================================
--- /dev/null
+++ sys/amd64/vmm/net/if_vmnic.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017-2018 Joyent Inc.
+ * Copyright (C) 2017-2018 Matthew Macy <matt.macy@joyent.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VTNETBE_H_
+#define _VTNETBE_H_
+struct iflib_ctx;
+
+extern struct vtnet_be *(*vtnet_be_init)(struct vm *);
+extern void (*vtnet_be_cleanup)(struct vtnet_be *);
+
+#endif /* _VTNETBE_H_ */
Index: sys/amd64/vmm/vmm.c
===================================================================
--- sys/amd64/vmm/vmm.c
+++ sys/amd64/vmm/vmm.c
@@ -53,6 +53,7 @@
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
@@ -75,6 +76,7 @@
#include "vhpet.h"
#include "vioapic.h"
#include "vlapic.h"
+#include "if_vmnic.h"
#include "vpmtmr.h"
#include "vrtc.h"
#include "vmm_stat.h"
@@ -128,6 +130,7 @@
struct mem_map {
vm_paddr_t gpa;
+ vm_offset_t kva;
size_t len;
vm_ooffset_t segoff;
int segid;
@@ -166,13 +169,18 @@
struct vmspace *vmspace; /* (o) guest's address space */
char name[VM_MAX_NAMELEN]; /* (o) virtual machine name */
struct vcpu vcpu[VM_MAXCPU]; /* (i) guest vcpus */
+ void *ioport; /* (i) ioport exit hook */
+ void *vtnet_be; /* (i) vmnic hook */
/* The following describe the vm cpu topology */
uint16_t sockets; /* (o) num of sockets */
uint16_t cores; /* (o) num of cores/socket */
uint16_t threads; /* (o) num of threads/core */
uint16_t maxcpus; /* (o) max pluggable cpus */
+
};
+void (*vtnet_be_cleanup)(struct vtnet_be *);
+struct vtnet_be *(*vtnet_be_init)(struct vm *vm);
static int vmm_initialized;
static struct vmm_ops *ops;
@@ -421,6 +429,9 @@
vm->vpmtmr = vpmtmr_init(vm);
if (create)
vm->vrtc = vrtc_init(vm);
+ vm->ioport = vm_ioport_init(vm);
+ if (vtnet_be_init)
+ vm->vtnet_be = vtnet_be_init(vm);
CPU_ZERO(&vm->active_cpus);
CPU_ZERO(&vm->debug_cpus);
@@ -520,6 +531,9 @@
vhpet_cleanup(vm->vhpet);
vatpic_cleanup(vm->vatpic);
vioapic_cleanup(vm->vioapic);
+ vm_ioport_cleanup(vm, vm->ioport);
+ if (vtnet_be_cleanup)
+ vtnet_be_cleanup(vm->vtnet_be);
for (i = 0; i < VM_MAXCPU; i++)
vcpu_cleanup(vm, i, destroy);
@@ -702,6 +716,7 @@
struct mem_seg *seg;
struct mem_map *m, *map;
vm_ooffset_t last;
+ vm_offset_t kva;
int i, error;
if (prot == 0 || (prot & ~(VM_PROT_ALL)) != 0)
@@ -736,29 +751,92 @@
if (map == NULL)
return (ENOSPC);
+ vm_object_reference(seg->object);
error = vm_map_find(&vm->vmspace->vm_map, seg->object, first, &gpa,
len, 0, VMFS_NO_SPACE, prot, prot, 0);
if (error != KERN_SUCCESS)
- return (EFAULT);
-
- vm_object_reference(seg->object);
+ goto mapfail;
+ kva = 0;
if (flags & VM_MEMMAP_F_WIRED) {
error = vm_map_wire(&vm->vmspace->vm_map, gpa, gpa + len,
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
if (error != KERN_SUCCESS) {
- vm_map_remove(&vm->vmspace->vm_map, gpa, gpa + len);
- return (EFAULT);
+ printf("failed to wire kva 0x%012lx to 0x%012lx\n", gpa, gpa + len);
+ goto kernfail;
+ }
+ }
+ if (flags & VM_MEMMAP_F_WIRED_KERNEL) {
+ /* 256G after first usable address post direct map */
+ kva = 0xfffffe4000000000;
+ vm_object_reference(seg->object);
+ error = vm_map_find(kernel_map, seg->object, first, &kva,
+ len, 0, VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
+ if (error != KERN_SUCCESS) {
+ printf("failed to map 0x%lx bytes in to kernel map first: 0x%lx error: %d\n",
+ len, first, error);
+ goto kernfail;
+ }
+ error = vm_map_wire(kernel_map, kva, kva + len,
+ VM_MAP_WIRE_NOHOLES);
+ if (error != KERN_SUCCESS) {
+ printf("failed to wire kva 0x%012lx to 0x%012lx\n", kva, kva + len);
+ goto wirefail;
}
}
map->gpa = gpa;
+ map->kva = kva;
map->len = len;
map->segoff = first;
map->segid = segid;
map->prot = prot;
map->flags = flags;
return (0);
+ wirefail:
+ vm_map_remove(kernel_map, kva, kva + len);
+ vm_map_remove(&vm->vmspace->vm_map, gpa, gpa + len);
+ return (vm_mmap_to_errno(error));
+ kernfail:
+ vm_map_remove(&vm->vmspace->vm_map, gpa, gpa + len);
+ mapfail:
+ vm_object_deallocate(seg->object);
+ return (vm_mmap_to_errno(error));
+}
+
+vm_offset_t
+vm_gpa_to_kva(struct vm *vm, vm_paddr_t gpa, int len, uint16_t *hint)
+{
+ vm_paddr_t curgpa;
+ vm_offset_t curkva;
+ struct mem_map *mm;
+ size_t curlen;
+ int i;
+
+ if (__predict_true(*hint < VM_MAX_MEMMAPS)) {
+ mm = &vm->mem_maps[*hint];
+ curlen = mm->len;
+ curgpa = mm->gpa;
+ curkva = mm->kva;
+ if (__predict_true((mm->flags & VM_MEMMAP_F_WIRED) && curlen &&
+ !(gpa < curgpa || gpa + len > curgpa + curlen)))
+ return (curkva + (gpa - curgpa));
+ }
+ for (i = 0; i < VM_MAX_MEMMAPS; i++) {
+ mm = &vm->mem_maps[i];
+ if (__predict_false(mm->flags & VM_MEMMAP_F_WIRED) == 0)
+ continue;
+ curlen = mm->len;
+ curgpa = mm->gpa;
+ curkva = mm->kva;
+ if (curlen && !(gpa < curgpa || gpa + len > curgpa + curlen))
+ break;
+ }
+ *hint = i;
+ if (i == VM_MAX_MEMMAPS)
+ return (0);
+ MPASS(curkva);
+ return (curkva + (gpa - curgpa));
}
int
@@ -802,13 +880,22 @@
int error;
mm = &vm->mem_maps[ident];
- if (mm->len) {
- error = vm_map_remove(&vm->vmspace->vm_map, mm->gpa,
- mm->gpa + mm->len);
+ if (mm->len == 0)
+ return;
+
+ error = vm_map_remove(&vm->vmspace->vm_map, mm->gpa,
+ mm->gpa + mm->len);
+ KASSERT(error == KERN_SUCCESS, ("%s: vm_map_remove error %d",
+ __func__, error));
+ if (mm->flags & VM_MEMMAP_F_WIRED_KERNEL) {
+ MPASS(mm->kva);
+ error = vm_map_remove(kernel_map, mm->kva,
+ mm->kva + mm->len);
KASSERT(error == KERN_SUCCESS, ("%s: vm_map_remove error %d",
- __func__, error));
- bzero(mm, sizeof(struct mem_map));
+ __func__, error));
+
}
+ bzero(mm, sizeof(struct mem_map));
}
static __inline bool
@@ -2569,6 +2656,13 @@
return (vm->vrtc);
}
+void *
+vm_ioport(struct vm *vm)
+{
+
+ return (vm->ioport);
+}
+
enum vm_reg_name
vm_segment_name(int seg)
{
Index: sys/amd64/vmm/vmm_ioport.h
===================================================================
--- sys/amd64/vmm/vmm_ioport.h
+++ sys/amd64/vmm/vmm_ioport.h
@@ -30,8 +30,13 @@
#define _VMM_IOPORT_H_
typedef int (*ioport_handler_func_t)(struct vm *vm, int vcpuid,
- bool in, int port, int bytes, uint32_t *val);
+ bool in, int port, int bytes, uint32_t *val, void *arg);
int vm_handle_inout(struct vm *vm, int vcpuid, struct vm_exit *vme, bool *retu);
+int vm_register_ioport(struct vm *vm, ioport_handler_func_t func, void *arg,
+ uint16_t start, uint16_t size);
+
+void *vm_ioport_init(struct vm *vm);
+void vm_ioport_cleanup(struct vm *vm, void *hdl);
#endif /* _VMM_IOPORT_H_ */
Index: sys/amd64/vmm/vmm_ioport.c
===================================================================
--- sys/amd64/vmm/vmm_ioport.c
+++ sys/amd64/vmm/vmm_ioport.c
@@ -29,6 +29,9 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
#include <machine/vmm.h>
#include <machine/vmm_instruction_emul.h>
@@ -42,6 +45,8 @@
#define MAX_IOPORTS 1280
+static MALLOC_DEFINE(M_VM_IOPORT, "vm_ioport", "vm_ioport");
+
ioport_handler_func_t ioport_handler[MAX_IOPORTS] = {
[TIMER_MODE] = vatpit_handler,
[TIMER_CNTR0] = vatpit_handler,
@@ -59,6 +64,17 @@
[IO_RTC + 1] = vrtc_data_handler,
};
+#define MAX_SEGS 20
+struct ioport_segs {
+ int numsegs;
+ struct {
+ uint16_t start;
+ uint16_t size;
+ ioport_handler_func_t func;
+ void *arg;
+ } seg[MAX_SEGS];
+};
+
#ifdef KTR
static const char *
inout_instruction(struct vm_exit *vmexit)
@@ -97,19 +113,47 @@
}
#endif /* KTR */
+static ioport_handler_func_t
+inout_search(struct vm *vm, uint16_t port, void **arg)
+{
+ struct ioport_segs *segs;
+ ioport_handler_func_t handler;
+ int i;
+
+ segs = vm_ioport(vm);
+ handler = NULL;
+
+ for (i = 0; i < segs->numsegs; i++) {
+ if (port >= segs->seg[i].start &&
+ port < (segs->seg[i].start + segs->seg[i].size)) {
+ handler = segs->seg[i].func;
+ *arg = segs->seg[i].arg;
+ break;
+ }
+ }
+
+ return (handler);
+}
+
static int
emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit,
bool *retu)
{
ioport_handler_func_t handler;
+ void *arg;
uint32_t mask, val;
int error;
/*
* If there is no handler for the I/O port then punt to userspace.
*/
- if (vmexit->u.inout.port >= MAX_IOPORTS ||
- (handler = ioport_handler[vmexit->u.inout.port]) == NULL) {
+ if (vmexit->u.inout.port < MAX_IOPORTS) {
+ handler = ioport_handler[vmexit->u.inout.port];
+ arg = NULL;
+ } else
+ handler = inout_search(vm, vmexit->u.inout.port, &arg);
+
+ if (handler == NULL) {
*retu = true;
return (0);
}
@@ -121,7 +165,8 @@
}
error = (*handler)(vm, vcpuid, vmexit->u.inout.in,
- vmexit->u.inout.port, vmexit->u.inout.bytes, &val);
+ vmexit->u.inout.port, vmexit->u.inout.bytes, &val, arg);
+
if (error) {
/*
* The value returned by this function is also the return value
@@ -174,3 +219,50 @@
return (error);
}
+
+void *
+vm_ioport_init(struct vm *vm)
+{
+
+ return (malloc(sizeof(struct ioport_segs), M_VM_IOPORT,
+ M_WAITOK | M_ZERO));
+}
+
+void
+vm_ioport_cleanup(struct vm *vm, void *hdl)
+{
+
+ free(hdl, M_VM_IOPORT);
+}
+
+int
+vm_register_ioport(struct vm *vm, ioport_handler_func_t func, void *arg,
+ uint16_t start, uint16_t size)
+{
+ struct ioport_segs *segs;
+ int i;
+
+ segs = vm_ioport(vm);
+
+ if (segs->numsegs == MAX_SEGS)
+ return (ENOSPC);
+
+ /*
+ * No locking needed - assumes all operations are done
+ * prior to running or in UP context
+ */
+ for (i = 0; i < segs->numsegs; i++) {
+ /* Make sure existing mappings don't overlap */
+ if (!(start >= (segs->seg[i].start + segs->seg[i].size) ||
+ (start + size) < segs->seg[i].start))
+ return (EINVAL);
+ }
+
+ segs->seg[i].start = start;
+ segs->seg[i].size = size;
+ segs->seg[i].func = func;
+ segs->seg[i].arg = arg;
+ segs->numsegs++;
+
+ return (0);
+}
Index: sys/modules/vmm/Makefile
===================================================================
--- sys/modules/vmm/Makefile
+++ sys/modules/vmm/Makefile
@@ -11,6 +11,7 @@
CFLAGS+= -I${SRCTOP}/sys/amd64/vmm/io
CFLAGS+= -I${SRCTOP}/sys/amd64/vmm/intel
CFLAGS+= -I${SRCTOP}/sys/amd64/vmm/amd
+CFLAGS+= -I${SRCTOP}/sys/amd64/vmm/net
# generic vmm support
.PATH: ${SRCTOP}/sys/amd64/vmm

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 1, 9:33 PM (2 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30078809
Default Alt Text
D15348.1790890437.diff (17 KB)

Event Timeline