From nobody Fri Nov 14 19:43:50 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1761809523; cv=none; d=zohomail.com; s=zohoarc; b=jehV9MyVKsYg0Bo335pHKHjvt1vLtfHsj9fgjOMuSmaUvlCY2MBnRQjwEhbbcBQP2Bps2toVE2zAigBQFtrnRllIBP0wWZLTKno+Ovfx5v+WH2V2OTI2PUXYqQynPg5OhON+8GLWQY4b36f/EON9vjY3PHyFSC6ct1IRPcZRbB8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1761809523; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Fe5bhLuyG5WOblCIlnczmwsx9+pG/Wxr2BLnDKiVnbY=; b=RV+o4cS7ww+4q8N+6hCzDzQghy3yLwEn+Vguveq9Fq9Yi++/jP9VXTpXLHsf0XUmW41hoPWJdFJlBFL3E9lHp2U7W0mrqLZoGnqd/ma1f3n27yWNwUGaQXlfm3bcKOvGyO35yr6A1qw8QlRNLb7UghbwmhfDbhjtWGWIJ1JVByw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761809523193200.03007229004447; Thu, 30 Oct 2025 00:32:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vEN7j-0003A6-9F; Thu, 30 Oct 2025 03:31:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEN7M-0002s9-PM; Thu, 30 Oct 2025 03:30:49 -0400 Received: from fout-a6-smtp.messagingengine.com ([103.168.172.149]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vEN7H-000554-TO; Thu, 30 Oct 2025 03:30:44 -0400 Received: from phl-compute-11.internal (phl-compute-11.internal [10.202.2.51]) by mailfout.phl.internal (Postfix) with ESMTP id D9861EC01BC; Thu, 30 Oct 2025 03:30:31 -0400 (EDT) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-11.internal (MEProxy); Thu, 30 Oct 2025 03:30:31 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 30 Oct 2025 03:30:30 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=irrelevant.dk; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1761809431; x= 1761895831; bh=Fe5bhLuyG5WOblCIlnczmwsx9+pG/Wxr2BLnDKiVnbY=; b=m k5votI4OdSQPp2PaJMZMYx+wDSHYOyAxN7kZ42He0kyLge9VxLNg8kGo+9WiHrS8 I1bdNQmW648q14d1ejyXFKTs3zUBKF2atgj2rvMvgOHeONQ/nFXNgc6mvjgV5Ie6 xnmK0WSkuIZ3wyHHuPUasTpOCaTRSuE/D3yD5/yjcJdMVYluv3A3UbGvMMV0trY1 LXPhAFeFNWCUxrMGSsdhaWWIUrHJljUnMkf2055mOkJa1CRVhSMO8UkbkzqIu5m3 nbv/YlUlFX8cdTnzozLvk1vpspuR07chs7BKWZA/SOzqN85w+JH+9toa2QpAFjIr Elfu2TN/zbrOB8bdZKrTg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1761809431; x=1761895831; bh=F e5bhLuyG5WOblCIlnczmwsx9+pG/Wxr2BLnDKiVnbY=; b=RMRxdEqf9fuE+ihJM TKrUrQehtnB4+dRgdhI0pQn+D8SRkNmXABuZOFZDulVFKqzddO33bg4VN87pnWLW WKQu31dYPHRuiBbxqloIHoRAxPnElYoR6sso5RREAnaL5CPwt/KTqVtOtUvLIflC 2Dnbz/NS5PsbiKuYwem2Ko0Gl5sjBQtg65nM6pWjKArmgASDGtc94URXYY1EQeSJ sdJt0Ra06ID3mj5EavgCwJC08KN7JqMZ/5oEa3pgMISjgh+GuRxvMzdk1f5lumWs O9O9v4UnytetONxoTQTsoaruCHQIyGNn5FDp2FdVzH5wSU9VlzW9/mfv0iY4thuR /A5bQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduieeitdduucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomhepmfhlrghushcu lfgvnhhsvghnuceoihhtshesihhrrhgvlhgvvhgrnhhtrdgukheqnecuggftrfgrthhtvg hrnhepjefgieelgfeiveehkeeuveehheekfeevgeeigfehfefgjeejhefffeegudejudeg necuvehluhhsthgvrhfuihiivgepudenucfrrghrrghmpehmrghilhhfrhhomhepihhtsh esihhrrhgvlhgvvhgrnhhtrdgukhdpnhgspghrtghpthhtohepkedpmhhouggvpehsmhht phhouhhtpdhrtghpthhtohepqhgvmhhuqdguvghvvghlsehnohhnghhnuhdrohhrghdprh gtphhtthhopehpvghtvghrrdhmrgihuggvlhhlsehlihhnrghrohdrohhrghdprhgtphht thhopegrlhgrnhdrrggurghmshhonhesohhrrggtlhgvrdgtohhmpdhrtghpthhtohepfh hoshhsseguvghfmhgrtghrohdrihhtpdhrtghpthhtohepkhdrjhgvnhhsvghnsehsrghm shhunhhgrdgtohhmpdhrtghpthhtohepkhgsuhhstghhsehkvghrnhgvlhdrohhrghdprh gtphhtthhopehithhssehirhhrvghlvghvrghnthdrughkpdhrtghpthhtohepqhgvmhhu qdgslhhotghksehnohhnghhnuhdrohhrgh X-ME-Proxy: Feedback-ID: idc91472f:Fastmail From: Klaus Jensen To: qemu-devel@nongnu.org Cc: Peter Maydell , Alan Adamson , Jesper Wendel Devantier , Klaus Jensen , Keith Busch , Klaus Jensen , qemu-block@nongnu.org Subject: [PULL 7/7] hw/nvme: add atomic boundary support Date: Thu, 30 Oct 2025 08:29:55 +0100 Message-ID: <20251030072956.1194-8-its@irrelevant.dk> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251030072956.1194-1-its@irrelevant.dk> References: <20251030072956.1194-1-its@irrelevant.dk> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=103.168.172.149; envelope-from=its@irrelevant.dk; helo=fout-a6-smtp.messagingengine.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @irrelevant.dk) X-ZM-MESSAGEID: 1761809526249158500 Content-Type: text/plain; charset="utf-8" From: Alan Adamson Add support for the namespace atomic boundary paramters: NABO, NABSN, and N= ABSPF. Writes that cross an atomic boundary whose size is less than or equal to va= lues reported by AWUN/AWUPF are guaranteed to be atomic. If AWUN/AWUPF is set to= zero, writes that cross an atomic boundary are not guaranteed to be atomic. The value reported by NABO field indicates the LBA on this namespace where = the first atomic boundary starts. New NVMe QEMU Paramters (See NVMe Specification for details): atomic.nabo=3DUINT16 (default: 0) atomic.nabsn=3DUINT16 (default: 0) atomic.nabspf=3DUINT16 (default: 0) See the NVMe Specification for more information. Signed-off-by: Alan Adamson Reviewed-by: Jesper Wendel Devantier Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/nvme/ns.c | 36 ++++++++++++++++++++++++++++++++++ hw/nvme/nvme.h | 8 ++++++++ 3 files changed, 97 insertions(+) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 121a95b2e373..4d150c7206ad 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -6711,9 +6711,21 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRe= quest *req) if (n->dn) { ns->atomic.atomic_max_write_size =3D le16_to_cpu(ns->id_ns.nawupf) + 1; + if (ns->id_ns.nabspf) { + ns->atomic.atomic_boundary =3D + le16_to_cpu(ns->id_ns.nabspf) + 1; + } else { + ns->atomic.atomic_boundary =3D 0; + } } else { ns->atomic.atomic_max_write_size =3D le16_to_cpu(ns->id_ns.nawun) + 1; + if (ns->id_ns.nabsn) { + ns->atomic.atomic_boundary =3D + le16_to_cpu(ns->id_ns.nabsn) + 1; + } else { + ns->atomic.atomic_boundary =3D 0; + } } if (ns->atomic.atomic_max_write_size =3D=3D 1) { ns->atomic.atomic_writes =3D 0; @@ -7636,6 +7648,36 @@ static void nvme_update_sq_tail(NvmeSQueue *sq) trace_pci_nvme_update_sq_tail(sq->sqid, sq->tail); } =20 +static int nvme_atomic_boundary_check(NvmeCtrl *n, NvmeCmd *cmd, + NvmeAtomic *atomic) +{ + NvmeRwCmd *rw =3D (NvmeRwCmd *)cmd; + + if (atomic->atomic_boundary) { + uint64_t slba =3D le64_to_cpu(rw->slba); + uint32_t nlb =3D (uint32_t)le16_to_cpu(rw->nlb); + uint64_t elba =3D slba + nlb; + uint64_t imask; + + if ((slba < atomic->atomic_nabo) || (elba < atomic->atomic_nabo)) { + return 0; + } + + /* Update slba/elba based on boundary offset */ + slba =3D slba - atomic->atomic_nabo; + elba =3D slba + nlb; + + imask =3D ~(atomic->atomic_boundary - 1); + if ((slba & imask) !=3D (elba & imask)) { + if (n->atomic.atomic_max_write_size && + ((nlb + 1) <=3D n->atomic.atomic_max_write_size)) { + return 1; + } + return 0; + } + } + return 1; +} #define NVME_ATOMIC_NO_START 0 #define NVME_ATOMIC_START_ATOMIC 1 #define NVME_ATOMIC_START_NONATOMIC 2 @@ -7655,6 +7697,15 @@ static int nvme_atomic_write_check(NvmeCtrl *n, Nvme= Cmd *cmd, cmd_atomic_wr =3D false; } =20 + /* + * Check if a write crosses an atomic boundary. + */ + if (cmd->opcode =3D=3D NVME_CMD_WRITE) { + if (!nvme_atomic_boundary_check(n, cmd, atomic)) { + cmd_atomic_wr =3D false; + } + } + /* * Walk the queues to see if there are any atomic conflicts. */ @@ -8741,6 +8792,8 @@ static void nvme_init_state(NvmeCtrl *n) } else { atomic->atomic_writes =3D 1; } + atomic->atomic_boundary =3D 0; + atomic->atomic_nabo =3D 0; } } =20 diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 28aacb8db59a..86f5ab0a7572 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -747,6 +747,28 @@ static void nvme_ns_realize(DeviceState *dev, Error **= errp) error_report("Invalid: NAWUN=3D%x NAWUPF=3D%x", id_ns->nawun, id_ns->nawupf); } + id_ns->nabsn =3D cpu_to_le16(ns->params.atomic_nabsn); + id_ns->nabspf =3D cpu_to_le16(ns->params.atomic_nabspf); + id_ns->nabo =3D cpu_to_le16(ns->params.atomic_nabo); + if (!id->awun || (id_ns->nabsn && ((id_ns->nabsn < id_ns->nawun) || + (id_ns->nabsn < id->awun)))) { + error_report("Invalid NABSN: %x NAWUN=3D%x AWUN=3D%x", + id_ns->nabsn, id_ns->nawun, id->awun); + } + if (!id->awupf || (id_ns->nabspf && ((id_ns->nabspf < id_ns->nawup= f) || + (id_ns->nawupf < id->awupf)))) { + error_report("Invalid NABSPF: %x NAWUPF=3D%x AWUPF=3D%x", + id_ns->nabspf, id_ns->nawupf, id->awupf); + } + if (id_ns->nabo && ((id_ns->nabo > id_ns->nabsn) || + (id_ns->nabo > id_ns->nabspf))) { + error_report("Invalid NABO: %x NABSN=3D%x NABSPF=3D%x", + id_ns->nabo, id_ns->nabsn, id_ns->nabspf); + } + if (id_ns->nawupf > id_ns->nawun) { + error_report("Invalid: NAWUN=3D%x NAWUPF=3D%x", id_ns->nawun, + id_ns->nawupf); + } } =20 if (id_ns->nawun || id_ns->nawupf) { @@ -754,14 +776,25 @@ static void nvme_ns_realize(DeviceState *dev, Error *= *errp) =20 if (n->dn) { atomic->atomic_max_write_size =3D cpu_to_le16(id_ns->nawupf) += 1; + if (id_ns->nabspf) { + atomic->atomic_boundary =3D cpu_to_le16(id_ns->nabspf) + 1; + } else { + atomic->atomic_boundary =3D 0; + } } else { atomic->atomic_max_write_size =3D cpu_to_le16(id_ns->nawun) + = 1; + if (id_ns->nabsn) { + atomic->atomic_boundary =3D cpu_to_le16(id_ns->nabsn) + 1; + } else { + atomic->atomic_boundary =3D 0; + } } if (atomic->atomic_max_write_size =3D=3D 1) { atomic->atomic_writes =3D 0; } else { atomic->atomic_writes =3D 1; } + atomic->atomic_nabo =3D cpu_to_le16(id_ns->nabo); } =20 /* reparent to subsystem bus */ @@ -841,6 +874,9 @@ static const Property nvme_ns_props[] =3D { DEFINE_PROP_STRING("fdp.ruhs", NvmeNamespace, params.fdp.ruhs), DEFINE_PROP_UINT16("atomic.nawun", NvmeNamespace, params.atomic_nawun,= 0), DEFINE_PROP_UINT16("atomic.nawupf", NvmeNamespace, params.atomic_nawup= f, 0), + DEFINE_PROP_UINT16("atomic.nabspf", NvmeNamespace, params.atomic_nabsp= f, 0), + DEFINE_PROP_UINT16("atomic.nabsn", NvmeNamespace, params.atomic_nabsn,= 0), + DEFINE_PROP_UINT16("atomic.nabo", NvmeNamespace, params.atomic_nabo, 0= ), DEFINE_PROP_BOOL("atomic.nsfeat", NvmeNamespace, params.atomic_nsfeat,= 0), }; =20 diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 7d01080fc1f9..a7d225d2d80b 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -220,11 +220,16 @@ typedef struct NvmeNamespaceParams { } fdp; uint16_t atomic_nawun; uint16_t atomic_nawupf; + uint16_t atomic_nabsn; + uint16_t atomic_nabspf; + uint16_t atomic_nabo; bool atomic_nsfeat; } NvmeNamespaceParams; =20 typedef struct NvmeAtomic { uint32_t atomic_max_write_size; + uint64_t atomic_boundary; + uint64_t atomic_nabo; bool atomic_writes; } NvmeAtomic; =20 @@ -285,6 +290,9 @@ typedef struct NvmeNamespace { } fdp; uint16_t atomic_nawun; uint16_t atomic_nawupf; + uint16_t atomic_nabsn; + uint16_t atomic_nabspf; + uint16_t atomic_nabo; NvmeAtomic atomic; } NvmeNamespace; =20 --=20 2.51.0