def test_format_invalid_lbaf(nvme0, nvme0n1, verify, qpair): if not nvme0.supports(0x80): pytest.skip("format is not support") orig_timeout = nvme0.timeout nvme0.timeout = 100000 # prepare data buffer and IO queue read_buf = Buffer(4096) write_buf = Buffer(4096) write_buf[10:21] = b'hello world' nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' with pytest.warns(UserWarning, match="ERROR status: 01/0a"): nvme0.format(2).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' with pytest.warns(UserWarning, match="ERROR status: (00/02|01/0a)"): nvme0.format(0, 7).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' nvme0n1.format(512) nvme0.timeout = orig_timeout
def test_aer_mask_event(nvme0): orig_config_b = nvme0.getfeatures(0xb).waitdone() # disable the SMART/health event nvme0.setfeatures(0xb, cdw11=orig_config_b & ~2).waitdone() config = nvme0.getfeatures(0xb).waitdone() assert not config & 2 # set temperature to generate event smart_log = Buffer() nvme0.getlogpage(0x02, smart_log, 512).waitdone() ktemp = smart_log.data(2, 1) logging.info("temperature: %d degreeF" % ktemp) # over composite temperature threshold orig_config_4 = nvme0.getfeatures(4).waitdone() nvme0.setfeatures(4, cdw11=ktemp - 10).waitdone() # AER should not be triggered here nvme0.getlogpage(0x02, smart_log, 512).waitdone() logging.info(smart_log.data(0)) assert smart_log.data(0) & 0x2 # revert to default nvme0.setfeatures(4, cdw11=orig_config_4).waitdone() nvme0.setfeatures(0xb, cdw11=orig_config_b).waitdone()
def hmb(nvme0): hmb_size = nvme0.id_data(275, 272) if hmb_size == 0: pytest.skip("hmb is not supported") hmb_buf = Buffer(4096 * hmb_size) assert hmb_buf hmb_list_buf = Buffer(4096) assert hmb_list_buf hmb_list_buf[0:8] = hmb_buf.phys_addr.to_bytes(8, 'little') hmb_list_buf[8:12] = hmb_size.to_bytes(4, 'little') hmb_list_phys = hmb_list_buf.phys_addr # enable hmb nvme0.setfeatures(0x0d, cdw11=1, cdw12=hmb_size, cdw13=hmb_list_phys & 0xffffffff, cdw14=hmb_list_phys >> 32, cdw15=1).waitdone() yield # disable hmb nvme0.setfeatures(0x0d, cdw11=0).waitdone() del hmb_buf del hmb_list_buf
def test_write_uncorrectable_read(nvme0, nvme0n1, repeat, qpair, lba_start=0, lba_step=8, lba_count=8): if not nvme0n1.supports(0x4): pytest.skip("Write Uncorrectable is not supported") buf = Buffer(4096) read_buf = Buffer(4096, "read") pattern = repeat + (repeat << 8) + (repeat << 16) + (repeat << 24) write_buf = Buffer(4096, "write", pattern, 32) nvme0n1.write_uncorrectable(qpair, lba_start + repeat * lba_step, lba_count).waitdone() with pytest.warns(UserWarning, match="ERROR status: 02/81"): nvme0n1.read(qpair, read_buf, lba_start + repeat * lba_step, lba_count).waitdone() nvme0n1.write(qpair, write_buf, lba_start + repeat * lba_step, lba_count).waitdone() nvme0n1.read(qpair, read_buf, lba_start + repeat * lba_step, lba_count).waitdone() for i in range(lba_count): assert read_buf[i * 512 + 10] == repeat
def test_dst_after_sanitize(nvme0, nvme0n1, stc, nsid=1): if not nvme0.supports(0x14): pytest.skip("dst command is not supported") if nvme0.id_data(331, 328) == 0: pytest.skip("sanitize operation is not supported") # check dst buf = Buffer(4096) nvme0.getlogpage(0x6, buf, 32).waitdone() assert not buf[0] logging.info("supported sanitize operation: %d" % nvme0.id_data(331, 328)) nvme0.sanitize().waitdone() # sanitize command is completed with pytest.warns(UserWarning, match="ERROR status: 00/1d"): # dst aborted due to in-progress sanitize nvme0.dst(stc, nsid).waitdone() # check sanitize status in log page with pytest.warns(UserWarning, match="AER notification is triggered"): nvme0.getlogpage(0x81, buf, 20).waitdone() while buf.data(3, 2) & 0x7 != 1: # sanitize operation is not completed time.sleep(1) nvme0.getlogpage(0x81, buf, 20).waitdone() #L20 progress = buf.data(1, 0) * 100 // 0xffff logging.info("%d%%" % progress)
def test_format_verify_data(nvme0, nvme0n1, verify, qpair): if not nvme0.supports(0x80): pytest.skip("format is not support") orig_timeout = nvme0.timeout nvme0.timeout = 100000 # prepare data buffer and IO queue read_buf = Buffer(4096) write_buf = Buffer(4096) write_buf[10:21] = b'hello world' nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' nvme0.format(0, 0).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] != b'hello world' assert read_buf[10:21] == b'\0'*11 nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' nvme0.format(0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] != b'hello world' assert read_buf[10:21] == b'\0'*11 nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' nvme0.format(0, 0, 0xffffffff).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] != b'hello world' assert read_buf[10:21] == b'\0'*11 nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' nvme0.format(0, 1, 0xffffffff).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] != b'hello world' assert read_buf[10:21] == b'\0'*11 # crypto erase fna = nvme0.id_data(524) if fna & 0x4: nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world' nvme0.format(0, 2, 0xffffffff).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] != b'hello world' assert read_buf[10:21] == b'\0'*11 nvme0n1.format(512) nvme0.timeout = orig_timeout
def test_deallocate_and_read(nvme0, nvme0n1, repeat, qpair, lba_start=1, lba_step=3, lba_count=3): if not nvme0n1.supports(0x9): pytest.skip("dsm is not supprted") buf = Buffer(4096) read_buf = Buffer(4096, "read") buf.set_dsm_range(0, lba_start+repeat*lba_step, lba_count) nvme0n1.dsm(qpair, buf, 1).waitdone() nvme0n1.read(qpair, read_buf, lba_start+repeat*lba_step, lba_count).waitdone()
def test_flush_with_read_write(nvme0, nvme0n1, qpair): # prepare data buffer and IO queue read_buf = Buffer(512) write_buf = Buffer(512) write_buf[10:21] = b'hello world' # send write and read command nvme0n1.write(qpair, write_buf, 0, 1).waitdone() nvme0n1.flush(qpair).waitdone() nvme0n1.read(qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world'
def test_zns_write_and_read_multiple(nvme0, nvme0n1, qpair, zone, io_counter,buf): buf_list = [Buffer(96*1024) for i in range(io_counter)] for i in range(io_counter): buf_list[i][8] = i zone.write(qpair, buf_list[i], i*16, 16).waitdone() zone.close() zone.finish() assert zone.state == 'Full' for i in range(io_counter): buf = Buffer(96*1024) zone.read(qpair, buf, i*16, 16).waitdone() logging.debug(buf.dump(16)) assert buf[8] == i
def test_read_valid(nvme0, nvme0n1, ioflag, qpair): # prepare data buffer and IO queue read_buf = Buffer(512) write_buf = Buffer(512) write_buf[10:21] = b'hello world' # send write and read command def write_cb(cdw0, status1): # command callback function nvme0n1.read(qpair, read_buf, 0, 1, io_flags=ioflag) nvme0n1.write(qpair, write_buf, 0, 1, cb=write_cb) # wait commands complete and verify data assert read_buf[10:21] != b'hello world' qpair.waitdone(2) assert read_buf[10:21] == b'hello world'
def test_page_offset_invalid(nvme0, nvme0n1, qpair, offset): # fill the data write_buf = Buffer(512) nvme0n1.write(qpair, write_buf, 0xa5).waitdone() # read the data to different offset and check lba buf = Buffer(1024, ptype=0, pvalue=1) buf.offset = offset buf.size = 512 # Spec NVM-Express-1_4-2019.06.10-Ratified # Figure 108:Note: The controller is not required to check that bits 1:0 # are cleared to 00b. The controller may report an error of PRP Offset Invalid # pytest warning may not appear here nvme0n1.read(qpair, buf, 0xa5).waitdone() assert buf[offset] != 0xa5
def nvme_init(nvme0): # 2. disable cc.en and wait csts.rdy to 0 nvme0[0x14] = 0 while not (nvme0[0x1c] & 0x1) == 0: pass # 3. set admin queue registers nvme0.init_adminq() # 4. set register cc nvme0[0x14] = 0x00460000 # 5. enable cc.en nvme0[0x14] = 0x00460001 # 6. wait csts.rdy to 1 while not (nvme0[0x1c] & 0x1) == 1: pass # 7. identify controller nvme0.identify(Buffer(4096)).waitdone() # 8. create and identify all namespace nvme0.init_ns() # 9. set/get num of queues nvme0.setfeatures(0x7, cdw11=0x00ff00ff).waitdone() nvme0.getfeatures(0x7).waitdone() # 10. send out all aer aerl = nvme0.id_data(259) + 1 for i in range(aerl): nvme0.aer(cb=aer_cb)
def test_getlogpage_invalid_numd(nvme0, repeat): dts = nvme0.mdts // 4 + 1 + repeat buf = Buffer(dts * 4) for lid in (1, 2, 3): with pytest.warns(UserWarning, match="ERROR status: 00/02"): nvme0.getlogpage(lid, buf).waitdone()
def test_identify_namespace_id_list(nvme0): if not nvme0.id_data(257, 256) & 0x8: pytest.skip("namespace management is not supported") buf = Buffer(4096) nvme0.identify(buf, nsid=0xffffffff, cns=0x10).waitdone() nvme0.identify(buf, nsid=0, cns=0x10).waitdone()
def nvme_init_wrr(nvme0): logging.info("user defined nvme init") nvme0[0x14] = 0 while not (nvme0[0x1c]&0x1) == 0: pass # 3. set admin queue registers nvme0.init_adminq() # 4. set register cc if (nvme0.cap>>17) & 0x1: logging.info("set WRR arbitration") nvme0[0x14] = 0x00460800 else: nvme0[0x14] = 0x00460000 # 5. enable cc.en nvme0[0x14] = nvme0[0x14] | 1 # 6. wait csts.rdy to 1 while not (nvme0[0x1c]&0x1) == 1: pass # 7. identify controller nvme0.identify(Buffer(4096)).waitdone() # 8. create and identify all namespace nvme0.init_ns() # 9. set/get num of queues logging.debug("init number of queues") nvme0.setfeatures(0x7, cdw11=0xfffefffe).waitdone() cdw0 = nvme0.getfeatures(0x7).waitdone() nvme0.init_queues(cdw0)
def test_firmware_commit(nvme0): frmw = nvme0.id_data(260) slot1_ro = frmw & 1 slot_count = (frmw >> 1) & 7 logging.info(slot1_ro) logging.info(slot_count) buf = Buffer(4096 * 16) nvme0.fw_download(buf, 0).waitdone() logging.info("commit with an invalid firmware image") for slot in range(1, slot_count + 1): with pytest.warns(UserWarning, match="ERROR status: 01/07"): nvme0.fw_commit(slot, 0).waitdone() logging.info("commit to invalid firmware slot") with pytest.warns(UserWarning, match="ERROR status: 01/07"): nvme0.fw_commit(0, 0).waitdone() if slot_count == 7: pytest.skip("no invalid slot") for slot in range(slot_count + 1, 8): with pytest.warns(UserWarning, match="ERROR status: 01/06"): nvme0.fw_commit(slot, 2).waitdone()
def test_identify_all_nsid(nvme0): buf = Buffer(4096) nvme0.identify(buf, nsid=0, cns=1).waitdone() nvme0.identify(buf, nsid=1, cns=0).waitdone() with pytest.warns(UserWarning, match="ERROR status: 00/0b"): nvme0.identify(buf, nsid=0xff, cns=0).waitdone() with pytest.warns(UserWarning, match="ERROR status: 00/0b"): nvme0.identify(buf, nsid=2, cns=0).waitdone()
def test_hello_world(nvme0, nvme0n1, repeat): # prepare data buffer and IO queue read_buf = Buffer(512) write_buf = Buffer(512) write_buf[10:21] = b'hello world' qpair = Qpair(nvme0, 16) # create IO SQ/CQ pair, with 16 queue-depth # send write and read command def write_cb(cdw0, status1): # command callback function nvme0n1.read(qpair, read_buf, 0, 1) assert status1 == 1 # phase-bit nvme0n1.write(qpair, write_buf, 0, 1, cb=write_cb) # wait commands complete and verify data assert read_buf[10:21] != b'hello world' qpair.waitdone(2) assert read_buf[10:21] == b'hello world'
def test_firmware_download(nvme0, size, offset): fwug = nvme0.id_data(319) if fwug == 0 or fwug == 0xff: pytest.skip("not applicable") buf = Buffer(size) with pytest.warns(UserWarning, match="ERROR status: 01/14"): nvme0.fw_download(buf, offset).waitdone()
def test_zns_write_twice(nvme0, nvme0n1, qpair, zone): buf = Buffer(96*1024) zone.write(qpair, buf, 0, 24).waitdone() with pytest.warns(UserWarning, match="ERROR status: 01/bc"): zone.write(qpair, buf, 0, 24).waitdone() zone.close() zone.finish() assert zone.state == 'Full'
def test_zns_write_192k(nvme0, nvme0n1, qpair, zone): buf = Buffer(96*1024) zone.write(qpair, buf, 0, 24) zone.write(qpair, buf, 24, 24).waitdone() zone.close() zone.finish() qpair.waitdone(1) assert zone.state == 'Full'
def test_deallocate_correct_range(nvme0, nvme0n1, qpair): if not nvme0n1.supports(0x9): pytest.skip("dsm is not supprted") buf = Buffer(4096) nvme0n1.write(qpair, buf, 1, 3).waitdone() buf.set_dsm_range(0, 2, 1) nvme0n1.dsm(qpair, buf, 1).waitdone() nvme0n1.read(qpair, buf, 1, 1).waitdone() logging.debug(buf[0:4]) assert buf[0] == 1 nvme0n1.read(qpair, buf, 2, 1).waitdone() logging.debug(buf[0:4]) nvme0n1.read(qpair, buf, 3, 1).waitdone() logging.debug(buf[0:4]) assert buf[0] == 3
def test_zns_write_full_zone(nvme0, nvme0n1, qpair, slba=0): buf = Buffer(96*1024) z0 = Zone(qpair, nvme0n1, slba) #with pytest.warns(UserWarning, match="ERROR status: 01/"): z0.write(qpair, buf, 0, 16).waitdone() z0.reset() z0.finish() assert z0.state == 'Full'
def _test_reset_with_hmb_disabled(nvme0, nvme0n1, buf): hmb_size = nvme0.id_data(275, 272) if hmb_size == 0: pytest.skip("hmb is not supported") nvme0n1.format(512) # single host memory buffer hmb_buf = Buffer(4096 * hmb_size + 4096) assert hmb_buf hmb_list_buf = Buffer(4096) assert hmb_list_buf hmb_list_buf[0:8] = hmb_buf.phys_addr.to_bytes(8, 'little') hmb_list_buf[8:12] = hmb_size.to_bytes(4, 'little') hmb_list_phys = hmb_list_buf.phys_addr for i in range(3): logging.info(i) with nvme0n1.ioworker(io_size=8, lba_random=False, qdepth=8, read_percentage=0, time=30): time.sleep(5) # enable hmb nvme0.setfeatures(0x0d, cdw11=1, cdw12=hmb_size, cdw13=hmb_list_phys & 0xffffffff, cdw14=hmb_list_phys >> 32, cdw15=1).waitdone() time.sleep(5) #disable hmb nvme0.setfeatures(0x0d, cdw11=0).waitdone() time.sleep(5) nvme0.reset() logging.info(hmb_buf.dump(4096 * 2)) del hmb_buf del hmb_list_buf
def test_page_offset(nvme0, nvme0n1, qpair, buf, offset): # fill the data write_buf = Buffer(512) nvme0n1.write(qpair, write_buf, 0x5aa5).waitdone() # read the data to different offset and check lba buf.offset = offset nvme0n1.read(qpair, buf, 0x5aa5).waitdone() assert buf[offset] == 0xa5 assert buf[offset + 1] == 0x5a
def test_dst_abort_by_sanitize(nvme0, nvme0n1, stc, nsid=1): if not nvme0.supports(0x14): pytest.skip("dst command is not supported") if nvme0.id_data(331, 328) == 0: pytest.skip("sanitize operation is not supported") buf = Buffer(4096) nvme0.getlogpage(0x6, buf, 32).waitdone() assert not buf[0] # aer callback function def cb(cdw0, status): warnings.warn("AER notification is triggered") nvme0.aer(cb) nvme0.dst(stc, nsid).waitdone() nvme0.getlogpage(0x6, buf, 32).waitdone() assert buf[0] nvme0.sanitize().waitdone() # sanitize command is completed # check sanitize status in log page with pytest.warns(UserWarning, match="AER notification is triggered"): nvme0.getlogpage(0x81, buf, 20).waitdone() while buf.data(3, 2) & 0x7 != 1: # sanitize operation is not completed nvme0.getlogpage(0x81, buf, 20).waitdone() progress = buf.data(1, 0) * 100 // 0xffff logging.info("%d%%" % progress) time.sleep(1) # check if dst aborted nvme0.getlogpage(0x6, buf, 32).waitdone() assert not buf[0] if stc == 1: assert buf[4] & 0xf0 == 0x10 if stc == 2: assert buf[4] & 0xf0 == 0x20 vs = nvme0[8] logging.info("%d" % vs) if vs >= 0x010400: assert buf[4] & 0xf == 0x09
def test_zns_hello_world_2(nvme0, nvme0n1, qpair, zone, buf): buf[10:21] = b'hello world' zone.write(qpair, buf, 0, 24) zone.close() zone.finish() qpair.waitdone(1) assert zone.state == 'Full' read_buf = Buffer() read_qpair = Qpair(nvme0, 10) zone.read(read_qpair, read_buf, 0, 1).waitdone() assert read_buf[10:21] == b'hello world'
def test_getlogpage_smart_composite_temperature(nvme0): smart_log = Buffer() nvme0.getlogpage(0x02, smart_log, 512).waitdone() ktemp = smart_log.data(2, 1) logging.debug("temperature: %d degreeF" % ktemp) # warning with AER with pytest.warns(UserWarning, match="AER notification is triggered"): # over composite temperature threshold nvme0.setfeatures(4, cdw11=ktemp - 10).waitdone() nvme0.getlogpage(0x02, smart_log, 512).waitdone() logging.debug("0x%x" % smart_log.data(0)) nvme0.getlogpage(0x02, smart_log, 512).waitdone() assert smart_log.data(0) & 0x2 # higher threshold nvme0.setfeatures(4, cdw11=ktemp + 10).waitdone() # aer is not expected nvme0.getlogpage(0x02, smart_log, 512).waitdone() ktemp = smart_log.data(2, 1) logging.debug("temperature: %d degreeF" % ktemp) # revert to default orig_config = 0 def getfeatures_cb_4(cdw0, status): nonlocal orig_config orig_config = cdw0 nvme0.getfeatures(4, sel=1, cb=getfeatures_cb_4).waitdone() nvme0.setfeatures(4, cdw11=orig_config).waitdone()
def test_write_zeroes_valid(nvme0, nvme0n1, ioflag, qpair): if not nvme0n1.supports(0x8): pytest.skip("Write zeroes is not supported") # prepare data buffer and IO queue read_buf = Buffer(512) write_buf = Buffer(512) write_buf[10:21] = b'hello world' nvme0n1.write(qpair, write_buf, 1).waitdone() nvme0n1.read(qpair, read_buf, 1).waitdone() assert read_buf[0] == 1 # send write and read command def write_cb(cdw0, status1): # command callback function nvme0n1.read(qpair, read_buf, 1) nvme0n1.write_zeroes(qpair, 1, 1, io_flags=ioflag, cb=write_cb) # wait commands complete and verify data assert read_buf[0] == 1 qpair.waitdone(2) assert read_buf[0] == 0
def test_multiple_hmb_buffer(nvme0, nvme0n1, buf): hmb_size = nvme0.id_data(275, 272) if hmb_size == 0: pytest.skip("hmb is not supported") # single host memory buffer hmb_buffer_list = [] hmb_list_buf = Buffer(hmb_size * 16) assert hmb_list_buf for i in range(hmb_size): hmb_buf = Buffer() assert hmb_buf hmb_buffer_list.append(hmb_buf) hmb_list_buf[16 * i + 0:16 * i + 8] = hmb_buf.phys_addr.to_bytes( 8, 'little') hmb_list_buf[16 * i + 8:16 * i + 12] = hmb_size.to_bytes(4, 'little') hmb_list_phys = hmb_list_buf.phys_addr # enable hmb nvme0.setfeatures(0x0d, cdw11=1, cdw12=hmb_size, cdw13=hmb_list_phys & 0xffffffff, cdw14=hmb_list_phys >> 32, cdw15=hmb_size).waitdone() for i in range(3): logging.info(i) with nvme0n1.ioworker(io_size=8, lba_random=False, qdepth=8, read_percentage=0, time=3): pass #disable hmb nvme0.setfeatures(0x0d, cdw11=0).waitdone() del hmb_buffer_list del hmb_list_buf