예제 #1
0
 def test_GET(self, loc_offset=0, rem_offset=0, sz=None, use_buffer=False):
     if sz is None:
         sz = self.maxsz // 2
     if self.physaddr:  # Revisit: physaddr temporary
         local_addr = self.lmr.physaddr
     else:
         local_addr = self.lmm_v
     local_addr += loc_offset
     rem_addr = self.rmr.req_addr + rem_offset
     get = zhpe.xdm_cmd()
     get.opcode = zhpe.XDM_CMD.GET | zhpe.XDM_CMD.FENCE
     get.getput.size = sz
     get.getput.read_addr = rem_addr
     get.getput.write_addr = local_addr
     if self.verbosity:
         print('test_GET: local_addr={:#x}, sz={}, rem_addr={:#x}'.format(
             local_addr, sz, rem_addr))
     start = time.monotonic()
     if use_buffer == True:
         self.xdm.buffer_cmd(get)
     else:
         self.xdm.queue_cmd(get)
     try:
         cmpl = self.xdm.get_cmpl()
         end = time.monotonic()
         if self.verbosity:
             print('GET cmpl: {}'.format(cmpl))
     except XDMcompletionError as e:
         print('GET cmpl error: {} {:#x} request_id {:#x}'.format(
             e, e.status, e.request_id))
     # Revisit: need fence/sync/flush to ensure visibility?
     if self.rmm:
         rmm_off = self.pg_off + rem_offset
         lmm_sha256 = hashlib.sha256(self.lmm[loc_offset:loc_offset +
                                              sz]).hexdigest()
         if self.verbosity:
             print('lmm sha256 after GET="{}"'.format(lmm_sha256))
             rmm_sha256 = hashlib.sha256(self.rmm[rmm_off:rmm_off +
                                                  sz]).hexdigest()
         if self.verbosity:
             print('rmm[{}:{}] sha256="{}"'.format(rmm_off, rmm_off + sz,
                                                   rmm_sha256))
         if lmm_sha256 != rmm_sha256:
             print('GET sha mismatch: {} != {}'.format(
                 lmm_sha256, rmm_sha256))
             # Revisit: temporary debug
             print('lmm[{}:{}]="{}"'.format(
                 loc_offset, loc_offset + 100,
                 self.lmm[loc_offset:loc_offset + 100]))
             print('rmm[{}:{}]="{}"'.format(
                 rmm_off, rmm_off + 100, self.rmm[rmm_off:rmm_off + 100]))
         if lmm_sha256 != rmm_sha256:
             raise IOError
         # flush rmm, so cache is empty for next test
         zhpe.pmem_flush(self.rmm_v + rmm_off, sz)
     # end if self.rmm
     secs = end - start
     if self.verbosity:
         print('GET of {} bytes in {} seconds = {} GiB/s'.format(
             get.getput.size, secs, get.getput.size / (secs * self.sz1G)))
예제 #2
0
 def test_GET_IMM(self, offset=0, sz=len1_2, use_buffer=False):
     if sz < 1 or sz > 32:
         raise ValueError
     rem_addr = self.rmr.req_addr + offset
     get_imm = zhpe.xdm_cmd()
     get_imm.opcode = zhpe.XDM_CMD.GET_IMM
     get_imm.getput_imm.size = sz
     get_imm.getput_imm.rem_addr = rem_addr
     if self.verbosity:
         print('test_GET_IMM: sz={}, offset={}, rem_addr={:#x}'.format(
             sz, offset, rem_addr))
     if use_buffer == True:
         self.xdm.buffer_cmd(get_imm)
     else:
         self.xdm.queue_cmd(get_imm)
     try:
         cmpl = self.xdm.get_cmpl()
         if self.verbosity:
             print('GET_IMM cmpl: {}'.format(cmpl.getimm))
     except XDMcompletionError as e:
         print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format(
             e, e.status, e.request_id))
     if self.rmm is not None:
         rmm_off = self.pg_off + offset
         if bytes(cmpl.getimm.payload[0:sz]) != self.rmm[rmm_off:rmm_off +
                                                         sz]:
             raise IOError
         # Revisit: check that payload bytes beyond sz are 0
         # flush rmm, so cache is empty for next test
         zhpe.pmem_flush(self.rmm_v + rmm_off, sz)
예제 #3
0
 def test_PUT_IMM(self, data=str3, offset=len1_2 + 1, use_buffer=False):
     sz = len(data)
     if sz < 1 or sz > 32:
         raise ValueError
     rem_addr = self.rmr.req_addr + offset
     put_imm = zhpe.xdm_cmd()
     put_imm.opcode = zhpe.XDM_CMD.PUT_IMM
     put_imm.getput_imm.size = sz
     put_imm.getput_imm.rem_addr = rem_addr
     put_imm.getput_imm.payload[0:sz] = data
     if self.verbosity:
         print('test_PUT_IMM: data={}, sz={}, offset={}, rem_addr={:#x}'.
               format(data, sz, offset, rem_addr))
     if use_buffer == True:
         self.xdm.buffer_cmd(put_imm)
     else:
         self.xdm.queue_cmd(put_imm)
     try:
         cmpl = self.xdm.get_cmpl()
         if self.verbosity:
             print('PUT_IMM cmpl: {}'.format(cmpl))
     except XDMcompletionError as e:
         print('PUT_IMM cmpl error: {} {:#x} request_id {:#x}'.format(
             e, e.status, e.request_id))
     # Revisit: need fence/sync to ensure visibility?
     if self.rmm is not None:
         rmm_off = self.pg_off + offset
         if self.verbosity:
             print('rmm[{}:{}] after PUT_IMM="{}"'.format(
                 rmm_off, rmm_off + sz,
                 self.rmm[rmm_off:rmm_off + sz].decode()))
         if self.rmm[rmm_off:rmm_off + sz] != data:
             raise IOError
         # flush rmm, so cache is empty for next test
         zhpe.pmem_flush(self.rmm_v + rmm_off, sz)
