summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/inout.c
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-04-10 02:12:39 +0000
committerneel <neel@FreeBSD.org>2013-04-10 02:12:39 +0000
commitc350fded205165d0bd29af8ce3f65001c40f144b (patch)
tree74404bb950a87fe0a043f8f34de128bc51966a5a /usr.sbin/bhyve/inout.c
parent649c9a27e957dc1ab3991162ff567f9bed73b3ad (diff)
downloadFreeBSD-src-c350fded205165d0bd29af8ce3f65001c40f144b.zip
FreeBSD-src-c350fded205165d0bd29af8ce3f65001c40f144b.tar.gz
Improve PCI BAR emulation:
- Respect the MEMEN and PORTEN bits in the command register - Allow the guest to reprogram the address decoded by the BAR Submitted by: Gopakumar T Obtained from: NetApp
Diffstat (limited to 'usr.sbin/bhyve/inout.c')
-rw-r--r--usr.sbin/bhyve/inout.c56
1 files changed, 44 insertions, 12 deletions
diff --git a/usr.sbin/bhyve/inout.c b/usr.sbin/bhyve/inout.c
index 5f47a89f..29d9f17 100644
--- a/usr.sbin/bhyve/inout.c
+++ b/usr.sbin/bhyve/inout.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker_set.h>
#include <stdio.h>
+#include <string.h>
#include <assert.h>
#include "inout.h"
@@ -41,6 +42,9 @@ SET_DECLARE(inout_port_set, struct inout_port);
#define MAX_IOPORTS (1 << 16)
+#define VERIFY_IOPORT(port, size) \
+ assert((port) >= 0 && (size) > 0 && ((port) + (size)) <= MAX_IOPORTS)
+
static struct {
const char *name;
int flags;
@@ -69,6 +73,23 @@ default_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
return (0);
}
+static void
+register_default_iohandler(int start, int size)
+{
+ struct inout_port iop;
+
+ VERIFY_IOPORT(start, size);
+
+ bzero(&iop, sizeof(iop));
+ iop.name = "default";
+ iop.port = start;
+ iop.size = size;
+ iop.flags = IOPORT_F_INOUT;
+ iop.handler = default_inout;
+
+ register_inout(&iop);
+}
+
int
emulate_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, int strict)
@@ -113,17 +134,11 @@ void
init_inout(void)
{
struct inout_port **iopp, *iop;
- int i;
/*
* Set up the default handler for all ports
*/
- for (i = 0; i < MAX_IOPORTS; i++) {
- inout_handlers[i].name = "default";
- inout_handlers[i].flags = IOPORT_F_IN | IOPORT_F_OUT;
- inout_handlers[i].handler = default_inout;
- inout_handlers[i].arg = NULL;
- }
+ register_default_iohandler(0, MAX_IOPORTS);
/*
* Overwrite with specified handlers
@@ -141,11 +156,28 @@ init_inout(void)
int
register_inout(struct inout_port *iop)
{
- assert(iop->port < MAX_IOPORTS);
- inout_handlers[iop->port].name = iop->name;
- inout_handlers[iop->port].flags = iop->flags;
- inout_handlers[iop->port].handler = iop->handler;
- inout_handlers[iop->port].arg = iop->arg;
+ int i;
+
+ VERIFY_IOPORT(iop->port, iop->size);
+
+ for (i = iop->port; i < iop->port + iop->size; i++) {
+ inout_handlers[i].name = iop->name;
+ inout_handlers[i].flags = iop->flags;
+ inout_handlers[i].handler = iop->handler;
+ inout_handlers[i].arg = iop->arg;
+ }
+
+ return (0);
+}
+
+int
+unregister_inout(struct inout_port *iop)
+{
+
+ VERIFY_IOPORT(iop->port, iop->size);
+ assert(inout_handlers[iop->port].name == iop->name);
+
+ register_default_iohandler(iop->port, iop->size);
return (0);
}
OpenPOWER on IntegriCloud