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
This commit is contained in:
Mark Johnston 2022-11-18 14:07:38 -05:00
parent c127c61efa
commit 0705b7f4e6

View file

@ -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