summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2011-06-07 18:35:45 +0000
committergrehan <grehan@FreeBSD.org>2011-06-07 18:35:45 +0000
commit3c35264f695e0a1f8a04dbcca1c93bb5159b2274 (patch)
tree0cd1544bc338a4ede8655980908e5cde3bceb647
parentacc044270835dd36a1405fca8d586d5008514a39 (diff)
downloadFreeBSD-src-3c35264f695e0a1f8a04dbcca1c93bb5159b2274.zip
FreeBSD-src-3c35264f695e0a1f8a04dbcca1c93bb5159b2274.tar.gz
Allow access to the device's config area with any size i/o access at any
offset. This is now spec-compliant.
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c12
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c31
2 files changed, 34 insertions, 9 deletions
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
index b86e21d..98c0695 100644
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -439,6 +439,7 @@ uint32_t
pci_vtblk_read(struct pci_devinst *pi, int baridx, int offset, int size)
{
struct pci_vtblk_softc *sc = pi->pi_arg;
+ void *ptr;
uint32_t value;
if (offset + size > VTBLK_REGSZ) {
@@ -481,8 +482,15 @@ pci_vtblk_read(struct pci_devinst *pi, int baridx, int offset, int size)
sc->vbsc_isr = 0; /* a read clears this flag */
break;
case VTBLK_R_CFG ... VTBLK_R_CFG_END:
- assert(size == 1);
- value = *((uint8_t *)&sc->vbsc_cfg + offset - VTBLK_R_CFG);
+ assert(size + offset <= (VTBLK_R_CFG_END + 1));
+ ptr = (uint8_t *)&sc->vbsc_cfg + offset - VTBLK_R_CFG;
+ if (size == 1) {
+ value = *(uint8_t *) ptr;
+ } else if (size == 2) {
+ value = *(uint16_t *) ptr;
+ } else {
+ value = *(uint32_t *) ptr;
+ }
break;
default:
DPRINTF(("vtblk: unknown i/o read offset %d\n\r", offset));
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
index 5db1eb7..6160b14 100644
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -594,7 +594,8 @@ pci_vtnet_write(struct pci_devinst *pi, int baridx, int offset, int size,
uint32_t value)
{
struct pci_vtnet_softc *sc = pi->pi_arg;
-
+ void *ptr;
+
if (offset + size > VTNET_REGSZ) {
DPRINTF(("vtnet_write: 2big, offset %d size %d\n",
offset, size));
@@ -632,11 +633,19 @@ pci_vtnet_write(struct pci_devinst *pi, int baridx, int offset, int size,
case VTNET_R_CFG3:
case VTNET_R_CFG4:
case VTNET_R_CFG5:
+ assert((size + offset) <= (VTNET_R_CFG5 + 1));
+ ptr = &sc->vsc_macaddr[offset - VTNET_R_CFG0];
/*
* The driver is allowed to change the MAC address
*/
- assert(size == 1);
sc->vsc_macaddr[offset - VTNET_R_CFG0] = value;
+ if (size == 1) {
+ *(uint8_t *) ptr = value;
+ } else if (size == 2) {
+ *(uint16_t *) ptr = value;
+ } else {
+ *(uint32_t *) ptr = value;
+ }
break;
case VTCFG_R_HOSTCAP:
case VTCFG_R_QNUM:
@@ -658,6 +667,7 @@ uint32_t
pci_vtnet_read(struct pci_devinst *pi, int baridx, int offset, int size)
{
struct pci_vtnet_softc *sc = pi->pi_arg;
+ void *ptr;
uint32_t value;
if (offset + size > VTNET_REGSZ) {
@@ -708,16 +718,23 @@ pci_vtnet_read(struct pci_devinst *pi, int baridx, int offset, int size)
case VTNET_R_CFG3:
case VTNET_R_CFG4:
case VTNET_R_CFG5:
- assert(size == 1);
- value = sc->vsc_macaddr[offset - VTNET_R_CFG0];
+ assert((size + offset) <= (VTNET_R_CFG5 + 1));
+ ptr = &sc->vsc_macaddr[offset - VTNET_R_CFG0];
+ if (size == 1) {
+ value = *(uint8_t *) ptr;
+ } else if (size == 2) {
+ value = *(uint16_t *) ptr;
+ } else {
+ value = *(uint32_t *) ptr;
+ }
break;
case VTNET_R_CFG6:
- assert(size == 1);
- value = 0x01; /* XXX link always up */
+ assert(size != 4);
+ value = 0x01; /* XXX link always up */
break;
case VTNET_R_CFG7:
assert(size == 1);
- value = 0; /* link status is in the LSB */
+ value = 0; /* XXX link status in LSB */
break;
default:
DPRINTF(("vtnet: unknown i/o read offset %d\n\r", offset));
OpenPOWER on IntegriCloud