From owner-svn-soc-all@freebsd.org Mon Aug 1 08:01:12 2016 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 97D57BAA6FF for ; Mon, 1 Aug 2016 08:01:12 +0000 (UTC) (envelope-from vincenzo@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8A43D1FAB for ; Mon, 1 Aug 2016 08:01:12 +0000 (UTC) (envelope-from vincenzo@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id u7181CZv007171 for ; Mon, 1 Aug 2016 08:01:12 GMT (envelope-from vincenzo@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id u71818pt005292 for svn-soc-all@FreeBSD.org; Mon, 1 Aug 2016 08:01:08 GMT (envelope-from vincenzo@FreeBSD.org) Date: Mon, 1 Aug 2016 08:01:08 GMT Message-Id: <201608010801.u71818pt005292@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to vincenzo@FreeBSD.org using -f From: vincenzo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r307050 - in soc2016/vincenzo/head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/modules/vmm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Aug 2016 08:01:12 -0000 Author: vincenzo Date: Mon Aug 1 08:01:05 2016 New Revision: 307050 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=307050 Log: vmm: add support needed for ptnetmap Modified: soc2016/vincenzo/head/lib/libvmmapi/vmmapi.c soc2016/vincenzo/head/lib/libvmmapi/vmmapi.h soc2016/vincenzo/head/sys/amd64/include/vmm.h soc2016/vincenzo/head/sys/amd64/include/vmm_dev.h soc2016/vincenzo/head/sys/amd64/vmm/vmm.c soc2016/vincenzo/head/sys/amd64/vmm/vmm_dev.c soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.c soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.h soc2016/vincenzo/head/sys/modules/vmm/Makefile Modified: soc2016/vincenzo/head/lib/libvmmapi/vmmapi.c ============================================================================== --- soc2016/vincenzo/head/lib/libvmmapi/vmmapi.c Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/lib/libvmmapi/vmmapi.c Mon Aug 1 08:01:05 2016 (r307050) @@ -883,6 +883,42 @@ } int +vm_get_fd(struct vmctx *ctx) +{ + return (ctx->fd); +} + +int +vm_map_user_buf(struct vmctx *ctx, vm_paddr_t gpa, size_t len, void *host_buf) +{ + struct vm_user_buf user_buf; + + bzero(&user_buf, sizeof(user_buf)); + user_buf.gpa = gpa; + user_buf.len = len; + user_buf.addr = host_buf; + + return (ioctl(ctx->fd, VM_MAP_USER_BUF, &user_buf)); +} + +int +vm_io_reg_handler(struct vmctx *ctx, uint16_t port, uint16_t in, uint32_t mask_data, uint32_t data, + enum vm_io_regh_type type, void *arg) +{ + struct vm_io_reg_handler ioregh; + + bzero(&ioregh, sizeof(ioregh)); + ioregh.port = port; + ioregh.in = in; + ioregh.mask_data = mask_data; + ioregh.data = data; + ioregh.type = type; + ioregh.arg = arg; + + return (ioctl(ctx->fd, VM_IO_REG_HANDLER, &ioregh)); +} + +int vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func, uint64_t addr, uint64_t msg, int numvec) { Modified: soc2016/vincenzo/head/lib/libvmmapi/vmmapi.h ============================================================================== --- soc2016/vincenzo/head/lib/libvmmapi/vmmapi.h Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/lib/libvmmapi/vmmapi.h Mon Aug 1 08:01:05 2016 (r307050) @@ -161,7 +161,10 @@ int vm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *i1, uint64_t *i2); int vm_set_intinfo(struct vmctx *ctx, int vcpu, uint64_t exit_intinfo); - +int vm_get_fd(struct vmctx *ctx); +int vm_map_user_buf(struct vmctx *ctx, vm_paddr_t gpa, size_t len, void *host_buf); +int vm_io_reg_handler(struct vmctx *ctx, uint16_t port, uint16_t in, + uint32_t mask_data, uint32_t data, enum vm_io_regh_type type, void *arg); /* * Return a pointer to the statistics buffer. Note that this is not MT-safe. */ Modified: soc2016/vincenzo/head/sys/amd64/include/vmm.h ============================================================================== --- soc2016/vincenzo/head/sys/amd64/include/vmm.h Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/amd64/include/vmm.h Mon Aug 1 08:01:05 2016 (r307050) @@ -183,6 +183,7 @@ int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem); void vm_free_memseg(struct vm *vm, int ident); int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); +int vm_map_usermem(struct vm *vm, vm_paddr_t gpa, size_t len, void *buf, struct thread *td); int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); @@ -321,6 +322,7 @@ struct vatpit *vm_atpit(struct vm *vm); struct vpmtmr *vm_pmtmr(struct vm *vm); struct vrtc *vm_rtc(struct vm *vm); +struct ioregh *vm_ioregh(struct vm *vm); /* * Inject exception 'vector' into the guest vcpu. This function returns 0 on @@ -417,7 +419,13 @@ EDGE_TRIGGER, LEVEL_TRIGGER }; - + +enum vm_io_regh_type { + VM_IO_REGH_DELETE, + VM_IO_REGH_KWEVENTS, /* kernel wait events */ + VM_IO_REGH_MAX +}; + /* * The 'access' field has the format specified in Table 21-2 of the Intel * Architecture Manual vol 3b. Modified: soc2016/vincenzo/head/sys/amd64/include/vmm_dev.h ============================================================================== --- soc2016/vincenzo/head/sys/amd64/include/vmm_dev.h Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/amd64/include/vmm_dev.h Mon Aug 1 08:01:05 2016 (r307050) @@ -123,6 +123,21 @@ size_t len; }; +struct vm_user_buf { + vm_paddr_t gpa; + void *addr; + size_t len; +}; + +struct vm_io_reg_handler { + uint16_t port; /* I/O address */ + uint16_t in; /* 0 out, 1 in */ + uint32_t mask_data; /* 0 means match anything */ + uint32_t data; /* data to match */ + enum vm_io_regh_type type; /* handler type */ + void *arg; /* handler argument */ +}; + struct vm_pptdev_msi { int vcpu; int bus; @@ -286,6 +301,10 @@ IOCNUM_RTC_WRITE = 101, IOCNUM_RTC_SETTIME = 102, IOCNUM_RTC_GETTIME = 103, + + /* host mmap and IO handler */ + IOCNUM_MAP_USER_BUF = 104, + IOCNUM_IO_REG_HANDLER = 105, }; #define VM_RUN \ @@ -344,6 +363,10 @@ _IOW('v', IOCNUM_UNBIND_PPTDEV, struct vm_pptdev) #define VM_MAP_PPTDEV_MMIO \ _IOW('v', IOCNUM_MAP_PPTDEV_MMIO, struct vm_pptdev_mmio) +#define VM_MAP_USER_BUF \ + _IOW('v', IOCNUM_MAP_USER_BUF, struct vm_user_buf) +#define VM_IO_REG_HANDLER \ + _IOW('v', IOCNUM_IO_REG_HANDLER, struct vm_io_reg_handler) #define VM_PPTDEV_MSI \ _IOW('v', IOCNUM_PPTDEV_MSI, struct vm_pptdev_msi) #define VM_PPTDEV_MSIX \ Modified: soc2016/vincenzo/head/sys/amd64/vmm/vmm.c ============================================================================== --- soc2016/vincenzo/head/sys/amd64/vmm/vmm.c Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/amd64/vmm/vmm.c Mon Aug 1 08:01:05 2016 (r307050) @@ -66,6 +66,7 @@ #include "vmm_ktr.h" #include "vmm_host.h" #include "vmm_mem.h" +#include "vmm_usermem.h" #include "vmm_util.h" #include "vatpic.h" #include "vatpit.h" @@ -148,6 +149,7 @@ struct vatpit *vatpit; /* (i) virtual atpit */ struct vpmtmr *vpmtmr; /* (i) virtual ACPI PM timer */ struct vrtc *vrtc; /* (o) virtual RTC */ + struct ioregh *ioregh; /* () I/O reg handler */ volatile cpuset_t active_cpus; /* (i) active vcpus */ int suspend; /* (i) stop VM execution */ volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */ @@ -419,6 +421,7 @@ vm->vpmtmr = vpmtmr_init(vm); if (create) vm->vrtc = vrtc_init(vm); + vm->ioregh = ioregh_init(vm); CPU_ZERO(&vm->active_cpus); @@ -475,11 +478,13 @@ vrtc_cleanup(vm->vrtc); else vrtc_reset(vm->vrtc); + ioregh_cleanup(vm->ioregh); vpmtmr_cleanup(vm->vpmtmr); vatpit_cleanup(vm->vatpit); vhpet_cleanup(vm->vhpet); vatpic_cleanup(vm->vatpic); vioapic_cleanup(vm->vioapic); + vmm_usermem_cleanup(vm->vmspace); for (i = 0; i < VM_MAXCPU; i++) vcpu_cleanup(vm, i, destroy); @@ -553,6 +558,17 @@ } int +vm_map_usermem(struct vm *vm, vm_paddr_t gpa, size_t len, void *buf, struct thread *td) +{ + vm_object_t obj; + + if ((obj = vmm_usermem_alloc(vm->vmspace, gpa, len, buf, td)) == NULL) + return (ENOMEM); + + return (0); +} + +int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len) { @@ -588,6 +604,9 @@ if (ppt_is_mmio(vm, gpa)) return (true); /* 'gpa' is pci passthru mmio */ + if (usermem_mapped(vm->vmspace, gpa)) + return (true); /* 'gpa' is user-space buffer mapped */ + return (false); } @@ -2457,6 +2476,12 @@ return (vm->vrtc); } +struct ioregh * +vm_ioregh(struct vm *vm) +{ + return (vm->ioregh); +} + enum vm_reg_name vm_segment_name(int seg) { Modified: soc2016/vincenzo/head/sys/amd64/vmm/vmm_dev.c ============================================================================== --- soc2016/vincenzo/head/sys/amd64/vmm/vmm_dev.c Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/amd64/vmm/vmm_dev.c Mon Aug 1 08:01:05 2016 (r307050) @@ -55,6 +55,7 @@ #include "vmm_lapic.h" #include "vmm_stat.h" #include "vmm_mem.h" +#include "vmm_ioport.h" #include "io/ppt.h" #include "io/vatpic.h" #include "io/vioapic.h" @@ -300,6 +301,8 @@ struct vm_pptdev_mmio *pptmmio; struct vm_pptdev_msi *pptmsi; struct vm_pptdev_msix *pptmsix; + struct vm_user_buf *usermem; + struct vm_io_reg_handler *ioregh; struct vm_nmi *vmnmi; struct vm_stats *vmstats; struct vm_stat_desc *statdesc; @@ -358,6 +361,7 @@ case VM_UNBIND_PPTDEV: case VM_ALLOC_MEMSEG: case VM_MMAP_MEMSEG: + case VM_MAP_USER_BUF: case VM_REINIT: /* * ioctls that operate on the entire virtual machine must @@ -433,6 +437,16 @@ pptmmio->func, pptmmio->gpa, pptmmio->len, pptmmio->hpa); break; + case VM_MAP_USER_BUF: + usermem = (struct vm_user_buf *)data; + error = vm_map_usermem(sc->vm, usermem->gpa, usermem->len, + usermem->addr, td); + break; + case VM_IO_REG_HANDLER: + ioregh = (struct vm_io_reg_handler *)data; + error = vmm_ioport_reg_handler(sc->vm, ioregh->port, ioregh->in, ioregh->mask_data, + ioregh->data, ioregh->type, ioregh->arg); + break; case VM_BIND_PPTDEV: pptdev = (struct vm_pptdev *)data; error = vm_assign_pptdev(sc->vm, pptdev->bus, pptdev->slot, Modified: soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.c ============================================================================== --- soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.c Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.c Mon Aug 1 08:01:05 2016 (r307050) @@ -97,31 +97,278 @@ } #endif /* KTR */ +#ifdef VMM_IOPORT_REG_HANDLER +#include +#include +#include +#include +#include + +static MALLOC_DEFINE(M_IOREGH, "ioregh", "bhyve ioport reg handlers"); + +#define IOREGH_LOCK(ioregh) mtx_lock_spin(&((ioregh)->mtx)) +#define IOREGH_UNLOCK(ioregh) mtx_unlock_spin(&((ioregh)->mtx)) + +#define IOPORT_MAX_REG_HANDLER 12 + +/* + * ioport_reg_handler functions allows us to to catch VM write/read + * on specific I/O address and send notification. + * + * When the VM writes or reads a specific value on I/O address, if the address + * and the value matches with the info stored durign the handler registration, + * then we send a notification (we can have multiple type of notification, + * but for now is implemented only the VM_IO_REGH_KWEVENTS handler. + */ + +typedef int (*ioport_reg_handler_func_t)(struct vm *vm, + struct ioport_reg_handler *regh, uint32_t *val); + +struct ioport_reg_handler { + uint16_t port; /* I/O address */ + uint16_t in; /* 0 out, 1 in */ + uint32_t mask_data; /* 0 means match anything */ + uint32_t data; /* data to match */ + ioport_reg_handler_func_t handler; /* handler pointer */ + void *handler_arg; /* handler argument */ +}; + +struct ioregh { + struct mtx mtx; + /* TODO: use hash table is better */ + struct ioport_reg_handler handlers[IOPORT_MAX_REG_HANDLER]; +}; + +/* ----- I/O reg handlers ----- */ + +/* + * VM_IO_REGH_KWEVENTS handler + * + * wakeup() on specified address that uniquely identifies the event + * + */ +static int +vmm_ioport_reg_wakeup(struct vm *vm, struct ioport_reg_handler *regh, uint32_t *val) +{ + wakeup(regh->handler_arg); + return (0); +} + +/* + * TODO: + * - VM_IO_REGH_CONDSIGNAL: pthread_cond_signal + * - VM_IO_REGH_WRITEFD: write on fd + * - VM_IO_REGH_IOCTL: ioctl on fd + */ + +/* call with ioregh->mtx held */ +static struct ioport_reg_handler * +vmm_ioport_find_handler(struct ioregh *ioregh, uint16_t port, uint16_t in, + uint32_t mask_data, uint32_t data) +{ + struct ioport_reg_handler *regh; + uint32_t mask; + int i; + + regh = ioregh->handlers; + for (i = 0; i < IOPORT_MAX_REG_HANDLER; i++) { + if (regh[i].handler != NULL) { + mask = regh[i].mask_data & mask_data; + if ((regh[i].port == port) && (regh[i].in == in) + && ((mask & regh[i].data) == (mask & data))) { + return ®h[i]; + } + } + } + + return (NULL); +} + +/* call with ioregh->mtx held */ +static struct ioport_reg_handler * +vmm_ioport_empty_handler(struct ioregh *ioregh) +{ + struct ioport_reg_handler *regh; + int i; + + regh = ioregh->handlers; + for (i = 0; i < IOPORT_MAX_REG_HANDLER; i++) { + if (regh[i].handler == NULL) { + return ®h[i]; + } + } + + return (NULL); +} + + +static int +vmm_ioport_add_handler(struct vm *vm, uint16_t port, uint16_t in, uint32_t mask_data, + uint32_t data, ioport_reg_handler_func_t handler, void *handler_arg) +{ + struct ioport_reg_handler *regh; + struct ioregh *ioregh; + int ret = 0; + + ioregh = vm_ioregh(vm); + + IOREGH_LOCK(ioregh); + + regh = vmm_ioport_find_handler(ioregh, port, in, mask_data, data); + if (regh != NULL) { + printf("%s: handler for port %d in %d mask_data %d data %d \ + already registered\n", + __FUNCTION__, port, in, mask_data, data); + ret = EEXIST; + goto err; + } + + regh = vmm_ioport_empty_handler(ioregh); + if (regh == NULL) { + printf("%s: empty reg_handler slot not found\n", __FUNCTION__); + ret = ENOMEM; + goto err; + } + + regh->port = port; + regh->in = in; + regh->mask_data = mask_data; + regh->data = data; + regh->handler = handler; + regh->handler_arg = handler_arg; + +err: + IOREGH_UNLOCK(ioregh); + return (ret); +} + +static int +vmm_ioport_del_handler(struct vm *vm, uint16_t port, uint16_t in, + uint32_t mask_data, uint32_t data) +{ + struct ioport_reg_handler *regh; + struct ioregh *ioregh; + int ret = 0; + + ioregh = vm_ioregh(vm); + + IOREGH_LOCK(ioregh); + + regh = vmm_ioport_find_handler(ioregh, port, in, mask_data, data); + + if (regh == NULL) { + ret = EINVAL; + goto err; + } + + bzero(regh, sizeof(struct ioport_reg_handler)); +err: + IOREGH_UNLOCK(ioregh); + return (ret); +} + +/* + * register or delete a new I/O event handler. + */ +int +vmm_ioport_reg_handler(struct vm *vm, uint16_t port, uint16_t in, + uint32_t mask_data, uint32_t data, enum vm_io_regh_type type, void *arg) +{ + int ret = 0; + + switch (type) { + case VM_IO_REGH_DELETE: + ret = vmm_ioport_del_handler(vm, port, in, mask_data, data); + break; + case VM_IO_REGH_KWEVENTS: + ret = vmm_ioport_add_handler(vm, port, in, mask_data, data, + vmm_ioport_reg_wakeup, arg); + break; + default: + printf("%s: unknown reg_handler type\n", __FUNCTION__); + ret = EINVAL; + break; + } + + return (ret); +} + +/* + * Invoke an handler, if the data matches. + */ +static int +invoke_reg_handler(struct vm *vm, int vcpuid, struct vm_exit *vmexit, + uint32_t *val, int *error) +{ + struct ioport_reg_handler *regh; + struct ioregh *ioregh; + uint32_t mask_data; + + mask_data = vie_size2mask(vmexit->u.inout.bytes); + ioregh = vm_ioregh(vm); + + IOREGH_LOCK(ioregh); + regh = vmm_ioport_find_handler(ioregh, vmexit->u.inout.port, + vmexit->u.inout.in, mask_data, vmexit->u.inout.eax); + if (regh == NULL) { + IOREGH_UNLOCK(ioregh); + return (0); + } + *error = (*(regh->handler))(vm, regh, val); + IOREGH_UNLOCK(ioregh); + return (1); +} + +struct ioregh * +ioregh_init(struct vm *vm) +{ + struct ioregh *ioregh; + + ioregh = malloc(sizeof(struct ioregh), M_IOREGH, M_WAITOK | M_ZERO); + + mtx_init(&ioregh->mtx, "ioregh lock", NULL, MTX_SPIN); + + return (ioregh); +} + +void +ioregh_cleanup(struct ioregh *ioregh) +{ + free(ioregh, M_IOREGH); +} +#else /* !VMM_IOPORT_REG_HANDLER */ +#define invoke_reg_handler(_1, _2, _3, _4, _5) (0) +#endif /* VMM_IOPORT_REG_HANDLER */ + static int emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu) { ioport_handler_func_t handler; uint32_t mask, val; - int error; + int regh = 0, error = 0; /* * 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]) == NULL) && + (regh = invoke_reg_handler(vm, vcpuid, vmexit, &val, &error)) == 0) { *retu = true; return (0); } - mask = vie_size2mask(vmexit->u.inout.bytes); + if (!regh) { + mask = vie_size2mask(vmexit->u.inout.bytes); + + if (!vmexit->u.inout.in) { + val = vmexit->u.inout.eax & mask; + } - if (!vmexit->u.inout.in) { - val = vmexit->u.inout.eax & mask; + error = (*handler)(vm, vcpuid, vmexit->u.inout.in, + vmexit->u.inout.port, vmexit->u.inout.bytes, &val); } - error = (*handler)(vm, vcpuid, vmexit->u.inout.in, - vmexit->u.inout.port, vmexit->u.inout.bytes, &val); if (error) { /* * The value returned by this function is also the return value Modified: soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.h ============================================================================== --- soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.h Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/amd64/vmm/vmm_ioport.h Mon Aug 1 08:01:05 2016 (r307050) @@ -29,6 +29,22 @@ #ifndef _VMM_IOPORT_H_ #define _VMM_IOPORT_H_ +#define VMM_IOPORT_REG_HANDLER +#ifdef VMM_IOPORT_REG_HANDLER +struct ioport_reg_handler; +struct ioregh; + +struct ioregh *ioregh_init(struct vm *vm); +void ioregh_cleanup(struct ioregh *ioregh); + +int vmm_ioport_reg_handler(struct vm *vm, uint16_t port, uint16_t in, + uint32_t mask_data, uint32_t data, enum vm_io_regh_type type, void *arg); +#else /* !VMM_IOPORT_REG_HANDLER */ +#define ioregh_init(_1) (NULL) +#define ioregh_cleanup(_1) +#define vmm_ioport_reg_handler(_1, _2, _3, _4,_5, _6, _7) (EINVAL) +#endif /* VMM_IOPORT_REG_HANDLER */ + typedef int (*ioport_handler_func_t)(struct vm *vm, int vcpuid, bool in, int port, int bytes, uint32_t *val); Modified: soc2016/vincenzo/head/sys/modules/vmm/Makefile ============================================================================== --- soc2016/vincenzo/head/sys/modules/vmm/Makefile Mon Aug 1 06:59:35 2016 (r307049) +++ soc2016/vincenzo/head/sys/modules/vmm/Makefile Mon Aug 1 08:01:05 2016 (r307050) @@ -21,6 +21,7 @@ vmm_ioport.c \ vmm_lapic.c \ vmm_mem.c \ + vmm_usermem.c \ vmm_stat.c \ vmm_util.c \ x86.c