Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163221221
D35453.id106833.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D35453.id106833.diff
View Options
Index: usr.sbin/bhyve/pci_nvme.c
===================================================================
--- usr.sbin/bhyve/pci_nvme.c
+++ usr.sbin/bhyve/pci_nvme.c
@@ -398,6 +398,7 @@
((sts) >> NVME_CSTS_REG_RDY_SHIFT & NVME_CSTS_REG_RDY_MASK)
#define NVME_CSTS_RDY (1 << NVME_CSTS_REG_RDY_SHIFT)
+#define NVME_CSTS_CFS (1 << NVME_CSTS_REG_CFS_SHIFT)
/* Completion Queue status word utils */
#define NVME_STATUS_P (1 << NVME_STATUS_P_SHIFT)
@@ -1081,30 +1082,61 @@
pthread_mutex_unlock(&sc->mtx);
}
-static void
+static int
pci_nvme_init_controller(struct vmctx *ctx, struct pci_nvme_softc *sc)
{
uint16_t acqs, asqs;
DPRINTF("%s", __func__);
- asqs = (sc->regs.aqa & NVME_AQA_REG_ASQS_MASK) + 1;
+ /*
+ * NVMe 2.0 states that "enabling a controller while this field is
+ * cleared to 0h produces undefined results" for both ACQS and
+ * ASQS. If zero, set CFS and do not become ready.
+ */
+ asqs = ONE_BASED(sc->regs.aqa & NVME_AQA_REG_ASQS_MASK);
+ if (asqs < 2) {
+ EPRINTLN("%s: illegal ASQS value %#x (aqa=%#x)", __func__,
+ asqs - 1, sc->regs.aqa);
+ sc->regs.csts |= NVME_CSTS_CFS;
+ return (-1);
+ }
sc->submit_queues[0].size = asqs;
sc->submit_queues[0].qbase = vm_map_gpa(ctx, sc->regs.asq,
sizeof(struct nvme_command) * asqs);
+ if (sc->submit_queues[0].qbase == NULL) {
+ EPRINTLN("%s: ASQ vm_map_gpa(%lx) failed", __func__,
+ sc->regs.asq);
+ sc->regs.csts |= NVME_CSTS_CFS;
+ return (-1);
+ }
DPRINTF("%s mapping Admin-SQ guest 0x%lx, host: %p",
__func__, sc->regs.asq, sc->submit_queues[0].qbase);
- acqs = ((sc->regs.aqa >> NVME_AQA_REG_ACQS_SHIFT) &
- NVME_AQA_REG_ACQS_MASK) + 1;
+ acqs = ONE_BASED((sc->regs.aqa >> NVME_AQA_REG_ACQS_SHIFT) &
+ NVME_AQA_REG_ACQS_MASK);
+ if (acqs < 2) {
+ EPRINTLN("%s: illegal ACQS value %#x (aqa=%#x)", __func__,
+ acqs - 1, sc->regs.aqa);
+ sc->regs.csts |= NVME_CSTS_CFS;
+ return (-1);
+ }
sc->compl_queues[0].size = acqs;
sc->compl_queues[0].qbase = vm_map_gpa(ctx, sc->regs.acq,
sizeof(struct nvme_completion) * acqs);
+ if (sc->compl_queues[0].qbase == NULL) {
+ EPRINTLN("%s: ACQ vm_map_gpa(%lx) failed", __func__,
+ sc->regs.acq);
+ sc->regs.csts |= NVME_CSTS_CFS;
+ return (-1);
+ }
sc->compl_queues[0].intr_en = NVME_CQ_INTEN;
DPRINTF("%s mapping Admin-CQ guest 0x%lx, host: %p",
__func__, sc->regs.acq, sc->compl_queues[0].qbase);
+
+ return (0);
}
static int
@@ -2867,6 +2899,12 @@
uint64_t idx = belloffset / 8; /* door bell size = 2*int */
int is_sq = (belloffset % 8) < 4;
+ if ((sc->regs.csts & NVME_CSTS_RDY) == 0) {
+ WPRINTF("doorbell write prior to RDY (offset=%#lx)\n",
+ offset);
+ return;
+ }
+
if (belloffset > ((sc->max_queues+1) * 8 - 4)) {
WPRINTF("guest attempted an overflow write offset "
"0x%lx, val 0x%lx in %s",
@@ -2874,6 +2912,12 @@
return;
}
+ if (is_sq) {
+ if (sc->submit_queues[idx].qbase == NULL)
+ return;
+ } else if (sc->compl_queues[idx].qbase == NULL)
+ return;
+
pci_nvme_handle_doorbell(ctx, sc, idx, is_sq, value);
return;
}
@@ -2940,7 +2984,8 @@
sc->regs.cc &= ~NVME_CC_NEN_WRITE_MASK;
sc->regs.cc |= ccreg & NVME_CC_NEN_WRITE_MASK;
sc->regs.csts &= ~NVME_CSTS_RDY;
- } else if (sc->pending_ios == 0) {
+ } else if ((sc->pending_ios == 0) &&
+ !(sc->regs.csts & NVME_CSTS_CFS)) {
sc->regs.csts |= NVME_CSTS_RDY;
}
break;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jul 22, 4:42 AM (14 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35347664
Default Alt Text
D35453.id106833.diff (3 KB)
Attached To
Mode
D35453: bhyve nvme: Fix Controller init error cases
Attached
Detach File
Event Timeline
Log In to Comment