svn commit: r258075 - in head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/io sys/modules/vmm usr.sbin/bhyve

Neel Natu neel at FreeBSD.org
Tue Nov 12 22:51:06 UTC 2013


Author: neel
Date: Tue Nov 12 22:51:03 2013
New Revision: 258075
URL: http://svnweb.freebsd.org/changeset/base/258075

Log:
  Move the ioapic device model from userspace into vmm.ko. This is needed for
  upcoming in-kernel device emulations like the HPET.
  
  The ioctls VM_IOAPIC_ASSERT_IRQ and VM_IOAPIC_DEASSERT_IRQ are used to
  manipulate the ioapic pin state.
  
  Discussed with:	grehan@
  Submitted by:	Tycho Nightingale (tycho.nightingale at pluribusnetworks.com)

Added:
  head/sys/amd64/vmm/io/vioapic.c   (contents, props changed)
  head/sys/amd64/vmm/io/vioapic.h   (contents, props changed)
Deleted:
  head/usr.sbin/bhyve/ioapic.c
  head/usr.sbin/bhyve/ioapic.h
Modified:
  head/lib/libvmmapi/vmmapi.c
  head/lib/libvmmapi/vmmapi.h
  head/sys/amd64/include/vmm.h
  head/sys/amd64/include/vmm_dev.h
  head/sys/amd64/vmm/vmm.c
  head/sys/amd64/vmm/vmm_dev.c
  head/sys/modules/vmm/Makefile
  head/usr.sbin/bhyve/Makefile
  head/usr.sbin/bhyve/bhyverun.c
  head/usr.sbin/bhyve/pci_emul.c
  head/usr.sbin/bhyve/pci_lpc.c
  head/usr.sbin/bhyve/pit_8254.c

Modified: head/lib/libvmmapi/vmmapi.c
==============================================================================
--- head/lib/libvmmapi/vmmapi.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/lib/libvmmapi/vmmapi.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -397,6 +397,28 @@ vm_lapic_irq(struct vmctx *ctx, int vcpu
 }
 
 int
