Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Aug 2012 00:00:52 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r239045 - projects/bhyve/usr.sbin/bhyve
Message-ID:  <201208050000.q7500qnJ012724@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Sun Aug  5 00:00:52 2012
New Revision: 239045
URL: http://svn.freebsd.org/changeset/base/239045

Log:
  Device model for ioapic emulation.
  
  With this change the uart emulation is entirely interrupt driven.
  
  Obtained from: NetApp

Added:
  projects/bhyve/usr.sbin/bhyve/ioapic.c   (contents, props changed)
  projects/bhyve/usr.sbin/bhyve/ioapic.h   (contents, props changed)
Modified:
  projects/bhyve/usr.sbin/bhyve/Makefile
  projects/bhyve/usr.sbin/bhyve/fbsdrun.c
  projects/bhyve/usr.sbin/bhyve/pci_emul.c

Modified: projects/bhyve/usr.sbin/bhyve/Makefile
==============================================================================
--- projects/bhyve/usr.sbin/bhyve/Makefile	Sat Aug  4 23:51:21 2012	(r239044)
+++ projects/bhyve/usr.sbin/bhyve/Makefile	Sun Aug  5 00:00:52 2012	(r239045)
@@ -5,7 +5,7 @@
 PROG=	bhyve
 
 SRCS=	atpic.c consport.c dbgport.c elcr.c fbsdrun.c inout.c 
-SRCS+=  instruction_emul.c mevent.c
+SRCS+=  instruction_emul.c ioapic.c mevent.c
 SRCS+=	pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c
 SRCS+=	pci_virtio_net.c pci_uart.c pit_8254.c post.c rtc.c uart.c xmsr.c
 

Modified: projects/bhyve/usr.sbin/bhyve/fbsdrun.c
==============================================================================
--- projects/bhyve/usr.sbin/bhyve/fbsdrun.c	Sat Aug  4 23:51:21 2012	(r239044)
+++ projects/bhyve/usr.sbin/bhyve/fbsdrun.c	Sun Aug  5 00:00:52 2012	(r239045)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #include "pci_emul.h"
 #include "xmsr.h"
 #include "instruction_emul.h"
+#include "ioapic.h"
 
 #define	DEFAULT_GUEST_HZ	100
 #define	DEFAULT_GUEST_TSLICE	200
@@ -651,6 +652,8 @@ main(int argc, char *argv[])
 
 	init_inout();
 	init_pci(ctx);
+	if (ioapic)
+		ioapic_init(0);
 
 	if (gdb_port != 0)
 		init_dbgport(gdb_port);

