diff options
author | grehan <grehan@FreeBSD.org> | 2013-10-09 23:53:21 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2013-10-09 23:53:21 +0000 |
commit | 26296c939c8a5298c4359e40187a22786bb86315 (patch) | |
tree | f477d30d76163cb288da0ea06ed4847257f4024b /usr.sbin | |
parent | fe75d5f1628223af17e92f06a8394c9c9aa6aca0 (diff) | |
download | FreeBSD-src-26296c939c8a5298c4359e40187a22786bb86315.zip FreeBSD-src-26296c939c8a5298c4359e40187a22786bb86315.tar.gz |
Allow a 4-byte write to PCI config space to overlap
the 2 read-only bytes at the start of a PCI capability.
This is the sequence that OpenBSD uses when enabling
MSI interrupts, and works fine on real h/w.
In bhyve, convert the 4 byte write to a 2-byte write to
the r/w area past the first 2 r/o bytes of a capability.
Reviewed by: neel
Approved by: re@ (blanket)
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bhyve/pci_emul.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index a95f261..fe21cee 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -941,10 +941,19 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val) assert(offset >= capoff); /* - * Capability ID and Next Capability Pointer are readonly + * Capability ID and Next Capability Pointer are readonly. + * However, some o/s's do 4-byte writes that include these. + * For this case, trim the write back to 2 bytes and adjust + * the data. */ - if (offset == capoff || offset == capoff + 1) - return; + if (offset == capoff || offset == capoff + 1) { + if (offset == capoff && bytes == 4) { + bytes = 2; + offset += 2; + val >>= 16; + } else + return; + } switch (capid) { case PCIY_MSI: |