git: f505f9a842eb - main - bhyve: simplify slot validation in xHCI emulation

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Sat, 21 Sep 2024 17:37:38 UTC
The branch main has been updated by emaste:

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

commit f505f9a842eb3e75e16e6c7c6f67d5b592b1bc65
Author:     Pierre Pronchery <pierre@freebsdfoundation.org>
AuthorDate: 2024-09-18 18:52:04 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-09-21 17:36:10 +0000

    bhyve: simplify slot validation in xHCI emulation
    
    This is a follow-up to commit e72d86ad9c62 ("bhyve: improve input
    validation in pci_xhci") -- introducing a helper for slot validation.
    
    Co-authored-by: John Baldwin <jhb@FreeBSD.org>
    Reviewed by:    markj, emaste
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D46696
---
 usr.sbin/bhyve/pci_xhci.c | 90 +++++++++++++++++------------------------------
 1 file changed, 32 insertions(+), 58 deletions(-)

diff --git a/usr.sbin/bhyve/pci_xhci.c b/usr.sbin/bhyve/pci_xhci.c
index 2399cb4fc9b8..5b21361f2823 100644
--- a/usr.sbin/bhyve/pci_xhci.c
+++ b/usr.sbin/bhyve/pci_xhci.c
@@ -348,6 +348,7 @@ static void pci_xhci_update_ep_ring(struct pci_xhci_softc *sc,
     struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep,
     struct xhci_endp_ctx *ep_ctx, uint32_t streamid,
     uint64_t ringaddr, int ccs);
+static int pci_xhci_validate_slot(uint32_t slot);
 
 static void
 pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port, uint32_t errcode,
@@ -849,17 +850,14 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_softc *sc, uint32_t slot)
 
 	DPRINTF(("pci_xhci disable slot %u", slot));
 
-	cmderr = XHCI_TRB_ERROR_NO_SLOTS;
-	if (sc->portregs == NULL)
+	if (sc->portregs == NULL) {
+		cmderr = XHCI_TRB_ERROR_NO_SLOTS;
 		goto done;
+	}
 
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
-		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	}
 
 	dev = XHCI_SLOTDEV_PTR(sc, slot);
 	if (dev) {
@@ -867,7 +865,6 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_softc *sc, uint32_t slot)
 			cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
 		} else {
 			dev->dev_slotstate = XHCI_ST_DISABLED;
-			cmderr = XHCI_TRB_ERROR_SUCCESS;
 			/* TODO: reset events and endpoints */
 		}
 	} else
@@ -886,19 +883,16 @@ pci_xhci_cmd_reset_device(struct pci_xhci_softc *sc, uint32_t slot)
 	uint32_t	cmderr;
 	int		i;
 
-	cmderr = XHCI_TRB_ERROR_NO_SLOTS;
-	if (sc->portregs == NULL)
+	if (sc->portregs == NULL) {
+		cmderr = XHCI_TRB_ERROR_NO_SLOTS;
 		goto done;
+	}
 
 	DPRINTF(("pci_xhci reset device slot %u", slot));
 
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
-		goto done;
-	}
 
 	dev = XHCI_SLOTDEV_PTR(sc, slot);
 	if (!dev || dev->dev_slotstate == XHCI_ST_DISABLED)
@@ -928,8 +922,6 @@ pci_xhci_cmd_reset_device(struct pci_xhci_softc *sc, uint32_t slot)
 			ep_ctx->dwEpCtx0 = FIELD_REPLACE( ep_ctx->dwEpCtx0,
 			    XHCI_ST_EPCTX_DISABLED, 0x7, 0);
 		}
-
-		cmderr = XHCI_TRB_ERROR_SUCCESS;
 	}
 
 	pci_xhci_reset_slot(sc, slot);
