diff --git a/include/hsakmt.h b/include/hsakmt.h index cc96e492b6..237f80bbc7 100644 --- a/include/hsakmt.h +++ b/include/hsakmt.h @@ -990,6 +990,7 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtSetAddressWatch( HSAuint32 NodeId, //IN + HSAuint32 Pid, //IN HSA_DBG_WATCH_MODE WatchMode, //IN void* WatchAddress, //IN HSAuint64 WatchAddrMask, //IN @@ -1013,6 +1014,7 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtClearAddressWatch( HSAuint32 NodeId, //IN + HSAuint32 Pid, //IN HSAuint32 WatchId //IN ); diff --git a/include/hsakmttypes.h b/include/hsakmttypes.h index 3aeba807ea..9abf4963c5 100644 --- a/include/hsakmttypes.h +++ b/include/hsakmttypes.h @@ -223,10 +223,10 @@ typedef union HSAuint64 Value; struct { - HSAuint64 WatchAddrMaskLoBit: 6; // Only bits + HSAuint64 WatchAddrMaskLoBit: 4; // Only bits // WatchAddrMaskLoBit..WatchAddrMaskHiBit // of the - HSAuint64 WatchAddrMaskHiBit: 4; // watch address mask are used. + HSAuint64 WatchAddrMaskHiBit: 6; // watch address mask are used. // 0 is the least significant bit. HSAuint64 TrapDataCount: 4; // Number of 32 bit TrapData // registers supported. diff --git a/include/linux/kfd_ioctl.h b/include/linux/kfd_ioctl.h index aa4292e629..6a7dd1f44a 100644 --- a/include/linux/kfd_ioctl.h +++ b/include/linux/kfd_ioctl.h @@ -28,8 +28,25 @@ #define KFD_IOCTL_MAJOR_VERSION 1 #define KFD_IOCTL_MINOR_VERSION 2 -#define KFD_IOCTL_DBG_MAJOR_VERSION 1 -#define KFD_IOCTL_DBG_MINOR_VERSION 0 + +/* + * Debug revision change log + * + * 0.1 - Initial revision + * 0.2 - Fix to include querying pending event that is both trap and vmfault + * 1.0 - Removed function to set debug data (renumbering functions broke ABI) + * 1.1 - Allow attaching to processes that have not opened /dev/kfd yet + * 1.2 - Allow flag option to clear queue status on queue suspend + * 1.3 - Fix race condition between clear on suspend and trap event handling + * 1.3 - Fix race condition between clear on suspend and trap event handling + * 1.4 - Fix bad kfifo free + * 1.5 - Fix ABA issue between queue snapshot and suspend + * 2.0 - Return number of queues suspended/resumed and mask invalid/error + * array slots + * 2.1 - Add Set Address Watch, and Clear Address Watch support. + */ +#define KFD_IOCTL_DBG_MAJOR_VERSION 2 +#define KFD_IOCTL_DBG_MINOR_VERSION 1 struct kfd_ioctl_get_version_args { __u32 major_version; /* from KFD */ @@ -257,6 +274,7 @@ struct kfd_ioctl_dbg_wave_control_args { * data2: flags (IN) * data3: suspend[2:2], event type [1:0] (OUT) */ + #define KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT 5 /* KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT: @@ -268,13 +286,28 @@ struct kfd_ioctl_dbg_wave_control_args { #define KFD_IOC_DBG_TRAP_GET_QUEUE_SNAPSHOT 6 /* KFD_IOC_DBG_TRAP_GET_VERSION: - * prt: unsused + * ptr: unsused * data1: major version (OUT) * data2: minor version (OUT) * data3: unused */ #define KFD_IOC_DBG_TRAP_GET_VERSION 7 +/* KFD_IOC_DBG_TRAP_CLEAR_ADDRESS_WATCH: + * ptr: unused + * data1: watch ID + * data2: unused + * data3: unused + */ +#define KFD_IOC_DBG_TRAP_CLEAR_ADDRESS_WATCH 8 + +/* KFD_IOC_DBG_TRAP_SET_ADDRESS_WATCH: + * ptr: Watch address + * data1: Watch ID (OUT) + * data2: watch_mode: 0=read, 1=nonread, 2=atomic, 3=all + * data3: watch address mask + */ +#define KFD_IOC_DBG_TRAP_SET_ADDRESS_WATCH 9 struct kfd_ioctl_dbg_trap_args { __u64 ptr; /* to KFD -- used for pointer arguments: queue arrays */ diff --git a/src/debug.c b/src/debug.c index f7d9cbd22d..caddc79a8e 100644 --- a/src/debug.c +++ b/src/debug.c @@ -30,6 +30,8 @@ #include static bool *is_device_debugged; + + int debug_get_reg_status(uint32_t node_id, bool *is_debugged); HSAKMT_STATUS init_device_debugging_memory(unsigned int NumNodes) @@ -669,3 +671,63 @@ hsaKmtGetQueueSnapshot( return 0; } + +HSAKMT_STATUS HSAKMTAPI hsaKmtSetAddressWatch( + HSAuint32 NodeId, + HSAuint32 Pid, + HSA_DBG_WATCH_MODE WatchMode, + void *WatchAddress, + HSAuint64 WatchAddrMask, + HSAuint32 *WatchId + ) +{ + + HSAKMT_STATUS result; + HSAuint32 TruncatedWatchAddressMask; + struct kfd_ioctl_dbg_trap_args argout = {0}; + + /* Right now we only support 32 bit watch address masks, so we need + * to check that we aren't losing data when we truncate the mask + * to be passed to the kernel. + */ + if (WatchAddrMask > (HSAuint64) UINT_MAX) + { + return HSAKMT_STATUS_INVALID_PARAMETER; + } + TruncatedWatchAddressMask = (HSAuint32) WatchAddrMask; + + if (WatchId == NULL) + return HSAKMT_STATUS_INVALID_PARAMETER; + + result = debug_trap(NodeId, + KFD_IOC_DBG_TRAP_SET_ADDRESS_WATCH, // op + *WatchId, + WatchMode, + TruncatedWatchAddressMask, + Pid, + (HSAuint64) WatchAddress, + &argout); + *WatchId = argout.data1; + + return result; +} + +HSAKMT_STATUS HSAKMTAPI hsaKmtClearAddressWatch( + HSAuint32 NodeId, + HSAuint32 Pid, + HSAuint32 WatchId + ) +{ + + HSAKMT_STATUS result; + + result = debug_trap(NodeId, + KFD_IOC_DBG_TRAP_CLEAR_ADDRESS_WATCH, // op + WatchId, + 0, + 0, + Pid, + 0, + NULL); + return result; +} diff --git a/src/libhsakmt.ver b/src/libhsakmt.ver index fc9564f3ec..d47f68d2d0 100644 --- a/src/libhsakmt.ver +++ b/src/libhsakmt.ver @@ -69,6 +69,8 @@ hsaKmtQueueResume; hsaKmtAllocQueueGWS; hsaKmtGetKernelDebugTrapVersionInfo; hsaKmtGetThunkDebugTrapVersionInfo; +hsaKmtSetAddressWatch; +hsaKmtClearAddressWatch; local: *; };