diff options
author | Peter Grehan <grehan@FreeBSD.org> | 2013-10-09 23:53:21 +0000 |
---|---|---|
committer | Peter Grehan <grehan@FreeBSD.org> | 2013-10-09 23:53:21 +0000 |
commit | 2a8d400a2e9918ef77d30bdc099f5c06bae4302d (patch) | |
tree | f477d30d76163cb288da0ea06ed4847257f4024b | |
parent | d5cc57e6abed1cff098cb8993c5c568a67c6ff60 (diff) | |
download | src-2a8d400a2e9918ef77d30bdc099f5c06bae4302d.tar.gz src-2a8d400a2e9918ef77d30bdc099f5c06bae4302d.zip |
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)
Notes
Notes:
svn path=/head/; revision=256248
-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 a95f26101e3d..fe21cee835c2 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: |