예제 #4
0
    def FAM_tests(self, gcid=0x40, size=2 << 20):
        # default CID for Carbon is 0x40 and create a ZUUID
        fam_zuu = zuuid(gcid)
        if args.verbosity:
            print('FAM zuuid={}'.format(fam_zuu))
        # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set
        conn.do_UUID_IMPORT(fam_zuu, 1, None)
        # RMR_IMPORT the FAM at address 0 and size 2M
        sz2M = 2 << 20
        FAMaccess = (zhpe.MR.GET_REMOTE | zhpe.MR.PUT_REMOTE
                     | zhpe.MR.INDIVIDUAL | zhpe.MR.REQ_CPU)
        self.fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, size, FAMaccess)
        # Do load/store to FAM at address 0
        self.fam_rmm = mmap.mmap(f.fileno(), size, offset=fam_rmr.offset)
        self.fam_v, self.fam_l = zhpe.mmap_vaddr_len(self.fam_rmm)
        for off in range(0, 64, 7):
            self.test.load_store(offset=off, use_fam=True)

        if args.fam:
            fam_zuu = zuuid(gcid=args.fam_gcid)
            print('FAM zuuid={}'.format(fam_zuu))
            # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set
            conn.do_UUID_IMPORT(fam_zuu, UU.IS_FAM, None)
            # RMR_IMPORT the FAM at address 0 and size 2M
            if args.load_store:
                fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRIC)
                # Do load/store to FAM
                fam_rmm = mmap.mmap(f.fileno(), sz2M, offset=fam_rmr.offset)
                fam_v, fam_l = zhpe.mmap_vaddr_len(fam_rmm)
                fam_rmm[0:len1] = str1
                fam_rmm[len1:len1_2] = str2
                # flush writes, so reads will see new data
                zhpe.pmem_flush(fam_v, len1_2)
            else:
                fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRI)
            # do an XDM command to get the data back and check it
            get_imm = zhpe.xdm_cmd()
            get_imm.opcode = zhpe.XDM_CMD.GET_IMM
            get_imm.getput_imm.size = len1_2
            get_imm.getput_imm.rem_addr = fam_rmr.req_addr
            xdm.queue_cmd(get_imm)
            try:
                get_imm_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm))
                # Verify the payload is what we expect
                if args.load_store:
                    retstr = bytearray(get_imm_cmpl.getimm.payload[0:len1_2])
                    if retstr == str1 + str2:
                        if args.verbosity:
                            print('FAM comparision PASS')
                    else:
                        print('FAM comparision FAIL')
            except XDMcompletionError as e:
                print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
예제 #5
0
 def test_load_store(self, offset=0):
     if self.rmm is None:
         if self.verbosity:
             print('test_load_store: skipping - no load/store rmm')
         return
     # Revisit: this assumes rmm is mapped writable
     rmm_off = self.pg_off + offset
     if self.verbosity:
         print('test_load_store: offset={}, rmm_off={}, rmm_v={:#x}'.format(
             offset, rmm_off, self.rmm_v))
     self.rmm[rmm_off:rmm_off + Tests.len1] = Tests.str1
     self.rmm[rmm_off + Tests.len1:rmm_off + Tests.len1_2] = Tests.str2
     # flush rmm writes, so rmm reads will generate new Gen-Z packets
     zhpe.pmem_flush(self.rmm_v + rmm_off, Tests.len1_2)
     expected = Tests.str1 + Tests.str2
     if self.verbosity:
         print('rmm[{}:{}] after load/store="{}"'.format(
             rmm_off, rmm_off + Tests.len1_2,
             self.rmm[rmm_off:rmm_off + Tests.len1_2].decode()))
     if self.rmm[rmm_off:rmm_off + Tests.len1_2] != expected:
         raise IOError
     # flush rmm again, so cache is empty for next test
     zhpe.pmem_flush(self.rmm_v + rmm_off, Tests.len1_2)
