NVMe command set specification for end-to-end data protection formatted namespace states:
o If the Reference Tag Check bit of the PRCHK field is set to ‘1’ and the namespace is formatted for Type 3 protection, then the controller: ▪ should not compare the protection Information Reference Tag field to the computed reference tag; and ▪ may ignore the ILBRT and EILBRT fields. If a command is aborted as a result of the Reference Tag Check bit of the PRCHK field being set to ‘1’, then that command should be aborted with a status code of Invalid Protection Information, but may be aborted with a status code of Invalid Field in Command. Currently qemu compares reftag in the nvme_dif_prchk function whenever Reference Tag Check bit is set in the command. For type 3 namespaces however, caller of nvme_dif_prchk - nvme_dif_check does not increment reftag for each subsequent logical block. That way commands incorporating more than one logical block for type 3 formatted namespaces with reftag check bit set, always fail with End-to-end Reference Tag Check Error. Comply with spec by handling case of set Reference Tag Check bit in the type 3 formatted namespace. Signed-off-by: Dmitry Tikhov <d.ti...@yadro.com> --- hw/nvme/dif.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c index 62d885f83e..63c44c86ab 100644 --- a/hw/nvme/dif.c +++ b/hw/nvme/dif.c @@ -26,6 +26,11 @@ uint16_t nvme_check_prinfo(NvmeNamespace *ns, uint8_t prinfo, uint64_t slba, return NVME_INVALID_PROT_INFO | NVME_DNR; } + if ((NVME_ID_NS_DPS_TYPE(ns->id_ns.dps) == NVME_ID_NS_DPS_TYPE_3) && + (prinfo & NVME_PRINFO_PRCHK_REF)) { + return NVME_INVALID_PROT_INFO; + } + return NVME_SUCCESS; } -- 2.35.1