diff options
author | grehan <grehan@FreeBSD.org> | 2012-10-19 18:11:17 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2012-10-19 18:11:17 +0000 |
commit | beaad57fa07508b2383454e13f0a26824ada6328 (patch) | |
tree | 32133e495715159b674a250fa62c5c04595e4753 /usr.sbin/bhyve/ioapic.c | |
parent | 8fb5b5f8de608d18362583be1e90150aab0b4d33 (diff) | |
download | FreeBSD-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.c | 79 |
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); +} |