From owner-svn-src-projects@FreeBSD.ORG Sun Aug 5 00:00:53 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 187A61065672; Sun, 5 Aug 2012 00:00:53 +0000 (UTC) (envelope-from neel@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 032718FC0C; Sun, 5 Aug 2012 00:00:53 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7500qIp012730; Sun, 5 Aug 2012 00:00:52 GMT (envelope-from neel@svn.freebsd.org) Received: (from neel@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7500qnJ012724; Sun, 5 Aug 2012 00:00:52 GMT (envelope-from neel@svn.freebsd.org) Message-Id: <201208050000.q7500qnJ012724@svn.freebsd.org> From: Neel Natu Date: Sun, 5 Aug 2012 00:00:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239045 - projects/bhyve/usr.sbin/bhyve X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Aug 2012 00:00:53 -0000 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 +__FBSDID("$FreeBSD$"); + +#include + +#include +#include + +#include +#include +#include + +#include + +#include "inout.h" +#include "instruction_emul.h" +#include "fbsdrun.h" + +#include + +#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); }