Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149774512
D15348.1790890437.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D15348.1790890437.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D15348: add supporting interfaces for in-kernel virtio backend
Attached
Detach File
Event Timeline
Log In to Comment