git: c8a6e51a4f86 - stable/13 - bhyve: Avoid using a packed struct for xhci port registers

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 26 Jan 2023 20:27:06 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=c8a6e51a4f866f5c497546f9657e44fe1ae0ff66

commit c8a6e51a4f866f5c497546f9657e44fe1ae0ff66
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-11-18 19:07:38 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2023-01-26 20:06:39 +0000

    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
    
    (cherry picked from commit 0705b7f4e64fdbad49a3a6d9131029a9734deb2c)
---
 usr.sbin/bhyve/pci_xhci.c | 36 ++++++++++++++++++++++++++++--------
 1 file 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