aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2022-11-18 19:07:38 +0000
committerMark Johnston <markj@FreeBSD.org>2022-11-18 19:11:48 +0000
commit0705b7f4e64fdbad49a3a6d9131029a9734deb2c (patch)
treeb851ed50864177a3af3351440d41a555f74a7889
parentc127c61efa4d8414be9a7373b50c7f348b6e461e (diff)
downloadsrc-0705b7f4e64fdbad49a3a6d9131029a9734deb2c.tar.gz
src-0705b7f4e64fdbad49a3a6d9131029a9734deb2c.zip
bhyve: Avoid using a packed struct for xhci port registers
I believe the __packed annotation is there only because pci_xhci_portregs_read() is treating the register set as an array of uint32_t. clang warns about taking the address of portregs->portsc because it is a packed member and thus might not have expected alignment. Fix the problem by simply selecting the field to read with a switch statement. This mimics pci_xhci_portregs_write(). While here, switch to using some symbolic constants. There is a small semantic change here in that pci_xhci_portregs_read() would silently truncate unaligned offsets. For consistency with pci_xhci_portregs_write(), which does not do that, return all ones for unaligned reads instead. MFC after: 2 weeks Reviewed by: corvink, jhb Differential Revision: https://reviews.freebsd.org/D37408
-rw-r--r--usr.sbin/bhyve/pci_xhci.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/usr.sbin/bhyve/pci_xhci.c b/usr.sbin/bhyve/pci_xhci.c
index 1f3d78a4cfea..f95f62fbf0e5 100644
--- a/usr.sbin/bhyve/pci_xhci.c
+++ b/usr.sbin/bhyve/pci_xhci.c
@@ -568,6 +568,10 @@ pci_xhci_portregs_write(struct pci_xhci_softc *sc, uint64_t offset,
*/
p->porthlpmc = value;
break;
+ default:
+ DPRINTF(("pci_xhci: unaligned portreg write offset %#lx",
+ offset));
+ break;
}
}
@@ -2132,12 +2136,13 @@ pci_xhci_portregs_read(struct pci_xhci_softc *sc, uint64_t offset)
{
struct pci_xhci_portregs *portregs;
int port;
- uint32_t *p;
+ uint32_t reg;
if (sc->portregs == NULL)
return (0);
- port = (offset - 0x3F0) / 0x10;
+ port = (offset - XHCI_PORTREGS_PORT0) / XHCI_PORTREGS_SETSZ;
+ offset = (offset - XHCI_PORTREGS_PORT0) % XHCI_PORTREGS_SETSZ;
if (port > XHCI_MAX_DEVS) {
DPRINTF(("pci_xhci: portregs_read port %d >= XHCI_MAX_DEVS",
@@ -2147,16 +2152,31 @@ pci_xhci_portregs_read(struct pci_xhci_softc *sc, uint64_t offset)
return (XHCI_PS_SPEED_SET(3));
}
- offset = (offset - 0x3F0) % 0x10;
-
portregs = XHCI_PORTREG_PTR(sc, port);
- p = &portregs->portsc;
- p += offset / sizeof(uint32_t);
+ switch (offset) {
+ case 0:
+ reg = portregs->portsc;
+ break;
+ case 4:
+ reg = portregs->portpmsc;
+ break;
+ case 8:
+ reg = portregs->portli;
+ break;
+ case 12:
+ reg = portregs->porthlpmc;
+ break;
+ default:
+ DPRINTF(("pci_xhci: unaligned portregs read offset %#lx",
+ offset));
+ reg = 0xffffffff;
+ break;
+ }
DPRINTF(("pci_xhci: portregs read offset 0x%lx port %u -> 0x%x",
- offset, port, *p));
+ offset, port, reg));
- return (*p);
+ return (reg);
}
static void