diff options
author | neel <neel@FreeBSD.org> | 2013-11-12 22:51:03 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2013-11-12 22:51:03 +0000 |
commit | 384d86e8883acf1387f02c9f3ec34798f973dd62 (patch) | |
tree | c5c556e061b1f182036d3b8ffc028cc9c7a83e2d /usr.sbin/bhyve | |
parent | e41d2fd565cf8d3945a0bbfc72489332deb7ae0d (diff) | |
download | FreeBSD-src-384d86e8883acf1387f02c9f3ec34798f973dd62.zip FreeBSD-src-384d86e8883acf1387f02c9f3ec34798f973dd62.tar.gz |
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@pluribusnetworks.com)
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r-- | usr.sbin/bhyve/Makefile | 2 | ||||
-rw-r--r-- | usr.sbin/bhyve/bhyverun.c | 3 | ||||
-rw-r--r-- | usr.sbin/bhyve/ioapic.c | 378 | ||||
-rw-r--r-- | usr.sbin/bhyve/ioapic.h | 38 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_emul.c | 5 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_lpc.c | 9 | ||||
-rw-r--r-- | usr.sbin/bhyve/pit_8254.c | 5 |
7 files changed, 11 insertions, 429 deletions
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index 570182e..a08341f 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -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 diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 8263602..652f402 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -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); diff --git a/usr.sbin/bhyve/ioapic.c b/usr.sbin/bhyve/ioapic.c deleted file mode 100644 index b996214..0000000 --- a/usr.sbin/bhyve/ioapic.c +++ /dev/null @@ -1,378 +0,0 @@ -/*- - * 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 <pthread.h> - -#include <vmmapi.h> - -#include "inout.h" -#include "mem.h" -#include "bhyverun.h" - -#include <stdio.h> - -static uint64_t ioapic_clearpend, ioapic_togglepend, ioapic_setpend; - -#define IOAPIC_PADDR 0xFEC00000 - -#define IOREGSEL 0x00 -#define IOWIN 0x10 - -#define REDIR_ENTRIES 16 -#define INTR_ASSERTED(ioapic, pin) \ - ((ioapic)->rtbl[(pin)].pinstate == true) - -struct ioapic { - int inited; - uint32_t id; - struct { - uint64_t reg; - bool pinstate; - bool pending; - } rtbl[REDIR_ENTRIES]; - - uintptr_t paddr; /* gpa where the ioapic is mapped */ - uint32_t ioregsel; - struct memory_region *region; - pthread_mutex_t mtx; -}; - -static struct ioapic ioapics[1]; /* only a single ioapic for now */ - -static int ioapic_region_read(struct vmctx *vm, struct ioapic *ioapic, - uintptr_t paddr, int size, uint64_t *data); -static int ioapic_region_write(struct vmctx *vm, struct ioapic *ioapic, - uintptr_t paddr, int size, uint64_t data); -static int ioapic_region_handler(struct vmctx *vm, int vcpu, int dir, - uintptr_t paddr, int size, uint64_t *val, void *arg1, long arg2); - -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 */ - - /* Nothing to do if interrupt pin has not changed state */ - if (ioapic->rtbl[pin].pinstate == newstate) - return; - - ioapic->rtbl[pin].pinstate = 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 - * - fixed delivery mode - * Level-triggered sources will work so long as there is - * no sharing. - */ - low = ioapic->rtbl[pin].reg; - high = ioapic->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 */ - 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++; - } - } - } else if ((low & IOART_INTMASK) != IOART_INTMCLR && - low & IOART_TRGRLVL) { - /* - * 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 - */ - ioapic_setpend++; - ioapic->rtbl[pin].pending = true; - } -} - -static void -ioapic_set_pinstate_locked(struct vmctx *ctx, int pin, bool newstate) -{ - struct ioapic *ioapic; - - if (pin < 0 || pin >= REDIR_ENTRIES) - return; - - ioapic = &ioapics[0]; - - pthread_mutex_lock(&ioapic->mtx); - ioapic_set_pinstate(ctx, pin, newstate); - pthread_mutex_unlock(&ioapic->mtx); -} - -/* - * External entry points require locking - */ -void -ioapic_deassert_pin(struct vmctx *ctx, int pin) -{ - ioapic_set_pinstate_locked(ctx, pin, false); -} - -void -ioapic_assert_pin(struct vmctx *ctx, int pin) -{ - ioapic_set_pinstate_locked(ctx, pin, true); -} - -void -ioapic_init(int which) -{ - struct mem_range memp; - struct ioapic *ioapic; - int error; - int i; - - assert(which == 0); - - ioapic = &ioapics[which]; - assert(ioapic->inited == 0); - - bzero(ioapic, sizeof(struct ioapic)); - - pthread_mutex_init(&ioapic->mtx, NULL); - - /* Initialize all redirection entries to mask all interrupts */ - for (i = 0; i < REDIR_ENTRIES; i++) - ioapic->rtbl[i].reg = 0x0001000000010000UL; - - ioapic->paddr = IOAPIC_PADDR; - - /* Register emulated memory region */ - memp.name = "ioapic"; - memp.flags = MEM_F_RW; - memp.handler = ioapic_region_handler; - memp.arg1 = ioapic; - memp.arg2 = which; - memp.base = ioapic->paddr; - memp.size = sizeof(struct IOAPIC); - error = register_mem(&memp); - - assert (error == 0); - - 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->rtbl[pin].reg >> rshift); - } - - return (0); -} - -static void -ioapic_write(struct vmctx *vm, 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->rtbl[pin].reg &= ~((uint64_t)0xffffffff << lshift); - ioapic->rtbl[pin].reg |= ((uint64_t)data << lshift); - - if (ioapic->rtbl[pin].pending && - ((ioapic->rtbl[pin].reg & IOART_INTMASK) == - IOART_INTMCLR)) { - ioapic->rtbl[pin].pending = false; - ioapic_clearpend++; - /* - * Inject the deferred level-triggered int if it is - * still asserted. Simulate by toggling the pin - * off and then on. - */ - if (ioapic->rtbl[pin].pinstate == true) { - ioapic_togglepend++; - ioapic_set_pinstate(vm, pin, false); - ioapic_set_pinstate(vm, pin, true); - } - } - } -} - -static int -ioapic_region_read(struct vmctx *vm, struct ioapic *ioapic, uintptr_t paddr, - int size, uint64_t *data) -{ - int offset; - - 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", - (int)(ioapic - ioapics), 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, struct ioapic *ioapic, uintptr_t paddr, - int size, uint64_t data) -{ - int offset; - - 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", - (int)(ioapic - ioapics), size, offset); -#endif - return (0); - } - - if (offset == IOREGSEL) - ioapic->ioregsel = data; - else - ioapic_write(vm, ioapic, ioapic->ioregsel, data); - - return (0); -} - -static int -ioapic_region_handler(struct vmctx *vm, int vcpu, int dir, uintptr_t paddr, - int size, uint64_t *val, void *arg1, long arg2) -{ - struct ioapic *ioapic; - int which; - - ioapic = arg1; - which = arg2; - - assert(ioapic == &ioapics[which]); - - pthread_mutex_lock(&ioapic->mtx); - if (dir == MEM_F_READ) - ioapic_region_read(vm, ioapic, paddr, size, val); - else - ioapic_region_write(vm, ioapic, paddr, size, *val); - pthread_mutex_unlock(&ioapic->mtx); - - return (0); -} diff --git a/usr.sbin/bhyve/ioapic.h b/usr.sbin/bhyve/ioapic.h deleted file mode 100644 index 4696f9a..0000000 --- a/usr.sbin/bhyve/ioapic.h +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * 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 diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index 3820b04..fd087fa 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -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 *pi) { 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); } /* diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c index 9fd5f5c..5dc79e0 100644 --- a/usr.sbin/bhyve/pci_lpc.c +++ b/usr.sbin/bhyve/pci_lpc.c @@ -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 diff --git a/usr.sbin/bhyve/pit_8254.c b/usr.sbin/bhyve/pit_8254.c index 88c2d22..fd05b00 100644 --- a/usr.sbin/bhyve/pit_8254.c +++ b/usr.sbin/bhyve/pit_8254.c @@ -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, void *param) 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 |