+vm_ioapic_assert_irq(struct vmctx *ctx, int irq)
+{
+	struct vm_ioapic_irq ioapic_irq;
+
+	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
+	ioapic_irq.irq = irq;
+
+	return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
+}
+
+int
+vm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
+{
+	struct vm_ioapic_irq ioapic_irq;
+
+	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
+	ioapic_irq.irq = irq;
+
+	return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
+}
+
+int
 vm_inject_nmi(struct vmctx *ctx, int vcpu)
 {
 	struct vm_nmi vmnmi;

Modified: head/lib/libvmmapi/vmmapi.h
==============================================================================
--- head/lib/libvmmapi/vmmapi.h	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/lib/libvmmapi/vmmapi.h	Tue Nov 12 22:51:03 2013	(r258075)
@@ -67,6 +67,8 @@ int	vm_inject_event(struct vmctx *ctx, i
 int	vm_inject_event2(struct vmctx *ctx, int vcpu, enum vm_event_type type,
 			 int vector, int error_code);
 int	vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector);
+int	vm_ioapic_assert_irq(struct vmctx *ctx, int irq);
+int	vm_ioapic_deassert_irq(struct vmctx *ctx, int irq);
 int	vm_inject_nmi(struct vmctx *ctx, int vcpu);
 int	vm_capability_name2type(const char *capname);
 const char *vm_capability_type2name(int type);

Modified: head/sys/amd64/include/vmm.h
==============================================================================
--- head/sys/amd64/include/vmm.h	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/sys/amd64/include/vmm.h	Tue Nov 12 22:51:03 2013	(r258075)
@@ -38,6 +38,7 @@ struct vm_memory_segment;
 struct seg_desc;
 struct vm_exit;
 struct vm_run;
+struct vioapic;
 struct vlapic;
 struct vmspace;
 struct vm_object;
@@ -116,10 +117,12 @@ int vm_nmi_pending(struct vm *vm, int vc
 void vm_nmi_clear(struct vm *vm, int vcpuid);
 uint64_t *vm_guest_msrs(struct vm *vm, int cpu);
 struct vlapic *vm_lapic(struct vm *vm, int cpu);
+struct vioapic *vm_ioapic(struct vm *vm);
 int vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
 int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
 int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
 int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
+int vm_apicid2vcpuid(struct vm *vm, int apicid);
 void vm_activate_cpu(struct vm *vm, int vcpu);
 cpuset_t vm_active_cpus(struct vm *vm);
 struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);

Modified: head/sys/amd64/include/vmm_dev.h
==============================================================================
--- head/sys/amd64/include/vmm_dev.h	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/sys/amd64/include/vmm_dev.h	Tue Nov 12 22:51:03 2013	(r258075)
@@ -71,6 +71,10 @@ struct vm_lapic_irq {
 	int		vector;
 };
 
+struct vm_ioapic_irq {
+	int		irq;
+};
+
 struct vm_capability {
 	int		cpuid;
 	enum vm_cap_type captype;
@@ -164,6 +168,8 @@ enum {
 	IOCNUM_INJECT_EVENT = 30,
 	IOCNUM_LAPIC_IRQ = 31,
 	IOCNUM_INJECT_NMI = 32,
+	IOCNUM_IOAPIC_ASSERT_IRQ = 33,
+	IOCNUM_IOAPIC_DEASSERT_IRQ = 34,
 
 	/* PCI pass-thru */
 	IOCNUM_BIND_PPTDEV = 40,
@@ -199,6 +205,10 @@ enum {
 	_IOW('v', IOCNUM_INJECT_EVENT, struct vm_event)
 #define	VM_LAPIC_IRQ 		\
 	_IOW('v', IOCNUM_LAPIC_IRQ, struct vm_lapic_irq)
+#define	VM_IOAPIC_ASSERT_IRQ	\
+	_IOW('v', IOCNUM_IOAPIC_ASSERT_IRQ, struct vm_ioapic_irq)
+#define	VM_IOAPIC_DEASSERT_IRQ	\
+	_IOW('v', IOCNUM_IOAPIC_DEASSERT_IRQ, struct vm_ioapic_irq)
 #define	VM_SET_CAPABILITY \
 	_IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability)
 #define	VM_GET_CAPABILITY \

Added: head/sys/amd64/vmm/io/vioapic.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/amd64/vmm/io/vioapic.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -0,0 +1,366 @@
+/*-
+ * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale at pluribusnetworks.com>
+ * Copyright (c) 2013 Neel Natu <neel at freebsd.org>
+ * 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 NETAPP, INC ``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 NETAPP, INC 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$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/cpuset.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <x86/apicreg.h>
+#include <machine/vmm.h>
+
+#include "vmm_ktr.h"
+#include "vmm_lapic.h"
+#include "vioapic.h"
+
+#define	IOREGSEL	0x00
+#define	IOWIN		0x10
+
+#define	REDIR_ENTRIES	16
+#define	INTR_ASSERTED(vioapic, pin) ((vioapic)->rtbl[(pin)].pinstate == true)
+
+struct vioapic {
+	struct vm	*vm;
+	struct mtx	mtx;
+	uint32_t	id;
+	uint32_t	ioregsel;
+	struct {
+		uint64_t reg;
+		bool     pinstate;
+		bool     pending;
+	} rtbl[REDIR_ENTRIES];
+};
+
+#define	VIOAPIC_LOCK(vioapic)		mtx_lock(&((vioapic)->mtx))
+#define	VIOAPIC_UNLOCK(vioapic)		mtx_unlock(&((vioapic)->mtx))
+#define	VIOAPIC_LOCKED(vioapic)		mtx_owned(&((vioapic)->mtx))
+
+static MALLOC_DEFINE(M_VIOAPIC, "vioapic", "bhyve virtual ioapic");
+
+#define	VIOAPIC_CTR1(vioapic, fmt, a1)					\
+	VM_CTR1((vioapic)->vm, fmt, a1)
+
+#define	VIOAPIC_CTR2(vioapic, fmt, a1, a2)				\
+	VM_CTR2((vioapic)->vm, fmt, a1, a2)
+
+#define	VIOAPIC_CTR3(vioapic, fmt, a1, a2, a3)				\
+	VM_CTR3((vioapic)->vm, fmt, a1, a2, a3)
+
+#ifdef KTR
+static const char *
+pinstate_str(bool asserted)
+{
+
+	if (asserted)
+		return ("asserted");
+	else
+		return ("deasserted");
+}
+#endif
+
+static void
+vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate)
+{
+	int vector, apicid, vcpuid;
+	uint32_t low, high;
+	cpuset_t dmask;
+
+	KASSERT(pin >= 0 && pin < REDIR_ENTRIES,
+	    ("vioapic_set_pinstate: invalid pin number %d", pin));
+
+	KASSERT(VIOAPIC_LOCKED(vioapic),
+	    ("vioapic_set_pinstate: vioapic is not locked"));
+
+	VIOAPIC_CTR2(vioapic, "ioapic pin%d %s", pin, pinstate_str(newstate));
+
+	/* Nothing to do if interrupt pin has not changed state */
+	if (vioapic->rtbl[pin].pinstate == newstate)
+		return;
+
+	vioapic->rtbl[pin].pinstate = newstate;	/* record it */
+
+	/* Nothing to do if interrupt pin is deasserted */
+	if (!INTR_ASSERTED(vioapic, pin))
+		return;
+
+	/*
+	 * XXX
+	 * We only deal with:
+	 * - edge triggered interrupts
+	 * - fixed delivery mode
+	 *  Level-triggered sources will work so long as there is no sharing.
+	 */
+	low = vioapic->rtbl[pin].reg;
+	high = vioapic->rtbl[pin].reg >> 32;
+	if ((low & IOART_INTMASK) == IOART_INTMCLR &&
+	    (low & IOART_DESTMOD) == IOART_DESTPHY &&
+	    (low & IOART_DELMOD) == IOART_DELFIXED) {
+		vector = low & IOART_INTVEC;
+		apicid = high >> APIC_ID_SHIFT;
+		if (apicid != 0xff) {
+			/* unicast */
+			vcpuid = vm_apicid2vcpuid(vioapic->vm, apicid);
+			VIOAPIC_CTR3(vioapic, "ioapic pin%d triggering "
+			    "intr vector %d on vcpuid %d", pin, vector, vcpuid);
+			lapic_set_intr(vioapic->vm, vcpuid, vector);
+		} else {
+			/* broadcast */
+			VIOAPIC_CTR2(vioapic, "ioapic pin%d triggering intr "
+			    "vector %d on all vcpus", pin, vector);
+			dmask = vm_active_cpus(vioapic->vm);
+			while ((vcpuid = CPU_FFS(&dmask)) != 0) {
+				vcpuid--;
+				CPU_CLR(vcpuid, &dmask);
+				lapic_set_intr(vioapic->vm, vcpuid, vector);
+			}
+		}
+	} else if ((low & IOART_INTMASK) != IOART_INTMCLR &&
+		   (low & IOART_TRGRLVL) != 0) {
+		/*
+		 * For level-triggered interrupts that have been
+		 * masked, set the pending bit so that an interrupt
+		 * will be generated on unmask and if the level is
+		 * still asserted
+		 */
+		VIOAPIC_CTR1(vioapic, "ioapic pin%d interrupt pending", pin);
+		vioapic->rtbl[pin].pending = true;
+	}
+}
+
+static int
+vioapic_set_irqstate(struct vm *vm, int irq, bool state)
+{
+	struct vioapic *vioapic;
+
+	if (irq < 0 || irq >= REDIR_ENTRIES)
+		return (EINVAL);
+
+	vioapic = vm_ioapic(vm);
+
+	VIOAPIC_LOCK(vioapic);
+	vioapic_set_pinstate(vioapic, irq, state);
+	VIOAPIC_UNLOCK(vioapic);
+
+	return (0);
+}
+
+int
+vioapic_assert_irq(struct vm *vm, int irq)
+{
+
+	return (vioapic_set_irqstate(vm, irq, true));
+}
+
+int
+vioapic_deassert_irq(struct vm *vm, int irq)
+{
+
+	return (vioapic_set_irqstate(vm, irq, false));
+}
+
+static uint32_t
+vioapic_read(struct vioapic *vioapic, uint32_t addr)
+{
+	int regnum, pin, rshift;
+
+	regnum = addr & 0xff;
+	switch (regnum) {
+	case IOAPIC_ID:
+		return (vioapic->id);
+		break;
+	case IOAPIC_VER:
+		return ((REDIR_ENTRIES << MAXREDIRSHIFT) | 0x11);
+		break;
+	case IOAPIC_ARB:
+		return (vioapic->id);
+		break;
+	default:
+		break;
+	}
+
+	/* redirection table entries */
+	if (regnum >= IOAPIC_REDTBL &&
+	    regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
+		pin = (regnum - IOAPIC_REDTBL) / 2;
+		if ((regnum - IOAPIC_REDTBL) % 2)
+			rshift = 32;
+		else
+			rshift = 0;
+
+		return (vioapic->rtbl[pin].reg >> rshift);
+	}
+
+	return (0);
+}
+
+static void
+vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data)
+{
+	int regnum, pin, lshift;
+
+	regnum = addr & 0xff;
+	switch (regnum) {
+	case IOAPIC_ID:
+		vioapic->id = data & APIC_ID_MASK;
+		break;
+	case IOAPIC_VER:
+	case IOAPIC_ARB:
+		/* readonly */
+		break;
+	default:
+		break;
+	}
+
+	/* redirection table entries */
+	if (regnum >= IOAPIC_REDTBL &&
+	    regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
+		pin = (regnum - IOAPIC_REDTBL) / 2;
+		if ((regnum - IOAPIC_REDTBL) % 2)
+			lshift = 32;
+		else
+			lshift = 0;
+
+		vioapic->rtbl[pin].reg &= ~((uint64_t)0xffffffff << lshift);
+		vioapic->rtbl[pin].reg |= ((uint64_t)data << lshift);
+
+		VIOAPIC_CTR2(vioapic, "ioapic pin%d redir table entry %#lx",
+		    pin, vioapic->rtbl[pin].reg);
+
+		if (vioapic->rtbl[pin].pending &&
+		    ((vioapic->rtbl[pin].reg & IOART_INTMASK) ==
+		    IOART_INTMCLR)) {
+			vioapic->rtbl[pin].pending = false;
+			/*
+			 * Inject the deferred level-triggered int if it is
+			 * still asserted. Simulate by toggling the pin
+			 * off and then on.
+			 */
+			if (vioapic->rtbl[pin].pinstate == true) {
+				VIOAPIC_CTR1(vioapic, "ioapic pin%d pending "
+				    "interrupt delivered", pin);
+				vioapic_set_pinstate(vioapic, pin, false);
+				vioapic_set_pinstate(vioapic, pin, true);
+			} else {
+				VIOAPIC_CTR1(vioapic, "ioapic pin%d pending "
+				    "interrupt dismissed", pin);
+			}
+		}
+	}
+}
+
+static int
+vioapic_mmio_rw(struct vioapic *vioapic, uint64_t gpa, uint64_t *data,
+    int size, bool doread)
+{
+	uint64_t offset;
+
+	offset = gpa - VIOAPIC_BASE;
+
+	/*
+	 * The IOAPIC specification allows 32-bit wide accesses to the
+	 * IOREGSEL (offset 0) and IOWIN (offset 16) registers.
+	 */
+	if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
+		if (doread)
+			*data = 0;
+		return (0);
+	}
+
+	VIOAPIC_LOCK(vioapic);
+	if (offset == IOREGSEL) {
+		if (doread)
+			*data = vioapic->ioregsel;
+		else
+			vioapic->ioregsel = *data;
+	} else {
+		if (doread)
+			*data = vioapic_read(vioapic, vioapic->ioregsel);
+		else
+			vioapic_write(vioapic, vioapic->ioregsel, *data);
+	}
+	VIOAPIC_UNLOCK(vioapic);
+
+	return (0);
+}
+
+int
+vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa, uint64_t *rval,
+    int size, void *arg)
+{
+	int error;
+	struct vioapic *vioapic;
+
+	vioapic = vm_ioapic(vm);
+	error = vioapic_mmio_rw(vioapic, gpa, rval, size, true);
+	return (error);
+}
+
+int
+vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa, uint64_t wval,
+    int size, void *arg)
+{
+	int error;
+	struct vioapic *vioapic;
+
+	vioapic = vm_ioapic(vm);
+	error = vioapic_mmio_rw(vioapic, gpa, &wval, size, false);
+	return (error);
+}
+
+struct vioapic *
+vioapic_init(struct vm *vm)
+{
+	int i;
+	struct vioapic *vioapic;
+
+	vioapic = malloc(sizeof(struct vioapic), M_VIOAPIC, M_WAITOK | M_ZERO);
+
+	vioapic->vm = vm;
+	mtx_init(&vioapic->mtx, "vioapic lock", NULL, MTX_DEF);
+
+	/* Initialize all redirection entries to mask all interrupts */
+	for (i = 0; i < REDIR_ENTRIES; i++)
+		vioapic->rtbl[i].reg = 0x0001000000010000UL;
+
+	return (vioapic);
+}
+
+void
+vioapic_cleanup(struct vioapic *vioapic)
+{
+
+	free(vioapic, M_VIOAPIC);
+}

