summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/ioapic.c
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2012-10-19 18:11:17 +0000
committergrehan <grehan@FreeBSD.org>2012-10-19 18:11:17 +0000
commitbeaad57fa07508b2383454e13f0a26824ada6328 (patch)
tree32133e495715159b674a250fa62c5c04595e4753 /usr.sbin/bhyve/ioapic.c
parent8fb5b5f8de608d18362583be1e90150aab0b4d33 (diff)
downloadFreeBSD-src-beaad57fa07508b2383454e13f0a26824ada6328.zip
FreeBSD-src-beaad57fa07508b2383454e13f0a26824ada6328.tar.gz
Rework how guest MMIO regions are dealt with.
- New memory region interface. An RB tree holds the regions, with a last-found per-vCPU cache to deal with the common case of repeated guest accesses to MMIO registers in the same page. - Support memory-mapped BARs in PCI emulation. mem.c/h - memory region interface instruction_emul.c/h - remove old region interface. Use gpa from EPT exit to avoid a tablewalk to determine operand address. Determine operand size and use when calling through to region handler. fbsdrun.c - call into region interface on paging exit. Distinguish between instruction emul error and region not found pci_emul.c/h - implement new BAR callback api. Split BAR alloc routine into routines that require/don't require the BAR phys address. ioapic.c pci_passthru.c pci_virtio_block.c pci_virtio_net.c pci_uart.c - update to new BAR callback i/f Reviewed by: neel Obtained from: NetApp
Diffstat (limited to 'usr.sbin/bhyve/ioapic.c')
-rw-r--r--usr.sbin/bhyve/ioapic.c79
1 files changed, 51 insertions, 28 deletions
diff --git a/usr.sbin/bhyve/ioapic.c b/usr.sbin/bhyve/ioapic.c
index dc74cfa..ea6e47c 100644
--- a/usr.sbin/bhyve/ioapic.c
+++ b/usr.sbin/bhyve/ioapic.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <vmmapi.h>
#include "inout.h"
+#include "mem.h"
#include "instruction_emul.h"
#include "fbsdrun.h"
@@ -67,10 +68,13 @@ struct ioapic {
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 int ioapic_region_read(struct ioapic *ioapic, uintptr_t paddr,
+ int size, uint64_t *data);
+static int ioapic_region_write(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)
@@ -139,8 +143,10 @@ ioapic_assert_pin(struct vmctx *ctx, int pin)
void
ioapic_init(int which)
{
- int i;
+ struct mem_range memp;
struct ioapic *ioapic;
+ int error;
+ int i;
assert(which == 0);
@@ -153,14 +159,19 @@ ioapic_init(int which)
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);
+
+ /* 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;
}
@@ -237,15 +248,11 @@ ioapic_write(struct ioapic *ioapic, uint32_t addr, uint32_t data)
}
static int
-ioapic_region_read(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
- uint64_t *data, void *arg)
+ioapic_region_read(struct ioapic *ioapic, uintptr_t paddr, int size,
+ uint64_t *data)
{
- int which, offset;
- struct ioapic *ioapic;
-
- which = (uintptr_t)arg;
+ int offset;
- ioapic = &ioapics[which];
offset = paddr - ioapic->paddr;
/*
@@ -255,7 +262,7 @@ ioapic_region_read(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
#if 1
printf("invalid access to ioapic%d: size %d, offset %d\n",
- which, size, offset);
+ (int)(ioapic - ioapics), size, offset);
#endif
*data = 0;
return (0);
@@ -270,15 +277,11 @@ ioapic_region_read(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
}
static int
-ioapic_region_write(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
- uint64_t data, void *arg)
+ioapic_region_write(struct ioapic *ioapic, uintptr_t paddr, int size,
+ uint64_t data)
{
- int which, offset;
- struct ioapic *ioapic;
-
- which = (uintptr_t)arg;
+ int offset;
- ioapic = &ioapics[which];
offset = paddr - ioapic->paddr;
/*
@@ -288,7 +291,7 @@ ioapic_region_write(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
#if 1
printf("invalid access to ioapic%d: size %d, offset %d\n",
- which, size, offset);
+ (int)(ioapic - ioapics), size, offset);
#endif
return (0);
}
@@ -300,3 +303,23 @@ ioapic_region_write(struct vmctx *vm, int vcpu, uintptr_t paddr, int size,
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]);
+
+ if (dir == MEM_F_READ)
+ ioapic_region_read(ioapic, paddr, size, val);
+ else
+ ioapic_region_write(ioapic, paddr, size, *val);
+
+ return (0);
+}
OpenPOWER on IntegriCloud