2022-05-09 23:52:12 +08:00
/*
2023-01-02 17:56:45 +08:00
* Copyright ( C ) 2022 - 2023 Intel Corporation
2022-05-09 23:52:12 +08:00
*
* SPDX - License - Identifier : MIT
*
*/
# include "level_zero/tools/source/debug/linux/prelim/debug_session.h"
2022-08-05 20:46:52 +08:00
# include "shared/source/built_ins/sip.h"
2022-05-09 23:52:12 +08:00
# include "shared/source/debug_settings/debug_settings_manager.h"
2022-07-24 12:21:16 +08:00
# include "shared/source/gmm_helper/gmm_helper.h"
2023-01-02 17:56:45 +08:00
# include "shared/source/helpers/aligned_memory.h"
2022-05-09 23:52:12 +08:00
# include "shared/source/helpers/array_count.h"
# include "shared/source/helpers/string.h"
# include "shared/source/memory_manager/memory_manager.h"
# include "shared/source/os_interface/linux/drm_debug.h"
# include "shared/source/os_interface/linux/ioctl_helper.h"
# include "shared/source/os_interface/os_interface.h"
# include "shared/source/os_interface/os_thread.h"
# include "level_zero/core/source/device/device.h"
# include "level_zero/core/source/device/device_imp.h"
2023-02-02 11:54:41 +08:00
# include "level_zero/core/source/gfx_core_helpers/l0_gfx_core_helper.h"
2022-05-09 23:52:12 +08:00
# include "level_zero/include/zet_intel_gpu_debug.h"
# include "level_zero/tools/source/debug/linux/prelim/drm_helper.h"
# include <level_zero/ze_api.h>
# include "common/StateSaveAreaHeader.h"
# include <algorithm>
# include <fcntl.h>
namespace L0 {
2022-11-14 23:52:05 +08:00
DebugSession * createDebugSessionHelper ( const zet_debug_config_t & config , Device * device , int debugFd , void * params ) ;
2022-05-09 23:52:12 +08:00
2022-11-14 23:52:05 +08:00
DebugSessionLinux : : DebugSessionLinux ( const zet_debug_config_t & config , Device * device , int debugFd , void * params ) : DebugSessionImp ( config , device ) , fd ( debugFd ) {
2022-05-09 23:52:12 +08:00
ioctlHandler . reset ( new IoctlHandler ) ;
2022-11-14 23:52:05 +08:00
if ( params ) {
this - > i915DebuggerVersion = reinterpret_cast < prelim_drm_i915_debugger_open_param * > ( params ) - > version ;
}
if ( this - > i915DebuggerVersion > = 3 ) {
this - > blockOnFenceMode = true ;
}
2022-05-09 23:52:12 +08:00
for ( size_t i = 0 ; i < arrayCount ( euControlInterruptSeqno ) ; i + + ) {
euControlInterruptSeqno [ i ] = invalidHandle ;
}
} ;
DebugSessionLinux : : ~ DebugSessionLinux ( ) {
closeAsyncThread ( ) ;
2022-06-02 17:09:31 +08:00
closeInternalEventsThread ( ) ;
2022-07-29 19:26:12 +08:00
for ( auto & session : tileSessions ) {
delete session . first ;
}
tileSessions . resize ( 0 ) ;
2022-08-24 20:03:47 +08:00
closeFd ( ) ;
2022-05-09 23:52:12 +08:00
}
2022-09-23 22:56:32 +08:00
DebugSession * DebugSession : : create ( const zet_debug_config_t & config , Device * device , ze_result_t & result , bool isRootAttach ) {
2022-05-09 23:52:12 +08:00
if ( device - > getOsInterface ( ) . isDebugAttachAvailable ( ) ) {
struct prelim_drm_i915_debugger_open_param open = { } ;
open . pid = config . pid ;
open . events = 0 ;
2022-11-14 23:52:05 +08:00
open . version = 0 ;
2022-05-09 23:52:12 +08:00
2022-05-26 01:05:52 +08:00
auto debugFd = DrmHelper : : ioctl ( device , NEO : : DrmIoctl : : DebuggerOpen , & open ) ;
2022-05-09 23:52:12 +08:00
if ( debugFd > = 0 ) {
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_DRM_IOCTL_I915_DEBUGGER_OPEN: open.pid: %d, open.events: %d, debugFd: %d \n " ,
open . pid , open . events , debugFd ) ;
2022-11-14 23:52:05 +08:00
auto debugSession = createDebugSessionHelper ( config , device , debugFd , & open ) ;
2022-09-23 22:56:32 +08:00
debugSession - > setAttachMode ( isRootAttach ) ;
2022-05-09 23:52:12 +08:00
result = debugSession - > initialize ( ) ;
if ( result ! = ZE_RESULT_SUCCESS ) {
debugSession - > closeConnection ( ) ;
delete debugSession ;
debugSession = nullptr ;
} else {
debugSession - > startAsyncThread ( ) ;
}
return debugSession ;
} else {
auto reason = DrmHelper : : getErrno ( device ) ;
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_DRM_IOCTL_I915_DEBUGGER_OPEN failed: open.pid: %d, open.events: %d, retCode: %d, errno: %d \n " ,
open . pid , open . events , debugFd , reason ) ;
result = DebugSessionLinux : : translateDebuggerOpenErrno ( reason ) ;
}
} else {
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE ;
}
return nullptr ;
}
ze_result_t DebugSessionLinux : : translateDebuggerOpenErrno ( int error ) {
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN ;
switch ( error ) {
case ENODEV :
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE ;
break ;
case EBUSY :
result = ZE_RESULT_ERROR_NOT_AVAILABLE ;
break ;
case EACCES :
result = ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS ;
break ;
}
return result ;
}
int DebugSessionLinux : : ioctl ( unsigned long request , void * arg ) {
return ioctlHandler - > ioctl ( fd , request , arg ) ;
}
ze_result_t DebugSessionLinux : : readGpuMemory ( uint64_t vmHandle , char * output , size_t size , uint64_t gpuVa ) {
prelim_drm_i915_debug_vm_open vmOpen = {
. client_handle = static_cast < decltype ( prelim_drm_i915_debug_vm_open : : client_handle ) > ( clientHandle ) ,
. handle = static_cast < decltype ( prelim_drm_i915_debug_vm_open : : handle ) > ( vmHandle ) ,
. flags = PRELIM_I915_DEBUG_VM_OPEN_READ_ONLY } ;
int vmDebugFd = ioctl ( PRELIM_I915_DEBUG_IOCTL_VM_OPEN , & vmOpen ) ;
if ( vmDebugFd < 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_I915_DEBUG_IOCTL_VM_OPEN failed = %d \n " , vmDebugFd ) ;
return ZE_RESULT_ERROR_UNKNOWN ;
}
int64_t retVal = 0 ;
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
gpuVa = gmmHelper - > decanonize ( gpuVa ) ;
if ( NEO : : DebugManager . flags . EnableDebuggerMmapMemoryAccess . get ( ) ) {
uint64_t alignedMem = alignDown ( gpuVa , MemoryConstants : : pageSize ) ;
uint64_t alignedDiff = gpuVa - alignedMem ;
uint64_t alignedSize = size + alignedDiff ;
void * mappedPtr = ioctlHandler - > mmap ( NULL , alignedSize , PROT_READ , MAP_SHARED , vmDebugFd , alignedMem ) ;
if ( mappedPtr = = MAP_FAILED ) {
PRINT_DEBUGGER_ERROR_LOG ( " Reading memory failed, errno = %d \n " , errno ) ;
retVal = - 1 ;
} else {
char * realSourceVA = static_cast < char * > ( mappedPtr ) + alignedDiff ;
retVal = memcpy_s ( output , size , static_cast < void * > ( realSourceVA ) , size ) ;
ioctlHandler - > munmap ( mappedPtr , alignedSize ) ;
}
} else {
size_t pendingSize = size ;
uint8_t retry = 0 ;
const uint8_t maxRetries = 3 ;
size_t retrySize = size ;
do {
PRINT_DEBUGGER_MEM_ACCESS_LOG ( " Reading (pread) memory from gpu va = %# " PRIx64 " , size = %zu \n " , gpuVa , pendingSize ) ;
retVal = ioctlHandler - > pread ( vmDebugFd , output , pendingSize , gpuVa ) ;
output + = retVal ;
gpuVa + = retVal ;
pendingSize - = retVal ;
if ( retVal = = 0 ) {
if ( pendingSize < retrySize ) {
retry = 0 ;
}
retry + + ;
retrySize = pendingSize ;
}
} while ( ( ( retVal = = 0 ) & & ( retry < maxRetries ) ) | | ( ( retVal > 0 ) & & ( pendingSize > 0 ) ) ) ;
if ( retVal < 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " Reading memory failed, errno = %d \n " , errno ) ;
}
retVal = pendingSize ;
}
NEO : : SysCalls : : close ( vmDebugFd ) ;
return ( retVal = = 0 ) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN ;
}
ze_result_t DebugSessionLinux : : writeGpuMemory ( uint64_t vmHandle , const char * input , size_t size , uint64_t gpuVa ) {
prelim_drm_i915_debug_vm_open vmOpen = {
. client_handle = static_cast < decltype ( prelim_drm_i915_debug_vm_open : : client_handle ) > ( clientHandle ) ,
. handle = static_cast < decltype ( prelim_drm_i915_debug_vm_open : : handle ) > ( vmHandle ) ,
. flags = PRELIM_I915_DEBUG_VM_OPEN_READ_WRITE } ;
int vmDebugFd = ioctl ( PRELIM_I915_DEBUG_IOCTL_VM_OPEN , & vmOpen ) ;
if ( vmDebugFd < 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_I915_DEBUG_IOCTL_VM_OPEN failed = %d \n " , vmDebugFd ) ;
return ZE_RESULT_ERROR_UNKNOWN ;
}
int64_t retVal = 0 ;
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
gpuVa = gmmHelper - > decanonize ( gpuVa ) ;
if ( NEO : : DebugManager . flags . EnableDebuggerMmapMemoryAccess . get ( ) ) {
uint64_t alignedMem = alignDown ( gpuVa , MemoryConstants : : pageSize ) ;
uint64_t alignedDiff = gpuVa - alignedMem ;
uint64_t alignedSize = size + alignedDiff ;
void * mappedPtr = ioctlHandler - > mmap ( NULL , alignedSize , PROT_WRITE , MAP_SHARED , vmDebugFd , alignedMem ) ;
if ( mappedPtr = = MAP_FAILED ) {
PRINT_DEBUGGER_ERROR_LOG ( " Writing memory failed, errno = %d \n " , errno ) ;
retVal = - 1 ;
} else {
char * realDestVA = static_cast < char * > ( mappedPtr ) + alignedDiff ;
retVal = memcpy_s ( static_cast < void * > ( realDestVA ) , size , input , size ) ;
ioctlHandler - > munmap ( mappedPtr , alignedSize ) ;
}
} else {
size_t pendingSize = size ;
uint8_t retry = 0 ;
const uint8_t maxRetries = 3 ;
size_t retrySize = size ;
do {
PRINT_DEBUGGER_MEM_ACCESS_LOG ( " Writing (pwrite) memory to gpu va = %# " PRIx64 " , size = %zu \n " , gpuVa , pendingSize ) ;
retVal = ioctlHandler - > pwrite ( vmDebugFd , input , pendingSize , gpuVa ) ;
input + = retVal ;
gpuVa + = retVal ;
pendingSize - = retVal ;
if ( retVal = = 0 ) {
if ( pendingSize < retrySize ) {
retry = 0 ;
}
retry + + ;
retrySize = pendingSize ;
}
} while ( ( ( retVal = = 0 ) & & ( retry < maxRetries ) ) | | ( ( retVal > 0 ) & & ( pendingSize > 0 ) ) ) ;
if ( retVal < 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " Writing memory failed, errno = %d \n " , errno ) ;
}
retVal = pendingSize ;
}
NEO : : SysCalls : : close ( vmDebugFd ) ;
return ( retVal = = 0 ) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN ;
}
ze_result_t DebugSessionLinux : : initialize ( ) {
struct pollfd pollFd = {
. fd = this - > fd ,
. events = POLLIN ,
. revents = 0 ,
} ;
auto numberOfFds = ioctlHandler - > poll ( & pollFd , 1 , 1000 ) ;
PRINT_DEBUGGER_INFO_LOG ( " initialization poll() retCode: %d \n " , numberOfFds ) ;
if ( numberOfFds < = 0 ) {
return ZE_RESULT_NOT_READY ;
}
2022-09-23 22:56:32 +08:00
bool isRootDevice = ! connectedDevice - > getNEODevice ( ) - > isSubDevice ( ) ;
if ( isRootDevice & & ! tileAttachEnabled ) {
createEuThreads ( ) ;
}
2022-08-17 02:21:08 +08:00
createTileSessionsIfEnabled ( ) ;
2022-06-02 17:09:31 +08:00
startInternalEventsThread ( ) ;
2022-05-09 23:52:12 +08:00
bool allEventsCollected = false ;
2022-10-18 19:49:16 +08:00
bool eventAvailable = true ;
float timeDelta = 0 ;
float timeStart = clock ( ) ;
2022-05-09 23:52:12 +08:00
do {
2022-10-18 19:49:16 +08:00
if ( internalThreadHasStarted ) {
auto eventMemory = getInternalEvent ( ) ;
auto debugEvent = reinterpret_cast < prelim_drm_i915_debug_event * > ( eventMemory . get ( ) ) ;
if ( eventMemory ! = nullptr ) {
handleEvent ( debugEvent ) ;
if ( debugEvent - > type ! = PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND & & pendingVmBindEvents . size ( ) > 0 ) {
processPendingVmBindEvents ( ) ;
}
eventAvailable = true ;
} else {
eventAvailable = false ;
2022-09-30 00:07:22 +08:00
}
2022-10-18 19:49:16 +08:00
allEventsCollected = checkAllEventsCollected ( ) ;
2022-06-02 17:09:31 +08:00
} else {
2022-10-18 19:49:16 +08:00
timeDelta = float ( clock ( ) - timeStart ) / CLOCKS_PER_SEC ;
2022-06-02 17:09:31 +08:00
}
2023-01-17 01:47:59 +08:00
} while ( ( eventAvailable & & ! allEventsCollected ) & & timeDelta < getThreadStartLimitTime ( ) ) ;
2022-05-09 23:52:12 +08:00
2022-10-18 19:49:16 +08:00
internalThreadHasStarted = false ;
2022-05-09 23:52:12 +08:00
if ( clientHandleClosed = = clientHandle & & clientHandle ! = invalidClientHandle ) {
return ZE_RESULT_ERROR_DEVICE_LOST ;
}
if ( allEventsCollected ) {
if ( ! readModuleDebugArea ( ) ) {
return ZE_RESULT_ERROR_UNKNOWN ;
}
return ZE_RESULT_SUCCESS ;
}
return ZE_RESULT_NOT_READY ;
}
2022-08-17 02:21:08 +08:00
void DebugSessionLinux : : createTileSessionsIfEnabled ( ) {
auto numTiles = connectedDevice - > getNEODevice ( ) - > getNumSubDevices ( ) ;
if ( numTiles > 0 & & tileAttachEnabled ) {
tileSessions . resize ( numTiles ) ;
for ( uint32_t i = 0 ; i < numTiles ; i + + ) {
auto subDevice = connectedDevice - > getNEODevice ( ) - > getSubDevice ( i ) - > getSpecializedDevice < Device > ( ) ;
2022-08-19 23:11:22 +08:00
tileSessions [ i ] = std : : pair < DebugSessionImp * , bool > { createTileSession ( config , subDevice , this ) , false } ;
2022-08-17 02:21:08 +08:00
}
tileSessionsEnabled = true ;
}
}
TileDebugSessionLinux * DebugSessionLinux : : createTileSession ( const zet_debug_config_t & config , Device * device , DebugSessionImp * rootDebugSession ) {
2022-09-23 22:56:32 +08:00
auto tileSession = new TileDebugSessionLinux ( config , device , rootDebugSession ) ;
tileSession - > initialize ( ) ;
return tileSession ;
2022-08-17 02:21:08 +08:00
}
2022-05-30 22:24:47 +08:00
void * DebugSessionLinux : : asyncThreadFunction ( void * arg ) {
2022-05-09 23:52:12 +08:00
DebugSessionLinux * self = reinterpret_cast < DebugSessionLinux * > ( arg ) ;
PRINT_DEBUGGER_INFO_LOG ( " Debugger async thread start \n " , " " ) ;
2022-05-30 22:24:47 +08:00
while ( self - > asyncThread . threadActive ) {
2022-06-02 17:09:31 +08:00
self - > handleEventsAsync ( ) ;
2022-05-09 23:52:12 +08:00
2022-08-19 23:11:22 +08:00
if ( self - > tileSessionsEnabled ) {
for ( size_t tileIndex = 0 ; tileIndex < self - > tileSessions . size ( ) ; tileIndex + + ) {
static_cast < TileDebugSessionLinux * > ( self - > tileSessions [ tileIndex ] . first ) - > sendInterrupts ( ) ;
static_cast < TileDebugSessionLinux * > ( self - > tileSessions [ tileIndex ] . first ) - > generateEventsAndResumeStoppedThreads ( ) ;
}
} else {
self - > sendInterrupts ( ) ;
self - > generateEventsAndResumeStoppedThreads ( ) ;
}
2022-05-09 23:52:12 +08:00
}
PRINT_DEBUGGER_INFO_LOG ( " Debugger async thread closing \n " , " " ) ;
return nullptr ;
}
2022-06-02 17:09:31 +08:00
void * DebugSessionLinux : : readInternalEventsThreadFunction ( void * arg ) {
DebugSessionLinux * self = reinterpret_cast < DebugSessionLinux * > ( arg ) ;
PRINT_DEBUGGER_INFO_LOG ( " Debugger internal event thread started \n " , " " ) ;
2022-10-18 19:49:16 +08:00
self - > internalThreadHasStarted = true ;
2022-06-02 17:09:31 +08:00
while ( self - > internalEventThread . threadActive ) {
self - > readInternalEventsAsync ( ) ;
}
PRINT_DEBUGGER_INFO_LOG ( " Debugger internal event thread closing \n " , " " ) ;
return nullptr ;
}
2022-05-09 23:52:12 +08:00
void DebugSessionLinux : : startAsyncThread ( ) {
2022-05-30 22:24:47 +08:00
asyncThread . thread = NEO : : Thread : : create ( asyncThreadFunction , reinterpret_cast < void * > ( this ) ) ;
2022-05-09 23:52:12 +08:00
}
void DebugSessionLinux : : closeAsyncThread ( ) {
2022-05-30 22:24:47 +08:00
asyncThread . close ( ) ;
2022-06-02 17:09:31 +08:00
internalEventThread . close ( ) ;
}
2022-08-24 20:03:47 +08:00
bool DebugSessionLinux : : closeFd ( ) {
if ( fd = = 0 ) {
return false ;
}
2023-01-19 04:22:32 +08:00
auto ret = NEO : : SysCalls : : close ( fd ) ;
2022-08-24 20:03:47 +08:00
2023-01-19 04:22:32 +08:00
if ( ret ! = 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " Debug connection close() on fd: %d failed: retCode: %d \n " , fd , ret ) ;
2022-08-24 20:03:47 +08:00
return false ;
}
fd = 0 ;
return true ;
}
2022-06-02 17:09:31 +08:00
std : : unique_ptr < uint64_t [ ] > DebugSessionLinux : : getInternalEvent ( ) {
std : : unique_ptr < uint64_t [ ] > eventMemory ;
{
std : : unique_lock < std : : mutex > lock ( internalEventThreadMutex ) ;
if ( internalEventQueue . empty ( ) ) {
2023-01-17 01:47:59 +08:00
internalEventCondition . wait_for ( lock , std : : chrono : : milliseconds ( 100 ) ) ;
2022-06-02 17:09:31 +08:00
}
if ( ! internalEventQueue . empty ( ) ) {
eventMemory = std : : move ( internalEventQueue . front ( ) ) ;
internalEventQueue . pop ( ) ;
}
}
return eventMemory ;
}
void DebugSessionLinux : : handleEventsAsync ( ) {
auto eventMemory = getInternalEvent ( ) ;
if ( eventMemory ! = nullptr ) {
2022-09-30 00:07:22 +08:00
auto debugEvent = reinterpret_cast < prelim_drm_i915_debug_event * > ( eventMemory . get ( ) ) ;
handleEvent ( debugEvent ) ;
if ( debugEvent - > type ! = PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND & & pendingVmBindEvents . size ( ) > 0 ) {
processPendingVmBindEvents ( ) ;
}
2022-06-02 17:09:31 +08:00
}
2022-05-09 23:52:12 +08:00
}
2022-06-02 17:09:31 +08:00
void DebugSessionLinux : : readInternalEventsAsync ( ) {
2022-05-09 23:52:12 +08:00
struct pollfd pollFd = {
. fd = fd ,
. events = POLLIN ,
. revents = 0 ,
} ;
int pollTimeout = 1000 ;
auto numberOfFds = ioctlHandler - > poll ( & pollFd , 1 , pollTimeout ) ;
PRINT_DEBUGGER_INFO_LOG ( " Debugger async thread readEvent poll() retCode: %d \n " , numberOfFds ) ;
2022-06-02 17:09:31 +08:00
if ( ! detached & & numberOfFds < 0 & & errno = = EINVAL ) {
2022-05-09 23:52:12 +08:00
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_DETACHED ;
debugEvent . info . detached . reason = ZET_DEBUG_DETACH_REASON_INVALID ;
PRINT_DEBUGGER_INFO_LOG ( " Debugger detached \n " , " " ) ;
2022-08-17 02:21:08 +08:00
if ( tileSessionsEnabled ) {
auto numTiles = connectedDevice - > getNEODevice ( ) - > getNumSubDevices ( ) ;
for ( uint32_t tileIndex = 0 ; tileIndex < numTiles ; tileIndex + + ) {
2022-11-14 23:52:05 +08:00
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > pushApiEvent ( debugEvent ) ;
2022-08-19 23:11:22 +08:00
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > detached = true ;
2022-08-17 02:21:08 +08:00
}
} else {
2022-11-14 23:52:05 +08:00
pushApiEvent ( debugEvent ) ;
2022-08-17 02:21:08 +08:00
}
2022-05-09 23:52:12 +08:00
detached = true ;
} else if ( numberOfFds > 0 ) {
ze_result_t result = ZE_RESULT_SUCCESS ;
int maxLoopCount = 3 ;
do {
2022-06-02 17:09:31 +08:00
uint8_t maxEventBuffer [ sizeof ( prelim_drm_i915_debug_event ) + maxEventSize ] ;
auto event = reinterpret_cast < prelim_drm_i915_debug_event * > ( maxEventBuffer ) ;
event - > size = maxEventSize ;
2022-05-09 23:52:12 +08:00
event - > type = PRELIM_DRM_I915_DEBUG_EVENT_READ ;
event - > flags = 0 ;
result = readEventImp ( event ) ;
maxLoopCount - - ;
2022-06-02 17:09:31 +08:00
if ( result = = ZE_RESULT_SUCCESS ) {
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( internalEventThreadMutex ) ;
2022-06-02 17:09:31 +08:00
auto memory = std : : make_unique < uint64_t [ ] > ( maxEventSize / sizeof ( uint64_t ) ) ;
memcpy ( memory . get ( ) , event , maxEventSize ) ;
internalEventQueue . push ( std : : move ( memory ) ) ;
internalEventCondition . notify_one ( ) ;
}
2022-05-09 23:52:12 +08:00
} while ( result = = ZE_RESULT_SUCCESS & & maxLoopCount > 0 ) ;
}
}
bool DebugSessionLinux : : closeConnection ( ) {
closeAsyncThread ( ) ;
2022-08-24 20:03:47 +08:00
closeInternalEventsThread ( ) ;
return closeFd ( ) ;
2022-05-09 23:52:12 +08:00
}
void DebugSessionLinux : : handleEvent ( prelim_drm_i915_debug_event * event ) {
auto type = event - > type ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type = %lu flags = %d seqno = %llu size = %llu " ,
( uint32_t ) event - > type , ( int ) event - > flags , ( uint64_t ) event - > seqno , ( uint64_t ) event - > size ) ;
switch ( type ) {
case PRELIM_DRM_I915_DEBUG_EVENT_CLIENT : {
auto clientEvent = reinterpret_cast < prelim_drm_i915_debug_event_client * > ( event ) ;
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ) {
DEBUG_BREAK_IF ( clientHandleToConnection . find ( clientEvent - > handle ) ! = clientHandleToConnection . end ( ) ) ;
clientHandleToConnection [ clientEvent - > handle ] . reset ( new ClientConnection ) ;
clientHandleToConnection [ clientEvent - > handle ] - > client = * clientEvent ;
}
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ) {
clientHandleClosed = clientEvent - > handle ;
}
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_CLIENT flags = %d size = %llu client.handle = %llu \n " ,
( int ) event - > flags , ( uint64_t ) event - > size , ( uint64_t ) clientEvent - > handle ) ;
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT : {
prelim_drm_i915_debug_event_context * context = reinterpret_cast < prelim_drm_i915_debug_event_context * > ( event ) ;
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ) {
UNRECOVERABLE_IF ( clientHandleToConnection . find ( context - > client_handle ) = = clientHandleToConnection . end ( ) ) ;
clientHandleToConnection [ context - > client_handle ] - > contextsCreated [ context - > handle ] . handle = context - > handle ;
}
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ) {
clientHandleToConnection [ context - > client_handle ] - > contextsCreated . erase ( context - > handle ) ;
}
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT flags = %d size = %llu client_handle = %llu handle = %llu \n " ,
( int ) event - > flags , ( uint64_t ) event - > size , ( uint64_t ) context - > client_handle , ( uint64_t ) context - > handle ) ;
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_UUID : {
prelim_drm_i915_debug_event_uuid * uuid = reinterpret_cast < prelim_drm_i915_debug_event_uuid * > ( event ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_UUID flags = %d size = %llu client_handle = %llu handle = %llu class_handle = %llu payload_size = %llu \n " ,
( int ) event - > flags , ( uint64_t ) event - > size , ( uint64_t ) uuid - > client_handle , ( uint64_t ) uuid - > handle , ( uint64_t ) uuid - > class_handle , ( uint64_t ) uuid - > payload_size ) ;
bool destroy = event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ;
bool create = event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ;
if ( destroy & & clientHandleToConnection [ uuid - > client_handle ] - > uuidMap [ uuid - > handle ] . classIndex = = NEO : : DrmResourceClass : : L0ZebinModule ) {
2022-08-08 20:15:29 +08:00
DEBUG_BREAK_IF ( clientHandleToConnection [ uuid - > client_handle ] - > uuidToModule [ uuid - > handle ] . segmentVmBindCounter [ 0 ] ! = 0 | |
clientHandleToConnection [ uuid - > client_handle ] - > uuidToModule [ uuid - > handle ] . loadAddresses [ 0 ] . size ( ) > 0 ) ;
2022-05-09 23:52:12 +08:00
clientHandleToConnection [ uuid - > client_handle ] - > uuidToModule . erase ( uuid - > handle ) ;
}
2022-07-22 20:07:36 +08:00
if ( destroy & & ( clientHandle = = uuid - > client_handle ) ) {
for ( const auto & uuidToDevice : uuidL0CommandQueueHandleToDevice ) {
if ( uuidToDevice . first = = uuid - > handle ) {
2022-08-17 02:21:08 +08:00
auto deviceIndex = uuidToDevice . second ;
2022-07-22 20:07:36 +08:00
uuidL0CommandQueueHandleToDevice . erase ( uuidToDevice . first ) ;
2022-08-17 02:21:08 +08:00
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT ;
if ( tileSessionsEnabled ) {
2022-11-14 23:52:05 +08:00
auto tileSession = reinterpret_cast < TileDebugSessionLinux * > ( tileSessions [ deviceIndex ] . first ) ;
tileSession - > processExit ( ) ;
tileSession - > pushApiEvent ( debugEvent ) ;
2022-08-17 02:21:08 +08:00
} else if ( uuidL0CommandQueueHandleToDevice . size ( ) = = 0 ) {
2022-11-14 23:52:05 +08:00
pushApiEvent ( debugEvent ) ;
2022-07-22 20:07:36 +08:00
}
2022-08-17 02:21:08 +08:00
2022-07-22 20:07:36 +08:00
break ;
}
}
2022-05-09 23:52:12 +08:00
break ;
}
if ( create ) {
const auto & connection = clientHandleToConnection [ uuid - > client_handle ] ;
if ( uuid - > payload_size ) {
prelim_drm_i915_debug_read_uuid readUuid = { } ;
auto payload = std : : make_unique < char [ ] > ( uuid - > payload_size ) ;
readUuid . client_handle = uuid - > client_handle ;
readUuid . handle = static_cast < decltype ( readUuid . handle ) > ( uuid - > handle ) ;
readUuid . payload_ptr = reinterpret_cast < uint64_t > ( payload . get ( ) ) ;
readUuid . payload_size = uuid - > payload_size ;
2023-01-19 04:22:32 +08:00
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_READ_UUID , & readUuid ) ;
2022-05-09 23:52:12 +08:00
2023-01-19 04:22:32 +08:00
if ( ret = = 0 ) {
2022-05-09 23:52:12 +08:00
std : : string uuidString = std : : string ( readUuid . uuid , 36 ) ;
uint32_t classIndex = static_cast < uint32_t > ( NEO : : DrmResourceClass : : MaxSize ) ;
auto validClassUuid = NEO : : DrmUuid : : getClassUuidIndex ( uuidString , classIndex ) ;
if ( uuidString = = NEO : : uuidL0CommandQueueHash ) {
if ( ( clientHandle = = invalidClientHandle ) | | ( clientHandle = = uuid - > client_handle ) ) {
clientHandle = uuid - > client_handle ;
2022-07-22 20:07:36 +08:00
uint32_t deviceIndex = 0 ;
if ( readUuid . payload_size = = sizeof ( NEO : : DebuggerL0 : : CommandQueueNotification ) ) {
auto notification = reinterpret_cast < NEO : : DebuggerL0 : : CommandQueueNotification * > ( payload . get ( ) ) ;
deviceIndex = notification - > subDeviceIndex ;
UNRECOVERABLE_IF ( notification - > subDeviceCount > 0 & & notification - > subDeviceIndex > = notification - > subDeviceCount ) ;
}
2022-08-17 02:21:08 +08:00
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY ;
if ( tileSessionsEnabled ) {
UNRECOVERABLE_IF ( uuidL0CommandQueueHandleToDevice . find ( uuid - > handle ) ! = uuidL0CommandQueueHandleToDevice . end ( ) ) ;
2022-11-14 23:52:05 +08:00
auto tileSession = static_cast < TileDebugSessionLinux * > ( tileSessions [ deviceIndex ] . first ) ;
tileSession - > processEntry ( ) ;
tileSession - > pushApiEvent ( debugEvent ) ;
2022-08-17 02:21:08 +08:00
} else if ( uuidL0CommandQueueHandleToDevice . size ( ) = = 0 ) {
2022-11-14 23:52:05 +08:00
pushApiEvent ( debugEvent ) ;
2022-07-22 20:07:36 +08:00
}
uuidL0CommandQueueHandleToDevice [ uuid - > handle ] = deviceIndex ;
2022-05-09 23:52:12 +08:00
}
}
if ( validClassUuid ) {
if ( clientHandle = = invalidClientHandle ) {
clientHandle = uuid - > client_handle ;
}
std : : string className ( reinterpret_cast < char * > ( readUuid . payload_ptr ) , readUuid . payload_size ) ;
connection - > classHandleToIndex [ uuid - > handle ] = { className , classIndex } ;
} else {
auto & uuidData = connection - > uuidMap [ uuid - > handle ] ;
uuidData . classHandle = uuid - > class_handle ;
uuidData . handle = uuid - > handle ;
uuidData . data = std : : move ( payload ) ;
uuidData . dataSize = uuid - > payload_size ;
uuidData . classIndex = NEO : : DrmResourceClass : : MaxSize ;
const auto indexIt = connection - > classHandleToIndex . find ( uuid - > class_handle ) ;
if ( indexIt ! = connection - > classHandleToIndex . end ( ) ) {
uuidData . classIndex = static_cast < NEO : : DrmResourceClass > ( indexIt - > second . second ) ;
}
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : Elf ) {
auto cpuVa = extractVaFromUuidString ( uuidString ) ;
uuidData . ptr = cpuVa ;
}
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : L0ZebinModule ) {
uint64_t handle = uuid - > handle ;
auto & newModule = connection - > uuidToModule [ handle ] ;
newModule . segmentCount = 0 ;
2022-11-14 23:52:05 +08:00
newModule . moduleUuidHandle = handle ;
2022-08-08 20:15:29 +08:00
for ( uint32_t i = 0 ; i < NEO : : EngineLimits : : maxHandleCount ; i + + ) {
newModule . segmentVmBindCounter [ i ] = 0 ;
newModule . loadAddresses [ i ] . clear ( ) ;
2022-11-14 23:52:05 +08:00
newModule . moduleLoadEventAcked [ i ] = false ;
2022-08-08 20:15:29 +08:00
}
2022-05-09 23:52:12 +08:00
}
extractUuidData ( uuid - > client_handle , uuidData ) ;
}
2023-01-19 04:22:32 +08:00
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_UUID client_handle = %llu handle = %llu flags = %d uuid = %s ret = %d \n " ,
( uint64_t ) readUuid . client_handle , ( uint64_t ) readUuid . handle , ( int ) readUuid . flags , uuidString . c_str ( ) , ret ) ;
2022-05-09 23:52:12 +08:00
} else {
2023-01-19 04:22:32 +08:00
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_UUID ret = %d errno = %d \n " , ret , errno ) ;
2022-05-09 23:52:12 +08:00
}
} else {
connection - > uuidMap [ uuid - > handle ] . classHandle = uuid - > class_handle ;
connection - > uuidMap [ uuid - > handle ] . handle = uuid - > handle ;
}
}
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_VM : {
prelim_drm_i915_debug_event_vm * vm = reinterpret_cast < prelim_drm_i915_debug_event_vm * > ( event ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_VM flags = %d size = %llu client_handle = %llu handle = %llu \n " ,
( int ) event - > flags , ( uint64_t ) event - > size , ( uint64_t ) vm - > client_handle , ( uint64_t ) vm - > handle ) ;
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ) {
UNRECOVERABLE_IF ( clientHandleToConnection . find ( vm - > client_handle ) = = clientHandleToConnection . end ( ) ) ;
clientHandleToConnection [ vm - > client_handle ] - > vmIds . emplace ( static_cast < uint64_t > ( vm - > handle ) ) ;
}
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ) {
UNRECOVERABLE_IF ( clientHandleToConnection . find ( vm - > client_handle ) = = clientHandleToConnection . end ( ) ) ;
clientHandleToConnection [ vm - > client_handle ] - > vmIds . erase ( static_cast < uint64_t > ( vm - > handle ) ) ;
}
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND : {
prelim_drm_i915_debug_event_vm_bind * vmBind = reinterpret_cast < prelim_drm_i915_debug_event_vm_bind * > ( event ) ;
2022-09-30 00:07:22 +08:00
if ( ! handleVmBindEvent ( vmBind ) ) {
if ( event - > flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) {
prelim_drm_i915_debug_event_ack eventToAck = { } ;
eventToAck . type = vmBind - > base . type ;
eventToAck . seqno = vmBind - > base . seqno ;
eventToAck . flags = 0 ;
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_ACK_EVENT , & eventToAck ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu ret = %d errno = %d \n " , ( uint64_t ) eventToAck . seqno , ret , ret ! = 0 ? errno : 0 ) ;
} else {
auto sizeAligned = alignUp ( event - > size , sizeof ( uint64_t ) ) ;
auto pendingEvent = std : : make_unique < uint64_t [ ] > ( sizeAligned / sizeof ( uint64_t ) ) ;
memcpy_s ( pendingEvent . get ( ) , sizeAligned , event , event - > size ) ;
pendingVmBindEvents . push_back ( std : : move ( pendingEvent ) ) ;
}
}
2022-05-09 23:52:12 +08:00
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM : {
prelim_drm_i915_debug_event_context_param * contextParam = reinterpret_cast < prelim_drm_i915_debug_event_context_param * > ( event ) ;
handleContextParamEvent ( contextParam ) ;
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_EU_ATTENTION : {
prelim_drm_i915_debug_event_eu_attention * attention = reinterpret_cast < prelim_drm_i915_debug_event_eu_attention * > ( event ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_EU_ATTENTION flags = %d, seqno = %d, size = %llu "
" client_handle = %llu flags = %llu class = %lu instance = %lu bitmask_size = %lu ctx_handle = %llu \n " ,
( int ) attention - > base . flags , ( uint64_t ) attention - > base . seqno , ( uint64_t ) attention - > base . size ,
( uint64_t ) attention - > client_handle , ( uint64_t ) attention - > flags , ( uint32_t ) attention - > ci . engine_class ,
( uint32_t ) attention - > ci . engine_instance , ( uint32_t ) attention - > bitmask_size , uint64_t ( attention - > ctx_handle ) ) ;
handleAttentionEvent ( attention ) ;
} break ;
case PRELIM_DRM_I915_DEBUG_EVENT_ENGINES : {
prelim_drm_i915_debug_event_engines * engines = reinterpret_cast < prelim_drm_i915_debug_event_engines * > ( event ) ;
handleEnginesEvent ( engines ) ;
} break ;
default :
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: UNHANDLED %d flags = %d size = %llu \n " , ( int ) event - > type , ( int ) event - > flags , ( uint64_t ) event - > size ) ;
break ;
}
}
2022-09-30 00:07:22 +08:00
void DebugSessionLinux : : processPendingVmBindEvents ( ) {
size_t processedEvents = 0 ;
for ( size_t index = 0 ; index < pendingVmBindEvents . size ( ) ; index + + ) {
auto debugEvent = reinterpret_cast < prelim_drm_i915_debug_event_vm_bind * > ( pendingVmBindEvents [ index ] . get ( ) ) ;
if ( handleVmBindEvent ( debugEvent ) = = false ) {
break ;
}
processedEvents + + ;
}
if ( processedEvents > 0 ) {
pendingVmBindEvents . erase ( pendingVmBindEvents . begin ( ) , pendingVmBindEvents . begin ( ) + processedEvents ) ;
}
}
2022-05-09 23:52:12 +08:00
bool DebugSessionLinux : : checkAllEventsCollected ( ) {
bool allEventsCollected = false ;
bool clientConnected = ( this - > clientHandle ! = invalidClientHandle ) ;
if ( clientConnected ) {
if ( clientHandleToConnection [ clientHandle ] - > vmToModuleDebugAreaBindInfo . size ( ) > 0 ) {
allEventsCollected = true ;
}
}
return allEventsCollected ;
}
bool DebugSessionLinux : : readModuleDebugArea ( ) {
auto vm = clientHandleToConnection [ clientHandle ] - > vmToModuleDebugAreaBindInfo . begin ( ) - > first ;
auto gpuVa = clientHandleToConnection [ clientHandle ] - > vmToModuleDebugAreaBindInfo . begin ( ) - > second . gpuVa ;
memset ( this - > debugArea . magic , 0 , sizeof ( this - > debugArea . magic ) ) ;
auto retVal = readGpuMemory ( vm , reinterpret_cast < char * > ( & this - > debugArea ) , sizeof ( this - > debugArea ) , gpuVa ) ;
2022-06-15 05:24:58 +08:00
if ( retVal ! = ZE_RESULT_SUCCESS | | strncmp ( this - > debugArea . magic , " dbgarea " , sizeof ( NEO : : DebugAreaHeader : : magic ) ) ! = 0 ) {
2022-05-09 23:52:12 +08:00
PRINT_DEBUGGER_ERROR_LOG ( " Reading Module Debug Area failed, error = %d \n " , retVal ) ;
return false ;
}
return true ;
}
void DebugSessionLinux : : readStateSaveAreaHeader ( ) {
if ( clientHandle = = invalidClientHandle ) {
return ;
}
uint64_t vm = 0 ;
uint64_t gpuVa = 0 ;
size_t totalSize = 0 ;
{
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-05-09 23:52:12 +08:00
if ( clientHandleToConnection [ clientHandle ] - > vmToContextStateSaveAreaBindInfo . size ( ) > 0 ) {
vm = clientHandleToConnection [ clientHandle ] - > vmToContextStateSaveAreaBindInfo . begin ( ) - > first ;
gpuVa = clientHandleToConnection [ clientHandle ] - > vmToContextStateSaveAreaBindInfo . begin ( ) - > second . gpuVa ;
totalSize = clientHandleToConnection [ clientHandle ] - > vmToContextStateSaveAreaBindInfo . begin ( ) - > second . size ;
}
}
if ( gpuVa > 0 ) {
auto headerSize = sizeof ( SIP : : StateSaveAreaHeader ) ;
if ( totalSize < headerSize ) {
PRINT_DEBUGGER_ERROR_LOG ( " Context State Save Area size incorrect \n " , " " ) ;
return ;
} else {
2022-11-09 02:51:55 +08:00
validateAndSetStateSaveAreaHeader ( vm , gpuVa ) ;
2022-05-09 23:52:12 +08:00
}
}
}
ze_result_t DebugSessionLinux : : readEventImp ( prelim_drm_i915_debug_event * drmDebugEvent ) {
2023-01-19 04:22:32 +08:00
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_READ_EVENT , drmDebugEvent ) ;
2022-05-09 23:52:12 +08:00
2023-01-19 04:22:32 +08:00
if ( ret ! = 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT failed: retCode: %d errno = %d \n " , ret , errno ) ;
2022-05-09 23:52:12 +08:00
} else {
if ( ( drmDebugEvent - > flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ) = = 0 & &
( drmDebugEvent - > flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ) = = 0 & &
( drmDebugEvent - > flags & PRELIM_DRM_I915_DEBUG_EVENT_STATE_CHANGE ) = = 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT unsupported flag = %d \n " , ( int ) drmDebugEvent - > flags ) ;
return ZE_RESULT_ERROR_UNKNOWN ;
}
return ZE_RESULT_SUCCESS ;
}
return ZE_RESULT_NOT_READY ;
}
2022-09-30 00:07:22 +08:00
bool DebugSessionLinux : : handleVmBindEvent ( prelim_drm_i915_debug_event_vm_bind * vmBind ) {
2022-05-09 23:52:12 +08:00
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND flags = %d size = %llu client_handle = %llu vm_handle = %llu va_start = %p va_lenght = %llu num_uuids = %lu \n " ,
( int ) vmBind - > base . flags , ( uint64_t ) vmBind - > base . size , ( uint64_t ) vmBind - > client_handle , ( uint64_t ) vmBind - > vm_handle , ( void * ) vmBind - > va_start , ( uint64_t ) vmBind - > va_length , ( uint32_t ) vmBind - > num_uuids ) ;
const bool createEvent = ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ) ;
const bool destroyEvent = ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ) ;
bool shouldAckEvent = true ;
if ( vmBind - > num_uuids > 0 & & vmBind - > base . size > sizeof ( prelim_drm_i915_debug_event_vm_bind ) ) {
auto vmHandle = vmBind - > vm_handle ;
auto connection = clientHandleToConnection [ vmBind - > client_handle ] . get ( ) ;
2022-09-08 01:12:17 +08:00
uint32_t index = 0 ;
2022-07-11 21:10:03 +08:00
const auto uuid = vmBind - > uuids [ index ] ;
2022-05-09 23:52:12 +08:00
if ( connection - > uuidMap . find ( uuid ) = = connection - > uuidMap . end ( ) ) {
PRINT_DEBUGGER_ERROR_LOG ( " Unknown UUID handle = %llu \n " , ( uint64_t ) uuid ) ;
2022-09-30 00:07:22 +08:00
return false ;
}
if ( connection - > vmToTile . find ( vmHandle ) = = connection - > vmToTile . end ( ) ) {
2022-09-30 21:00:05 +08:00
DEBUG_BREAK_IF ( connection - > vmToTile . find ( vmHandle ) = = connection - > vmToTile . end ( ) & & ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) & &
2022-09-30 00:07:22 +08:00
( connection - > uuidMap [ uuid ] . classIndex = = NEO : : DrmResourceClass : : Isa | | connection - > uuidMap [ uuid ] . classIndex = = NEO : : DrmResourceClass : : ModuleHeapDebugArea ) ) ;
return false ;
2022-05-09 23:52:12 +08:00
}
2022-09-14 17:23:40 +08:00
const auto tileIndex = connection - > vmToTile [ vmHandle ] ;
2022-10-04 22:14:01 +08:00
PRINT_DEBUGGER_INFO_LOG ( " UUID handle = %llu class index = %d \n " , static_cast < uint64_t > ( vmBind - > uuids [ index ] ) , static_cast < int > ( clientHandleToConnection [ vmBind - > client_handle ] - > uuidMap [ vmBind - > uuids [ index ] ] . classIndex ) ) ;
2022-05-09 23:52:12 +08:00
auto classUuid = connection - > uuidMap [ uuid ] . classHandle ;
if ( connection - > classHandleToIndex . find ( classUuid ) ! = connection - > classHandleToIndex . end ( ) ) {
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-05-09 23:52:12 +08:00
if ( connection - > classHandleToIndex [ classUuid ] . second = =
static_cast < uint32_t > ( NEO : : DrmResourceClass : : SbaTrackingBuffer ) ) {
connection - > vmToStateBaseAreaBindInfo [ vmHandle ] = { vmBind - > va_start , vmBind - > va_length } ;
}
if ( connection - > classHandleToIndex [ classUuid ] . second = =
static_cast < uint32_t > ( NEO : : DrmResourceClass : : ModuleHeapDebugArea ) ) {
connection - > vmToModuleDebugAreaBindInfo [ vmHandle ] = { vmBind - > va_start , vmBind - > va_length } ;
}
if ( connection - > classHandleToIndex [ classUuid ] . second = =
static_cast < uint32_t > ( NEO : : DrmResourceClass : : ContextSaveArea ) ) {
connection - > vmToContextStateSaveAreaBindInfo [ vmHandle ] = { vmBind - > va_start , vmBind - > va_length } ;
}
}
2022-09-14 17:23:40 +08:00
bool handleEvent = isTileWithinDeviceBitfield ( tileIndex ) ;
2022-09-08 01:12:17 +08:00
if ( handleEvent & & connection - > uuidMap [ uuid ] . classIndex = = NEO : : DrmResourceClass : : Isa ) {
2022-10-04 22:14:01 +08:00
uint32_t deviceBitfield = 0 ;
memcpy_s ( & deviceBitfield , sizeof ( uint32_t ) , connection - > uuidMap [ uuid ] . data . get ( ) , connection - > uuidMap [ uuid ] . dataSize ) ;
const NEO : : DeviceBitfield devices ( deviceBitfield ) ;
PRINT_DEBUGGER_INFO_LOG ( " ISA vm_handle = %llu, tileIndex = %lu, deviceBitfield = %llu " , vmHandle , tileIndex , devices . to_ulong ( ) ) ;
2022-05-09 23:52:12 +08:00
2022-07-11 21:10:03 +08:00
const auto isaUuidHandle = connection - > uuidMap [ uuid ] . handle ;
2022-05-09 23:52:12 +08:00
bool perKernelModules = true ;
int moduleUUIDindex = - 1 ;
2022-07-11 21:10:03 +08:00
bool tileInstanced = false ;
2022-09-14 17:23:40 +08:00
bool allInstancesEventsReceived = true ;
2022-05-09 23:52:12 +08:00
for ( uint32_t uuidIter = 1 ; uuidIter < vmBind - > num_uuids ; uuidIter + + ) {
if ( connection - > uuidMap [ vmBind - > uuids [ uuidIter ] ] . classIndex = = NEO : : DrmResourceClass : : L0ZebinModule ) {
perKernelModules = false ;
moduleUUIDindex = static_cast < int > ( uuidIter ) ;
}
2022-07-11 21:10:03 +08:00
if ( connection - > uuidMap [ vmBind - > uuids [ uuidIter ] ] . classHandle = = isaUuidHandle ) {
tileInstanced = true ;
}
2022-05-09 23:52:12 +08:00
}
2022-08-08 20:15:29 +08:00
if ( connection - > isaMap [ tileIndex ] . find ( vmBind - > va_start ) = = connection - > isaMap [ tileIndex ] . end ( ) & & createEvent ) {
2022-07-11 21:10:03 +08:00
2022-08-08 20:15:29 +08:00
auto & isaMap = connection - > isaMap [ tileIndex ] ;
2022-05-09 23:52:12 +08:00
auto & elfMap = connection - > elfMap ;
auto isa = std : : make_unique < IsaAllocation > ( ) ;
isa - > bindInfo = { vmBind - > va_start , vmBind - > va_length } ;
isa - > vmHandle = vmHandle ;
isa - > elfUuidHandle = invalidHandle ;
isa - > moduleBegin = 0 ;
isa - > moduleEnd = 0 ;
2022-07-11 21:10:03 +08:00
isa - > tileInstanced = tileInstanced ;
2022-08-10 23:24:13 +08:00
isa - > perKernelModule = perKernelModules ;
2022-09-14 17:23:40 +08:00
isa - > deviceBitfield = devices ;
2022-05-09 23:52:12 +08:00
for ( index = 1 ; index < vmBind - > num_uuids ; index + + ) {
if ( connection - > uuidMap [ vmBind - > uuids [ index ] ] . classIndex = = NEO : : DrmResourceClass : : Elf ) {
isa - > elfUuidHandle = vmBind - > uuids [ index ] ;
if ( ! perKernelModules ) {
auto & module = connection - > uuidToModule [ vmBind - > uuids [ moduleUUIDindex ] ] ;
DEBUG_BREAK_IF ( module . elfUuidHandle ! = 0 & & connection - > uuidMap [ vmBind - > uuids [ index ] ] . ptr ! = connection - > uuidMap [ module . elfUuidHandle ] . ptr ) ;
module . elfUuidHandle = vmBind - > uuids [ index ] ;
2022-09-27 02:28:04 +08:00
module . deviceBitfield = devices ;
2022-05-09 23:52:12 +08:00
}
}
}
if ( isa - > elfUuidHandle ! = invalidHandle ) {
isa - > moduleBegin = connection - > uuidMap [ isa - > elfUuidHandle ] . ptr ;
isa - > moduleEnd = isa - > moduleBegin + connection - > uuidMap [ isa - > elfUuidHandle ] . dataSize ;
elfMap [ isa - > moduleBegin ] = isa - > elfUuidHandle ;
} else {
PRINT_DEBUGGER_ERROR_LOG ( " No ELF provided by application \n " , " " ) ;
}
2022-06-11 00:02:39 +08:00
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
auto loadAddress = gmmHelper - > canonize ( vmBind - > va_start ) ;
2022-05-09 23:52:12 +08:00
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD ;
debugEvent . info . module . format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF ;
debugEvent . info . module . load = loadAddress ;
debugEvent . info . module . moduleBegin = isa - > moduleBegin ;
debugEvent . info . module . moduleEnd = isa - > moduleEnd ;
std : : unique_lock < std : : mutex > memLock ( asyncThreadMutex ) ;
isaMap [ vmBind - > va_start ] = std : : move ( isa ) ;
2022-06-07 01:23:58 +08:00
2022-06-11 00:02:39 +08:00
// Expect non canonical va_start
DEBUG_BREAK_IF ( gmmHelper - > decanonize ( vmBind - > va_start ) ! = vmBind - > va_start ) ;
2022-08-17 02:21:08 +08:00
bool apiEventNeedsAck = ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) ;
2022-06-07 01:23:58 +08:00
// If ACK flag is not set when triggering MODULE LOAD event, auto-ack immediately
2022-08-17 02:21:08 +08:00
if ( apiEventNeedsAck = = false ) {
2022-08-08 20:15:29 +08:00
isaMap [ vmBind - > va_start ] - > moduleLoadEventAck = true ;
2022-06-07 01:23:58 +08:00
}
2022-08-17 02:21:08 +08:00
if ( tileSessionsEnabled ) {
auto tileAttached = tileSessions [ tileIndex ] . second ;
2022-08-19 23:11:22 +08:00
2022-08-17 02:21:08 +08:00
if ( ! tileAttached ) {
isaMap [ vmBind - > va_start ] - > moduleLoadEventAck = true ;
apiEventNeedsAck = false ;
}
2022-08-19 23:11:22 +08:00
PRINT_DEBUGGER_INFO_LOG ( " TileDebugSession attached = %d, tileIndex = %lu, apiEventNeedsAck = %d " , ( int ) tileAttached , tileIndex , ( int ) apiEventNeedsAck ) ;
2022-08-17 02:21:08 +08:00
}
2022-05-09 23:52:12 +08:00
memLock . unlock ( ) ;
if ( perKernelModules ) {
2022-08-17 02:21:08 +08:00
debugEvent . flags = apiEventNeedsAck ? ZET_DEBUG_EVENT_FLAG_NEED_ACK : 0 ;
2022-08-26 01:33:23 +08:00
2022-08-17 02:21:08 +08:00
if ( tileSessionsEnabled ) {
2022-08-26 01:33:23 +08:00
auto tileAttached = static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > insertModule ( debugEvent . info . module ) ;
if ( tileAttached ) {
2022-11-14 23:52:05 +08:00
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > pushApiEvent ( debugEvent ) ;
2022-08-26 01:33:23 +08:00
}
2022-08-17 02:21:08 +08:00
} else {
2022-09-14 17:23:40 +08:00
if ( devices . count ( ) > 1 ) {
allInstancesEventsReceived = checkAllOtherTileIsaAllocationsPresent ( tileIndex , vmBind - > va_start ) ;
}
if ( allInstancesEventsReceived ) {
2022-11-14 23:52:05 +08:00
pushApiEvent ( debugEvent ) ;
2022-09-14 17:23:40 +08:00
}
2022-08-17 02:21:08 +08:00
}
2022-05-09 23:52:12 +08:00
}
}
if ( createEvent ) {
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-11-14 23:52:05 +08:00
if ( ! connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] - > moduleLoadEventAck & & perKernelModules ) {
bool doNotAutoAckEvent = ( ! blockOnFenceMode & & allInstancesEventsReceived ) ; // in block on CPU mode - do not auto-ack last event for isa instance
doNotAutoAckEvent | = blockOnFenceMode ; // in block on fence mode - do not auto-ack any events
if ( doNotAutoAckEvent ) {
PRINT_DEBUGGER_INFO_LOG ( " Add event to ack, seqno = %llu " , ( uint64_t ) vmBind - > base . seqno ) ;
connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] - > ackEvents . push_back ( vmBind - > base ) ;
shouldAckEvent = false ;
}
2022-05-09 23:52:12 +08:00
}
2022-08-08 20:15:29 +08:00
connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] - > vmBindCounter + + ;
2022-05-09 23:52:12 +08:00
}
2022-08-08 20:15:29 +08:00
if ( destroyEvent & & connection - > isaMap [ tileIndex ] . find ( vmBind - > va_start ) ! = connection - > isaMap [ tileIndex ] . end ( ) ) {
DEBUG_BREAK_IF ( connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] - > vmBindCounter = = 0 ) ;
connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] - > vmBindCounter - - ;
if ( connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] - > vmBindCounter = = 0 ) {
const auto & isa = connection - > isaMap [ tileIndex ] [ vmBind - > va_start ] ;
2022-05-09 23:52:12 +08:00
zet_debug_event_t debugEvent = { } ;
2022-06-11 00:02:39 +08:00
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
auto loadAddress = gmmHelper - > canonize ( isa - > bindInfo . gpuVa ) ;
2022-05-09 23:52:12 +08:00
debugEvent . type = ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD ;
debugEvent . info . module . format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF ;
2022-06-11 00:02:39 +08:00
debugEvent . info . module . load = loadAddress ;
2022-05-09 23:52:12 +08:00
debugEvent . info . module . moduleBegin = isa - > moduleBegin ;
debugEvent . info . module . moduleEnd = isa - > moduleEnd ;
if ( perKernelModules ) {
2022-08-17 02:21:08 +08:00
if ( tileSessionsEnabled ) {
2022-08-26 01:33:23 +08:00
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > removeModule ( debugEvent . info . module ) ;
2022-11-14 23:52:05 +08:00
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > pushApiEvent ( debugEvent ) ;
2022-08-17 02:21:08 +08:00
} else {
2022-09-14 17:23:40 +08:00
bool notifyEvent = true ;
if ( isa - > deviceBitfield . count ( ) > 1 ) {
notifyEvent = checkAllOtherTileIsaAllocationsRemoved ( tileIndex , vmBind - > va_start ) ;
}
if ( notifyEvent ) {
2022-11-14 23:52:05 +08:00
pushApiEvent ( debugEvent ) ;
2022-09-14 17:23:40 +08:00
}
2022-08-17 02:21:08 +08:00
}
2022-05-09 23:52:12 +08:00
}
std : : unique_lock < std : : mutex > memLock ( asyncThreadMutex ) ;
2022-08-08 20:15:29 +08:00
connection - > isaMap [ tileIndex ] . erase ( vmBind - > va_start ) ;
2022-05-09 23:52:12 +08:00
memLock . unlock ( ) ;
}
}
}
2023-01-04 16:55:29 +08:00
if ( handleEvent ) {
2022-05-09 23:52:12 +08:00
2023-01-04 16:55:29 +08:00
for ( uint32_t uuidIter = 0 ; uuidIter < vmBind - > num_uuids ; uuidIter + + ) {
if ( connection - > uuidMap [ vmBind - > uuids [ uuidIter ] ] . classIndex = = NEO : : DrmResourceClass : : L0ZebinModule ) {
uint64_t loadAddress = 0 ;
auto & module = connection - > uuidToModule [ vmBind - > uuids [ uuidIter ] ] ;
if ( createEvent ) {
module . segmentVmBindCounter [ tileIndex ] + + ;
DEBUG_BREAK_IF ( module . loadAddresses [ tileIndex ] . size ( ) > module . segmentCount ) ;
bool canTriggerEvent = module . loadAddresses [ tileIndex ] . size ( ) = = ( module . segmentCount - 1 ) ;
module . loadAddresses [ tileIndex ] . insert ( vmBind - > va_start ) ;
if ( ! blockOnFenceMode ) {
if ( canTriggerEvent & & module . loadAddresses [ tileIndex ] . size ( ) = = module . segmentCount ) {
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
loadAddress = gmmHelper - > canonize ( * std : : min_element ( module . loadAddresses [ tileIndex ] . begin ( ) , module . loadAddresses [ tileIndex ] . end ( ) ) ) ;
PRINT_DEBUGGER_INFO_LOG ( " Zebin module loaded at: %p, with %u isa allocations " , ( void * ) loadAddress , module . segmentCount ) ;
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD ;
debugEvent . info . module . format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF ;
debugEvent . info . module . load = loadAddress ;
debugEvent . info . module . moduleBegin = connection - > uuidMap [ module . elfUuidHandle ] . ptr ;
debugEvent . info . module . moduleEnd = connection - > uuidMap [ module . elfUuidHandle ] . ptr + connection - > uuidMap [ module . elfUuidHandle ] . dataSize ;
if ( ! tileSessionsEnabled ) {
bool allInstancesEventsReceived = true ;
if ( module . deviceBitfield . count ( ) > 1 ) {
allInstancesEventsReceived = checkAllOtherTileModuleSegmentsPresent ( tileIndex , module ) ;
2022-11-14 23:52:05 +08:00
}
2023-01-04 16:55:29 +08:00
if ( allInstancesEventsReceived ) {
if ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) {
debugEvent . flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK ;
module . ackEvents [ tileIndex ] . push_back ( vmBind - > base ) ;
}
pushApiEvent ( debugEvent , vmBind - > uuids [ uuidIter ] ) ;
shouldAckEvent = false ;
}
} else {
auto tileAttached = static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > insertModule ( debugEvent . info . module ) ;
if ( tileAttached ) {
if ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) {
debugEvent . flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK ;
module . ackEvents [ tileIndex ] . push_back ( vmBind - > base ) ;
}
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > pushApiEvent ( debugEvent , vmBind - > uuids [ uuidIter ] ) ;
shouldAckEvent = false ;
2022-11-14 23:52:05 +08:00
}
}
}
2023-01-04 16:55:29 +08:00
} else {
if ( canTriggerEvent & & module . loadAddresses [ tileIndex ] . size ( ) = = module . segmentCount ) {
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
loadAddress = gmmHelper - > canonize ( * std : : min_element ( module . loadAddresses [ tileIndex ] . begin ( ) , module . loadAddresses [ tileIndex ] . end ( ) ) ) ;
PRINT_DEBUGGER_INFO_LOG ( " Zebin module loaded at: %p, with %u isa allocations " , ( void * ) loadAddress , module . segmentCount ) ;
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD ;
debugEvent . info . module . format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF ;
debugEvent . info . module . load = loadAddress ;
debugEvent . info . module . moduleBegin = connection - > uuidMap [ module . elfUuidHandle ] . ptr ;
debugEvent . info . module . moduleEnd = connection - > uuidMap [ module . elfUuidHandle ] . ptr + connection - > uuidMap [ module . elfUuidHandle ] . dataSize ;
if ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) {
debugEvent . flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK ;
2022-11-14 23:52:05 +08:00
}
2023-01-04 16:55:29 +08:00
if ( ! tileSessionsEnabled ) {
bool allInstancesEventsReceived = true ;
if ( module . deviceBitfield . count ( ) > 1 ) {
allInstancesEventsReceived = checkAllOtherTileModuleSegmentsPresent ( tileIndex , module ) ;
}
if ( allInstancesEventsReceived ) {
pushApiEvent ( debugEvent , vmBind - > uuids [ uuidIter ] ) ;
shouldAckEvent = false ;
}
} else {
auto tileAttached = static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > insertModule ( debugEvent . info . module ) ;
if ( tileAttached ) {
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > pushApiEvent ( debugEvent , vmBind - > uuids [ uuidIter ] ) ;
shouldAckEvent = false ;
}
2022-11-14 23:52:05 +08:00
}
2023-01-04 16:55:29 +08:00
}
{
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
if ( ! module . moduleLoadEventAcked [ tileIndex ] ) {
2022-11-14 23:52:05 +08:00
shouldAckEvent = false ;
}
2022-08-26 01:33:23 +08:00
2023-01-04 16:55:29 +08:00
if ( tileSessionsEnabled & & ! static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > isAttached ) {
shouldAckEvent = true ;
}
if ( ! shouldAckEvent & & ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) ) {
module . ackEvents [ tileIndex ] . push_back ( vmBind - > base ) ;
}
2022-08-17 02:21:08 +08:00
}
}
2022-11-14 23:52:05 +08:00
2023-01-04 16:55:29 +08:00
} else { // destroyEvent
2022-05-09 23:52:12 +08:00
2023-01-04 16:55:29 +08:00
module . segmentVmBindCounter [ tileIndex ] - - ;
2022-05-09 23:52:12 +08:00
2023-01-04 16:55:29 +08:00
if ( module . segmentVmBindCounter [ tileIndex ] = = 0 ) {
2022-05-09 23:52:12 +08:00
2023-01-04 16:55:29 +08:00
zet_debug_event_t debugEvent = { } ;
2022-05-09 23:52:12 +08:00
2023-01-04 16:55:29 +08:00
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
auto loadAddress = gmmHelper - > canonize ( * std : : min_element ( module . loadAddresses [ tileIndex ] . begin ( ) , module . loadAddresses [ tileIndex ] . end ( ) ) ) ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD ;
debugEvent . info . module . format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF ;
debugEvent . info . module . load = loadAddress ;
debugEvent . info . module . moduleBegin = connection - > uuidMap [ module . elfUuidHandle ] . ptr ;
debugEvent . info . module . moduleEnd = connection - > uuidMap [ module . elfUuidHandle ] . ptr + connection - > uuidMap [ module . elfUuidHandle ] . dataSize ;
2022-05-09 23:52:12 +08:00
2023-01-04 16:55:29 +08:00
if ( tileSessionsEnabled ) {
2022-08-26 01:33:23 +08:00
2023-01-04 16:55:29 +08:00
auto tileAttached = static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > removeModule ( debugEvent . info . module ) ;
2022-08-26 01:33:23 +08:00
2023-01-04 16:55:29 +08:00
if ( tileAttached ) {
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > pushApiEvent ( debugEvent , vmBind - > uuids [ uuidIter ] ) ;
}
2022-08-26 01:33:23 +08:00
2023-01-04 16:55:29 +08:00
} else {
bool notifyEvent = true ;
if ( module . deviceBitfield . count ( ) > 1 ) {
notifyEvent = checkAllOtherTileModuleSegmentsRemoved ( tileIndex , module ) ;
}
if ( notifyEvent ) {
pushApiEvent ( debugEvent , vmBind - > uuids [ uuidIter ] ) ;
}
2022-09-27 02:28:04 +08:00
}
2023-01-04 16:55:29 +08:00
module . loadAddresses [ tileIndex ] . clear ( ) ;
module . moduleLoadEventAcked [ tileIndex ] = false ;
2022-08-17 02:21:08 +08:00
}
2022-05-09 23:52:12 +08:00
}
2023-01-04 16:55:29 +08:00
break ;
2022-05-09 23:52:12 +08:00
}
}
}
2022-09-30 21:00:05 +08:00
}
2022-05-09 23:52:12 +08:00
2022-09-30 21:00:05 +08:00
if ( shouldAckEvent & & ( vmBind - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK ) ) {
prelim_drm_i915_debug_event_ack eventToAck = { } ;
eventToAck . type = vmBind - > base . type ;
eventToAck . seqno = vmBind - > base . seqno ;
eventToAck . flags = 0 ;
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_ACK_EVENT , & eventToAck ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu ret = %d errno = %d \n " , ( uint64_t ) eventToAck . seqno , ret , ret ! = 0 ? errno : 0 ) ;
2022-05-09 23:52:12 +08:00
}
2022-09-30 21:00:05 +08:00
return true ;
2022-05-09 23:52:12 +08:00
}
void DebugSessionLinux : : handleContextParamEvent ( prelim_drm_i915_debug_event_context_param * contextParam ) {
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM flags = %d size = %llu client_handle = %llu ctx_handle = %llu \n " ,
( int ) contextParam - > base . flags , ( uint64_t ) contextParam - > base . size , ( uint64_t ) contextParam - > client_handle , ( uint64_t ) contextParam - > ctx_handle ) ;
if ( clientHandleToConnection [ contextParam - > client_handle ] - > contextsCreated . find ( contextParam - > ctx_handle ) = =
clientHandleToConnection [ contextParam - > client_handle ] - > contextsCreated . end ( ) ) {
PRINT_DEBUGGER_ERROR_LOG ( " CONTEXT handle does not exist \n " , " " ) ;
return ;
}
switch ( contextParam - > param . param ) {
case I915_CONTEXT_PARAM_VM :
PRINT_DEBUGGER_INFO_LOG ( " I915_CONTEXT_PARAM_VM vm = %llu \n " , ( uint64_t ) contextParam - > param . value ) ;
clientHandleToConnection [ contextParam - > client_handle ] - > contextsCreated [ contextParam - > ctx_handle ] . vm = contextParam - > param . value ;
break ;
case I915_CONTEXT_PARAM_ENGINES : {
2022-07-11 21:10:03 +08:00
PRINT_DEBUGGER_INFO_LOG ( " I915_CONTEXT_PARAM_ENGINES ctx_id = %lu param = %llu value = %llu size = %lu " ,
2022-05-09 23:52:12 +08:00
( uint32_t ) contextParam - > param . ctx_id ,
( uint64_t ) contextParam - > param . param ,
( uint64_t ) contextParam - > param . value , ( uint32_t ) contextParam - > param . size ) ;
auto numEngines = ( contextParam - > param . size - sizeof ( i915_context_param_engines ) ) / sizeof ( i915_engine_class_instance ) ;
auto engines = reinterpret_cast < i915_context_param_engines * > ( & ( contextParam - > param . value ) ) ;
clientHandleToConnection [ contextParam - > client_handle ] - > contextsCreated [ contextParam - > ctx_handle ] . engines . clear ( ) ;
for ( uint32_t i = 0 ; i < numEngines ; i + + ) {
clientHandleToConnection [ contextParam - > client_handle ] - > contextsCreated [ contextParam - > ctx_handle ] . engines . push_back ( engines - > engines [ i ] ) ;
}
2022-07-11 21:10:03 +08:00
auto vm = clientHandleToConnection [ contextParam - > client_handle ] - > contextsCreated [ contextParam - > ctx_handle ] . vm ;
if ( numEngines & & vm ! = invalidHandle ) {
NEO : : EngineClassInstance engineClassInstance = { engines - > engines [ 0 ] . engine_class , engines - > engines [ 0 ] . engine_instance } ;
auto tileIndex = DrmHelper : : getEngineTileIndex ( connectedDevice , engineClassInstance ) ;
clientHandleToConnection [ contextParam - > client_handle ] - > vmToTile [ vm ] = tileIndex ;
PRINT_DEBUGGER_INFO_LOG ( " VM = %llu mapped to TILE = %lu \n " , vm , tileIndex ) ;
}
2022-05-09 23:52:12 +08:00
break ;
}
default :
PRINT_DEBUGGER_INFO_LOG ( " I915_CONTEXT_PARAM UNHANDLED = %llu \n " , ( uint64_t ) contextParam - > param . param ) ;
break ;
}
}
void DebugSessionLinux : : handleAttentionEvent ( prelim_drm_i915_debug_event_eu_attention * attention ) {
NEO : : EngineClassInstance engineClassInstance = { attention - > ci . engine_class , attention - > ci . engine_instance } ;
auto tileIndex = DrmHelper : : getEngineTileIndex ( connectedDevice , engineClassInstance ) ;
if ( interruptSent & & attention - > base . seqno < = euControlInterruptSeqno [ tileIndex ] ) {
PRINT_DEBUGGER_INFO_LOG ( " Discarding EU ATTENTION event for interrupt request. Event seqno == %d <= %d == interrupt seqno \n " ,
( uint32_t ) attention - > base . seqno ,
( uint32_t ) euControlInterruptSeqno [ tileIndex ] ) ;
return ;
}
newAttentionRaised ( tileIndex ) ;
if ( clientHandleToConnection . find ( attention - > client_handle ) = = clientHandleToConnection . end ( ) ) {
return ;
}
auto & clientConnection = clientHandleToConnection [ attention - > client_handle ] ;
if ( clientConnection - > lrcToContextHandle . find ( attention - > lrc_handle ) = = clientConnection - > lrcToContextHandle . end ( ) ) {
return ;
}
auto contextHandle = clientConnection - > lrcToContextHandle [ attention - > lrc_handle ] ;
if ( clientConnection - > contextsCreated . find ( contextHandle ) = = clientConnection - > contextsCreated . end ( ) ) {
return ;
}
auto vmHandle = clientConnection - > contextsCreated [ contextHandle ] . vm ;
if ( vmHandle = = invalidHandle ) {
return ;
}
2022-09-08 01:12:17 +08:00
if ( ! connectedDevice - > getNEODevice ( ) - > getDeviceBitfield ( ) . test ( tileIndex ) ) {
return ;
}
2022-05-09 23:52:12 +08:00
auto hwInfo = connectedDevice - > getHwInfo ( ) ;
2023-01-02 21:06:10 +08:00
auto & l0GfxCoreHelper = connectedDevice - > getL0GfxCoreHelper ( ) ;
2022-05-09 23:52:12 +08:00
2022-12-02 23:24:50 +08:00
auto threadsWithAttention = l0GfxCoreHelper . getThreadsFromAttentionBitmask ( hwInfo , tileIndex , attention - > bitmask , attention - > bitmask_size ) ;
2022-05-09 23:52:12 +08:00
printBitmask ( attention - > bitmask , attention - > bitmask_size ) ;
PRINT_DEBUGGER_THREAD_LOG ( " ATTENTION for tile = %d thread count = %d \n " , tileIndex , ( int ) threadsWithAttention . size ( ) ) ;
2022-07-15 02:14:46 +08:00
for ( auto & threadId : threadsWithAttention ) {
2022-05-09 23:52:12 +08:00
PRINT_DEBUGGER_THREAD_LOG ( " ATTENTION event for thread: %s \n " , EuThread : : toString ( threadId ) . c_str ( ) ) ;
2022-08-19 23:11:22 +08:00
if ( tileSessionsEnabled ) {
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention ( threadId , vmHandle ) ;
} else {
markPendingInterruptsOrAddToNewlyStoppedFromRaisedAttention ( threadId , vmHandle ) ;
}
2022-05-09 23:52:12 +08:00
}
2022-08-19 23:11:22 +08:00
if ( tileSessionsEnabled ) {
static_cast < TileDebugSessionLinux * > ( tileSessions [ tileIndex ] . first ) - > checkTriggerEventsForAttention ( ) ;
} else {
checkTriggerEventsForAttention ( ) ;
}
2022-05-09 23:52:12 +08:00
}
void DebugSessionLinux : : handleEnginesEvent ( prelim_drm_i915_debug_event_engines * engines ) {
PRINT_DEBUGGER_INFO_LOG ( " ENGINES event: client_handle = %llu, ctx_handle = %llu, num_engines = %llu %s \n " ,
( uint64_t ) engines - > client_handle ,
( uint64_t ) engines - > ctx_handle ,
( uint64_t ) engines - > num_engines ,
engines - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ? " CREATE " : engines - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ? " DESTROY "
: " " ) ;
UNRECOVERABLE_IF ( clientHandleToConnection . find ( engines - > client_handle ) = = clientHandleToConnection . end ( ) ) ;
if ( engines - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_CREATE ) {
for ( uint64_t i = 0 ; i < engines - > num_engines ; + + i ) {
auto lrc = engines - > engines [ i ] . lrc_handle ;
if ( lrc ! = 0 ) {
PRINT_DEBUGGER_INFO_LOG ( " lrc%llu = %llu " , i , lrc ) ;
}
clientHandleToConnection [ engines - > client_handle ] - > lrcToContextHandle [ lrc ] = engines - > ctx_handle ;
}
}
if ( engines - > base . flags & PRELIM_DRM_I915_DEBUG_EVENT_DESTROY ) {
for ( uint64_t i = 0 ; i < engines - > num_engines ; + + i ) {
auto lrc = engines - > engines [ i ] . lrc_handle ;
PRINT_DEBUGGER_INFO_LOG ( " lrc%llu = %llu \n " , i , lrc ) ;
clientHandleToConnection [ engines - > client_handle ] - > lrcToContextHandle . erase ( lrc ) ;
}
}
}
void DebugSessionLinux : : extractUuidData ( uint64_t client , const UuidData & uuidData ) {
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : SbaTrackingBuffer | |
uuidData . classIndex = = NEO : : DrmResourceClass : : ModuleHeapDebugArea | |
uuidData . classIndex = = NEO : : DrmResourceClass : : ContextSaveArea ) {
UNRECOVERABLE_IF ( uuidData . dataSize ! = 8 ) ;
uint64_t * data = ( uint64_t * ) uuidData . data . get ( ) ;
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : SbaTrackingBuffer ) {
clientHandleToConnection [ client ] - > stateBaseAreaGpuVa = * data ;
PRINT_DEBUGGER_INFO_LOG ( " SbaTrackingBuffer GPU VA = %p " , ( void * ) clientHandleToConnection [ clientHandle ] - > stateBaseAreaGpuVa ) ;
}
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : ModuleHeapDebugArea ) {
clientHandleToConnection [ client ] - > moduleDebugAreaGpuVa = * data ;
PRINT_DEBUGGER_INFO_LOG ( " ModuleHeapDebugArea GPU VA = %p " , ( void * ) clientHandleToConnection [ clientHandle ] - > moduleDebugAreaGpuVa ) ;
}
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : ContextSaveArea ) {
clientHandleToConnection [ client ] - > contextStateSaveAreaGpuVa = * data ;
PRINT_DEBUGGER_INFO_LOG ( " ContextSaveArea GPU VA = %p " , ( void * ) clientHandleToConnection [ clientHandle ] - > contextStateSaveAreaGpuVa ) ;
}
}
if ( uuidData . classIndex = = NEO : : DrmResourceClass : : L0ZebinModule ) {
uint32_t segmentCount = 0 ;
memcpy_s ( & segmentCount , sizeof ( uint32_t ) , uuidData . data . get ( ) , uuidData . dataSize ) ;
clientHandleToConnection [ client ] - > uuidToModule [ uuidData . handle ] . segmentCount = segmentCount ;
}
}
uint64_t DebugSessionLinux : : extractVaFromUuidString ( std : : string & uuid ) {
const char uuidString [ ] = " %04 " SCNx64 " -%012 " SCNx64 ;
auto subString = uuid . substr ( 19 ) ;
uint64_t parts [ 2 ] = { 0 , 0 } ;
sscanf ( subString . c_str ( ) , uuidString , & parts [ 1 ] , & parts [ 0 ] ) ;
parts [ 0 ] | = ( parts [ 1 ] & 0xFFFF ) < < 48 ;
return parts [ 0 ] ;
}
2022-07-15 02:14:46 +08:00
int DebugSessionLinux : : threadControl ( const std : : vector < EuThread : : ThreadId > & threads , uint32_t tile , ThreadControlCmd threadCmd , std : : unique_ptr < uint8_t [ ] > & bitmaskOut , size_t & bitmaskSizeOut ) {
2022-05-09 23:52:12 +08:00
auto hwInfo = connectedDevice - > getHwInfo ( ) ;
auto classInstance = DrmHelper : : getEngineInstance ( connectedDevice , tile , hwInfo . capabilityTable . defaultEngineType ) ;
UNRECOVERABLE_IF ( ! classInstance ) ;
2023-01-02 21:06:10 +08:00
auto & l0GfxCoreHelper = connectedDevice - > getL0GfxCoreHelper ( ) ;
2022-05-09 23:52:12 +08:00
bitmaskSizeOut = 0 ;
struct prelim_drm_i915_debug_eu_control euControl = { } ;
euControl . client_handle = clientHandle ;
euControl . ci . engine_class = classInstance - > engineClass ;
euControl . ci . engine_instance = classInstance - > engineInstance ;
euControl . bitmask_size = 0 ;
euControl . bitmask_ptr = 0 ;
decltype ( prelim_drm_i915_debug_eu_control : : cmd ) command = 0 ;
switch ( threadCmd ) {
case ThreadControlCmd : : InterruptAll :
command = PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT_ALL ;
break ;
case ThreadControlCmd : : Interrupt :
command = PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT ;
break ;
case ThreadControlCmd : : Resume :
command = PRELIM_I915_DEBUG_EU_THREADS_CMD_RESUME ;
break ;
case ThreadControlCmd : : Stopped :
command = PRELIM_I915_DEBUG_EU_THREADS_CMD_STOPPED ;
break ;
}
euControl . cmd = command ;
std : : unique_ptr < uint8_t [ ] > bitmask ;
size_t bitmaskSize = 0 ;
if ( command = = PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT | |
command = = PRELIM_I915_DEBUG_EU_THREADS_CMD_RESUME | |
command = = PRELIM_I915_DEBUG_EU_THREADS_CMD_STOPPED ) {
2022-12-02 23:24:50 +08:00
l0GfxCoreHelper . getAttentionBitmaskForSingleThreads ( threads , hwInfo , bitmask , bitmaskSize ) ;
2022-05-09 23:52:12 +08:00
euControl . bitmask_size = static_cast < uint32_t > ( bitmaskSize ) ;
euControl . bitmask_ptr = reinterpret_cast < uint64_t > ( bitmask . get ( ) ) ;
}
if ( command = = PRELIM_I915_DEBUG_EU_THREADS_CMD_RESUME ) {
2022-07-14 22:24:56 +08:00
applyResumeWa ( bitmask . get ( ) , bitmaskSize ) ;
2022-05-09 23:52:12 +08:00
}
printBitmask ( bitmask . get ( ) , bitmaskSize ) ;
2023-01-19 04:22:32 +08:00
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_EU_CONTROL , & euControl ) ;
if ( ret ! = 0 ) {
PRINT_DEBUGGER_ERROR_LOG ( " PRELIM_I915_DEBUG_IOCTL_EU_CONTROL failed: retCode: %d errno = %d command = %d \n " , ret , errno , command ) ;
2022-05-09 23:52:12 +08:00
} else {
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_EU_CONTROL: seqno = %llu command = %u \n " , ( uint64_t ) euControl . seqno , command ) ;
}
if ( command = = PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT | |
command = = PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT_ALL ) {
2023-01-19 04:22:32 +08:00
if ( ret = = 0 ) {
2022-05-09 23:52:12 +08:00
euControlInterruptSeqno [ tile ] = euControl . seqno ;
} else {
euControlInterruptSeqno [ tile ] = invalidHandle ;
}
}
if ( threadCmd = = ThreadControlCmd : : Stopped ) {
bitmaskOut = std : : move ( bitmask ) ;
bitmaskSizeOut = euControl . bitmask_size ;
}
2023-01-19 04:22:32 +08:00
return ret ;
2022-05-09 23:52:12 +08:00
}
2022-07-15 02:14:46 +08:00
ze_result_t DebugSessionLinux : : resumeImp ( const std : : vector < EuThread : : ThreadId > & threads , uint32_t deviceIndex ) {
2022-05-09 23:52:12 +08:00
std : : unique_ptr < uint8_t [ ] > bitmask ;
size_t bitmaskSize ;
auto result = threadControl ( threads , deviceIndex , ThreadControlCmd : : Resume , bitmask , bitmaskSize ) ;
return result = = 0 ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_NOT_AVAILABLE ;
}
ze_result_t DebugSessionLinux : : interruptImp ( uint32_t deviceIndex ) {
std : : unique_ptr < uint8_t [ ] > bitmask ;
size_t bitmaskSize ;
auto result = threadControl ( { } , deviceIndex , ThreadControlCmd : : InterruptAll , bitmask , bitmaskSize ) ;
return result = = 0 ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_NOT_AVAILABLE ;
}
2022-08-31 02:06:04 +08:00
ze_result_t DebugSessionLinux : : getISAVMHandle ( uint32_t deviceIndex , const zet_debug_memory_space_desc_t * desc , size_t size , uint64_t & vmHandle ) {
2022-09-05 21:08:24 +08:00
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
auto accessVA = gmmHelper - > decanonize ( desc - > address ) ;
2022-08-31 02:06:04 +08:00
auto & isaMap = clientHandleToConnection [ clientHandle ] - > isaMap [ deviceIndex ] ;
2022-05-09 23:52:12 +08:00
ze_result_t status = ZE_RESULT_ERROR_UNINITIALIZED ;
vmHandle = invalidHandle ;
if ( isaMap . size ( ) > 0 ) {
uint64_t baseVa ;
uint64_t ceilVa ;
for ( const auto & isa : isaMap ) {
baseVa = isa . second - > bindInfo . gpuVa ;
ceilVa = isa . second - > bindInfo . gpuVa + isa . second - > bindInfo . size ;
if ( accessVA > = baseVa & & accessVA < ceilVa ) {
if ( accessVA + size > ceilVa ) {
status = ZE_RESULT_ERROR_INVALID_ARGUMENT ;
} else {
vmHandle = isa . second - > vmHandle ;
status = ZE_RESULT_SUCCESS ;
}
break ;
}
}
}
return status ;
}
2022-09-14 17:23:40 +08:00
bool DebugSessionLinux : : getIsaInfoForAllInstances ( NEO : : DeviceBitfield deviceBitfield , const zet_debug_memory_space_desc_t * desc , size_t size , uint64_t vmHandles [ ] , ze_result_t & status ) {
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
auto accessVA = gmmHelper - > decanonize ( desc - > address ) ;
status = ZE_RESULT_ERROR_UNINITIALIZED ;
bool tileInstancedIsa = false ;
bool invalidIsaRange = false ;
uint32_t isaFound = 0 ;
for ( uint32_t i = 0 ; i < NEO : : EngineLimits : : maxHandleCount ; i + + ) {
vmHandles [ i ] = invalidHandle ;
if ( deviceBitfield . test ( i ) ) {
auto & isaMap = clientHandleToConnection [ clientHandle ] - > isaMap [ i ] ;
if ( isaMap . size ( ) > 0 ) {
uint64_t baseVa ;
uint64_t ceilVa ;
for ( const auto & isa : isaMap ) {
baseVa = isa . second - > bindInfo . gpuVa ;
ceilVa = isa . second - > bindInfo . gpuVa + isa . second - > bindInfo . size ;
if ( accessVA > = baseVa & & accessVA < ceilVa ) {
isaFound + + ;
if ( accessVA + size > ceilVa ) {
invalidIsaRange = true ;
} else {
vmHandles [ i ] = isa . second - > vmHandle ;
}
tileInstancedIsa = isa . second - > tileInstanced ;
break ;
}
}
}
}
}
if ( invalidIsaRange ) {
status = ZE_RESULT_ERROR_INVALID_ARGUMENT ;
} else if ( isaFound > 0 ) {
if ( ( tileInstancedIsa & & deviceBitfield . count ( ) = = isaFound ) | |
! tileInstancedIsa ) {
status = ZE_RESULT_SUCCESS ;
}
}
return isaFound > 0 ;
}
2022-05-09 23:52:12 +08:00
void DebugSessionLinux : : printContextVms ( ) {
if ( NEO : : DebugManager . flags . DebuggerLogBitmask . get ( ) & NEO : : DebugVariables : : DEBUGGER_LOG_BITMASK : : LOG_INFO ) {
PRINT_DEBUGGER_LOG ( stdout , " \n INFO: Context - VM map: " , " " ) ;
for ( size_t i = 0 ; i < clientHandleToConnection [ clientHandle ] - > contextsCreated . size ( ) ; i + + ) {
PRINT_DEBUGGER_LOG ( stdout , " \n Context = %llu : %llu " , ( uint64_t ) clientHandleToConnection [ clientHandle ] - > contextsCreated [ i ] . handle ,
( uint64_t ) clientHandleToConnection [ clientHandle ] - > contextsCreated [ i ] . vm ) ;
}
}
}
2022-08-09 22:55:08 +08:00
bool DebugSessionLinux : : tryReadElf ( const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer , ze_result_t & status ) {
const char * elfData = nullptr ;
uint64_t offset = 0 ;
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > memLock ( asyncThreadMutex ) ;
2022-08-09 22:55:08 +08:00
status = getElfOffset ( desc , size , elfData , offset ) ;
if ( status = = ZE_RESULT_ERROR_INVALID_ARGUMENT ) {
return true ;
}
if ( elfData ) {
status = readElfSpace ( desc , size , buffer , elfData , offset ) ;
return true ;
}
return false ;
}
2022-05-09 23:52:12 +08:00
ze_result_t DebugSessionLinux : : getElfOffset ( const zet_debug_memory_space_desc_t * desc , size_t size , const char * & elfData , uint64_t & offset ) {
auto & elfMap = clientHandleToConnection [ clientHandle ] - > elfMap ;
auto accessVA = desc - > address ;
ze_result_t status = ZE_RESULT_ERROR_UNINITIALIZED ;
elfData = nullptr ;
if ( elfMap . size ( ) > 0 ) {
uint64_t baseVa ;
uint64_t ceilVa ;
for ( auto elf : elfMap ) {
baseVa = elf . first ;
ceilVa = elf . first + clientHandleToConnection [ clientHandle ] - > uuidMap [ elf . second ] . dataSize ;
if ( accessVA > = baseVa & & accessVA < ceilVa ) {
if ( accessVA + size > ceilVa ) {
status = ZE_RESULT_ERROR_INVALID_ARGUMENT ;
} else {
DEBUG_BREAK_IF ( clientHandleToConnection [ clientHandle ] - > uuidMap [ elf . second ] . data . get ( ) = = nullptr ) ;
elfData = clientHandleToConnection [ clientHandle ] - > uuidMap [ elf . second ] . data . get ( ) ;
offset = accessVA - baseVa ;
status = ZE_RESULT_SUCCESS ;
}
break ;
}
}
}
return status ;
}
ze_result_t DebugSessionLinux : : readElfSpace ( const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer ,
const char * & elfData , const uint64_t offset ) {
int retVal = - 1 ;
elfData + = offset ;
retVal = memcpy_s ( buffer , size , elfData , size ) ;
return ( retVal = = 0 ) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN ;
}
ze_result_t DebugSessionLinux : : readMemory ( ze_device_thread_t thread , const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer ) {
2022-07-14 00:05:36 +08:00
ze_result_t status = validateThreadAndDescForMemoryAccess ( thread , desc ) ;
2022-05-09 23:52:12 +08:00
if ( status ! = ZE_RESULT_SUCCESS ) {
return status ;
}
2022-08-05 20:46:52 +08:00
if ( desc - > type = = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT ) {
status = readDefaultMemory ( thread , desc , size , buffer ) ;
} else {
auto threadId = convertToThreadId ( thread ) ;
2022-11-09 02:51:55 +08:00
status = slmMemoryAccess < void * , false > ( threadId , desc , size , buffer ) ;
2022-08-05 20:46:52 +08:00
}
return status ;
}
ze_result_t DebugSessionLinux : : readDefaultMemory ( ze_device_thread_t thread , const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer ) {
2023-02-08 22:02:29 +08:00
ze_result_t status = ZE_RESULT_SUCCESS ;
2022-08-05 20:46:52 +08:00
2022-09-14 17:23:40 +08:00
bool isa = tryReadIsa ( connectedDevice - > getNEODevice ( ) - > getDeviceBitfield ( ) , desc , size , buffer , status ) ;
2022-08-09 22:55:08 +08:00
if ( isa ) {
return status ;
2022-05-09 23:52:12 +08:00
}
2022-08-09 22:55:08 +08:00
bool elf = tryReadElf ( desc , size , buffer , status ) ;
if ( elf ) {
return status ;
}
2022-05-09 23:52:12 +08:00
2022-08-09 22:55:08 +08:00
if ( DebugSession : : isThreadAll ( thread ) ) {
return accessDefaultMemForThreadAll ( desc , size , const_cast < void * > ( buffer ) , false ) ;
2022-07-20 22:49:45 +08:00
}
2022-05-09 23:52:12 +08:00
2022-07-20 22:49:45 +08:00
auto threadId = convertToThreadId ( thread ) ;
2022-08-09 22:55:08 +08:00
auto vmHandle = allThreads [ threadId ] - > getMemoryHandle ( ) ;
2022-07-20 22:49:45 +08:00
if ( vmHandle = = invalidHandle ) {
return ZE_RESULT_ERROR_NOT_AVAILABLE ;
2022-05-09 23:52:12 +08:00
}
return readGpuMemory ( vmHandle , static_cast < char * > ( buffer ) , size , desc - > address ) ;
}
ze_result_t DebugSessionLinux : : writeMemory ( ze_device_thread_t thread , const zet_debug_memory_space_desc_t * desc , size_t size , const void * buffer ) {
2022-07-14 00:05:36 +08:00
ze_result_t status = validateThreadAndDescForMemoryAccess ( thread , desc ) ;
2022-05-09 23:52:12 +08:00
if ( status ! = ZE_RESULT_SUCCESS ) {
return status ;
}
2022-09-27 20:10:18 +08:00
if ( desc - > type = = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT ) {
status = writeDefaultMemory ( thread , desc , size , buffer ) ;
} else {
auto threadId = convertToThreadId ( thread ) ;
2022-11-09 02:51:55 +08:00
status = slmMemoryAccess < const void * , true > ( threadId , desc , size , buffer ) ;
2022-08-05 20:46:52 +08:00
}
2022-09-27 20:10:18 +08:00
return status ;
}
ze_result_t DebugSessionLinux : : writeDefaultMemory ( ze_device_thread_t thread , const zet_debug_memory_space_desc_t * desc , size_t size , const void * buffer ) {
2023-02-08 22:02:29 +08:00
ze_result_t status = ZE_RESULT_SUCCESS ;
2022-09-27 20:10:18 +08:00
2022-09-14 17:23:40 +08:00
auto deviceBitfield = connectedDevice - > getNEODevice ( ) - > getDeviceBitfield ( ) ;
2022-08-17 02:21:08 +08:00
2022-09-14 17:23:40 +08:00
bool isa = tryWriteIsa ( deviceBitfield , desc , size , buffer , status ) ;
2022-08-09 22:55:08 +08:00
if ( isa ) {
return status ;
}
if ( DebugSession : : isThreadAll ( thread ) ) {
return accessDefaultMemForThreadAll ( desc , size , const_cast < void * > ( buffer ) , true ) ;
}
auto threadId = convertToThreadId ( thread ) ;
auto threadVmHandle = allThreads [ threadId ] - > getMemoryHandle ( ) ;
if ( threadVmHandle = = invalidHandle ) {
return ZE_RESULT_ERROR_NOT_AVAILABLE ;
}
return writeGpuMemory ( threadVmHandle , static_cast < const char * > ( buffer ) , size , desc - > address ) ;
}
2022-09-14 17:23:40 +08:00
bool DebugSessionLinux : : tryWriteIsa ( NEO : : DeviceBitfield deviceBitfield , const zet_debug_memory_space_desc_t * desc , size_t size , const void * buffer , ze_result_t & status ) {
return tryAccessIsa ( deviceBitfield , desc , size , const_cast < void * > ( buffer ) , true , status ) ;
2022-08-09 22:55:08 +08:00
}
2022-09-14 17:23:40 +08:00
bool DebugSessionLinux : : tryReadIsa ( NEO : : DeviceBitfield deviceBitfield , const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer , ze_result_t & status ) {
return tryAccessIsa ( deviceBitfield , desc , size , buffer , false , status ) ;
2022-08-09 22:55:08 +08:00
}
2022-09-14 17:23:40 +08:00
bool DebugSessionLinux : : tryAccessIsa ( NEO : : DeviceBitfield deviceBitfield , const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer , bool write , ze_result_t & status ) {
2022-08-09 22:55:08 +08:00
status = ZE_RESULT_ERROR_NOT_AVAILABLE ;
2022-09-14 17:23:40 +08:00
uint64_t vmHandle [ NEO : : EngineLimits : : maxHandleCount ] = { invalidHandle } ;
uint32_t deviceIndex = Math : : getMinLsbSet ( static_cast < uint32_t > ( deviceBitfield . to_ulong ( ) ) ) ;
2022-07-20 22:49:45 +08:00
bool isaAccess = false ;
2022-09-14 17:23:40 +08:00
auto checkIfAnyFailed = [ ] ( const auto & result ) { return result ! = ZE_RESULT_SUCCESS ; } ;
2022-05-09 23:52:12 +08:00
{
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > memLock ( asyncThreadMutex ) ;
2022-05-09 23:52:12 +08:00
2022-09-14 17:23:40 +08:00
if ( deviceBitfield . count ( ) = = 1 ) {
status = getISAVMHandle ( deviceIndex , desc , size , vmHandle [ deviceIndex ] ) ;
if ( status = = ZE_RESULT_SUCCESS ) {
isaAccess = true ;
}
if ( status = = ZE_RESULT_ERROR_INVALID_ARGUMENT ) {
return true ;
}
} else {
isaAccess = getIsaInfoForAllInstances ( deviceBitfield , desc , size , vmHandle , status ) ;
2022-05-09 23:52:12 +08:00
}
}
2022-09-14 17:23:40 +08:00
if ( isaAccess & & status = = ZE_RESULT_SUCCESS ) {
2022-08-09 22:55:08 +08:00
2022-09-14 17:23:40 +08:00
if ( write ) {
if ( deviceBitfield . count ( ) = = 1 ) {
if ( vmHandle [ deviceIndex ] ! = invalidHandle ) {
status = writeGpuMemory ( vmHandle [ deviceIndex ] , static_cast < char * > ( buffer ) , size , desc - > address ) ;
} else {
status = ZE_RESULT_ERROR_UNINITIALIZED ;
}
2022-08-09 22:55:08 +08:00
} else {
2022-09-14 17:23:40 +08:00
std : : vector < ze_result_t > results ( NEO : : EngineLimits : : maxHandleCount ) ;
for ( uint32_t i = 0 ; i < NEO : : EngineLimits : : maxHandleCount ; i + + ) {
results [ i ] = ZE_RESULT_SUCCESS ;
if ( deviceBitfield . test ( i ) & & vmHandle [ i ] ! = invalidHandle ) {
results [ i ] = writeGpuMemory ( vmHandle [ i ] , static_cast < char * > ( buffer ) , size , desc - > address ) ;
if ( results [ i ] ! = ZE_RESULT_SUCCESS ) {
break ;
}
}
}
const bool anyFailed = std : : any_of ( results . begin ( ) , results . end ( ) , checkIfAnyFailed ) ;
if ( anyFailed ) {
status = ZE_RESULT_ERROR_UNKNOWN ;
}
2022-05-09 23:52:12 +08:00
}
2022-08-09 22:55:08 +08:00
} else {
2022-09-14 17:23:40 +08:00
if ( deviceBitfield . count ( ) > 1 ) {
for ( uint32_t i = 0 ; i < NEO : : EngineLimits : : maxHandleCount ; i + + ) {
if ( vmHandle [ i ] ! = invalidHandle ) {
deviceIndex = i ;
break ;
}
}
}
if ( vmHandle [ deviceIndex ] ! = invalidHandle ) {
status = readGpuMemory ( vmHandle [ deviceIndex ] , static_cast < char * > ( buffer ) , size , desc - > address ) ;
} else {
status = ZE_RESULT_ERROR_UNINITIALIZED ;
}
2022-05-09 23:52:12 +08:00
}
2022-07-20 22:49:45 +08:00
}
2022-08-09 22:55:08 +08:00
return isaAccess ;
}
2022-09-14 17:23:40 +08:00
2022-08-09 22:55:08 +08:00
ze_result_t DebugSessionLinux : : accessDefaultMemForThreadAll ( const zet_debug_memory_space_desc_t * desc , size_t size , void * buffer , bool write ) {
auto status = ZE_RESULT_ERROR_UNINITIALIZED ;
std : : vector < uint64_t > allVms ;
2022-07-20 22:49:45 +08:00
2022-08-17 02:21:08 +08:00
allVms = getAllMemoryHandles ( ) ;
2022-05-09 23:52:12 +08:00
2022-08-09 22:55:08 +08:00
if ( allVms . size ( ) > 0 ) {
for ( auto vmHandle : allVms ) {
if ( write ) {
status = writeGpuMemory ( vmHandle , static_cast < char * > ( buffer ) , size , desc - > address ) ;
} else {
status = readGpuMemory ( vmHandle , static_cast < char * > ( buffer ) , size , desc - > address ) ;
}
if ( status = = ZE_RESULT_SUCCESS ) {
return status ;
}
}
status = ZE_RESULT_ERROR_NOT_AVAILABLE ;
}
return status ;
2022-05-09 23:52:12 +08:00
}
2022-08-10 23:24:13 +08:00
bool DebugSessionLinux : : ackIsaEvents ( uint32_t deviceIndex , uint64_t isaVa ) {
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-05-09 23:52:12 +08:00
2022-08-10 23:24:13 +08:00
auto connection = clientHandleToConnection [ clientHandle ] . get ( ) ;
2022-06-11 00:02:39 +08:00
2022-08-10 23:24:13 +08:00
auto gmmHelper = connectedDevice - > getNEODevice ( ) - > getGmmHelper ( ) ;
auto isaVaStart = gmmHelper - > decanonize ( isaVa ) ;
auto isa = connection - > isaMap [ deviceIndex ] . find ( isaVaStart ) ;
2022-05-09 23:52:12 +08:00
2022-08-10 23:24:13 +08:00
if ( isa ! = connection - > isaMap [ deviceIndex ] . end ( ) ) {
2022-05-09 23:52:12 +08:00
2023-01-04 23:00:09 +08:00
// zebin modules do not store ackEvents per ISA
2022-08-10 23:24:13 +08:00
UNRECOVERABLE_IF ( isa - > second - > ackEvents . size ( ) > 0 & & isa - > second - > perKernelModule = = false ) ;
2022-05-09 23:52:12 +08:00
2022-08-10 23:24:13 +08:00
for ( auto & event : isa - > second - > ackEvents ) {
prelim_drm_i915_debug_event_ack eventToAck = { } ;
eventToAck . type = event . type ;
eventToAck . seqno = event . seqno ;
eventToAck . flags = 0 ;
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_ACK_EVENT , & eventToAck ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu, ret = %d errno = %d \n " , ( uint64_t ) event . seqno , ret , ret ! = 0 ? errno : 0 ) ;
}
isa - > second - > ackEvents . clear ( ) ;
isa - > second - > moduleLoadEventAck = true ;
return true ;
}
return false ;
}
2022-11-14 23:52:05 +08:00
bool DebugSessionLinux : : ackModuleEvents ( uint32_t deviceIndex , uint64_t moduleUuidHandle ) {
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
auto connection = clientHandleToConnection [ clientHandle ] . get ( ) ;
if ( connection - > uuidToModule . find ( moduleUuidHandle ) ! = connection - > uuidToModule . end ( ) ) {
auto & module = connection - > uuidToModule [ moduleUuidHandle ] ;
for ( auto & event : module . ackEvents [ deviceIndex ] ) {
prelim_drm_i915_debug_event_ack eventToAck = { } ;
eventToAck . type = event . type ;
eventToAck . seqno = event . seqno ;
eventToAck . flags = 0 ;
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_ACK_EVENT , & eventToAck ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu, ret = %d errno = %d \n " , ( uint64_t ) event . seqno , ret , ret ! = 0 ? errno : 0 ) ;
}
module . ackEvents [ deviceIndex ] . clear ( ) ;
module . moduleLoadEventAcked [ deviceIndex ] = true ;
return true ;
}
DEBUG_BREAK_IF ( true ) ;
return false ;
}
2022-08-26 01:33:23 +08:00
void DebugSessionLinux : : cleanRootSessionAfterDetach ( uint32_t deviceIndex ) {
auto connection = clientHandleToConnection [ clientHandle ] . get ( ) ;
for ( const auto & isa : connection - > isaMap [ deviceIndex ] ) {
2023-01-04 23:00:09 +08:00
// zebin modules do not store ackEvents per ISA
2022-08-26 01:33:23 +08:00
UNRECOVERABLE_IF ( isa . second - > ackEvents . size ( ) > 0 & & isa . second - > perKernelModule = = false ) ;
for ( auto & event : isa . second - > ackEvents ) {
prelim_drm_i915_debug_event_ack eventToAck = { } ;
eventToAck . type = event . type ;
eventToAck . seqno = event . seqno ;
eventToAck . flags = 0 ;
auto ret = ioctl ( PRELIM_I915_DEBUG_IOCTL_ACK_EVENT , & eventToAck ) ;
PRINT_DEBUGGER_INFO_LOG ( " PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu, ret = %d errno = %d \n " , ( uint64_t ) event . seqno , ret , ret ! = 0 ? errno : 0 ) ;
}
isa . second - > ackEvents . clear ( ) ;
isa . second - > moduleLoadEventAck = true ;
}
}
2022-08-10 23:24:13 +08:00
ze_result_t DebugSessionLinux : : acknowledgeEvent ( const zet_debug_event_t * event ) {
const zet_debug_event_t apiEventToAck = * event ;
{
2022-11-14 23:52:05 +08:00
std : : unique_lock < std : : mutex > lock ( asyncThreadMutex ) ;
2022-08-10 23:24:13 +08:00
for ( size_t i = 0 ; i < eventsToAck . size ( ) ; i + + ) {
if ( apiEventCompare ( apiEventToAck , eventsToAck [ i ] . first ) ) {
2022-05-09 23:52:12 +08:00
2022-11-14 23:52:05 +08:00
auto moduleUUID = eventsToAck [ i ] . second ;
2022-08-10 23:24:13 +08:00
auto iter = eventsToAck . begin ( ) + i ;
eventsToAck . erase ( iter ) ;
2022-11-14 23:52:05 +08:00
lock . unlock ( ) ;
for ( uint32_t i = 0 ; i < NEO : : EngineLimits : : maxHandleCount ; i + + ) {
if ( connectedDevice - > getNEODevice ( ) - > getDeviceBitfield ( ) . test ( i ) ) {
ackModuleEvents ( i , moduleUUID ) ;
}
}
2022-08-10 23:24:13 +08:00
return ZE_RESULT_SUCCESS ;
2022-05-09 23:52:12 +08:00
}
2022-08-10 23:24:13 +08:00
}
}
2022-05-09 23:52:12 +08:00
2022-08-10 23:24:13 +08:00
if ( apiEventToAck . type = = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD ) {
2022-09-14 17:23:40 +08:00
bool allIsaAcked = true ;
for ( uint32_t i = 0 ; i < NEO : : EngineLimits : : maxHandleCount ; i + + ) {
if ( connectedDevice - > getNEODevice ( ) - > getDeviceBitfield ( ) . test ( i ) ) {
if ( ! ackIsaEvents ( i , apiEventToAck . info . module . load ) ) {
allIsaAcked = false ;
}
}
}
if ( allIsaAcked ) {
2022-05-09 23:52:12 +08:00
return ZE_RESULT_SUCCESS ;
}
}
2022-08-10 23:24:13 +08:00
return ZE_RESULT_ERROR_UNINITIALIZED ;
2022-05-09 23:52:12 +08:00
}
2022-06-15 05:24:58 +08:00
ze_result_t DebugSessionLinux : : readSbaBuffer ( EuThread : : ThreadId threadId , NEO : : SbaTrackedAddresses & sbaBuffer ) {
2022-05-09 23:52:12 +08:00
auto vmHandle = allThreads [ threadId ] - > getMemoryHandle ( ) ;
if ( vmHandle = = invalidHandle ) {
return ZE_RESULT_ERROR_NOT_AVAILABLE ;
}
auto gpuVa = getSbaBufferGpuVa ( vmHandle ) ;
if ( gpuVa = = 0 ) {
return ZE_RESULT_ERROR_UNKNOWN ;
}
return readGpuMemory ( vmHandle , reinterpret_cast < char * > ( & sbaBuffer ) , sizeof ( sbaBuffer ) , gpuVa ) ;
}
uint64_t DebugSessionLinux : : getSbaBufferGpuVa ( uint64_t memoryHandle ) {
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-05-09 23:52:12 +08:00
auto bindInfo = clientHandleToConnection [ clientHandle ] - > vmToStateBaseAreaBindInfo . find ( memoryHandle ) ;
if ( bindInfo = = clientHandleToConnection [ clientHandle ] - > vmToStateBaseAreaBindInfo . end ( ) ) {
return 0 ;
}
return bindInfo - > second . gpuVa ;
}
uint64_t DebugSessionLinux : : getContextStateSaveAreaGpuVa ( uint64_t memoryHandle ) {
2022-08-26 01:33:23 +08:00
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-05-09 23:52:12 +08:00
auto bindInfo = clientHandleToConnection [ clientHandle ] - > vmToContextStateSaveAreaBindInfo . find ( memoryHandle ) ;
if ( bindInfo = = clientHandleToConnection [ clientHandle ] - > vmToContextStateSaveAreaBindInfo . end ( ) ) {
return 0 ;
}
return bindInfo - > second . gpuVa ;
}
2022-08-17 02:21:08 +08:00
void TileDebugSessionLinux : : readStateSaveAreaHeader ( ) {
2022-07-29 19:26:12 +08:00
2022-08-17 02:21:08 +08:00
const auto header = rootDebugSession - > getStateSaveAreaHeader ( ) ;
if ( header ) {
auto headerSize = rootDebugSession - > stateSaveAreaHeader . size ( ) ;
this - > stateSaveAreaHeader . assign ( reinterpret_cast < const char * > ( header ) , reinterpret_cast < const char * > ( header ) + headerSize ) ;
2023-01-20 23:13:50 +08:00
this - > sipSupportsSlm = rootDebugSession - > sipSupportsSlm ;
2022-08-17 02:21:08 +08:00
}
2022-07-29 19:26:12 +08:00
} ;
2022-08-26 01:33:23 +08:00
bool TileDebugSessionLinux : : insertModule ( zet_debug_event_info_module_t module ) {
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
modules . insert ( { module . load , module } ) ;
return isAttached ;
}
bool TileDebugSessionLinux : : removeModule ( zet_debug_event_info_module_t module ) {
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
modules . erase ( module . load ) ;
return isAttached ;
}
bool TileDebugSessionLinux : : processEntry ( ) {
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
processEntryState = true ;
return isAttached ;
}
bool TileDebugSessionLinux : : processExit ( ) {
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
processEntryState = false ;
return isAttached ;
}
void TileDebugSessionLinux : : attachTile ( ) {
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
// clear apiEvents queue
apiEvents = decltype ( apiEvents ) { } ;
if ( detached ) {
zet_debug_event_t debugEvent = { } ;
debugEvent . type = ZET_DEBUG_EVENT_TYPE_DETACHED ;
debugEvent . info . detached . reason = ZET_DEBUG_DETACH_REASON_INVALID ;
apiEvents . push ( debugEvent ) ;
} else {
if ( processEntryState ) {
zet_debug_event_t event = { } ;
event . type = ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY ;
event . flags = 0 ;
apiEvents . push ( event ) ;
}
if ( modules . size ( ) ) {
zet_debug_event_t event = { } ;
event . type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD ;
event . flags = 0 ;
for ( const auto & module : modules ) {
memcpy_s ( & event . info . module , sizeof ( event . info . module ) , & module . second , sizeof ( module . second ) ) ;
apiEvents . push ( event ) ;
}
}
}
isAttached = true ;
}
void TileDebugSessionLinux : : detachTile ( ) {
2022-11-14 23:52:05 +08:00
std : : vector < uint64_t > moduleUuids ;
2022-08-26 01:33:23 +08:00
{
std : : lock_guard < std : : mutex > lock ( asyncThreadMutex ) ;
2022-11-14 23:52:05 +08:00
for ( const auto & eventToAck : eventsToAck ) {
auto moduleUUID = eventToAck . second ;
moduleUuids . push_back ( moduleUUID ) ;
2022-08-26 01:33:23 +08:00
}
eventsToAck . clear ( ) ;
2022-11-14 23:52:05 +08:00
isAttached = false ;
}
for ( const auto & uuid : moduleUuids ) {
rootDebugSession - > ackModuleEvents ( this - > tileIndex , uuid ) ;
2022-08-26 01:33:23 +08:00
}
}
2022-05-09 23:52:12 +08:00
} // namespace L0