[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 28/30] hw/block/nvme: fix prp mapping status codes
From: |
Klaus Jensen |
Subject: |
[PULL 28/30] hw/block/nvme: fix prp mapping status codes |
Date: |
Tue, 27 Oct 2020 11:49:30 +0100 |
From: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Address 0 is not an invalid address. Remove those invalikd checks.
Unaligned PRP2 and PRP list entries should result in Invalid PRP Offset
status code and not Invalid Field. Fix that.
See NVMe Express v1.3d, Section 4.3 ("Physical Region Page Entry and
List").
Suggested-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
---
include/block/nvme.h | 1 +
hw/block/nvme.c | 20 +++++---------------
hw/block/trace-events | 4 +---
3 files changed, 7 insertions(+), 18 deletions(-)
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 6de2d5aa75a9..8a46d9cf015f 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -655,6 +655,7 @@ enum NvmeStatusCodes {
NVME_MD_SGL_LEN_INVALID = 0x0010,
NVME_SGL_DESCR_TYPE_INVALID = 0x0011,
NVME_INVALID_USE_OF_CMB = 0x0012,
+ NVME_INVALID_PRP_OFFSET = 0x0013,
NVME_LBA_RANGE = 0x0080,
NVME_CAP_EXCEEDED = 0x0081,
NVME_NS_NOT_READY = 0x0082,
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index b8c6be63186f..2896bb49b9c0 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -327,11 +327,6 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1,
uint64_t prp2,
trace_pci_nvme_map_prp(trans_len, len, prp1, prp2, num_prps);
- if (unlikely(!prp1)) {
- trace_pci_nvme_err_invalid_prp();
- return NVME_INVALID_FIELD | NVME_DNR;
- }
-
if (nvme_addr_is_cmb(n, prp1)) {
qemu_iovec_init(iov, num_prps);
} else {
@@ -345,11 +340,6 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1,
uint64_t prp2,
len -= trans_len;
if (len) {
- if (unlikely(!prp2)) {
- trace_pci_nvme_err_invalid_prp2_missing();
- return NVME_INVALID_FIELD | NVME_DNR;
- }
-
if (len > n->page_size) {
uint64_t prp_list[n->max_prp_ents];
uint32_t nents, prp_trans;
@@ -370,9 +360,9 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1,
uint64_t prp2,
uint64_t prp_ent = le64_to_cpu(prp_list[i]);
if (i == n->max_prp_ents - 1 && len > n->page_size) {
- if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
+ if (unlikely(prp_ent & (n->page_size - 1))) {
trace_pci_nvme_err_invalid_prplist_ent(prp_ent);
- return NVME_INVALID_FIELD | NVME_DNR;
+ return NVME_INVALID_PRP_OFFSET | NVME_DNR;
}
if (prp_list_in_cmb != nvme_addr_is_cmb(n, prp_ent)) {
@@ -391,9 +381,9 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1,
uint64_t prp2,
prp_ent = le64_to_cpu(prp_list[i]);
}
- if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
+ if (unlikely(prp_ent & (n->page_size - 1))) {
trace_pci_nvme_err_invalid_prplist_ent(prp_ent);
- return NVME_INVALID_FIELD | NVME_DNR;
+ return NVME_INVALID_PRP_OFFSET | NVME_DNR;
}
trans_len = MIN(len, n->page_size);
@@ -408,7 +398,7 @@ static uint16_t nvme_map_prp(NvmeCtrl *n, uint64_t prp1,
uint64_t prp2,
} else {
if (unlikely(prp2 & (n->page_size - 1))) {
trace_pci_nvme_err_invalid_prp2_align(prp2);
- return NVME_INVALID_FIELD | NVME_DNR;
+ return NVME_INVALID_PRP_OFFSET | NVME_DNR;
}
status = nvme_map_addr(n, qsg, iov, prp2, len);
if (status) {
diff --git a/hw/block/trace-events b/hw/block/trace-events
index cab9913b1f2d..c1537e3ac0b0 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -97,10 +97,8 @@ pci_nvme_err_invalid_sgld(uint16_t cid, uint8_t typ) "cid
%"PRIu16" type 0x%"PRI
pci_nvme_err_invalid_num_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type
0x%"PRIx8""
pci_nvme_err_invalid_sgl_excess_length(uint16_t cid) "cid %"PRIu16""
pci_nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size"
-pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or
not page aligned: 0x%"PRIx64""
+pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is not page
aligned: 0x%"PRIx64""
pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned:
0x%"PRIx64""
-pci_nvme_err_invalid_prp2_missing(void) "PRP2 is null and more data to be
transferred"
-pci_nvme_err_invalid_prp(void) "invalid PRP"
pci_nvme_err_invalid_opc(uint8_t opc) "invalid opcode 0x%"PRIx8""
pci_nvme_err_invalid_admin_opc(uint8_t opc) "invalid admin opcode 0x%"PRIx8""
pci_nvme_err_invalid_lba_range(uint64_t start, uint64_t len, uint64_t limit)
"Invalid LBA start=%"PRIu64" len=%"PRIu64" limit=%"PRIu64""
--
2.29.1
- [PULL 17/30] hw/block/nvme: change controller pci id, (continued)
- [PULL 17/30] hw/block/nvme: change controller pci id, Klaus Jensen, 2020/10/27
- [PULL 21/30] hw/block/nvme: support per-namespace smart log, Klaus Jensen, 2020/10/27
- [PULL 23/30] hw/block/nvme: support for admin-only command set, Klaus Jensen, 2020/10/27
- [PULL 22/30] hw/block/nvme: validate command set selected, Klaus Jensen, 2020/10/27
- [PULL 20/30] hw/block/nvme: fix log page offset check, Klaus Jensen, 2020/10/27
- [PULL 25/30] hw/block/nvme: add nsid to get/setfeat trace events, Klaus Jensen, 2020/10/27
- [PULL 26/30] hw/block/nvme: add trace event for requests with non-zero status code, Klaus Jensen, 2020/10/27
- [PULL 24/30] hw/block/nvme: reject io commands if only admin command set selected, Klaus Jensen, 2020/10/27
- [PULL 27/30] hw/block/nvme: report actual LBA data shift in LBAF, Klaus Jensen, 2020/10/27
- [PULL 29/30] hw/block/nvme: fix create IO SQ/CQ status codes, Klaus Jensen, 2020/10/27
- [PULL 28/30] hw/block/nvme: fix prp mapping status codes,
Klaus Jensen <=
- [PULL 30/30] hw/block/nvme: fix queue identifer validation, Klaus Jensen, 2020/10/27
- Re: [PULL 00/30] nvme emulation patches for 5.2, Peter Maydell, 2020/10/29