From nobody Sun Aug 14 15:04:07 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4M5LKN1BYTz4ZJfR; Sun, 14 Aug 2022 15:04:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4M5LKN0NF7z3bxb; Sun, 14 Aug 2022 15:04:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1660489448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NVcz5cxggLlyG0dZY5RusmSCc6dU2IrZF+k8ax7RqV8=; b=wXGTgSzGL/OC+6fYKxw+XyIcoz0L12q9R40PLAkrKCxb2G5bfyrgThO+7b0kLeFbeoIJho 4P5e1C08RSEkAb0aVSNVJM90i3f8/igk4SzetknAk3Jplp0xo8Y0wu4uYCBQM5t/29A2PK yNEX1depOQUVJvLgV0OEnEu5u2/GGHO0nqntmHsZtthvOrVoQ5cK3Pe1r0VDMpoY8XRMH7 mGU4VTLyZy9O4SR16fkZKO02nWYLRZD9k+lmI9YUwyo9zVB8cCOl5VaUGGVGeNk1F2BCVb 1M3GMoPP8X3ptr/HHnzlq2/4oXNeKbr0jLpE7Sq94MzbVSSs8vKi1A0zfLPLhg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4M5LKM6SrTzvPh; Sun, 14 Aug 2022 15:04:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 27EF47NG076989; Sun, 14 Aug 2022 15:04:07 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 27EF475T076988; Sun, 14 Aug 2022 15:04:07 GMT (envelope-from git) Date: Sun, 14 Aug 2022 15:04:07 GMT Message-Id: <202208141504.27EF475T076988@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Chuck Tuffli Subject: git: d7d1becad4b6 - main - bhyve nvme: Fix Controller init error cases List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: chuck X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d7d1becad4b692b97dd1f32706947aae5118294b Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1660489448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NVcz5cxggLlyG0dZY5RusmSCc6dU2IrZF+k8ax7RqV8=; b=bhmUtQbuB04afw2U/bgMSKdX4micd/QWY1qvRFtWpdd+l2/bSqGXON619J5E9h9ezXURf6 XSHNSBNATmxE8e4FtJlOdGQ5hZqVurZ8qTEGDzh7DCL9a6XfQG9/gKCaXlSQ4sgOmmmZkr tv4S/9h2cbhPUhhMi/SXZReICTKE8u+bZmLBxLlisJ+n1xxFiLEuimmyqVcmfuTRLAqfJR snp6NCVCLSND15GJl12xWsou+ejn3kFF90asHYPOFoKCCJ+IQ03WfVokZsSN33eRQ49xck QGXBo8M1X1tosgL8u0i6Q61P5AQ26Z3FBv22WcXSADq0HOYcX/TSvdy6LcjHXQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1660489448; a=rsa-sha256; cv=none; b=Vu8F+m3eXs5L4+zDjekIzFYPgvsGckb+7A/RWVPNwhcawQRX1N9mdljHj5j/LlJ5mpPJD+ gdhUoBpla+0XjLXR6q4KnxYZcK/q2fHYBOUloaB+6UKTrAX8+GaQovi3bgClEASJKfXxBw af4rZ5yV5lUSws9QKKy/iwnVouGA3vZ3JG2uyx1VCBQNDJymiIs/H8zFmtrz8FW2wXmR// Ctq/tWvtvUfquDHqf1GTbrndQ2oe7BKr7tShDoVLIHECOy/mgll34GsDOu7ayh9iy2DHeV +qAXfgKTZm6KcckvFHwTASqDs/pu9zZWeMvTViQzjs89dxWliOTy4+EeSh4TNQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by chuck: URL: https://cgit.FreeBSD.org/src/commit/?id=d7d1becad4b692b97dd1f32706947aae5118294b commit d7d1becad4b692b97dd1f32706947aae5118294b Author: Chuck Tuffli AuthorDate: 2022-08-14 14:47:34 +0000 Commit: Chuck Tuffli CommitDate: 2022-08-14 14:47:34 +0000 bhyve nvme: Fix Controller init error cases Fuzzing of bhyve uncovered an assertion failure in the NVMe emulation. Investigation uncovered several corner cases the code did not handle. This change handles several Controller initialization errors, including - bad AQ sizes - bad AQ vm_map_gpa - doorbell writes prior to RDY - doorbell writes to uninitialized queue - CSTS.RDY if CFS set PR: 256317,256319,256320,256322 Reported by: Cheolwoo Myung Reviewed by: jhb Differential Revision: https://reviews.freebsd.org/D35453 --- usr.sbin/bhyve/pci_nvme.c | 55 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/usr.sbin/bhyve/pci_nvme.c b/usr.sbin/bhyve/pci_nvme.c index e10c8bd437e2..46a8104be9f6 100644 --- a/usr.sbin/bhyve/pci_nvme.c +++ b/usr.sbin/bhyve/pci_nvme.c @@ -398,6 +398,7 @@ static void pci_nvme_io_done(struct blockif_req *, int); ((sts) >> NVME_CSTS_REG_RDY_SHIFT & NVME_CSTS_REG_RDY_MASK) #define NVME_CSTS_RDY (1 << NVME_CSTS_REG_RDY_SHIFT) +#define NVME_CSTS_CFS (1 << NVME_CSTS_REG_CFS_SHIFT) /* Completion Queue status word utils */ #define NVME_STATUS_P (1 << NVME_STATUS_P_SHIFT) @@ -1081,30 +1082,61 @@ pci_nvme_reset(struct pci_nvme_softc *sc) pthread_mutex_unlock(&sc->mtx); } -static void +static int pci_nvme_init_controller(struct vmctx *ctx, struct pci_nvme_softc *sc) { uint16_t acqs, asqs; DPRINTF("%s", __func__); - asqs = (sc->regs.aqa & NVME_AQA_REG_ASQS_MASK) + 1; + /* + * NVMe 2.0 states that "enabling a controller while this field is + * cleared to 0h produces undefined results" for both ACQS and + * ASQS. If zero, set CFS and do not become ready. + */ + asqs = ONE_BASED(sc->regs.aqa & NVME_AQA_REG_ASQS_MASK); + if (asqs < 2) { + EPRINTLN("%s: illegal ASQS value %#x (aqa=%#x)", __func__, + asqs - 1, sc->regs.aqa); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } sc->submit_queues[0].size = asqs; sc->submit_queues[0].qbase = vm_map_gpa(ctx, sc->regs.asq, sizeof(struct nvme_command) * asqs); + if (sc->submit_queues[0].qbase == NULL) { + EPRINTLN("%s: ASQ vm_map_gpa(%lx) failed", __func__, + sc->regs.asq); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } DPRINTF("%s mapping Admin-SQ guest 0x%lx, host: %p", __func__, sc->regs.asq, sc->submit_queues[0].qbase); - acqs = ((sc->regs.aqa >> NVME_AQA_REG_ACQS_SHIFT) & - NVME_AQA_REG_ACQS_MASK) + 1; + acqs = ONE_BASED((sc->regs.aqa >> NVME_AQA_REG_ACQS_SHIFT) & + NVME_AQA_REG_ACQS_MASK); + if (acqs < 2) { + EPRINTLN("%s: illegal ACQS value %#x (aqa=%#x)", __func__, + acqs - 1, sc->regs.aqa); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } sc->compl_queues[0].size = acqs; sc->compl_queues[0].qbase = vm_map_gpa(ctx, sc->regs.acq, sizeof(struct nvme_completion) * acqs); + if (sc->compl_queues[0].qbase == NULL) { + EPRINTLN("%s: ACQ vm_map_gpa(%lx) failed", __func__, + sc->regs.acq); + sc->regs.csts |= NVME_CSTS_CFS; + return (-1); + } sc->compl_queues[0].intr_en = NVME_CQ_INTEN; DPRINTF("%s mapping Admin-CQ guest 0x%lx, host: %p", __func__, sc->regs.acq, sc->compl_queues[0].qbase); + + return (0); } static int @@ -2872,6 +2904,12 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, uint64_t idx = belloffset / 8; /* door bell size = 2*int */ int is_sq = (belloffset % 8) < 4; + if ((sc->regs.csts & NVME_CSTS_RDY) == 0) { + WPRINTF("doorbell write prior to RDY (offset=%#lx)\n", + offset); + return; + } + if (belloffset > ((sc->max_queues+1) * 8 - 4)) { WPRINTF("guest attempted an overflow write offset " "0x%lx, val 0x%lx in %s", @@ -2879,6 +2917,12 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, return; } + if (is_sq) { + if (sc->submit_queues[idx].qbase == NULL) + return; + } else if (sc->compl_queues[idx].qbase == NULL) + return; + pci_nvme_handle_doorbell(ctx, sc, idx, is_sq, value); return; } @@ -2945,7 +2989,8 @@ pci_nvme_write_bar_0(struct vmctx *ctx, struct pci_nvme_softc* sc, sc->regs.cc &= ~NVME_CC_NEN_WRITE_MASK; sc->regs.cc |= ccreg & NVME_CC_NEN_WRITE_MASK; sc->regs.csts &= ~NVME_CSTS_RDY; - } else if (sc->pending_ios == 0) { + } else if ((sc->pending_ios == 0) && + !(sc->regs.csts & NVME_CSTS_CFS)) { sc->regs.csts |= NVME_CSTS_RDY; } break;