Added: head/sys/amd64/vmm/io/vioapic.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/amd64/vmm/io/vioapic.h	Tue Nov 12 22:51:03 2013	(r258075)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale at pluribusnetworks.com>
+ * Copyright (c) 2013 Neel Natu <neel at freebsd.org>
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VIOAPIC_H_
+#define	_VIOAPIC_H_
+
+struct vm;
+struct vioapic;
+
+#define	VIOAPIC_BASE	0xFEC00000
+#define	VIOAPIC_SIZE	4096
+
+struct vioapic *vioapic_init(struct vm *vm);
+void	vioapic_cleanup(struct vioapic *vioapic);
+
+int	vioapic_assert_irq(struct vm *vm, int irq);
+int	vioapic_deassert_irq(struct vm *vm, int irq);
+
+int	vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa,
+	    uint64_t wval, int size, void *arg);
+int	vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa,
+	    uint64_t *rval, int size, void *arg);
+#endif

Modified: head/sys/amd64/vmm/vmm.c
==============================================================================
--- head/sys/amd64/vmm/vmm.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/sys/amd64/vmm/vmm.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -59,11 +59,13 @@ __FBSDID("$FreeBSD$");
 #include <machine/vmparam.h>
 
 #include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
 #include "vmm_ktr.h"
 #include "vmm_host.h"
 #include "vmm_mem.h"
 #include "vmm_util.h"