Added: projects/bhyve/usr.sbin/bhyve/ioapic.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve/usr.sbin/bhyve/ioapic.c	Sun Aug  5 00:00:52 2012	(r239045)
@@ -0,0 +1,302 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * 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/types.h>
+
+#include <x86/apicreg.h>
+#include <machine/vmm.h>
+
+#include <string.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include <vmmapi.h>
+
+#include "inout.h"
+#include "instruction_emul.h"
+#include "fbsdrun.h"
+
+#include <stdio.h>
+
+#define	IOAPIC_PADDR	0xFEC00000
+
+#define	IOREGSEL	0x00
+#define	IOWIN		0x10
+
+#define	REDIR_ENTRIES	16
+#define	INTR_ASSERTED(ioapic, pin)	((ioapic)->pinstate[(pin)] == true)
+
+struct ioapic {
+	int		inited;
+	uint32_t	id;
+	uint64_t	redtbl[REDIR_ENTRIES];
+	bool		pinstate[REDIR_ENTRIES];
+
+	uintptr_t	paddr;		/* gpa where the ioapic is mapped */
+	uint32_t	ioregsel;
+	struct memory_region *region;
+};
+
+static struct ioapic ioapics[1];	/* only a single ioapic for now */
+
+static int ioapic_region_read(struct vmctx *vm, int vcpu, uintptr_t paddr,
+				int size, uint64_t *data, void *arg);
+static int ioapic_region_write(struct vmctx *vm, int vcpu, uintptr_t paddr,
+				int size, uint64_t data, void *arg);
+
+static void
+ioapic_set_pinstate(struct vmctx *ctx, int pin, bool newstate)
+{
+	int vector, apicid, vcpu;
+	uint32_t low, high;
+	struct ioapic *ioapic;
+	
+	ioapic = &ioapics[0];		/* assume a single ioapic */
+
+	if (pin < 0 || pin >= REDIR_ENTRIES)
+		return;
+
+	/* Nothing to do if interrupt pin has not changed state */
+	if (ioapic->pinstate[pin] == newstate)
+		return;
+
+	ioapic->pinstate[pin] = newstate;	/* record it */
+
+	/* Nothing to do if interrupt pin is deasserted */
+	if (!INTR_ASSERTED(ioapic, pin))
+		return;
+
+	/*
+	 * XXX
+	 * We only deal with:
+	 * - edge triggered interrupts
+	 * - physical destination mode
+	 * - fixed delivery mode
+	 */
+	low = ioapic->redtbl[pin];
+	high = ioapic->redtbl[pin] >> 32;
+	if ((low & IOART_INTMASK) == IOART_INTMCLR &&
+	    (low & IOART_TRGRMOD) == IOART_TRGREDG &&
+	    (low & IOART_DESTMOD) == IOART_DESTPHY &&
+	    (low & IOART_DELMOD) == IOART_DELFIXED) {
+		vector = low & IOART_INTVEC;
+		apicid = high >> APIC_ID_SHIFT;
+		if (apicid != 0xff) {
+			/* unicast */
+			vcpu = vm_apicid2vcpu(ctx, apicid);
+			vm_lapic_irq(ctx, vcpu, vector);
+		} else {
+			/* broadcast */
+			vcpu = 0;
+			while (vcpu < guest_ncpus) {
+				vm_lapic_irq(ctx, vcpu, vector);
+				vcpu++;
+			}
+		}
+	}
+}
+
+void
+ioapic_deassert_pin(struct vmctx *ctx, int pin)
+{
+	ioapic_set_pinstate(ctx, pin, false);
+}
+
+void
+ioapic_assert_pin(struct vmctx *ctx, int pin)
+{
+	ioapic_set_pinstate(ctx, pin, true);
+}
+
+void
+ioapic_init(int which)
+{
+	int i;
+	struct ioapic *ioapic;
+
+	assert(which == 0);
+
+	ioapic = &ioapics[which];
+	assert(ioapic->inited == 0);
+
+	bzero(ioapic, sizeof(struct ioapic));
+
+	/* Initialize all redirection entries to mask all interrupts */
+	for (i = 0; i < REDIR_ENTRIES; i++)
+		ioapic->redtbl[i] = 0x0001000000010000UL;
+
+	/* Register emulated memory region */
+	ioapic->paddr = IOAPIC_PADDR;
+	ioapic->region = register_emulated_memory(ioapic->paddr,
+						  sizeof(struct IOAPIC),
+						  ioapic_region_read,
+						  ioapic_region_write,
+						  (void *)(uintptr_t)which);
+	assert(ioapic->region != NULL);
+
+	ioapic->inited = 1;
+}
+
+static uint32_t
+ioapic_read(struct ioapic *ioapic, uint32_t addr)
+{
+	int regnum, pin, rshift;
+
+	assert(ioapic->inited);
+
+	regnum = addr & 0xff;
+	switch (regnum) {
+	case IOAPIC_ID:
+		return (ioapic->id);
+		break;
+	case IOAPIC_VER:
+		return ((REDIR_ENTRIES << MAXREDIRSHIFT) | 0x11);
+		break;
+	case IOAPIC_ARB:
+		return (ioapic->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 (ioapic->redtbl[pin] >> rshift);
+	}
+
+	return (0);
+}
+
+static void
+ioapic_write(struct ioapic *ioapic, uint32_t addr, uint32_t data)
+{
+	int regnum, pin, lshift;
+
+	assert(ioapic->inited);
+
+	regnum = addr & 0xff;
+	switch (regnum) {
+	case IOAPIC_ID:
+		ioapic->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;
+
+		ioapic->redtbl[pin] &= ~((uint64_t)0xffffffff << lshift);
+		ioapic->redtbl[pin] |= ((uint64_t)data << lshift);
+	}
+}
+
+static int
+ioapic_region_read(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
+		   uint64_t *data, void *arg)
+{
+	int which, offset;
+	struct ioapic *ioapic;
+
+	which = (uintptr_t)arg;
+
+	ioapic = &ioapics[which];
+	offset = paddr - ioapic->paddr;
+
+	/*
+	 * 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 1
+		printf("invalid access to ioapic%d: size %d, offset %d\n",
+			which, size, offset);
+#endif
+		*data = 0;
+		return (0);
+	}
+
+	if (offset == IOREGSEL)
+		*data = ioapic->ioregsel;
+	else
+		*data = ioapic_read(ioapic, ioapic->ioregsel);
+
+	return (0);
+}
+
+static int
+ioapic_region_write(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
+		    uint64_t data, void *arg)
+{
+	int which, offset;
+	struct ioapic *ioapic;
+
+	which = (uintptr_t)arg;
+
+	ioapic = &ioapics[which];
+	offset = paddr - ioapic->paddr;
+
+	/*
+	 * 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 1
+		printf("invalid access to ioapic%d: size %d, offset %d\n",
+			which, size, offset);
+#endif
+		return (0);
+	}
+
+	if (offset == IOREGSEL)
+		ioapic->ioregsel = data;
+	else
+		ioapic_write(ioapic, ioapic->ioregsel, data);
+
+	return (0);
+}

Added: projects/bhyve/usr.sbin/bhyve/ioapic.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve/usr.sbin/bhyve/ioapic.h	Sun Aug  5 00:00:52 2012	(r239045)
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * 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 _IOAPIC_H_
+#define	_IOAPIC_H_
+
+struct vmctx;
+
+void	ioapic_init(int num);
+void	ioapic_deassert_pin(struct vmctx *ctx, int pin);
+void	ioapic_assert_pin(struct vmctx *ctx, int pin);
+
+#endif

Modified: projects/bhyve/usr.sbin/bhyve/pci_emul.c
==============================================================================
--- projects/bhyve/usr.sbin/bhyve/pci_emul.c	Sat Aug  4 23:51:21 2012	(r239044)
+++ projects/bhyve/usr.sbin/bhyve/pci_emul.c	Sun Aug  5 00:00:52 2012	(r239045)
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
 #include "inout.h"
 #include "pci_emul.h"
 #include "instruction_emul.h"
+#include "ioapic.h"
 
 #define CONF1_ADDR_PORT    0x0cf8
 #define CONF1_DATA_PORT    0x0cfc
@@ -835,7 +836,7 @@ pci_lintr_assert(struct pci_devinst *pi)
 {
 
 	assert(pi->pi_lintr_pin);
-	/* ioapic_assert_pin(pi->pi_vmctx, pi->pi_lintr_pin); */
+	ioapic_assert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
 }
 
 void
@@ -843,7 +844,7 @@ pci_lintr_deassert(struct pci_devinst *p
 {
 
 	assert(pi->pi_lintr_pin);
-	/* ioapic_deassert_pin(pi->pi_vmctx, pi->pi_lintr_pin); */
+	ioapic_deassert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
 }
 
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208050000.q7500qnJ012724>