@@ -953,8 +945,6 @@ pci_xhci_cmd_address_device(struct pci_xhci_softc *sc, uint32_t slot,
 	islot_ctx = &input_ctx->ctx_slot;
 	ep0_ctx = &input_ctx->ctx_ep[1];
 
-	cmderr = XHCI_TRB_ERROR_SUCCESS;
-
 	DPRINTF(("pci_xhci: address device, input ctl: D 0x%08x A 0x%08x,",
 	        input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1));
 	DPRINTF(("          slot %08x %08x %08x %08x",
@@ -972,13 +962,9 @@ pci_xhci_cmd_address_device(struct pci_xhci_softc *sc, uint32_t slot,
 		goto done;
 	}
 
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
-		goto done;
-	}
 
 	/* assign address to slot */
 	dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
@@ -1042,17 +1028,11 @@ pci_xhci_cmd_config_ep(struct pci_xhci_softc *sc, uint32_t slot,
 	uint32_t	cmderr;
 	int		i;
 
-	cmderr = XHCI_TRB_ERROR_SUCCESS;
-
 	DPRINTF(("pci_xhci config_ep slot %u", slot));
 
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
-		goto done;
-	}
 
 	dev = XHCI_SLOTDEV_PTR(sc, slot);
 	assert(dev != NULL);
@@ -1175,15 +1155,9 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_softc *sc, uint32_t slot,
 
 	DPRINTF(("pci_xhci: reset ep %u: slot %u", epid, slot));
 
-	cmderr = XHCI_TRB_ERROR_SUCCESS;
-
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
-		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	}
 
 	dev = XHCI_SLOTDEV_PTR(sc, slot);
 	assert(dev != NULL);
@@ -1272,15 +1246,9 @@ pci_xhci_cmd_set_tr(struct pci_xhci_softc *sc, uint32_t slot,
 	uint32_t	cmderr, epid;
 	uint32_t	streamid;
 
-	cmderr = XHCI_TRB_ERROR_SUCCESS;
-
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
-		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	}
 
 	dev = XHCI_SLOTDEV_PTR(sc, slot);
 	assert(dev != NULL);
@@ -1362,7 +1330,6 @@ pci_xhci_cmd_eval_ctx(struct pci_xhci_softc *sc, uint32_t slot,
 	islot_ctx = &input_ctx->ctx_slot;
 	ep0_ctx = &input_ctx->ctx_ep[1];
 
-	cmderr = XHCI_TRB_ERROR_SUCCESS;
 	DPRINTF(("pci_xhci: eval ctx, input ctl: D 0x%08x A 0x%08x,",
 	        input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1));
 	DPRINTF(("          slot %08x %08x %08x %08x",
@@ -1380,13 +1347,9 @@ pci_xhci_cmd_eval_ctx(struct pci_xhci_softc *sc, uint32_t slot,
 		goto done;
 	}
 
-	if (slot == 0) {
-		cmderr = XHCI_TRB_ERROR_TRB;
-		goto done;
-	} else if (slot > XHCI_MAX_SLOTS) {
-		cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON;
+	cmderr = pci_xhci_validate_slot(slot);
+	if (cmderr != XHCI_TRB_ERROR_SUCCESS)
 		goto done;
-	}
 
 	/* assign address to slot; in this emulation, slot_id = address */
 	dev_ctx = pci_xhci_get_dev_ctx(sc, slot);
@@ -1723,6 +1686,17 @@ pci_xhci_update_ep_ring(struct pci_xhci_softc *sc,
 	}
 }
 
+static int
+pci_xhci_validate_slot(uint32_t slot)
+{
+	if (slot == 0)
+		return (XHCI_TRB_ERROR_TRB);
+	else if (slot > XHCI_MAX_SLOTS)
+		return (XHCI_TRB_ERROR_SLOT_NOT_ON);
+	else
+		return (XHCI_TRB_ERROR_SUCCESS);
+}
+
 /*
  * Outstanding transfer still in progress (device NAK'd earlier) so retry
  * the transfer again to see if it succeeds.