-#include <machine/vmm_dev.h>
+#include "vioapic.h"
 #include "vlapic.h"
 #include "vmm_msr.h"
 #include "vmm_ipi.h"
@@ -106,6 +108,7 @@ struct mem_seg {
 struct vm {
 	void		*cookie;	/* processor-specific data */
 	void		*iommu;		/* iommu-specific data */
+	struct vioapic	*vioapic;	/* virtual ioapic */
 	struct vmspace	*vmspace;	/* guest's address space */
 	struct vcpu	vcpu[VM_MAXCPU];
 	int		num_mem_segs;
@@ -300,6 +303,7 @@ vm_create(const char *name, struct vm **
 	vm = malloc(sizeof(struct vm), M_VM, M_WAITOK | M_ZERO);
 	strcpy(vm->name, name);
 	vm->cookie = VMINIT(vm, vmspace_pmap(vmspace));
+	vm->vioapic = vioapic_init(vm);
 
 	for (i = 0; i < VM_MAXCPU; i++) {
 		vcpu_init(vm, i);
@@ -341,6 +345,8 @@ vm_destroy(struct vm *vm)
 	for (i = 0; i < VM_MAXCPU; i++)
 		vcpu_cleanup(&vm->vcpu[i]);
 
+	vioapic_cleanup(vm->vioapic);
+
 	VMSPACE_FREE(vm->vmspace);
 
 	VMCLEANUP(vm->cookie);
@@ -938,6 +944,8 @@ vm_handle_inst_emul(struct vm *vm, int v
 	struct vm_exit *vme;
 	int error, inst_length;
 	uint64_t rip, gla, gpa, cr3;
+	mem_region_read_t mread;
+	mem_region_write_t mwrite;
 
 	vcpu = &vm->vcpu[vcpuid];
 	vme = &vcpu->exitinfo;
@@ -960,13 +968,18 @@ vm_handle_inst_emul(struct vm *vm, int v
 		return (EFAULT);
 
 	/* return to userland unless this is a local apic access */
-	if (gpa < DEFAULT_APIC_BASE || gpa >= DEFAULT_APIC_BASE + PAGE_SIZE) {
+	if (gpa >= DEFAULT_APIC_BASE && gpa < DEFAULT_APIC_BASE + PAGE_SIZE) {
+		mread = lapic_mmio_read;
+		mwrite = lapic_mmio_write;
+	} else if (gpa >= VIOAPIC_BASE && gpa < VIOAPIC_BASE + VIOAPIC_SIZE) {
+		mread = vioapic_mmio_read;
+		mwrite = vioapic_mmio_write;
+	} else {
 		*retu = TRUE;
 		return (0);
 	}
 
-	error = vmm_emulate_instruction(vm, vcpuid, gpa, vie,
-					lapic_mmio_read, lapic_mmio_write, 0);
+	error = vmm_emulate_instruction(vm, vcpuid, gpa, vie, mread, mwrite, 0);
 
 	/* return to userland to spin up the AP */
 	if (error == 0 && vme->exitcode == VM_EXITCODE_SPINUP_AP)
@@ -1149,6 +1162,13 @@ vm_lapic(struct vm *vm, int cpu)
 	return (vm->vcpu[cpu].vlapic);
 }
 
+struct vioapic *
+vm_ioapic(struct vm *vm)
+{
+
+	return (vm->vioapic);
+}
+
 boolean_t
 vmm_is_pptdev(int bus, int slot, int func)
 {
@@ -1313,3 +1333,12 @@ vm_get_vmspace(struct vm *vm)
 
 	return (vm->vmspace);
 }
+
+int
+vm_apicid2vcpuid(struct vm *vm, int apicid)
+{
+	/*
+	 * XXX apic id is assumed to be numerically identical to vcpu id
+	 */
+	return (apicid);
+}

Modified: head/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- head/sys/amd64/vmm/vmm_dev.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/sys/amd64/vmm/vmm_dev.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include "vmm_stat.h"
 #include "vmm_mem.h"
 #include "io/ppt.h"
+#include "io/vioapic.h"
 #include <machine/vmm_dev.h>
 
 struct vmmdev_softc {
@@ -146,10 +147,11 @@ vmmdev_ioctl(struct cdev *cdev, u_long c
 	struct vmmdev_softc *sc;
 	struct vm_memory_segment *seg;
 	struct vm_register *vmreg;
-	struct vm_seg_desc* vmsegdesc;
+	struct vm_seg_desc *vmsegdesc;
 	struct vm_run *vmrun;
 	struct vm_event *vmevent;
 	struct vm_lapic_irq *vmirq;
+	struct vm_ioapic_irq *ioapic_irq;
 	struct vm_capability *vmcap;
 	struct vm_pptdev *pptdev;
 	struct vm_pptdev_mmio *pptmmio;
@@ -293,6 +295,14 @@ vmmdev_ioctl(struct cdev *cdev, u_long c
 		vmirq = (struct vm_lapic_irq *)data;
 		error = lapic_set_intr(sc->vm, vmirq->cpuid, vmirq->vector);
 		break;
+	case VM_IOAPIC_ASSERT_IRQ:
+		ioapic_irq = (struct vm_ioapic_irq *)data;
+		error = vioapic_assert_irq(sc->vm, ioapic_irq->irq);
+		break;
+	case VM_IOAPIC_DEASSERT_IRQ:
+		ioapic_irq = (struct vm_ioapic_irq *)data;
+		error = vioapic_deassert_irq(sc->vm, ioapic_irq->irq);
+		break;
 	case VM_MAP_MEMORY:
 		seg = (struct vm_memory_segment *)data;
 		error = vm_malloc(sc->vm, seg->gpa, seg->len);

Modified: head/sys/modules/vmm/Makefile
==============================================================================
--- head/sys/modules/vmm/Makefile	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/sys/modules/vmm/Makefile	Tue Nov 12 22:51:03 2013	(r258075)
@@ -27,6 +27,7 @@ SRCS+=	vmm.c		\
 .PATH: ${.CURDIR}/../../amd64/vmm/io
 SRCS+=	iommu.c		\
 	ppt.c           \
+	vioapic.c	\
 	vlapic.c
 
 # intel-specific files

Modified: head/usr.sbin/bhyve/Makefile
==============================================================================
--- head/usr.sbin/bhyve/Makefile	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/usr.sbin/bhyve/Makefile	Tue Nov 12 22:51:03 2013	(r258075)
@@ -7,7 +7,7 @@ PROG=	bhyve
 DEBUG_FLAGS= -g -O0 
 
 SRCS=	acpi.c atpic.c bhyverun.c block_if.c consport.c dbgport.c elcr.c
-SRCS+=  inout.c ioapic.c legacy_irq.c mem.c mevent.c mptbl.c pci_ahci.c
+SRCS+=  inout.c legacy_irq.c mem.c mevent.c mptbl.c pci_ahci.c
 SRCS+=	pci_emul.c pci_hostbridge.c pci_lpc.c pci_passthru.c pci_virtio_block.c
 SRCS+=	pci_virtio_net.c pci_uart.c pit_8254.c pmtmr.c post.c rtc.c
 SRCS+=	uart_emul.c virtio.c xmsr.c spinup_ap.c

Modified: head/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- head/usr.sbin/bhyve/bhyverun.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/usr.sbin/bhyve/bhyverun.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
 #include "pci_emul.h"
 #include "pci_lpc.h"
 #include "xmsr.h"
-#include "ioapic.h"
 #include "spinup_ap.h"
 #include "rtc.h"
 
@@ -663,8 +662,6 @@ main(int argc, char *argv[])
 	if (init_pci(ctx) != 0)
 		exit(1);
 
-	ioapic_init(0);
-
 	if (gdb_port != 0)
 		init_dbgport(gdb_port);
 

Modified: head/usr.sbin/bhyve/pci_emul.c
==============================================================================
--- head/usr.sbin/bhyve/pci_emul.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/usr.sbin/bhyve/pci_emul.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
 #include "legacy_irq.h"
 #include "mem.h"
 #include "pci_emul.h"
-#include "ioapic.h"
 
 #define CONF1_ADDR_PORT    0x0cf8
 #define CONF1_DATA_PORT    0x0cfc
@@ -1136,7 +1135,7 @@ pci_lintr_assert(struct pci_devinst *pi)
 {
 
 	assert(pi->pi_lintr_pin >= 0);
-	ioapic_assert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
+	vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr_pin);
 }
 
 void
@@ -1144,7 +1143,7 @@ pci_lintr_deassert(struct pci_devinst *p
 {
 
 	assert(pi->pi_lintr_pin >= 0);
-	ioapic_deassert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
+	vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr_pin);
 }
 
 /*

Modified: head/usr.sbin/bhyve/pci_lpc.c
==============================================================================
--- head/usr.sbin/bhyve/pci_lpc.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/usr.sbin/bhyve/pci_lpc.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -31,13 +31,16 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include <vmmapi.h>
+
 #include "inout.h"
-#include "ioapic.h"
 #include "pci_emul.h"
 #include "uart_emul.h"
 
@@ -91,7 +94,7 @@ lpc_uart_intr_assert(void *arg)
 
 	assert(sc->irq >= 0);
 
-	ioapic_assert_pin(lpc_bridge->pi_vmctx, sc->irq);
+	vm_ioapic_assert_irq(lpc_bridge->pi_vmctx, sc->irq);
 }
 
 static void
@@ -101,7 +104,7 @@ lpc_uart_intr_deassert(void *arg)
 
 	assert(sc->irq >= 0);
 
-	ioapic_deassert_pin(lpc_bridge->pi_vmctx, sc->irq);
+	vm_ioapic_deassert_irq(lpc_bridge->pi_vmctx, sc->irq);
 }
 
 static int

Modified: head/usr.sbin/bhyve/pit_8254.c
==============================================================================
--- head/usr.sbin/bhyve/pit_8254.c	Tue Nov 12 22:43:27 2013	(r258074)
+++ head/usr.sbin/bhyve/pit_8254.c	Tue Nov 12 22:51:03 2013	(r258075)
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
 
 #include "bhyverun.h"
 #include "inout.h"
-#include "ioapic.h"
 #include "mevent.h"
 #include "pit_8254.h"
 
@@ -106,8 +105,8 @@ pit_mevent_cb(int fd, enum ev_type type,
 
 	pit_mev_count++;
 
-	ioapic_assert_pin(c->ctx, 2);
-	ioapic_deassert_pin(c->ctx, 2);
+	vm_ioapic_assert_irq(c->ctx, 2);
+	vm_ioapic_deassert_irq(c->ctx, 2);
 
 	/*
 	 * Delete the timer for one-shots


More information about the svn-src-head mailing list