Device model for ioapic emulation.
With this change the uart emulation is entirely interrupt driven. Obtained from: NetApp
This commit is contained in:
parent
da91bbd7a7
commit
b0b53d3af9
usr.sbin/bhyve
@ -5,7 +5,7 @@
|
|||||||
PROG= bhyve
|
PROG= bhyve
|
||||||
|
|
||||||
SRCS= atpic.c consport.c dbgport.c elcr.c fbsdrun.c inout.c
|
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_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
|
SRCS+= pci_virtio_net.c pci_uart.c pit_8254.c post.c rtc.c uart.c xmsr.c
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "pci_emul.h"
|
#include "pci_emul.h"
|
||||||
#include "xmsr.h"
|
#include "xmsr.h"
|
||||||
#include "instruction_emul.h"
|
#include "instruction_emul.h"
|
||||||
|
#include "ioapic.h"
|
||||||
|
|
||||||
#define DEFAULT_GUEST_HZ 100
|
#define DEFAULT_GUEST_HZ 100
|
||||||
#define DEFAULT_GUEST_TSLICE 200
|
#define DEFAULT_GUEST_TSLICE 200
|
||||||
@ -651,6 +652,8 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
init_inout();
|
init_inout();
|
||||||
init_pci(ctx);
|
init_pci(ctx);
|
||||||
|
if (ioapic)
|
||||||
|
ioapic_init(0);
|
||||||
|
|
||||||
if (gdb_port != 0)
|
if (gdb_port != 0)
|
||||||
init_dbgport(gdb_port);
|
init_dbgport(gdb_port);
|
||||||
|
302
usr.sbin/bhyve/ioapic.c
Normal file
302
usr.sbin/bhyve/ioapic.c
Normal file
@ -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);
|
||||||
|
}
|
38
usr.sbin/bhyve/ioapic.h
Normal file
38
usr.sbin/bhyve/ioapic.h
Normal file
@ -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
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "inout.h"
|
#include "inout.h"
|
||||||
#include "pci_emul.h"
|
#include "pci_emul.h"
|
||||||
#include "instruction_emul.h"
|
#include "instruction_emul.h"
|
||||||
|
#include "ioapic.h"
|
||||||
|
|
||||||
#define CONF1_ADDR_PORT 0x0cf8
|
#define CONF1_ADDR_PORT 0x0cf8
|
||||||
#define CONF1_DATA_PORT 0x0cfc
|
#define CONF1_DATA_PORT 0x0cfc
|
||||||
@ -835,7 +836,7 @@ pci_lintr_assert(struct pci_devinst *pi)
|
|||||||
{
|
{
|
||||||
|
|
||||||
assert(pi->pi_lintr_pin);
|
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
|
void
|
||||||
@ -843,7 +844,7 @@ pci_lintr_deassert(struct pci_devinst *pi)
|
|||||||
{
|
{
|
||||||
|
|
||||||
assert(pi->pi_lintr_pin);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user