summaryrefslogtreecommitdiffstats
path: root/usr.sbin/vmd/pci.c
diff options
context:
space:
mode:
authormlarkin <mlarkin@openbsd.org>2017-03-25 15:47:37 +0000
committermlarkin <mlarkin@openbsd.org>2017-03-25 15:47:37 +0000
commiteef1411ca5cc749290400d77f43fdbd764961d4b (patch)
treec102b638540ca1b6efebc2842d70b6daba1f6276 /usr.sbin/vmd/pci.c
parentUse explicit operand with SVM instructions as clang doesn't recognize the (diff)
downloadwireguard-openbsd-eef1411ca5cc749290400d77f43fdbd764961d4b.tar.xz
wireguard-openbsd-eef1411ca5cc749290400d77f43fdbd764961d4b.zip
Implement some missing functionality and clean up some code in vmd
pci emulation. ok kettenis
Diffstat (limited to 'usr.sbin/vmd/pci.c')
-rw-r--r--usr.sbin/vmd/pci.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/usr.sbin/vmd/pci.c b/usr.sbin/vmd/pci.c
index 3f098aa5ca8..f106747b8de 100644
--- a/usr.sbin/vmd/pci.c
+++ b/usr.sbin/vmd/pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci.c,v 1.13 2017/01/21 12:45:41 mlarkin Exp $ */
+/* $OpenBSD: pci.c,v 1.14 2017/03/25 15:47:37 mlarkin Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -26,6 +26,7 @@
#include <string.h>
#include "vmd.h"
#include "pci.h"
+#include "vmm.h"
struct pci pci;
@@ -214,14 +215,14 @@ pci_handle_address_reg(struct vm_run_params *vrp)
* The guest wrote to the address register.
*/
if (vei->vei.vei_dir == VEI_DIR_OUT) {
- pci.pci_addr_reg = vei->vei.vei_data;
+ pci.pci_addr_reg = get_input_data(vei);
} else {
/*
* vei_dir == VEI_DIR_IN : in instruction
*
* The guest read the address register
*/
- vei->vei.vei_data = pci.pci_addr_reg;
+ set_return_data(vei, pci.pci_addr_reg);
}
}
@@ -258,7 +259,8 @@ pci_handle_io(struct vm_run_params *vrp)
if (fn(vei->vei.vei_dir, reg -
PCI_MAPREG_IO_ADDR(pci.pci_devices[l].pd_bar[k]),
&vei->vei.vei_data, &intr,
- pci.pci_devices[l].pd_bar_cookie[k])) {
+ pci.pci_devices[l].pd_bar_cookie[k],
+ vei->vei.vei_size)) {
log_warnx("%s: pci i/o access function failed",
__progname);
}
@@ -267,7 +269,7 @@ pci_handle_io(struct vm_run_params *vrp)
__progname, (uint64_t)reg);
/* Reads from undefined ports return 0xFF */
if (dir == 1)
- vei->vei.vei_data = 0xFFFFFFFF;
+ set_return_data(vei, 0xFFFFFFFF);
}
if (intr != 0xFF) {
@@ -281,7 +283,7 @@ void
pci_handle_data_reg(struct vm_run_params *vrp)
{
union vm_exit *vei = vrp->vrp_exit;
- uint8_t b, d, f, o, baridx;
+ uint8_t b, d, f, o, baridx, ofs, sz;
int ret;
pci_cs_fn_t csfunc;
@@ -289,12 +291,16 @@ pci_handle_data_reg(struct vm_run_params *vrp)
if (!(pci.pci_addr_reg & PCI_MODE1_ENABLE)) {
/* if read, return FFs */
if (vei->vei.vei_dir == VEI_DIR_IN)
- vei->vei.vei_data = 0xffffffff;
+ set_return_data(vei, 0xFFFFFFFF);
log_warnx("invalid address register during pci read: "
"0x%llx", (uint64_t)pci.pci_addr_reg);
return;
}
+ /* I/Os to 0xCFC..0xCFF are permitted */
+ ofs = vei->vei.vei_port - 0xCFC;
+ sz = vei->vei.vei_size;
+
b = (pci.pci_addr_reg >> 16) & 0xff;
d = (pci.pci_addr_reg >> 11) & 0x1f;
f = (pci.pci_addr_reg >> 8) & 0x7;
@@ -311,6 +317,8 @@ pci_handle_data_reg(struct vm_run_params *vrp)
/* No config space function, fallback to default simple r/w impl. */
+ o += ofs;
+
/*
* vei_dir == VEI_DIR_OUT : out instruction
*
@@ -335,7 +343,16 @@ pci_handle_data_reg(struct vm_run_params *vrp)
else
vei->vei.vei_data = 0;
}
- pci.pci_devices[d].pd_cfg_space[o / 4] = vei->vei.vei_data;
+
+ /* XXX - discard writes to reassign IRQs / pins */
+ if (o != 0x3c)
+ pci.pci_devices[d].pd_cfg_space[o / 4] =
+ get_input_data(vei);
+
+ /* IOBAR registers must have bit 0 set */
+ if (o == 0x10)
+ pci.pci_devices[d].pd_cfg_space[o / 4] |= 1;
+
} else {
/*
* vei_dir == VEI_DIR_IN : in instruction
@@ -343,6 +360,6 @@ pci_handle_data_reg(struct vm_run_params *vrp)
* The guest read from the config space location determined by
* the current value in the address register.
*/
- vei->vei.vei_data = pci.pci_devices[d].pd_cfg_space[o / 4];
+ set_return_data(vei, pci.pci_devices[d].pd_cfg_space[o / 4]);
}
}