From 076c816f4e62824714427a9d193f31ccb693d404 Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Sun, 23 Feb 2020 16:12:12 +0100 Subject: hw/block/nvme: verify validity of prp lists in the cmb Before this patch the device already supported PRP lists in the CMB, but it did not check for the validity of it nor announced the support in the Identify Controller data structure LISTS field. If some of the PRPs in a PRP list are in the CMB, then ALL entries must be there. This patch makes sure that requirement is verified as well as properly announcing support for PRP lists in the CMB. Signed-off-by: Klaus Jensen Reviewed-by: Maxim Levitsky Reviewed-by: Minwoo Im --- hw/block/nvme.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'hw/block/nvme.c') diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 78b4873710..fc629cd8b2 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -288,6 +288,7 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, trans_len = MIN(len, trans_len); int num_prps = (len >> n->page_bits) + 1; uint16_t status; + bool prp_list_in_cmb = false; trace_pci_nvme_map_prp(trans_len, len, prp1, prp2, num_prps); @@ -314,11 +315,16 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, status = NVME_INVALID_FIELD | NVME_DNR; goto unmap; } + if (len > n->page_size) { uint64_t prp_list[n->max_prp_ents]; uint32_t nents, prp_trans; int i = 0; + if (nvme_addr_is_cmb(n, prp2)) { + prp_list_in_cmb = true; + } + nents = (len + n->page_size - 1) >> n->page_bits; prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t); nvme_addr_read(n, prp2, (void *)prp_list, prp_trans); @@ -332,6 +338,11 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, goto unmap; } + if (prp_list_in_cmb != nvme_addr_is_cmb(n, prp_ent)) { + status = NVME_INVALID_USE_OF_CMB | NVME_DNR; + goto unmap; + } + i = 0; nents = (len + n->page_size - 1) >> n->page_bits; prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t); @@ -351,6 +362,7 @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1, if (status) { goto unmap; } + len -= trans_len; i++; } @@ -2168,7 +2180,7 @@ static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev) NVME_CMBSZ_SET_SQS(n->bar.cmbsz, 1); NVME_CMBSZ_SET_CQS(n->bar.cmbsz, 0); - NVME_CMBSZ_SET_LISTS(n->bar.cmbsz, 0); + NVME_CMBSZ_SET_LISTS(n->bar.cmbsz, 1); NVME_CMBSZ_SET_RDS(n->bar.cmbsz, 1); NVME_CMBSZ_SET_WDS(n->bar.cmbsz, 1); NVME_CMBSZ_SET_SZU(n->bar.cmbsz, 2); /* MBs */ -- cgit v1.2.3