git: cd8a5d2316a1 - stable/12 - bhyve: Fix NVMe iovec construction for large IOs
Chuck Tuffli
chuck at FreeBSD.org
Fri Jul 9 14:27:34 UTC 2021
The branch stable/12 has been updated by chuck:
URL: https://cgit.FreeBSD.org/src/commit/?id=cd8a5d2316a12a8abca458c31467dc9dcf8361ce
commit cd8a5d2316a12a8abca458c31467dc9dcf8361ce
Author: Chuck Tuffli <chuck at FreeBSD.org>
AuthorDate: 2021-06-27 22:14:52 +0000
Commit: Chuck Tuffli <chuck at FreeBSD.org>
CommitDate: 2021-07-09 14:25:45 +0000
bhyve: Fix NVMe iovec construction for large IOs
The UEFI driver included with Rocky Linux 8.4 uncovered an existing bug
in the NVMe emulation's construction of iovec's.
By default, NVMe data transfer operations use a scatter-gather list in
which all entries point to a fixed size memory region. For example, if
the Memory Page Size is 4KiB, a 2MiB IO requires 512 entries. Lists
themselves are also fixed size (default is 512 entries).
Because the list size is fixed, the last entry is special. If the IO
requires more than 512 entries, the last entry in the list contains the
address of the next list of entries. But if the IO requires exactly 512
entries, the last entry points to data.
The NVMe emulation missed this logic and unconditionally treated the
last entry as a pointer to the next list. Fix is to check if the
remaining data is greater than the page size before using the last entry
as a pointer to the next list.
PR: 256422
Reported by: dave at syix.com
Tested by: jason at tubnor.net
Relnotes: yes
(cherry picked from commit 91064841d72b285a146a3f1c32cb447251e062ea)
---
usr.sbin/bhyve/pci_nvme.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/usr.sbin/bhyve/pci_nvme.c b/usr.sbin/bhyve/pci_nvme.c
index 2679874d73fc..5f7a13d492f2 100644
--- a/usr.sbin/bhyve/pci_nvme.c
+++ b/usr.sbin/bhyve/pci_nvme.c
@@ -1973,7 +1973,7 @@ nvme_write_read_blockif(struct pci_nvme_softc *sc,
/* PRP2 is pointer to a physical region page list */
while (bytes) {
/* Last entry in list points to the next list */
- if (prp_list == last) {
+ if ((prp_list == last) && (bytes > PAGE_SIZE)) {
uint64_t prp = *prp_list;
prp_list = paddr_guest2host(vmctx, prp,
More information about the dev-commits-src-all
mailing list