void AdminQFull_r10b::AdminQFull(uint16_t numASQEntries, uint16_t numACQEntries, SharedIdentifyPtr idCmdCtrlr) { uint32_t numCE; uint32_t isrCount; uint16_t uniqueId; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); // Create Admin Q Objects for test lifetime SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(mFd))) acq->Init(numACQEntries); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd))) asq->Init(numASQEntries); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); uint32_t nCmdsToSubmit = numASQEntries - 1; LOG_NRM("Send #%d cmds to hdw via ASQ", nCmdsToSubmit); for (uint32_t nCmds = 0; nCmds < nCmdsToSubmit; nCmds++) { LOG_NRM("Sending #%d of #%d Identify Cmds thru ASQ", nCmds + 1, nCmdsToSubmit); asq->Send(idCmdCtrlr, uniqueId); asq->Ring(); LOG_NRM("Wait for the CE to arrive in ACQ"); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, (nCmds + 1), numCE, isrCount) == false) { // when asq size = acq size + 1, last CE will never arrive. if ((numASQEntries == numACQEntries + 1) && (nCmds == nCmdsToSubmit - 1)) { // Reap one element from IOCQ to make room for last CE. IO::ReapCE(acq, 1, isrCount, mGrpName, mTestName, "ACQCE", CESTAT_SUCCESS); if (acq->ReapInquiryWaitSpecify(DEFAULT_CMD_WAIT_ms, nCmds, numCE, isrCount) == false) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq." + idCmdCtrlr->GetName()), "Dump entire ACQ"); throw FrmwkEx(HERE, "Unable to see last CE as expected"); } break; } acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq." + idCmdCtrlr->GetName()), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Unable to see CE for issued cmd #%d", nCmds + 1); } else if (numCE != nCmds + 1) { acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq." + idCmdCtrlr->GetName()), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Missing last CE, #%d cmds of #%d received", nCmds + 1, numCE); } } }
bool CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw exception(); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw exception(); return true; }
void PRP1PRP2_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group string work; uint64_t i; SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); LOG_NRM("Get log page to request firmware slot information"); getLogPgCmd->SetNUMD(PRP1_ONLY_NUMD - 1); // 0-based getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID); getLogPgCmd->SetNSID(0xFFFFFFFF); LOG_NRM("Set the offset into the buffer at 0x%04X", BUFFER_OFFSET); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE, BUFFER_OFFSET, true); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, "prp1prp2", true); }
bool CreateACQASQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpBasicInit. * 2) The NVME device is disabled * 3) All interrupts are disabled. * \endverbatim */ KernelAPI::DumpKernelMetrics(mFd, FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "before")); // After disabling the defaults for AMS & CSS are fine, no need to modify if (gCtrlrConfig->SetMPS() == false) throw exception(); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw exception(); KernelAPI::DumpKernelMetrics(mFd, FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "after")); return true; }
void PRP1PRP2_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ LOG_NRM("Lookup objs which were created in a prior test within group"); SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Determine if DUT has atleast one namespace support"); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); LOG_NRM("Form identify namespace cmd and associate some buffer"); SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify()); idCmdNamSpc->SetCNS(false); idCmdNamSpc->SetNSID(1); SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer()); idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_OFFSET, true); LOG_NRM("Allow PRP1 and PRP2"); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "prp1Prp2", true); }
void DeleteIOQContig_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Both test CreateIOQContigPoll_r10b & CreateIOQDiscontigPoll_r10b has * run prior, or Both test CreateIOQContigIrq_r10b & * CreateIOQDiscontigIrq_r10b has run prior * 2) An individual test within this group cannot run, the entire group * must be executed every time. Each subsequent test relies on the prior. * \endverbatim */ // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) // According to spec, if one deletes the CQ before the SQ it's a "shall not" // statement which means it will have undefined behavior and thus there is // nothing to gain by attempting such action. LOG_NRM("Lookup IOSQ which was created in a prior test within group"); SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_CONTIG_GROUP_ID)) Queues::DeleteIOSQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, asq, acq); LOG_NRM("Lookup IOCQ which was created in a prior test within group"); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_CONTIG_GROUP_ID)) Queues::DeleteIOCQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iocq, asq, acq); }
void CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); }
void IllegalCreateQs_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) uint32_t numEntries = 2; uint8_t dword; uint32_t mask; uint32_t value; { LOG_NRM("Create IOCQ ID #%d but toxify its QID to 0", IOQ_ID); SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(mFd)); iocq->Init(IOQ_ID, numEntries, true, 0); LOG_NRM("Form a Create IOCQ cmd"); SharedCreateIOCQPtr iocqCmd = SharedCreateIOCQPtr(new CreateIOCQ()); iocqCmd->Init(iocq); dword = 10; mask = 0xFFFF; value = 0; SendToxicCmd(asq, acq, iocqCmd, dword, mask, value, CESTAT_INVALID_QID); } { LOG_NRM("Create IOSQ ID #%d but toxify its QID to 0", IOQ_ID); SharedIOSQPtr iosq = SharedIOSQPtr(new IOSQ(mFd)); iosq->Init(IOQ_ID, numEntries, IOQ_ID, 0); LOG_NRM("Form a Create IOSQ cmd"); SharedCreateIOSQPtr iosqCmd = SharedCreateIOSQPtr(new CreateIOSQ()); iosqCmd->Init(iosq); dword = 10; mask = 0xFFFF; value = 0; SendToxicCmd(asq, acq, iosqCmd, dword, mask, value, CESTAT_INVALID_QID); } { LOG_NRM("Create IOSQ ID #%d but wrongly associate to ACQ", IOQ_ID); SharedIOSQPtr iosq = SharedIOSQPtr(new IOSQ(mFd)); iosq->Init(IOQ_ID, numEntries, IOQ_ID, 0); LOG_NRM("Form a Create IOSQ cmd"); SharedCreateIOSQPtr iosqCmd = SharedCreateIOSQPtr(new CreateIOSQ()); iosqCmd->Init(iosq); dword = 11; mask = 0xFFFF0000; value = 0; SendToxicCmd(asq, acq, iosqCmd, dword, mask, value, CESTAT_CQ_INVALID); } }
bool DeleteIOQDiscontigPoll_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) The ASQ & ACQ's have been created by the RsrcMngr for group lifetime * 2) All interrupts are disabled. * 3) CreateIOQDiscontigPoll_r10b test case has setup the Q's to delete * 4) CC.IOCQES and CC.IOSQES are already setup with correct values. * \endverbatim */ uint64_t regVal; if (gRegisters->Read(CTLSPC_CAP, regVal) == false) { LOG_ERR("Unable to determine Q memory requirements"); throw exception(); } else if (regVal & CAP_CQR) { LOG_NRM("Unable to utilize discontig Q's, DUT requires contig"); return true; } KernelAPI::DumpKernelMetrics(mFd, FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "before")); // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) DeleteIOCQDiscontigPoll(asq, acq); DeleteIOSQDiscontigPoll(asq, acq); KernelAPI::DumpKernelMetrics(mFd, FileSystem::PrepLogFile(mGrpName, mTestName, "kmetrics", "after")); return true; }
void InvalidLogPageNVMSet_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ string work; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); getLogPageMem->InitOffset1stPage(BUFFER_SIZE, 0, true); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); getLogPgCmd->SetNUMD(NUMD - 1); // 0-based getLogPgCmd->SetNSID(0xFFFFFFFF); list<uint32_t> invalidLIDs = GetInvalidLIDs(); for (list<uint32_t>::iterator invalidLID = invalidLIDs.begin(); invalidLID != invalidLIDs.end(); invalidLID++) { LOG_NRM("Processing for invalid LID = 0x%04X", *invalidLID); getLogPgCmd->SetLID(*invalidLID); work = str(boost::format("invalidLID.%d") % *invalidLID); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true, CESTAT_INVAL_LOG_PAGE); } }
void MandatoryErrInfo_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ string work; uint64_t i; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint8_t X = idCtrlrStruct->GetValue(IDCTRLRCAP_ELPE) + 1; LOG_NRM("Identify controller ELPE = %d (1-based)", X); LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); LOG_NRM("Create memory buffer for log page to request error information"); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); LOG_NRM("Get log page to request error information"); getLogPgCmd->SetLID(ERRINFO_LID); // loop for all log entries supported by controller for (uint32_t numd = ERRINFO_NUMD; numd <= (X * ERRINFO_NUMD); numd += ERRINFO_NUMD) { LOG_NRM("Issue Get log page cmd with NUMD = %d and log entries = %d", numd, (numd/ERRINFO_NUMD)); getLogPageMem->Init(GetLogPage::ERRINFO_DATA_SIZE * X, true); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); getLogPgCmd->SetNUMD(numd - 1); // 0-based getLogPgCmd->SetNSID(0xFFFFFFFF); work = str(boost::format("logEnties%d") % (numd / ERRINFO_NUMD)); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, work, true); // Verify the buffer's non-retrieved log entries = 0x00. SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer(); uint32_t offset = (numd * 4); uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset; for (; offset < (X * GetLogPage::ERRINFO_DATA_SIZE); offset++) { LOG_NRM("Verify data at offset = 0x%X", offset); if (*cmdPayloadBuff != 0x0) { throw FrmwkEx(HERE, "Invalid data at buffer offset = 0x%08X, " "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff); } cmdPayloadBuff++; } } }
void UnsupportRsvdFields_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group string globalWork; //uint64_t i; SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); LOG_NRM("Get log page to request firmware slot information"); getLogPgCmd->SetNUMD(PRP1_ONLY_NUMD - 1); // 0-based getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID); getLogPgCmd->SetNSID(0xFFFFFFFF); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE, BUFFER_OFFSET, true); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); LOG_NRM("Issue GetLogPage cmd without setting reserved bits."); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, "rsvd.notset", true); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = getLogPgCmd->GetDword(0); work |= 0x0000fc00; // Set DW0_b15:10 bits getLogPgCmd->SetDword(work, 0); getLogPgCmd->SetDword(0xffffffff, 2); getLogPgCmd->SetDword(0xffffffff, 3); getLogPgCmd->SetDword(0xffffffff, 4); getLogPgCmd->SetDword(0xffffffff, 5); work = getLogPgCmd->GetDword(10); work |= 0xf0000000; // Set DW10_b31:28 bits getLogPgCmd->SetDword(work, 10); getLogPgCmd->SetDword(0xffffffff, 11); getLogPgCmd->SetDword(0xffffffff, 12); getLogPgCmd->SetDword(0xffffffff, 13); getLogPgCmd->SetDword(0xffffffff, 14); getLogPgCmd->SetDword(0xffffffff, 15); LOG_NRM("Issue GetLogPage cmd after setting reserved bits."); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, "rsvd.set", true); }
void UnsupportRsvdFields_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ LOG_NRM("Lookup objs which were created in a prior test within group"); SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Determine if DUT has atleast one namespace support"); ConstSharedIdentifyPtr idCmdCtrlr = gInformative->GetIdentifyCmdCtrlr(); if ((idCmdCtrlr->GetValue(IDCTRLRCAP_NN)) == 0) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); LOG_NRM("Form identify namespace cmd and associate some buffer"); SharedIdentifyPtr idCmdNamSpc = SharedIdentifyPtr(new Identify()); idCmdNamSpc->SetCNS(0); idCmdNamSpc->SetNSID(1); SharedMemBufferPtr idMemNamSpc = SharedMemBufferPtr(new MemBuffer()); idMemNamSpc->InitOffset1stPage(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_OFFSET, true); LOG_NRM("Allow PRP1 and PRP2"); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpc->SetPrpBuffer(idPrpNamSpc, idMemNamSpc); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdnone.set", true); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = idCmdNamSpc->GetDword(0); work |= 0x0000fc00; // Set DW0_b15:10 bits idCmdNamSpc->SetDword(work, 0); idCmdNamSpc->SetDword(0xffffffff, 2); idCmdNamSpc->SetDword(0xffffffff, 3); idCmdNamSpc->SetDword(0xffffffff, 4); idCmdNamSpc->SetDword(0xffffffff, 5); work = idCmdNamSpc->GetDword(10); work |= 0xfffffffe; // Set DW10_b31:1 bits idCmdNamSpc->SetDword(work, 10); idCmdNamSpc->SetDword(0xffffffff, 11); idCmdNamSpc->SetDword(0xffffffff, 12); idCmdNamSpc->SetDword(0xffffffff, 13); idCmdNamSpc->SetDword(0xffffffff, 14); idCmdNamSpc->SetDword(0xffffffff, 15); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpc, "rsvdall.set", true); }
void CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpBasicInit. * \endverbatim */ static uint32_t NumEntriesIOQ = 2; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); { uint64_t maxIOQEntries; // Determine the max IOQ entries supported if (gRegisters->Read(CTLSPC_CAP, maxIOQEntries) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); maxIOQEntries &= CAP_MQES; maxIOQEntries += 1; // convert to 1-based if (maxIOQEntries < (uint64_t)NumEntriesIOQ) { LOG_NRM("Changing number of Q elements from %d to %lld", NumEntriesIOQ, (unsigned long long)maxIOQEntries); NumEntriesIOQ = maxIOQEntries; } gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); Queues::CreateIOCQContigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, NumEntriesIOQ, true, IOCQ_GROUP_ID, true, 0); gCtrlrConfig->SetIOSQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); Queues::CreateIOSQContigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, NumEntriesIOQ, true, IOSQ_GROUP_ID, IOQ_ID, 0); } }
void CIDAcceptedIOSQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); LOG_NRM("Create ACQ and ASQ objects which have test life time"); SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(gDutFd))) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(gDutFd))) asq->Init(5); IRQ::SetAnySchemeSpecifyNum(2); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); vector<SharedIOSQPtr> iosqs; SharedIOCQPtr iocq; InitTstRsrcs(asq, acq, iosqs, iocq); SharedWritePtr writeCmd = CreateWriteCmd(); LOG_NRM("Learn initial unique command id assigned by dnvme"); uint16_t curCID; vector <SharedIOSQPtr>::iterator iosq; for (iosq = iosqs.begin(); iosq != iosqs.end(); iosq++) (*iosq)->Send(writeCmd, curCID); uint16_t prevCID = curCID; for (uint32_t nCmds = 0; nCmds < MAX_CMDS; nCmds++) { for (iosq = iosqs.begin(); iosq != iosqs.end(); iosq++) { LOG_NRM("(nCmds, curCID, prevCID, SQ ID) = (%d, %d, %d, %d)", nCmds, curCID, prevCID, (*iosq)->GetQId()); (*iosq)->Ring(); ReapVerifyCID(*iosq, iocq, prevCID); (*iosq)->Send(writeCmd, curCID); if (curCID != (uint16_t)(prevCID + 1)) { (*iosq)->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iosq.fail." + (*iosq)->GetQId()), "Dump Entire IOSQ"); iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq.fail." + iocq->GetQId()), "Dump Entire IOCQ"); throw FrmwkEx(HERE, "curCID(%d) != (prevCID + 1)(%d)", curCID, (prevCID + 1)); } } prevCID = curCID; } }
void CIDAcceptedASQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint32_t isrCount; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Verifying that the ACQ is empty"); if (acq->ReapInquiry(isrCount, true) != 0) { acq->Dump( FileSystem::PrepDumpFile(mGrpName, mTestName, "acq", "notEmpty"), "Test assumption have not been met"); throw FrmwkEx(HERE, "The ACQ should not have any CE's waiting before testing"); } LOG_NRM("Create identify cmd and assoc some buffer memory"); SharedIdentifyPtr idCmdCap = SharedIdentifyPtr(new Identify()); LOG_NRM("Force identify to request ctrlr capabilities struct"); idCmdCap->SetCNS(CNS_Controller); SharedMemBufferPtr idMemCap = SharedMemBufferPtr(new MemBuffer()); idMemCap->InitAlignment(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_ALIGNMENT, false, 0); send_64b_bitmask idPrpCap = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdCap->SetPrpBuffer(idPrpCap, idMemCap); LOG_NRM("Learn initial unique command id assigned by dnvme."); uint16_t currCID; asq->Send(idCmdCap, currCID); uint16_t prevCID = currCID; for (uint32_t nCmds = 0; nCmds < MAX_CMDS; nCmds++) { asq->Ring(); LOG_NRM("Verify unique CID #%d for Cmd #%d", currCID, nCmds + 1); ReapVerifyCID(asq, acq, currCID); asq->Send(idCmdCap, currCID); if (currCID != (uint16_t)(prevCID + 1)) { asq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "asq.fail"), "Dump Entire ASQ"); acq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "acq.fail"), "Dump Entire ACQ"); throw FrmwkEx(HERE, "Current CID(%d) != prev + 1(%d)", currCID, prevCID); } prevCID = currCID; } }
void NUMDIsAdhered_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group string work; uint64_t i; SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); LOG_NRM("Get log page to request firmware slot information"); getLogPgCmd->SetNUMD(NUMDW_ADHERED - 1); // 0-based getLogPgCmd->SetLID(FIRM_SLOT_INFO_LID); getLogPgCmd->SetNSID(0xFFFFFFFF); LOG_NRM("Set the offset into the buffer at 0x%04X", BUFFER_OFFSET); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); getLogPageMem->InitOffset1stPage(GetLogPage::FIRMSLOT_DATA_SIZE, BUFFER_OFFSET, true, BUFFER_INIT_VAL); send_64b_bitmask prpReq = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); getLogPgCmd->SetPrpBuffer(prpReq, getLogPageMem); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getLogPgCmd, "NUMD.adhered", true); LOG_NRM("Compare cmd buffer to verify the last half of buffer = 0xA5"); SharedMemBufferPtr cmdPayload = getLogPgCmd->GetRWPrpBuffer(); uint16_t offset = (NUMDW_ADHERED * 4); uint8_t *cmdPayloadBuff = (uint8_t *)cmdPayload->GetBuffer() + offset; for (; offset < (GetLogPage::FIRMSLOT_DATA_SIZE); offset++) { LOG_NRM("Verify data at offset = 0x%X", offset); if (*cmdPayloadBuff != BUFFER_INIT_VAL) { throw FrmwkEx(HERE, "NUMD not adhered at offset = 0x%08X, " "value = 0x%08X", cmdPayloadBuff, *cmdPayloadBuff); } cmdPayloadBuff++; } }
void InvalidFieldInCmd_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ string work; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Create Get features cmd"); SharedGetFeaturesPtr getFeaturesCmd = SharedGetFeaturesPtr(new GetFeatures()); LOG_NRM("Form a vector of invalid FID's"); vector<uint16_t> invalidFIDs; uint8_t invalFID; invalidFIDs.push_back(0x00); for (uint8_t invalFID = 0x0D; invalFID <= 0x7F; invalFID++) invalidFIDs.push_back(invalFID); if ((gInformative->GetIdentifyCmdCtrlr()->GetValue(IDCTRLRCAP_ONCS)) & ONCS_SUP_RSRV) invalFID = 0x84; else invalFID = 0x81; for (; invalFID <= 0xBF; invalFID++) invalidFIDs.push_back(invalFID); for (uint16_t i = 0; i < invalidFIDs.size(); i++) { if (invalidFIDs[i] == 0x81) continue; LOG_NRM("Issue get feat cmd using invalid FID = 0x%X", invalidFIDs[i]); getFeaturesCmd->SetFID(invalidFIDs[i]); work = str(boost::format("invalidFIDs.%xh") % invalidFIDs[i]); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, getFeaturesCmd, work, true, CESTAT_INVAL_FIELD); } }
void DeleteIOQDiscontig_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Both test CreateIOQContigPoll_r10b & CreateIOQDiscontigPoll_r10b has * run prior, or Both test CreateIOQContigIrq_r10b & * CreateIOQDiscontigIrq_r10b has run prior * 2) An individual test within this group cannot run, the entire group * must be executed every time. Each subsequent test relies on the prior. * \endverbatim */ uint64_t regVal; // DUT must support discontig memory backing a IOQ to run this test if (gRegisters->Read(CTLSPC_CAP, regVal) == false) { throw FrmwkEx(HERE, "Unable to determine Q memory requirements"); } else if (regVal & CAP_CQR) { LOG_NRM("Unable to utilize discontig Q's, DUT requires contig"); return; } // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) // According to spec, if one deletes the CQ before the SQ it's a "shall not" // statement which means it will have undefined behavior and thus there is // nothing to gain by attempting such action. LOG_NRM("Lookup IOSQ which was created in a prior test within group"); SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_DISCONTIG_GROUP_ID)) Queues::DeleteIOSQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, asq, acq); LOG_NRM("Lookup IOCQ which was created in a prior test within group"); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_DISCONTIG_GROUP_ID)) Queues::DeleteIOCQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iocq, asq, acq); }
void IOQRollChkDiff_r10b::IOQRollChkDiff(uint32_t numEntriesIOSQ, uint32_t numEntriesIOCQ) { uint16_t uniqueId; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, numEntriesIOCQ, false, IOCQ_CONTIG_GROUP_ID, false, 1); SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, IOQ_ID, numEntriesIOSQ, false, IOSQ_CONTIG_GROUP_ID, IOQ_ID, 0); LOG_NRM("(IOCQ Size, IOSQ Size)=(%d,%d)", iocq->GetNumEntries(), iosq->GetNumEntries()); SharedWritePtr writeCmd = SetWriteCmd(); LOG_NRM("Send #%d cmds to hdw via the contiguous IOSQ #%d", MAX(iosq->GetNumEntries(), iocq->GetNumEntries()) + 2, iosq->GetQId()); for (uint32_t numEntries = 0; numEntries < (uint32_t)(MAX (iosq->GetNumEntries(), iocq->GetNumEntries()) + 2); numEntries++) { LOG_NRM("Processing #%d entries", numEntries); iosq->Send(writeCmd, uniqueId); iosq->Ring(); ReapAndVerifyCE(iocq, (numEntries + 1) % iosq->GetNumEntries()); } VerifyQPointers(iosq, iocq); LOG_NRM("Delete IOSQ before the IOCQ to comply with spec."); Queues::DeleteIOSQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iosq, asq, acq); Queues::DeleteIOCQToHdw(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, iocq, asq, acq); }
void ReadWriteToUnacquiredReservation::RunCoreTest() { /** \verbatim * Assumptions: * None. * \endverbatim */ LOG_NRM("Start ReadWriteToUnacquiredReservation::RunCoreTest") SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)); SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)); SharedWritePtr writeCmd = SharedWritePtr(new Write()); SharedReadPtr readCmd = SharedReadPtr(new Read()); SharedMemBufferPtr lbaWriteBuffer = SharedMemBufferPtr(new MemBuffer()); SharedMemBufferPtr lbaReadBuffer = SharedMemBufferPtr(new MemBuffer()); LOG_NRM("Create nvmeWrite Cmd and write 1 block of data to LBA 5, expecting 0:0x83 for HostB"); lbaWriteBuffer->Init(512, true, 0xDD); writeCmd->SetPrpBuffer( (send_64b_bitmask)( MASK_PRP1_PAGE | MASK_PRP2_PAGE), lbaWriteBuffer); writeCmd->SetNSID(1); writeCmd->SetSLBA(5); writeCmd->SetNLB(0); // 0's based! IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, writeCmd, "write 0xDD's to LBA5 using hostB", true, CESTAT_RSRV_CONFLICT); LOG_NRM("Create nvmeRead Cmd and read back 1 block of data to LBA 5, expecting 0:0x83 for HostA"); lbaReadBuffer->Init(512, true, 0x00); readCmd->SetPrpBuffer( (send_64b_bitmask) (MASK_PRP1_PAGE | MASK_PRP2_PAGE), lbaReadBuffer); readCmd->SetNSID(1); readCmd->SetSLBA(5); readCmd->SetNLB(0); // 0's based! IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, readCmd, "read from LBA5 using hostB", true, CESTAT_RSRV_CONFLICT); LOG_NRM("Completed ReadWriteToUnacquiredReservation::RunCoreTest") }
void IllegalDeleteQs_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) SharedDeleteIOSQPtr deleteIOSQCmd = SharedDeleteIOSQPtr(new DeleteIOSQ()); deleteIOSQCmd->SetWord(0x0, 10, 0); // Set illegal QID to Cmd DW10 IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, deleteIOSQCmd, "illegalDeleteIOSQ.invalidQId", true, CESTAT_INVALID_QID); SharedDeleteIOCQPtr deleteIOCQCmd = SharedDeleteIOCQPtr(new DeleteIOCQ()); deleteIOSQCmd->SetWord(0x0, 10, 0); // Set illegal QID to Cmd DW10 IO::SendAndReapCmd(mGrpName, mTestName, DEFAULT_CMD_WAIT_ms, asq, acq, deleteIOCQCmd, "illegalDeleteIOCQ.invalidQId", true, CESTAT_INVALID_QID); }
void MandatorySMART_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint32_t nn = idCtrlrStruct->GetValue(IDCTRLRCAP_NN); if (nn == 0 ) throw FrmwkEx(HERE, "Required to support >= 1 namespace"); uint8_t logPageAttr = (uint8_t)idCtrlrStruct->GetValue(IDCTRLRCAP_LPA); LOG_NRM("Create get log page cmd and assoc some buffer memory"); SharedGetLogPagePtr getLogPgCmd = SharedGetLogPagePtr(new GetLogPage()); SharedMemBufferPtr getLogPageMem = SharedMemBufferPtr(new MemBuffer()); getLogPgCmd->SetLID(GetLogPage::LOGID_SMART_HEALTH); getLogPgCmd->SetNSID(0xFFFFFFFF); LOG_NRM("Issue cmd multiple times such that NUMD loops X=[0...512]"); IssueGetLogPgCmdLessDwords(asq, acq, getLogPgCmd, getLogPageMem); LOG_NRM("If SMART supported per namspc, Reissue cmd for valid NSID's"); if (logPageAttr) { for (uint32_t i = 1; i <= nn; i++) { LOG_NRM("Issue Get log page cmd with NSID = %u", i); getLogPgCmd->SetNSID(i); IssueGetLogPgCmdLessDwords(asq, acq, getLogPgCmd, getLogPageMem); } } }
void CtrlrResetDefaults_r10b::VerifyCtrlrResetDefaults() { std::map<int, uint64_t> ctrlRegsMap; // Issue a cntl'r reset for a clean controller state to begin with if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); // Create ACQ and ASQ objects which have test life time SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(mFd))) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(mFd))) asq->Init(5); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); // Dump Controller space registers to known file before ctrlr reset KernelAPI::DumpCtrlrSpaceRegs(FileSystem:: PrepDumpFile(mGrpName, mTestName, "ctrlRegs", "beforeReset"), false); ModifyRWBitsOfCtrlrRegisters(ctrlRegsMap); // Issue a cntl'r reset. CC.EN transitions from 1 to 0 if (gCtrlrConfig->SetState(ST_DISABLE) == false) throw FrmwkEx(HERE); // Dump Controller space registers to known file after ctrlr reset KernelAPI::DumpCtrlrSpaceRegs(FileSystem:: PrepDumpFile(mGrpName, mTestName, "ctrlRegs", "afterReset"), false); ValidateCtrlrRWDefaultsAfterReset(ctrlRegsMap); }
void UnsupportRsvdFields_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint64_t maxIOQEntries = 2; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Setup element sizes for the IOQ's"); uint8_t iocqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); uint8_t iosqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); gCtrlrConfig->SetIOCQES(iocqes); gCtrlrConfig->SetIOSQES(iosqes); LOG_NRM("Create IOCQ"); SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false, IOCQ_GROUP_ID, true, 0); LOG_NRM("Create IOSQ"); SharedIOSQPtr iosq = SharedIOSQPtr(new IOSQ(gDutFd)); LOG_NRM("Allocate contiguous memory; IOSQ has ID=%d", IOQ_ID); iosq->Init(IOQ_ID, maxIOQEntries, IOQ_ID, 0); LOG_NRM("Form a Create IOSQ cmd to perform queue creation"); SharedCreateIOSQPtr createIOSQCmd = SharedCreateIOSQPtr(new CreateIOSQ()); createIOSQCmd->Init(iosq); LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = createIOSQCmd->GetDword(0); work |= 0x0000fc00; // Set DW0_b15:10 bits createIOSQCmd->SetDword(work, 0); createIOSQCmd->SetDword(0xffffffff, 2); createIOSQCmd->SetDword(0xffffffff, 3); createIOSQCmd->SetDword(0xffffffff, 4); createIOSQCmd->SetDword(0xffffffff, 5); createIOSQCmd->SetDword(0xffffffff, 6); createIOSQCmd->SetDword(0xffffffff, 7); // DW11_b15:3 work = createIOSQCmd->GetDword(11); work |= 0x0000fff8; createIOSQCmd->SetDword(work, 11); createIOSQCmd->SetDword(0xffffffff, 12); createIOSQCmd->SetDword(0xffffffff, 13); createIOSQCmd->SetDword(0xffffffff, 14); createIOSQCmd->SetDword(0xffffffff, 15); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, createIOSQCmd, "", true); WriteReadVerify(iosq, iocq); Queues::DeleteIOSQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, asq, acq, "", false); Queues::DeleteIOCQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iocq, asq, acq, "", false); }
void CreateResources_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) This is the 1st within GrpNVMWriteReadCombo. * \endverbatim */ if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); SharedACQPtr acq = CAST_TO_ACQ( gRsrcMngr->AllocObj(Trackable::OBJ_ACQ, ACQ_GROUP_ID)) acq->Init(5); SharedASQPtr asq = CAST_TO_ASQ( gRsrcMngr->AllocObj(Trackable::OBJ_ASQ, ASQ_GROUP_ID)) asq->Init(5); // All queues will use identical IRQ vector IRQ::SetAnySchemeSpecifyNum(1); // throws upon error gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); { uint64_t maxIOQEntries; // Determine the max IOQ entries supported if (gRegisters->Read(CTLSPC_CAP, maxIOQEntries) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); maxIOQEntries &= CAP_MQES; maxIOQEntries += 1; // convert to 1-based if (maxIOQEntries < (uint64_t)NumEntriesIOQ) { LOG_NRM("Changing number of Q elements from %d to %lld", NumEntriesIOQ, (unsigned long long)maxIOQEntries); NumEntriesIOQ = maxIOQEntries; } uint8_t iocqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); uint8_t iosqes = (gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_SQES) & 0xf); gCtrlrConfig->SetIOCQES(iocqes); gCtrlrConfig->SetIOSQES(iosqes); if (Queues::SupportDiscontigIOQ() == true) { SharedMemBufferPtr iocqBackedMem = SharedMemBufferPtr(new MemBuffer()); iocqBackedMem->InitOffset1stPage ((NumEntriesIOQ * (1 << iocqes)), 0, true); Queues::CreateIOCQDiscontigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOCQ_GROUP_ID, true, 0, iocqBackedMem); SharedMemBufferPtr iosqBackedMem = SharedMemBufferPtr(new MemBuffer()); iosqBackedMem->InitOffset1stPage ((NumEntriesIOQ * (1 << iosqes)), 0, true); Queues::CreateIOSQDiscontigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOSQ_GROUP_ID, IOQ_ID, 0, iosqBackedMem); } else { Queues::CreateIOCQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOCQ_GROUP_ID, true, 0); Queues::CreateIOSQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, NumEntriesIOQ, true, IOSQ_GROUP_ID, IOQ_ID, 0); } } }
void InvalidMSIXIRQ_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Requires test createResources_r10b to execute 1st * \endverbatim */ bool capable; uint16_t numIrqSupport; // Only allowed to execute if DUT supports MSI-X IRQ's if (gCtrlrConfig->IsMSIXCapable(capable, numIrqSupport) == false) throw FrmwkEx(HERE); else if (capable == false) { LOG_NRM("DUT does not support MSI-X IRQ's; unable to execute test"); return; } if (gCtrlrConfig->SetState(ST_DISABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Notify DUT we plan on using all IRQ's that it supports"); if (gCtrlrConfig->SetIrqScheme(INT_MSIX, numIrqSupport) == false) { throw FrmwkEx(HERE, "Unable to use %d IRQ's, but DUT reports it supports", numIrqSupport); } gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Set legal IOCQ element size"); gCtrlrConfig->SetIOCQES(gInformative->GetIdentifyCmdCtrlr()-> GetValue(IDCTRLRCAP_CQES) & 0xf); // This test expects the DUT to reject the usage of illegal/unsupported // MSIX IRQ vectors, thus they should never be used. In order to safely fool // dnvme's safeguards, thus preventing a kernel crash, we need to issue a // legal cmd and allow dnvme to do it job. Then just before ringing the // doorbell inject a toxic illegal MSIX IRQ vector, the guts of this test. // So lets prepare that "legal" cmd here and then corrupt/toxify it later. LOG_NRM("Last supported MSIX IRQ vec = %d", (numIrqSupport - 1)); for (uint32_t i = numIrqSupport; i <= CtrlrConfig::MAX_MSIX_IRQ_VEC; i++) { // We must re-init the objects because a failed attempt at creating an // IOCQ forces dnvme to deconstruct the entire thing when it is reaped. LOG_NRM("Create the IOCQ and the cmd to issue to the DUT"); SharedIOCQPtr iocq = SharedIOCQPtr(new IOCQ(gDutFd)); LOG_NRM("Allocate contiguous memory; IOCQ has ID=%d", IOQ_ID); iocq->Init(IOQ_ID, NUM_IOQ_ENTRY, true, (numIrqSupport - 1)); SharedCreateIOCQPtr createIOCQCmd = SharedCreateIOCQPtr(new CreateIOCQ()); createIOCQCmd->Init(iocq); SendToxicCmd(asq, acq, createIOCQCmd, i); } }
void AdminQRollChkDiff_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) none. * \endverbatim */ uint16_t mACQSize = MIN_ADMIN_Q_SIZE; // Start ACQ with min size. uint16_t mASQSize = MAX_ADMIN_Q_SIZE; uint16_t loopCnt = 0; if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); while (1) { LOG_NRM("(ASQSize, ACQSize, Loop Cnt) = (%d, %d, %d)", mASQSize, mACQSize, loopCnt++); // Issue cntl'r disable completely for every iteration. if (gCtrlrConfig->SetState(ST_DISABLE_COMPLETELY) == false) throw FrmwkEx(HERE); // Create ACQ and ASQ objects which have test life time SharedACQPtr acq = CAST_TO_ACQ(SharedACQPtr(new ACQ(gDutFd))) acq->Init(mACQSize); SharedASQPtr asq = CAST_TO_ASQ(SharedASQPtr(new ASQ(gDutFd))) asq->Init(mASQSize); gCtrlrConfig->SetCSS(CtrlrConfig::CSS_NVM_CMDSET); if (gCtrlrConfig->SetState(ST_ENABLE) == false) throw FrmwkEx(HERE); LOG_NRM("Create identify cmd and assoc some buffer memory"); SharedIdentifyPtr idCmdCap = SharedIdentifyPtr(new Identify()); LOG_NRM("Force identify to request ctrlr capabilities struct"); idCmdCap->SetCNS(true); SharedMemBufferPtr idMemCap = SharedMemBufferPtr(new MemBuffer()); idMemCap->InitAlignment(Identify::IDEAL_DATA_SIZE, PRP_BUFFER_ALIGNMENT, false, 0); send_64b_bitmask idPrpCap = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdCap->SetPrpBuffer(idPrpCap, idMemCap); LOG_NRM("Submit Idtfy cmds to fill & roll over the Q (Q_SIZE plus 2)."); for (uint16_t nsubmitTimes = 0; nsubmitTimes < MAX(asq->GetNumEntries(), acq->GetNumEntries()) + 2; nsubmitTimes++) { LOG_NRM("Sending #%d times of %d", (nsubmitTimes + 1), (acq->GetNumEntries() + 2)); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdCap, "AdminQRollChkDiff", false); VerifyCESQValues(acq, (nsubmitTimes + 1) % asq->GetNumEntries()); } // Verify final Q pointers after all the cmds are submitted and reaped VerifyQPointers(acq, asq); if (mACQSize >= MAX_ADMIN_Q_SIZE) { break; } // If the test requires incremental sizes then edit here. mACQSize = MAX_ADMIN_Q_SIZE; // Assign MAX Q Size of ACQ. mASQSize = MIN_ADMIN_Q_SIZE; } }
void ManyCmdSubmit_r10b::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ uint32_t nCmds; uint32_t isrCount; uint32_t ceRemain; uint32_t numReaped; uint32_t numCE; uint16_t uniqueId; // Lookup objs which were created in a prior test within group SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)) SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)) LOG_NRM("Determine the max IOQ entries supported"); uint64_t ctrlCapReg; if (gRegisters->Read(CTLSPC_CAP, ctrlCapReg) == false) throw FrmwkEx(HERE, "Unable to determine MQES"); uint32_t maxIOQEntries = (uint32_t)(ctrlCapReg & CAP_MQES); maxIOQEntries += 1; // convert to 1-based. LOG_NRM("Create contig IOQ's"); SharedIOCQPtr iocq = Queues::CreateIOCQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false, IOCQ_CONTIG_GROUP_ID, true, 0); SharedIOSQPtr iosq = Queues::CreateIOSQContigToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, IOQ_ID, maxIOQEntries, false, IOSQ_CONTIG_GROUP_ID, IOQ_ID, 0); SharedWritePtr writeCmd = SetWriteCmd(); uint32_t increment = 1; for (uint32_t x = 1; x < maxIOQEntries; x += increment) { LOG_NRM("Sending #%d simultaneous NVM write cmds to IOSQ", x); // Issue x simultaneous NVM write cmds. for (nCmds = 1; nCmds <= x; nCmds++) iosq->Send(writeCmd, uniqueId); iosq->Ring(); // Variable wait time w.r.t "x" and expect all CE's to arrive in CQ. if (iocq->ReapInquiryWaitSpecify(CALC_TIMEOUT_ms(x), x, numCE, isrCount) == false) { iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq.reqpinq." + writeCmd->GetName()), "Dump Entire IOCQ"); LogCEAndCQMetrics(iocq); throw FrmwkEx(HERE, "Unable to see CEs for issued cmds #%d", x); } else if (numCE != x) { iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq.reqpinq." + writeCmd->GetName()), "Dump Entire IOCQ"); LogCEAndCQMetrics(iocq); throw FrmwkEx(HERE, "The IOCQ should only have #%d CE's as a result " "of #%d simultaneous cmds but found #%d", x, x, numCE); } SharedMemBufferPtr ceMem = SharedMemBufferPtr(new MemBuffer()); if ((numReaped = iocq->Reap(ceRemain, ceMem, isrCount, x, true)) != x) { iocq->Dump(FileSystem::PrepDumpFile(mGrpName, mTestName, "iocq.reap." + writeCmd->GetName()), "Dump Entire IOCQ"); LogCEAndCQMetrics(iocq); throw FrmwkEx(HERE, "Unable to reap on IOCQ #%d. Reaped #%d of #%d", IOQ_ID, numReaped, x); } // Testing every cmd takes numerous hrs, so compromise. if ((maxIOQEntries - 1000) % x == 0) increment = 100; else if ((x % 1000) == 0) increment = 1000; else if ((maxIOQEntries - 100) % x == 0) increment = 10; else if ((x % 100) == 0) increment = 100; else if ((maxIOQEntries - 10) % x == 0) increment = 1; else if ((x % 10) == 0) increment = 10; } // Delete IOSQ before the IOCQ to comply with spec. Queues::DeleteIOSQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, asq, acq); Queues::DeleteIOCQToHdw(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iocq, asq, acq); }
void UnsupportRsvdFields_r12::RunCoreTest() { /** \verbatim * Assumptions: * 1) Test CreateResources_r10b has run prior. * \endverbatim */ CE ce; vector<uint32_t> activeNamespaces; string work; LOG_NRM("Admin queue setup"); SharedASQPtr asq = CAST_TO_ASQ(gRsrcMngr->GetObj(ASQ_GROUP_ID)); SharedACQPtr acq = CAST_TO_ACQ(gRsrcMngr->GetObj(ACQ_GROUP_ID)); LOG_NRM("Test proper"); LOG_NRM("Form identify cmd for namespace list and associate some buffer"); SharedIdentifyPtr idCmdNamSpcList = SharedIdentifyPtr(new Identify()); idCmdNamSpcList->SetCNS(CNS_NamespaceListActive); idCmdNamSpcList->SetNSID(0); SharedMemBufferPtr idMemNamSpcList = SharedMemBufferPtr(new MemBuffer()); idMemNamSpcList->InitAlignment(NAMSPC_LIST_SIZE * NAMSPC_ENTRY_SIZE); send_64b_bitmask idPrpNamSpc = (send_64b_bitmask)(MASK_PRP1_PAGE | MASK_PRP2_PAGE); idCmdNamSpcList->SetPrpBuffer(idPrpNamSpc, idMemNamSpcList); LOG_NRM("Sending Identify command CNS.%02Xh", CNS_NamespaceListActive); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), asq, acq, idCmdNamSpcList, "namspcList", true); LOG_NRM("Reading in active Namespaces."); const uint8_t *data = &((idCmdNamSpcList->GetROPrpBuffer())[0]); while ((*((uint32_t *)data) & 0xffff) != 0x0000){ uint32_t nsid = (*((uint32_t *)data) & 0xffff); LOG_NRM("Found active NSID: %08X", nsid); activeNamespaces.push_back(nsid); data += 4; } // Lookup objs which were created in a prior test within group SharedIOSQPtr iosq = CAST_TO_IOSQ(gRsrcMngr->GetObj(IOSQ_GROUP_ID)); SharedIOCQPtr iocq = CAST_TO_IOCQ(gRsrcMngr->GetObj(IOCQ_GROUP_ID)); ConstSharedIdentifyPtr idCtrlr = gInformative->GetIdentifyCmdCtrlr(); for (size_t i = 0; i < activeNamespaces.size(); i++) { LOG_NRM("Processing namspc %ld", i); SharedFlushPtr flushCmd = SharedFlushPtr(new Flush()); flushCmd->SetNSID(activeNamespaces[i]); ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, flushCmd, "none.set", true); if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){ throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, " "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC); } if (ce.n.reserved != 0){ throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X", ce.n.reserved); } else if(ce.n.cmdSpec != 0){ throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X", ce.n.cmdSpec); } LOG_NRM("Set all cmd's rsvd bits"); uint32_t work = flushCmd->GetDword(0); work |= 0x00003c00; // Set DW0_b13:10 bits flushCmd->SetDword(work, 0); flushCmd->SetDword(0xffffffff, 2); flushCmd->SetDword(0xffffffff, 3); flushCmd->SetDword(0xffffffff, 4); flushCmd->SetDword(0xffffffff, 5); flushCmd->SetDword(0xffffffff, 6); flushCmd->SetDword(0xffffffff, 7); flushCmd->SetDword(0xffffffff, 8); flushCmd->SetDword(0xffffffff, 9); flushCmd->SetDword(0xffffffff, 10); flushCmd->SetDword(0xffffffff, 11); flushCmd->SetDword(0xffffffff, 12); flushCmd->SetDword(0xffffffff, 13); flushCmd->SetDword(0xffffffff, 14); flushCmd->SetDword(0xffffffff, 15); ce = IO::SendAndReapCmdWhole(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq,flushCmd, "all.set", true); if (ce.n.SF.b.SC != 0x0 || ce.n.SF.b.SCT != 0x0){ throw new FrmwkEx(HERE, "Error sending flush command expected (SCT:SC) 0x00:0x00, " "but detected 0x%02X:0x%02X", ce.n.SF.b.SCT, ce.n.SF.b.SC); } if (ce.n.reserved != 0){ throw new FrmwkEx(HERE, "Reserved completion entry not cleared found: %08X", ce.n.reserved); } else if(ce.n.cmdSpec != 0){ throw new FrmwkEx(HERE, "Command specific field not cleared found: %08X", ce.n.cmdSpec); } } // This highestNSID could provide a case where it issues to an inactive NSID // In the case of an inactive NSID the error status would be Invalid Field /*uint32_t highestNSID = 0; for (uint32_t i = 0; i < activeNamespaces.size(); i++){ if (activeNamespaces[i] > highestNSID) highestNSID = activeNamespaces[i]; } if (highestNSID != 0xffffffff){ SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush()); invalidFlushCmd->SetNSID(highestNSID + 1); // Could be Invalid Field or Invalid Namespace or Format IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, invalidFlushCmd, "none.set", true, CESTAT_INVAL_NAMSPC); }*/ ConstSharedIdentifyPtr idCtrlrStruct = gInformative->GetIdentifyCmdCtrlr(); uint32_t nn = (uint32_t)idCtrlrStruct->GetValue(IDCTRLRCAP_NN); // Issuing flush cmd with a few invalid NSIDs int count = 0; for (uint64_t i = 0; pow(2, i) <= 0xffffffff; i++) { if (pow(2, i) <= nn) continue; LOG_NRM("Issue flush cmd with illegal namspc ID=%llu", (unsigned long long)i); SharedFlushPtr invalidFlushCmd = SharedFlushPtr(new Flush()); invalidFlushCmd->SetNSID(pow(2, i)); IO::SendAndReapCmd(mGrpName, mTestName, CALC_TIMEOUT_ms(1), iosq, iocq, invalidFlushCmd, "Flush.Invalid", true, CESTAT_INVAL_NAMSPC); count++; } LOG_NRM("Ran with: %d invalid NSIDs", count); }