From nobody Thu Jan 26 19:47:43 2023 X-Original-To: dev-commits-src-branches@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 4P2rpR3Czjz3bn9Z; Thu, 26 Jan 2023 19:47:43 +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 4P2rpR2Npkz3CSC; Thu, 26 Jan 2023 19:47:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1674762463; 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=kzj3NG8Ka40omLy3yYwx3W2W9ZSFqY5O+WQWF13a9us=; b=kj1f4j5vYsIjqDhT4n/L5dIIA9Fai5f+y+EDjLcjk6kngGePZY4GRMT2BkQa9gfDMu5VD5 CwCAowBtE1nuZBIvkP4i0CyEtrWfWNUdIq6qP5Nn7DhX/KZomcTfDbY4W6WM4kp9zosKsf mFYbJ0xJptZF48ph1zA/3HO/o4VvdfVLimJt7ltvwlOUsxcivwCqqhzwo6SwnbrfNVBktQ aY+9hukuuS9ZI7bBUXBSZNMbATPwrv2J9mrxeuZDhjlwQANxTfCUSX7jVh7vLRyo7KedBc oNjDiyLAwxUbyCP0M73t7pUNsSXkDAOdR+dENw1VbhDkywrcyl7WwGi/OE1pvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1674762463; 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=kzj3NG8Ka40omLy3yYwx3W2W9ZSFqY5O+WQWF13a9us=; b=KJq9Evn29Xuw7LlY+gJhJd9ml3AzRBYy0Pcz3+AXhhcxnpQ/C1O7zWPK0X/Zv3oymkv7vP iqF1pUpPyFbepGtqS9Jaj9YKzN2bKaHApmwdk0Cf/ukDvJs/axIcXpyRyhiTFLWByZc83C IS2ww60E6ltcF2/CCc6KxhkYIPGCzAkHjQMCuylAZJl0dkZF56gWKahm64aRnmo+v/k/Mm EQECOmwdGXHyFxECg1hkjbVt1sx5CAH2yJYxdWXjPt0GGzL3x7GERXDRky23pl+y5e29nd ijk8ms3YMNvCDSgLUzft+jCm3g75sX91fz3ThH1oH04h4dhFkxwxfud/pR3xag== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1674762463; a=rsa-sha256; cv=none; b=nrpoXanWx2wFFsZkMwVGW94HxuuXFcLab4802/Z5mjXKTlEcdhVYf9sfHyiDUc0B+i6+DW doTMY1IMMuMnH3kwWU444XelId9QxWppM8q0YPYhH9suV+nnFZJfgledeJSGWMxmM8Sfgi 3oLnPhvNCV4E2KvDoAlh7KW6dzzCWYlUnryZRB+5GoHH7WEI+jS4huwtF8BGV+ZLcfYGla lRcRGSLEZDdHC/dmLmpXV01LUU/tNn7U9u9/U3d8uf3t66cGvqCnp9QkSpUt0ZrzT29W0I OIqxXlT6wehwWLgw3W6qLs928ZCOIRhqgkbyme4+kDE3EpiZHUMjZITwX7NTDA== 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 4P2rpR1Rf1zhkv; Thu, 26 Jan 2023 19:47:43 +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 30QJlh8U006986; Thu, 26 Jan 2023 19:47:43 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 30QJlhbv006985; Thu, 26 Jan 2023 19:47:43 GMT (envelope-from git) Date: Thu, 26 Jan 2023 19:47:43 GMT Message-Id: <202301261947.30QJlhbv006985@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: John Baldwin Subject: git: 6c708e91f447 - stable/13 - bhyve nvme: Fix Controller init error cases List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 6c708e91f447d6e080125bfaff85e5507c9445fb Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=6c708e91f447d6e080125bfaff85e5507c9445fb commit 6c708e91f447d6e080125bfaff85e5507c9445fb Author: Chuck Tuffli AuthorDate: 2022-08-14 14:47:34 +0000 Commit: John Baldwin CommitDate: 2023-01-26 19:29:51 +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 (cherry picked from commit d7d1becad4b692b97dd1f32706947aae5118294b) --- 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 123f91158a21..2bb3f0f8a7d5 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) @@ -1096,30 +1097,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 @@ -2904,6 +2936,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", @@ -2911,6 +2949,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; } @@ -2977,7 +3021,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;