kfdtest: add address watch test
Address watch test will test read and write operations. Test will also check if operation is precise if precise address watch is available. Signed-off-by: Jonathan Kim <jonathan.kim@amd.com> Change-Id: I7ef835790e26bf6345682755d7dd26a35853bcd5
This commit is contained in:
@@ -518,3 +518,115 @@ exit:
|
||||
LOG() << std::endl;
|
||||
TEST_END
|
||||
}
|
||||
|
||||
TEST_F(KFDDBGTest, HitAddressWatch) {
|
||||
TEST_START(TESTPROFILE_RUNALL)
|
||||
if (m_FamilyId >= FAMILY_VI) {
|
||||
int defaultGPUNode = m_NodeInfo.HsaDefaultGPUNode();
|
||||
|
||||
if (hsaKmtCheckRuntimeDebugSupport()) {
|
||||
LOG() << "Skip test as debug API not supported";
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ASSERT_GE(defaultGPUNode, 0) << "failed to get default GPU Node";
|
||||
HsaNodeProperties nodeProps;
|
||||
ASSERT_SUCCESS(hsaKmtGetNodeProperties(defaultGPUNode, &nodeProps));
|
||||
|
||||
HsaMemoryBuffer readerBuf(PAGE_SIZE, defaultGPUNode, true, false, true);
|
||||
HsaMemoryBuffer writerBuf(PAGE_SIZE, defaultGPUNode, true, false, true);
|
||||
HsaMemoryBuffer trap(PAGE_SIZE*2, defaultGPUNode, true, false, true);
|
||||
HsaMemoryBuffer tmaBuf(PAGE_SIZE, defaultGPUNode, false, false, false);
|
||||
|
||||
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(watch_read_isa, readerBuf.As<char*>()));
|
||||
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(watch_write_isa, writerBuf.As<char*>()));
|
||||
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(trap_handler_gfx, trap.As<char*>()));
|
||||
ASSERT_SUCCESS(hsaKmtSetTrapHandler(defaultGPUNode,
|
||||
trap.As<void *>(),
|
||||
0x1000,
|
||||
tmaBuf.As<void*>(),
|
||||
0x1000));
|
||||
|
||||
uint32_t rDebug;
|
||||
ASSERT_SUCCESS(hsaKmtRuntimeEnable(&rDebug, true));
|
||||
|
||||
struct kfd_runtime_info r_info = {0};
|
||||
BaseDebug *debug = new BaseDebug();
|
||||
ASSERT_SUCCESS(debug->Attach(&r_info, sizeof(r_info), getpid(), 0));
|
||||
ASSERT_EQ(r_info.runtime_state, DEBUG_RUNTIME_STATE_ENABLED);
|
||||
|
||||
const std::vector<int> gpuNodes = m_NodeInfo.GetNodesWithGPU();
|
||||
uint32_t numDevices = gpuNodes.size();
|
||||
struct kfd_dbg_device_info_entry deviceInfo[numDevices] = {0};
|
||||
ASSERT_SUCCESS(debug->DeviceSnapshot(0, (uint64_t)(&deviceInfo[0]), &numDevices));
|
||||
ASSERT_EQ(numDevices, gpuNodes.size());
|
||||
bool is_precise = nodeProps.Capability.ui32.PreciseMemoryOperationsSupported;
|
||||
|
||||
if (is_precise) {
|
||||
uint32_t trapFlags = KFD_DBG_TRAP_FLAG_SINGLE_MEM_OP;
|
||||
ASSERT_SUCCESS(debug->SetFlags(&trapFlags));
|
||||
}
|
||||
|
||||
uint32_t enableMask = KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH;
|
||||
uint32_t supportedMask = enableMask;
|
||||
ASSERT_SUCCESS(debug->SetWaveLaunchOverride(KFD_DBG_TRAP_OVERRIDE_OR,
|
||||
&enableMask,
|
||||
&supportedMask));
|
||||
ASSERT_NE(supportedMask & KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH, 0);
|
||||
ASSERT_EQ(enableMask & KFD_DBG_TRAP_MASK_DBG_ADDRESS_WATCH, 0); // previous set mask
|
||||
|
||||
PM4Queue queue;
|
||||
ASSERT_SUCCESS(queue.Create(defaultGPUNode));
|
||||
const uint32_t watchMask = -1 & UINT_MAX;
|
||||
|
||||
HsaMemoryBuffer targetBuf(PAGE_SIZE, defaultGPUNode, true, false, false);
|
||||
HsaMemoryBuffer resultBuf(PAGE_SIZE, defaultGPUNode, true, false, false);
|
||||
unsigned int *target = targetBuf.As<unsigned int*>();
|
||||
unsigned int *result = resultBuf.As<unsigned int*>();
|
||||
|
||||
for (int mode = KFD_DBG_TRAP_ADDRESS_WATCH_MODE_READ;
|
||||
mode < KFD_DBG_TRAP_ADDRESS_WATCH_MODE_ALL; mode++) {
|
||||
|
||||
// atomics may not be supported on all devices so skip for now.
|
||||
if (mode != KFD_DBG_TRAP_ADDRESS_WATCH_MODE_READ &&
|
||||
mode != KFD_DBG_TRAP_ADDRESS_WATCH_MODE_NONREAD)
|
||||
continue;
|
||||
|
||||
uint32_t watchId = -1;
|
||||
ASSERT_SUCCESS(debug->SetAddressWatch((uint64_t)(&target[0]), mode,
|
||||
watchMask, deviceInfo[0].gpu_id, &watchId));
|
||||
ASSERT_EQ(watchId, 0);
|
||||
|
||||
const HsaMemoryBuffer &shaderBuf =
|
||||
mode == KFD_DBG_TRAP_ADDRESS_WATCH_MODE_READ ? readerBuf : writerBuf;
|
||||
uint32_t preciseMask = 0x1;
|
||||
uint32_t watchStsMask = 0x80;
|
||||
result[0] = preciseMask;
|
||||
Dispatch dispatch(shaderBuf);
|
||||
dispatch.SetDim(1, 1, 1);
|
||||
dispatch.SetArgs(&target[0], &result[0]);
|
||||
dispatch.SetPriv(false); // Override GFX11 CWSR WA
|
||||
dispatch.Submit(queue);
|
||||
dispatch.Sync();
|
||||
|
||||
ASSERT_EQ(result[0] & watchStsMask, watchStsMask);
|
||||
|
||||
if (is_precise)
|
||||
ASSERT_EQ(result[0] & preciseMask, preciseMask);
|
||||
|
||||
ASSERT_SUCCESS(debug->ClearAddressWatch(deviceInfo[0].gpu_id, watchId));
|
||||
resultBuf.Fill(0);
|
||||
targetBuf.Fill(0);
|
||||
}
|
||||
|
||||
ASSERT_SUCCESS(queue.Destroy());
|
||||
debug->Detach();
|
||||
hsaKmtRuntimeDisable();
|
||||
} else {
|
||||
LOG() << "Skipping test: Test not supported on family ID 0x"
|
||||
<< m_FamilyId << "." << std::endl;
|
||||
}
|
||||
exit:
|
||||
LOG() << std::endl;
|
||||
TEST_END
|
||||
}
|
||||
|
||||
@@ -926,6 +926,12 @@ const char *trap_handler_gfx =
|
||||
s_getreg_b32 ttmp14, hwreg(HW_REG_TRAPSTS)
|
||||
s_and_b32 ttmp2, ttmp14, 0x800
|
||||
s_cbranch_scc1 RESTORE_AND_EXIT
|
||||
/*check for address watch event and record pc check point delta*/
|
||||
s_and_b32 ttmp2, ttmp14, 0x7080
|
||||
s_cbranch_scc0 GET_DOORBELL
|
||||
v_mov_b32 v5, v4 // capture watch checkpoint
|
||||
v_mov_b32 v6, ttmp14 // capture watch trapsts
|
||||
s_branch RESTORE_AND_EXIT
|
||||
GET_DOORBELL:
|
||||
.if .amdgcn.gfx_generation_number < 11
|
||||
s_mov_b32 ttmp2, exec_lo
|
||||
@@ -971,3 +977,33 @@ const char *trap_handler_gfx =
|
||||
s_setreg_b32 hwreg(HW_REG_STATUS), ttmp12
|
||||
s_rfe_b64 [ttmp0, ttmp1]
|
||||
)";
|
||||
|
||||
#define WATCH_START SHADER_START SHADER_MACROS_U32\
|
||||
"v_mov_b32 v0, s0\n"\
|
||||
"v_mov_b32 v1, s1\n"\
|
||||
"v_mov_b32 v2, s2\n"\
|
||||
"v_mov_b32 v3, s3\n"\
|
||||
"flat_load_dword v4, v[2:3]\n"\
|
||||
"s_waitcnt vmcnt(0) & lgkmcnt(0)\n"\
|
||||
"v_mov_b32 v5, 0\n"\
|
||||
"v_mov_b32 v6, 0\n"
|
||||
|
||||
#define WATCH_END "\n"\
|
||||
"v_mov_b32 v4, 2\n"\
|
||||
"LOOP:\n"\
|
||||
"V_CMP_EQ_U32 v6, 0\n"\
|
||||
"s_cbranch_vccnz LOOP\n"\
|
||||
"V_ADD_CO_U32 v6, v6, v5\n"\
|
||||
"flat_store_dword v[2:3], v6\n"\
|
||||
"s_waitcnt vmcnt(0) & lgkmcnt(0)\n"\
|
||||
"s_endpgm\n"
|
||||
|
||||
const char *watch_read_isa =
|
||||
WATCH_START
|
||||
"flat_load_dword v7, v[0:1]"
|
||||
WATCH_END;
|
||||
|
||||
const char *watch_write_isa =
|
||||
WATCH_START
|
||||
"flat_store_dword v[0:1], v4"
|
||||
WATCH_END;
|
||||
|
||||
@@ -66,4 +66,9 @@ extern const char *GwsAtomicIncreaseIsa;
|
||||
extern const char *jump_to_trap_gfx;
|
||||
extern const char *trap_handler_gfx;
|
||||
|
||||
/* HitWatchPointEvent */
|
||||
extern const char *watch_read_isa;
|
||||
extern const char *watch_write_isa;
|
||||
extern const char *watch_atomic_isa;
|
||||
|
||||
#endif // _SHADERSTORE_H_
|
||||
|
||||
Reference in New Issue
Block a user