예제 #6
0
def main():
    '''summary of MR_REG regions:
    name       | access   | args     | mmap  | v         | sz  |
    -----------+----------+----------+-------+-----------+-----+
    rsp        |GPI       |requester | mm    | v         | 4K
    rsp2       |GRPRI     |responder | mm2   | v2        | 4K
    rsp2M      |GRPRI     |always    | mm2M  | v2M+0x1242| 2M-0x5000
    rsp2M_l    |GP        |always    | mm2M  | v2M       | 2M
    rsp2M_b    |GRPRI     |responder | mm2M  | v2M       | 2M
    rsp2M_r    |GPGRPRI   |loopback  | mm2M  | v2M       | 2M

    summary of RMR_IMPORT regions:
    name       | access   | args     |memreg | mmap  | rmr sz | mmap sz |
    -----------+----------+----------+-------+-------+--------+---------+
    rsp_rmr    |GRPRI     |loopback  |rsp2M_b|---    | 4K     | --      |
    rsp_rmr_c  |GRPRIC    |load_store|rsp2M_b|rmm    | 2M     | 4K      |
    rsp_rmr2   |GRPRIC    |load_store|rsp2   |rmm2   | 4K     | 4K      |
    rsp_rmr2   |GRPRI     |else      |rsp2   |---    | 4K     | --      |
    rsp_rmr_ro |GRIC      |load_store|rsp2   |rmm2_ro| 4K     | 4K      |
    rsp_rmr2M  |GRPRIC    |load_store|rsp2M_r|rmm2M  | 2M     | 2M      |
    rsp_rmr2M  |GRPRI     |else      |rsp2M_r|---    | 2M     | --      |
    fam_rmr    |GRPRIC    |fam+ld_st | ---   |fam_rmm| 2M     | 2M      |
    '''
    global args
    args = parse_args()
    if args.verbosity:
        print('pid={}'.format(os.getpid()))
    nodes = [item for item in args.nodes.split(',')] if args.nodes else []
    datasize = os.path.getsize(args.datafile)
    bigsize = os.path.getsize(args.bigfile)
    hugesize = os.path.getsize(args.hugefile)
    if 3 * datasize > bigsize:
        print('3*datafile size (3*{}) > bigfile size ({})'.format(
            datasize, bigsize))
        sys.exit(1)
    modp = ModuleParams()
    with open(args.devfile, 'rb+', buffering=0) as f:
        conn = zhpe.Connection(f, args.verbosity)
        init = conn.do_INIT()
        gcid = init.uuid.gcid
        if args.verbosity:
            print('do_INIT: uuid={}, gcid={}'.format(init.uuid,
                                                     init.uuid.gcid_str))
        # doing a 2nd INIT should fail
        exc = False
        try:
            bad = conn.do_INIT()
        except OSError:
            exc = True
        if exc:
            if args.verbosity:
                print('do_INIT: got expected error on 2nd INIT')
        else:
            print('fail: no error on 2nd INIT')

        if args.loopback and modp.genz_loopback == 0:
            print(
                'Configuration error - loopback test requested but driver has genz_loopback=0'
            )

        if args.loopback and modp.genz_loopback:
            zuu = zuuid(gcid=gcid)
            if args.bringup:
                conn.do_UUID_IMPORT(zuu, UU.IS_FAM, None)
            else:
                conn.do_UUID_IMPORT(zuu, 0, None)

        sz4K = 4096
        sz2M = 2 << 20
        sz1G = 1 << 30

        if args.requester:
            mm = mmap.mmap(-1, sz4K)
            v, l = zhpe.mmap_vaddr_len(mm)
            rsp = conn.do_MR_REG(v, l, MR.GPI)  # req: GET/PUT, 4K
            # register the same thing memory twice to force EEXIST
            try:
                bad = conn.do_MR_REG(v, l, MR.GPI)  # req: GET/PUT, 4K
            except OSError:
                exc = True
            if exc:
                if args.verbosity:
                    print('do_MR_REG: got expected error on 2nd MR_REG')
            else:
                print('fail: no error on 2nd MR_REG')

        if args.responder or args.loopback:
            mm2 = mmap.mmap(-1, sz4K)
            mm2[0:sz4K] = os.urandom(sz4K)  # fill with random bytes
            v2, l2 = zhpe.mmap_vaddr_len(mm2)
            rsp2 = conn.do_MR_REG(v2, l2, MR.GRPRI)  # rsp: GET_REM/PUT_REM, 4K

        data = open(args.datafile, 'rb')
        mmdata = mmap.mmap(data.fileno(), 0, access=mmap.ACCESS_READ)
        datasha256 = hashlib.sha256(mmdata[0:datasize]).hexdigest()
        if args.verbosity:
            print('datafile sha256={}'.format(datasha256))
        # Revisit: using a hugepage file to guarantee a physically contiguous
        # region until the IOMMU works in the sim
        f2M = open(args.bigfile, 'rb+')
        mm2M = mmap.mmap(f2M.fileno(), 0, access=mmap.ACCESS_WRITE)
        mm2M[0:datasize] = mmdata[0:datasize]
        if args.huge:
            print('opening hugefile "{}"'.format(args.hugefile))
            f1G = open(args.hugefile, 'rb+')
            print('mmapping hugefile')
            mm1G = mmap.mmap(f1G.fileno(), 0, access=mmap.ACCESS_WRITE)
            print('initializing hugefile with random data')
            mm1G[0:hugesize // 2] = os.urandom(hugesize // 2)
            v1G, l1G = zhpe.mmap_vaddr_len(mm1G)
        mmdata.close()
        data.close()
        v2M, l2M = zhpe.mmap_vaddr_len(mm2M)
        rsp2M = conn.do_MR_REG(v2M + 0x1242, l2M - 0x5000,
                               MR.GRPRI)  # GET_REM/PUT_REM, 2M-0x5000

        rsp2M_l = conn.do_MR_REG(v2M, l2M, MR.GP)  # GET/PUT, 2M
        lmr = rsp2M_l
        lmm = mm2M

        if args.responder or args.loopback:
            rsp2M_b = conn.do_MR_REG(v2M, l2M,
                                     MR.GRPRI)  # rsp: GET_REM/PUT_REM, 2M

        if args.loopback and modp.genz_loopback:
            rsp_rmr = conn.do_RMR_IMPORT(zuu, rsp2M_b.rsp_zaddr, sz4K,
                                         MR.GRPRI)
            # individual, cpu-visible, 2M mapping allowing
            # GET/PUT/GET_REMOTE/PUT_REMOTE
            rsp2M_r = conn.do_MR_REG(v2M, sz2M, MR.GPGRPRI)  # loop: ALL, 2M

            if args.load_store:
                rsp_rmr_c = conn.do_RMR_IMPORT(zuu, rsp2M_b.rsp_zaddr, sz4K,
                                               MR.GRPRIC)
                rmm = mmap.mmap(f.fileno(), sz4K, offset=rsp_rmr_c.offset)

                rsp_rmr2 = conn.do_RMR_IMPORT(zuu, rsp2.rsp_zaddr, sz4K,
                                              MR.GRPRIC)
                rmm2 = mmap.mmap(f.fileno(), sz4K, offset=rsp_rmr2.offset)
                v_rmm2, l_rmm2 = zhpe.mmap_vaddr_len(rmm2)

                rsp_rmr_ro = conn.do_RMR_IMPORT(zuu, rsp2.rsp_zaddr, sz4K,
                                                MR.GRIC)
                rmm2_ro = mmap.mmap(f.fileno(), sz4K, offset=rsp_rmr_ro.offset)
                v_rmm2_ro, l_rmm2_ro = zhpe.mmap_vaddr_len(rmm2_ro)
                # Revisit: why does trying to write rmm2_ro (to test that it's
                # really RO) cause a python3 segfault?
                # rmm2_ro[0:3] = b'Joe'

                rsp_rmr2M = conn.do_RMR_IMPORT(zuu, rsp2M_r.rsp_zaddr, sz2M,
                                               MR.GRPRIC)
                rmm2M = mmap.mmap(f.fileno(), sz2M, offset=rsp_rmr2M.offset)
            else:
                rsp_rmr2 = conn.do_RMR_IMPORT(zuu, rsp2.rsp_zaddr, sz4K,
                                              MR.GRPRI)
                rsp_rmr2M = conn.do_RMR_IMPORT(zuu, rsp2M_r.rsp_zaddr, sz2M,
                                               MR.GRPRI)

        xdm = zhpe.XDM(conn, 256, 256, slice_mask=0x1)
        rdm = zhpe.RDM(conn, 1024, slice_mask=0x2)

        nop = zhpe.xdm_cmd()
        nop.opcode = zhpe.XDM_CMD.NOP | zhpe.XDM_CMD.FENCE

        if args.huge:
            # individual, 1G mapping allowing
            # GET/PUT/GET_REMOTE/PUT_REMOTE (not cpu-visible)
            mm1Gsha256h = hashlib.sha256(mm1G[0:hugesize // 2]).hexdigest()
            rsp1G = conn.do_MR_REG(v1G, sz1G, MR.GPGRPRI)  # huge: ALL, 1G
            lmr = rsp1G
            lmm = mm1G

        if args.net:
            if args.verbosity:
                print('Starting networking - this is very slow in sim')
            import network as net
            factory = net.MyFactory(conn, lmr, lmm, xdm, args.verbosity,
                                    args.bringup, args.load_store,
                                    args.requester, args.responder,
                                    modp.no_iommu)
            try:
                factory.setup(args.port, nodes)
            except net.CannotListenError:
                print('Error: Address in use')

        # str1+str2 & str3 must fit in a 32-byte GET_IMM/PUT_IMM
        str1 = b'J/B/S '
        str2 = b'making PFS awesome!'
        str3 = b'PF Slice is awesome too!'
        # str4 & str5 must fit in a 52-byte ENQA
        str4 = b'But sometimes, madness is the only path forward.'
        str5 = b'Interrupts are distractions.'
        len1 = len(str1)
        len2 = len(str2)
        len3 = len(str3)
        len4 = len(str4)
        len5 = len(str5)
        len1_2 = len1 + len2
        mm2[0:len1] = str1
        if args.verbosity:
            print('mm2 (initial)="{}"'.format(mm2[0:len1].decode()))
        if args.loopback and modp.genz_loopback:
            if args.load_store:
                if args.verbosity:
                    print('rmm2 (remote)="{}"'.format(rmm2[0:len1].decode()))
                if mm2[0:len1] != rmm2[0:len1]:
                    print('Error: mm2 "{}" != rmm2 "{}"'.format(
                        mm2[0:len1].decode(), rmm2[0:len1].decode()))
                rmm2[len1:len1_2] = str2
                # flush rmm2 writes, so mm2 reads will see new data
                zhpe.pmem_flush(v_rmm2 + len1, len2)
                if args.verbosity:
                    print('mm2 after remote update="{}"'.format(
                        mm2[0:len1_2].decode()))
                if mm2[0:len1_2] != rmm2[0:len1_2]:
                    print('Error: mm2 "{}" != rmm2 "{}"'.format(
                        mm2[0:len1_2].decode(), rmm2[0:len1_2].decode()))
            else:
                # just write mm2 directly, so it has the right stuff
                mm2[len1:len1_2] = str2

        sync = zhpe.xdm_cmd()
        sync.opcode = zhpe.XDM_CMD.SYNC | zhpe.XDM_CMD.FENCE

        xdm.buffer_cmd(nop)
        nop_cmpl = xdm.get_cmpl()
        if args.verbosity:
            print('NOP cmpl: {}'.format(nop_cmpl))
        if args.keyboard:
            set_trace()

        if args.loopback and modp.genz_loopback:
            # test PUT_IMM
            put_imm_offset = len1_2 + 1
            rem_addr = rsp_rmr2.req_addr + put_imm_offset
            put_imm = zhpe.xdm_cmd()
            put_imm.opcode = zhpe.XDM_CMD.PUT_IMM
            put_imm.getput_imm.size = len3
            put_imm.getput_imm.rem_addr = rem_addr
            put_imm.getput_imm.payload[0:len3] = str3
            if args.keyboard:
                set_trace()
            xdm.queue_cmd(put_imm)
            try:
                put_imm_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('PUT_IMM cmpl: {}'.format(put_imm_cmpl))
            except XDMcompletionError as e:
                print('PUT_IMM cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.keyboard:
                set_trace()
            # Revisit: need fence/sync to ensure visibility
            if args.verbosity:
                print('mm2 after PUT_IMM="{}"'.format(
                    mm2[put_imm_offset:put_imm_offset + len3].decode()))
            # Revisit: check that mm2 got str3
            # test GET_IMM
            get_imm = zhpe.xdm_cmd()
            get_imm.opcode = zhpe.XDM_CMD.GET_IMM
            get_imm.getput_imm.size = len1_2
            get_imm.getput_imm.rem_addr = rsp_rmr2.req_addr
            xdm.queue_cmd(get_imm)
            try:
                get_imm_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm))
            except XDMcompletionError as e:
                print('GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))

            if args.keyboard:
                set_trace()
            # test PUT
            put_offset = datasize
            if modp.no_iommu:
                local_addr = rsp2M_r.physaddr  # Revisit: physaddr temporary
            else:
                local_addr = v2M
            rem_addr = rsp_rmr2M.req_addr + put_offset
            put = zhpe.xdm_cmd()
            put.opcode = zhpe.XDM_CMD.PUT | zhpe.XDM_CMD.FENCE
            put.getput.size = datasize
            put.getput.read_addr = local_addr
            put.getput.write_addr = rem_addr
            xdm.queue_cmd(put)
            try:
                put_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('PUT cmpl: {}'.format(put_cmpl))
            except XDMcompletionError as e:
                print('PUT cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            # Revisit: need fence/sync to ensure visibility
            mm2Msha256p = hashlib.sha256(mm2M[put_offset:put_offset +
                                              datasize]).hexdigest()
            if args.verbosity:
                print('mm2M sha256 after PUT="{}"'.format(mm2Msha256p))
            if mm2Msha256p != datasha256:
                print('PUT sha mismatch: {} != {}'.format(
                    datasha256, mm2Msha256p))

            if args.keyboard:
                set_trace()
            # test GET+SYNC
            get_offset = 2 * datasize
            if modp.no_iommu:
                local_addr = rsp2M_r.physaddr + get_offset  # Revisit: physaddr temporary
            else:
                local_addr = v2M + get_offset
            rem_addr = rsp_rmr2M.req_addr + put_offset
            get = zhpe.xdm_cmd()
            get.opcode = zhpe.XDM_CMD.GET | zhpe.XDM_CMD.FENCE
            get.getput.size = datasize
            get.getput.read_addr = rem_addr
            get.getput.write_addr = local_addr
            xdm.queue_cmds([get, sync])
            try:
                get_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('GET cmpl: {}'.format(get_cmpl))
            except XDMcompletionError as e:
                print('GET cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            try:
                sync_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('SYNC cmpl: {}'.format(sync_cmpl))
            except XDMcompletionError as e:
                print('SYNC cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            mm2Msha256g = hashlib.sha256(mm2M[get_offset:get_offset +
                                              datasize]).hexdigest()
            if args.verbosity:
                print('mm2M sha256 after GET="{}"'.format(mm2Msha256g))
            if mm2Msha256g != datasha256:
                print('GET sha mismatch: {} != {}'.format(
                    datasha256, mm2Msha256g))

            # Do the atomic tests at the 1M point in the 2M region
            atomic_offset = rsp_rmr2M.req_addr + 1048576

            # test atomic 32 bit SWAP
            swap32 = zhpe.xdm_cmd()
            swap32.opcode = zhpe.XDM_CMD.ATM_SWAP
            swap32.atomic_one_op32.r = 1  # return a value
            swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT
            swap32.atomic_one_op32.rem_addr = atomic_offset
            swap32.atomic_one_op32.operand = 0x12345678
            xdm.queue_cmd(swap32)
            try:
                swap32_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('SWAP32 cmpl: {}'.format(swap32_cmpl))
            except XDMcompletionError as e:
                print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('SWAP32 return value: {}'.format(swap32_cmpl.atomic32))
            if args.keyboard:
                set_trace()

            # test the same atomic 32 bit SWAP to see if the prev val is now 0x12345678
            swap32 = zhpe.xdm_cmd()
            swap32.opcode = zhpe.XDM_CMD.ATM_SWAP
            swap32.atomic_one_op32.r = 1  # return a value
            swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT
            swap32.atomic_one_op32.rem_addr = atomic_offset
            swap32.atomic_one_op32.operand = 0xDEADBEEF
            xdm.queue_cmd(swap32)
            try:
                swap32_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('SWAP32 cmpl: {}'.format(swap32_cmpl))
            except XDMcompletionError as e:
                print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('SWAP32 return value: {}'.format(swap32_cmpl.atomic32))
            if swap32_cmpl.atomic32.retval != 0x12345678:
                print('FAIL: SWAP32: retval is {:#x} and should be 0x12345678'.
                      format(swap32_cmpl.atomic32.retval))
            if args.keyboard:
                set_trace()

            # test atomic 32 bit COMPARE AND SWAP - val is now 0xDEADBEEF
            cas32 = zhpe.xdm_cmd()
            cas32.opcode = zhpe.XDM_CMD.ATM_CAS
            cas32.atomic_two_op32.r = 1  # return a value
            cas32.atomic_two_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT
            cas32.atomic_two_op32.rem_addr = atomic_offset
            cas32.atomic_two_op32.operand1 = 0xDEADBEEF
            cas32.atomic_two_op32.operand2 = 0xBDA11FED
            xdm.queue_cmd(cas32)
            try:
                cas32_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('CAS32 cmpl: {}'.format(cas32_cmpl))
            except XDMcompletionError as e:
                print('CAS32 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('CAS32 return value: {}'.format(cas32_cmpl.atomic32))
            if cas32_cmpl.atomic32.retval != 0xDEADBEEF:
                print('FAIL: CAS32: retval is {:#x} and should be 0xDEADBEEF'.
                      format(cas32_cmpl.atomic32.retval))
            if args.keyboard:
                set_trace()

            # test atomic 32 bit FETCH AND ADD - val is now 0xBDA11FED
            add32 = zhpe.xdm_cmd()
            add32.opcode = zhpe.XDM_CMD.ATM_ADD
            add32.atomic_one_op32.r = 1  # return a value
            add32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT
            add32.atomic_one_op32.rem_addr = atomic_offset
            add32.atomic_one_op32.operand = 0x12345678
            xdm.queue_cmd(add32)
            try:
                add32_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('ADD32 cmpl: {}'.format(add32_cmpl))
            except XDMcompletionError as e:
                print('ADD32 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('ADD32 return value: {}'.format(add32_cmpl.atomic32))
            if add32_cmpl.atomic32.retval != 0xBDA11FED:
                print('FAIL: ADD32: retval is {:#x} and should be 0xBDA11FED'.
                      format(add32_cmpl.atomic32.retval))
            if args.keyboard:
                set_trace()

            # use SWAP to get the sum from the previous ADD32
            swap32 = zhpe.xdm_cmd()
            swap32.opcode = zhpe.XDM_CMD.ATM_SWAP
            swap32.atomic_one_op32.r = 1  # return a value
            swap32.atomic_one_op32.size = zhpe.ATOMIC_SIZE.SIZE_32BIT
            swap32.atomic_one_op32.rem_addr = atomic_offset
            swap32.atomic_one_op32.operand = 0x0
            xdm.queue_cmd(swap32)
            try:
                swap32_cmpl = xdm.get_cmpl()
            except XDMcompletionError as e:
                print('SWAP32 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if swap32_cmpl.atomic32.retval != 0xCFD57665:
                print('FAIL: ADD32: retval is {:#x} and should be 0xCFD57665'.
                      format(swap32_cmpl.atomic32.retval))
            else:
                if args.verbosity:
                    print('ADD32: PASS: sum is {:#x}'.format(
                        swap32_cmpl.atomic32.retval))

            # test atomic 64 bit SWAP
            swap64 = zhpe.xdm_cmd()
            swap64.opcode = zhpe.XDM_CMD.ATM_SWAP
            swap64.atomic_one_op64.r = 1  # return a value
            swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT
            swap64.atomic_one_op64.rem_addr = atomic_offset
            swap64.atomic_one_op64.operand = 0xDEADBEEFEDA11AB
            xdm.queue_cmd(swap64)
            try:
                swap64_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('SWAP64 cmpl: {}'.format(swap64_cmpl))
            except XDMcompletionError as e:
                print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('SWAP64 return value: {}'.format(swap64_cmpl.atomic64))
            if args.keyboard:
                set_trace()
            # second test atomic 64 bit SWAP - val is now 0xDEADBEEFEDA11AB
            swap64 = zhpe.xdm_cmd()
            swap64.opcode = zhpe.XDM_CMD.ATM_SWAP
            swap64.atomic_one_op64.r = 1  # return a value
            swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT
            swap64.atomic_one_op64.rem_addr = atomic_offset
            swap64.atomic_one_op64.operand = 0x123456789ABCDEF1
            xdm.queue_cmd(swap64)
            try:
                swap64_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('SWAP64 cmpl: {}'.format(swap64_cmpl))
            except XDMcompletionError as e:
                print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('SWAP64 return value: {}'.format(swap64_cmpl.atomic64))
            if swap64_cmpl.atomic64.retval != 0xDEADBEEFEDA11AB:
                print(
                    'FAIL: SWAP64: retval is {:#x} and should be 0xDEADBEEFEDA11AB'
                    .format(swap64_cmpl.atomic64.retval))
            if args.keyboard:
                set_trace()

            # test atomic 64 bit COMPARE AND SWAP - val is now 0x12356789ABCDEF1
            cas64 = zhpe.xdm_cmd()
            cas64.opcode = zhpe.XDM_CMD.ATM_CAS
            cas64.atomic_two_op64.r = 1  # return a value
            cas64.atomic_two_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT
            cas64.atomic_two_op64.rem_addr = atomic_offset
            cas64.atomic_two_op64.operand1 = 0x12356789ABCDEF12
            cas64.atomic_two_op64.operand2 = 0xBADDECAFBADDECAF
            xdm.queue_cmd(cas64)
            try:
                cas64_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('CAS64 cmpl: {}'.format(cas64_cmpl))
            except XDMcompletionError as e:
                print('CAS64 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('CAS64 return value: {}'.format(cas64_cmpl.atomic64))
            if cas64_cmpl.atomic64.retval != 0x123456789ABCDEF1:
                print(
                    'FAIL: CAS64: retval is {:#x} and should be 0x123456789ABCDEF1'
                    .format(cas64_cmpl.atomic64.retval))
            if args.keyboard:
                set_trace()

            # test atomic 64 bit FETCH AND ADD - val is now 0x123456789ABCDEF1
            add64 = zhpe.xdm_cmd()
            add64.opcode = zhpe.XDM_CMD.ATM_ADD
            add64.atomic_one_op64.r = 1  # return a value
            add64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT
            add64.atomic_one_op64.rem_addr = atomic_offset
            add64.atomic_one_op64.operand = 0x1111111111111111
            xdm.queue_cmd(add64)
            try:
                add64_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('ADD64 cmpl: {}'.format(add64_cmpl))
            except XDMcompletionError as e:
                print('ADD64 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if args.verbosity:
                print('ADD64 return value: {}'.format(add64_cmpl.atomic64))
            if add64_cmpl.atomic64.retval != 0x123456789abcdef1:
                print(
                    'FAIL: ADD64: retval is {:#x} and should be 0x0x123456789abcdef1'
                    .format(add64_cmpl.atomic64.retval))
            # use atomic 64 bit SWAP to get the sum from previous ADD
            swap64 = zhpe.xdm_cmd()
            swap64.opcode = zhpe.XDM_CMD.ATM_SWAP
            swap64.atomic_one_op64.r = 1  # return a value
            swap64.atomic_one_op64.size = zhpe.ATOMIC_SIZE.SIZE_64BIT
            swap64.atomic_one_op64.rem_addr = atomic_offset
            swap64.atomic_one_op64.operand = 0x0
            xdm.queue_cmd(swap64)
            try:
                swap64_cmpl = xdm.get_cmpl()
            except XDMcompletionError as e:
                print('SWAP64 cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            if swap64_cmpl.atomic64.retval != 0x23456789ABCDF002:
                print(
                    'FAIL: ADD64: retval is {:#x} and should be 0x23456789ABCDF002'
                    .format(swap64_cmpl.atomic64.retval))
            else:
                if args.verbosity:
                    print('ADD64: PASS: sum is {:#x}'.format(
                        swap64_cmpl.atomic64.retval))
            if args.keyboard:
                set_trace()

            # test EnqA/RDM
            enqa = zhpe.xdm_cmd()
            enqa.opcode = zhpe.XDM_CMD.ENQA
            enqa.enqa.dgcid = zuu.gcid
            enqa.enqa.rspctxid = rdm.rsp_rqa.info.rspctxid
            enqa.enqa.payload[0:len4] = str4
            xdm.queue_cmd(enqa)
            try:
                enqa_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('ENQA cmpl: {}'.format(enqa_cmpl))
            except XDMcompletionError as e:
                print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            rdm_cmpl = rdm.get_cmpl()
            if args.verbosity:
                print('RDM cmpl: {}'.format(rdm_cmpl.enqa))
            if enqa.enqa.payload[0:52] != rdm_cmpl.enqa.payload[0:52]:
                print('FAIL: RDM: payload is {} and should be {}'.format(
                    rdm_cmpl.enqa.payload[0:52], enqa.enqa.payload[0:52]))
            # Revisit: check other cmpl fields
            if args.keyboard:
                set_trace()

            # test EnqA/RDM with poll
            enqa = zhpe.xdm_cmd()
            enqa.opcode = zhpe.XDM_CMD.ENQA
            enqa.enqa.dgcid = zuu.gcid
            enqa.enqa.rspctxid = rdm.rsp_rqa.info.rspctxid
            enqa.enqa.payload[0:len4] = str4
            xdm.queue_cmd(enqa)
            try:
                enqa_cmpl = xdm.get_cmpl()
                if args.verbosity:
                    print('ENQA cmpl: {}'.format(enqa_cmpl))
            except XDMcompletionError as e:
                print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            rdm_cmpls = rdm.get_poll(verbosity=args.verbosity)
            if args.verbosity:
                for c in range(len(rdm_cmpls)):
                    if c != None:
                        print('RDM cmpl: {}'.format(rdm_cmpls[c].enqa))
            for c in range(len(rdm_cmpls)):
                if enqa.enqa.payload[0:52] != rdm_cmpls[c].enqa.payload[0:52]:
                    print('FAIL: RDM: payload is {} and should be {}'.format(
                        rdm_cmpls[c].enqa.payload[0:52],
                        enqa.enqa.payload[0:52]))
            if args.keyboard:
                set_trace()

            # second test EnqA/RDM with poll
            if args.verbosity:
                print('SECOND EnqA/RDM poll test')
            enqa2 = zhpe.xdm_cmd()
            enqa2.opcode = zhpe.XDM_CMD.ENQA
            enqa2.enqa.dgcid = zuu.gcid
            enqa2.enqa.rspctxid = rdm.rsp_rqa.info.rspctxid
            enqa2.enqa.payload[0:len5] = str5
            xdm.queue_cmd(enqa2)
            try:
                enqa_cmpl2 = xdm.get_cmpl()
                if args.verbosity:
                    print('ENQA cmpl: {}'.format(enqa_cmpl2))
            except XDMcompletionError as e:
                print('ENQA cmpl error: {} {:#x} request_id {:#x}'.format(
                    e, e.status, e.request_id))
            rdm_cmpls2 = rdm.get_poll(verbosity=args.verbosity)
            if args.verbosity:
                for c in range(len(rdm_cmpls2)):
                    if c != None:
                        print('RDM cmpl: {}'.format(rdm_cmpls2[c].enqa))
            for c in range(len(rdm_cmpls2)):
                if enqa2.enqa.payload[0:52] != rdm_cmpls2[c].enqa.payload[0:52]:
                    print('FAIL: RDM: payload is {} and should be {}'.format(
                        rdm_cmpls[c].enqa.payload[0:52],
                        enqa.enqa.payload[0:52]))
            if args.keyboard:
                set_trace()
            # test FAM
            if args.fam:
                fam_zuu = zuuid(gcid=args.fam_gcid)
                if args.verbosity:
                    print('FAM zuuid={}'.format(fam_zuu))
                # Do a UUID_IMPORT with the ZHPE_IS_FAM flag set
                conn.do_UUID_IMPORT(fam_zuu, UU.IS_FAM, None)
                # RMR_IMPORT the FAM at address 0 and size 2M
                if args.load_store:
                    fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRIC)
                    # Do load/store to FAM
                    fam_rmm = mmap.mmap(f.fileno(),
                                        sz2M,
                                        offset=fam_rmr.offset)
                    fam_v, fam_l = zhpe.mmap_vaddr_len(fam_rmm)
                    fam_rmm[0:len1] = str1
                    fam_rmm[len1:len1_2] = str2
                    # flush writes, so reads will see new data
                    zhpe.pmem_flush(fam_v, len1_2)
                else:
                    fam_rmr = conn.do_RMR_IMPORT(fam_zuu, 0, sz2M, MR.GRPRI)
                # do an XDM command to get the data back and check it
                get_imm = zhpe.xdm_cmd()
                get_imm.opcode = zhpe.XDM_CMD.GET_IMM
                get_imm.getput_imm.size = len1_2
                get_imm.getput_imm.rem_addr = fam_rmr.req_addr
                if args.keyboard:
                    set_trace()
                xdm.queue_cmd(get_imm)
                try:
                    get_imm_cmpl = xdm.get_cmpl()
                    if args.verbosity:
                        print('GET_IMM cmpl: {}'.format(get_imm_cmpl.getimm))
                    # Verify the payload is what we expect
                    if args.load_store:
                        retstr = bytearray(
                            get_imm_cmpl.getimm.payload[0:len1_2])
                        if retstr == str1 + str2:
                            if args.verbosity:
                                print('FAM comparision PASS')
                        else:
                            print('FAM comparision FAIL')
                except XDMcompletionError as e:
                    print(
                        'GET_IMM cmpl error: {} {:#x} request_id {:#x}'.format(
                            e, e.status, e.request_id))
                # Revisit: check that we got str1+str2
                if args.keyboard:
                    set_trace()
            # end if FAM

            # Test a huge PUT
            if args.huge:
                rsp_rmr1G = conn.do_RMR_IMPORT(zuu, rsp1G.rsp_zaddr, sz1G,
                                               MR.GRPRI)
                put_offset = hugesize // 2
                local_addr = v1G
                rem_addr = rsp_rmr1G.req_addr + put_offset
                put = zhpe.xdm_cmd()
                put.opcode = zhpe.XDM_CMD.PUT | zhpe.XDM_CMD.FENCE
                put.getput.size = hugesize // 2
                put.getput.read_addr = local_addr
                put.getput.write_addr = rem_addr
                if args.keyboard:
                    set_trace()
                start = time.monotonic()
                xdm.queue_cmd(put)
                try:
                    put_cmpl = xdm.get_cmpl()
                    end = time.monotonic()
                    if args.verbosity:
                        print('huge PUT cmpl: {}'.format(put_cmpl))
                except XDMcompletionError as e:
                    print('huge PUT cmpl error: {} {:#x} request_id {:#x}'.
                          format(e, e.status, e.request_id))
                # Revisit: need fence/sync to ensure visibility
                mm1Gsha256p = hashlib.sha256(mm1G[put_offset:put_offset +
                                                  hugesize // 2]).hexdigest()
                if args.verbosity:
                    print('mm1G sha256 after PUT="{}"'.format(mm1Gsha256p))
                if mm1Gsha256p != mm1Gsha256h:
                    print('huge PUT sha mismatch: {} != {}'.format(
                        mm1Gsha256h, mm1Gsha256h))
                secs = end - start
                if args.verbosity:
                    print(
                        'huge PUT of {} bytes in {} seconds = {} GiB/s'.format(
                            put.getput.size, secs,
                            put.getput.size / (secs * sz1G)))
            # end if huge
        # end if loopback

        if args.net:
            if args.verbosity:
                print('Waiting for network connections')
            net.reactor.run()
        if args.keyboard:
            set_trace()
        conn.do_XQUEUE_FREE(xdm.rsp_xqa.info)
        conn.do_RQUEUE_FREE(rdm.rsp_rqa.info)
        if args.requester:
            conn.do_MR_FREE(v, l, MR.GPI, rsp.rsp_zaddr)
        conn.do_MR_FREE(v2M, l2M, MR.GP, rsp2M_l.rsp_zaddr)
        conn.do_MR_FREE(v2M + 0x1242, l2M - 0x5000, MR.GRPRI, rsp2M.rsp_zaddr)

        # we do not MR_FREE rsp2M_b, to see if it is cleaned up at close
        # same for RMR_FREE of rsp_rmr
        if args.loopback and modp.genz_loopback:
            if args.load_store:
                conn.do_RMR_FREE(zuu, rsp2M_b.rsp_zaddr, sz4K, MR.GRPRIC,
                                 rsp_rmr_c.req_addr)
            exc = False
            try:
                conn.do_UUID_FREE(zuu)
            except OSError:
                exc = True
            if exc:
                if args.verbosity:
                    print('do_UUID_FREE of zuu: got expected error')
            else:
                print('fail: no error on UUID_FREE of zuu')
        exc = False
        try:
            conn.do_UUID_FREE(init.uuid)
        except OSError:
            exc = True
        if exc:
            if args.verbosity:
                print('do_UUID_FREE of init.uuid: got expected error')
        else:
            print('fail: no error on UUID_FREE of init.uuid')