diff --git a/runtime/device/device.cpp b/runtime/device/device.cpp index 85916416ca..48fe3ce4ce 100644 --- a/runtime/device/device.cpp +++ b/runtime/device/device.cpp @@ -22,6 +22,7 @@ #include "hw_cmds.h" #include "runtime/built_ins/built_ins.h" +#include "runtime/built_ins/sip.h" #include "runtime/command_stream/command_stream_receiver.h" #include "runtime/command_stream/device_command_stream.h" #include "runtime/command_stream/preemption.h" @@ -33,7 +34,9 @@ #include "runtime/helpers/debug_helpers.h" #include "runtime/helpers/options.h" #include "runtime/memory_manager/memory_manager.h" +#include "runtime/os_interface/os_interface.h" #include "runtime/os_interface/os_time.h" +#include "runtime/source_level_debugger/source_level_debugger.h" #include #include @@ -84,6 +87,12 @@ Device::Device(const HardwareInfo &hwInfo, engineType = DebugManager.flags.NodeOrdinal.get() == -1 ? hwInfo.capabilityTable.defaultEngineType : static_cast(DebugManager.flags.NodeOrdinal.get()); + + sourceLevelDebugger.reset(SourceLevelDebugger::create()); + if (sourceLevelDebugger) { + bool localMemorySipAvailable = (SipKernelType::DbgCsrLocal == SipKernel::getSipKernelType(hwInfo.pPlatform->eRenderCoreFamily, true)); + sourceLevelDebugger->initialize(localMemorySipAvailable); + } } Device::~Device() { @@ -163,6 +172,15 @@ bool Device::createDeviceImpl(const HardwareInfo *pHwInfo, } } + uint32_t deviceHandle = 0; + if (commandStreamReceiver->getOSInterface()) { + deviceHandle = commandStreamReceiver->getOSInterface()->getDeviceHandle(); + } + + if (pDevice->deviceInfo.sourceLevelDebuggerActive) { + pDevice->sourceLevelDebugger->notifyNewDevice(deviceHandle); + } + outDevice.memoryManager->setForce32BitAllocations(pDevice->getDeviceInfo().force32BitAddressess); outDevice.memoryManager->device = pDevice; diff --git a/runtime/device/device.h b/runtime/device/device.h index a3e9581f0a..3511b82efe 100644 --- a/runtime/device/device.h +++ b/runtime/device/device.h @@ -37,6 +37,7 @@ class MemoryManager; class OSTime; class DriverInfo; struct HardwareInfo; +class SourceLevelDebugger; template <> struct OpenCLObjectMapper<_cl_device_id> { @@ -169,6 +170,7 @@ class Device : public BaseObject<_cl_device_id> { PreemptionMode preemptionMode; EngineType engineType; + std::unique_ptr sourceLevelDebugger; }; template diff --git a/runtime/device/device_caps.cpp b/runtime/device/device_caps.cpp index bf66b80f2f..0bda5e822b 100644 --- a/runtime/device/device_caps.cpp +++ b/runtime/device/device_caps.cpp @@ -30,6 +30,7 @@ #include "runtime/os_interface/os_interface.h" #include "runtime/platform/extensions.h" #include "runtime/sharings/sharing_factory.h" +#include "runtime/source_level_debugger/source_level_debugger.h" #include "CL/cl_ext_intel.h" #include "driver_version.h" @@ -361,6 +362,6 @@ void Device::initializeCaps() { deviceInfo.preferredLocalAtomicAlignment = MemoryConstants::cacheLineSize; deviceInfo.preferredPlatformAtomicAlignment = MemoryConstants::cacheLineSize; - deviceInfo.sourceLevelDebuggerActive = false; + deviceInfo.sourceLevelDebuggerActive = sourceLevelDebugger ? sourceLevelDebugger->isDebuggerActive() : false; } } // namespace OCLRT diff --git a/runtime/program/kernel_info.h b/runtime/program/kernel_info.h index d745684225..0f25f1a143 100644 --- a/runtime/program/kernel_info.h +++ b/runtime/program/kernel_info.h @@ -117,6 +117,13 @@ struct WorkSizeInfo { void checkRatio(const size_t workItems[3]); }; +struct DebugData { + uint32_t vIsaSize = 0; + uint32_t genIsaSize = 0; + const char *vIsa = nullptr; + const char *genIsa = nullptr; +}; + struct KernelInfo { public: static KernelInfo *create(); @@ -243,5 +250,6 @@ struct KernelInfo { uint64_t kernelId = 0; bool isKernelHeapSubstituted = false; GraphicsAllocation *kernelAllocation = nullptr; + DebugData debugData; }; } // namespace OCLRT diff --git a/runtime/source_level_debugger/CMakeLists.txt b/runtime/source_level_debugger/CMakeLists.txt index c4e2c5b7b9..caffa18f52 100644 --- a/runtime/source_level_debugger/CMakeLists.txt +++ b/runtime/source_level_debugger/CMakeLists.txt @@ -28,7 +28,9 @@ else() set(RUNTIME_SRCS_SOURCE_LEVEL_DEBUGGER ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/source_level_debugger.h + ${CMAKE_CURRENT_SOURCE_DIR}/source_level_debugger_stubs.cpp ) endif() target_sources(${NEO_STATIC_LIB_NAME} PRIVATE ${RUNTIME_SRCS_SOURCE_LEVEL_DEBUGGER}) +set_property(GLOBAL PROPERTY RUNTIME_SRCS_SOURCE_LEVEL_DEBUGGER ${RUNTIME_SRCS_SOURCE_LEVEL_DEBUGGER}) diff --git a/runtime/source_level_debugger/source_level_debugger.cpp b/runtime/source_level_debugger/source_level_debugger.cpp index e87757681e..454834ffa8 100644 --- a/runtime/source_level_debugger/source_level_debugger.cpp +++ b/runtime/source_level_debugger/source_level_debugger.cpp @@ -23,6 +23,7 @@ #include "igfx_debug_interchange_types.h" #include "runtime/helpers/debug_helpers.h" +#include "runtime/program/kernel_info.h" #include "runtime/source_level_debugger/source_level_debugger.h" #include "runtime/os_interface/os_interface.h" @@ -32,39 +33,68 @@ const char *SourceLevelDebugger::notifySourceCodeSymbol = "notifySourceCode"; const char *SourceLevelDebugger::getDebuggerOptionSymbol = "getDebuggerOption"; const char *SourceLevelDebugger::notifyKernelDebugDataSymbol = "notifyKernelDebugData"; const char *SourceLevelDebugger::initSymbol = "init"; +const char *SourceLevelDebugger::isDebuggerActiveSymbol = "isDebuggerActive"; class SourceLevelDebugger::SourceLevelDebuggerInterface { public: SourceLevelDebuggerInterface() = default; ~SourceLevelDebuggerInterface() = default; - typedef int (*pfNotifyNewDevice)(GfxDbgNewDeviceData *data); - typedef int (*pfNotifySourceCode)(GfxDbgSourceCode *data); - typedef int (*pfGetDebuggerOption)(GfxDbgOption *); - typedef int (*pfNotifyKernelDebugData)(GfxDbgKernelDebugData *data); - typedef int (*pfInit)(GfxDbgTargetCaps *data); + typedef int (*NotifyNewDeviceFunction)(GfxDbgNewDeviceData *data); + typedef int (*NotifySourceCodeFunction)(GfxDbgSourceCode *data); + typedef int (*GetDebuggerOptionFunction)(GfxDbgOption *); + typedef int (*NotifyKernelDebugDataFunction)(GfxDbgKernelDebugData *data); + typedef int (*InitFunction)(GfxDbgTargetCaps *data); + typedef int (*IsDebuggerActiveFunction)(void); - pfNotifyNewDevice fNotifyNewDevice = nullptr; - pfNotifySourceCode fNotifySourceCode = nullptr; - pfGetDebuggerOption fGetDebuggerOption = nullptr; - pfNotifyKernelDebugData fNotifyKernelDebugData = nullptr; - pfInit fInit = nullptr; + NotifyNewDeviceFunction notifyNewDeviceFunc = nullptr; + NotifySourceCodeFunction notifySourceCodeFunc = nullptr; + GetDebuggerOptionFunction getDebuggerOptionFunc = nullptr; + NotifyKernelDebugDataFunction notifyKernelDebugDataFunc = nullptr; + InitFunction initFunc = nullptr; + IsDebuggerActiveFunction isDebuggerActive = nullptr; }; -SourceLevelDebugger::SourceLevelDebugger() { - debuggerLibrary.reset(SourceLevelDebugger::loadDebugger()); +SourceLevelDebugger *SourceLevelDebugger::create() { + auto library = SourceLevelDebugger::loadDebugger(); + if (library) { + auto isActiveFunc = reinterpret_cast(library->getProcAddress(isDebuggerActiveSymbol)); + int result = isActiveFunc(); + if (result == 1) { + // pass library ownership to Source Level Debugger + return new SourceLevelDebugger(library); + } + delete library; + } + return nullptr; +} +SourceLevelDebugger::SourceLevelDebugger(OsLibrary *library) { + debuggerLibrary.reset(library); if (debuggerLibrary.get() == nullptr) { return; } - interface = new SourceLevelDebuggerInterface; + sourceLevelDebuggerInterface = new SourceLevelDebuggerInterface; getFunctions(); - isActive = true; + + if (sourceLevelDebuggerInterface->isDebuggerActive == nullptr) { + return; + } + + int result = sourceLevelDebuggerInterface->isDebuggerActive(); + if (result == 1) { + UNRECOVERABLE_IF(sourceLevelDebuggerInterface->getDebuggerOptionFunc == nullptr); + UNRECOVERABLE_IF(sourceLevelDebuggerInterface->initFunc == nullptr); + UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyKernelDebugDataFunc == nullptr); + UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyNewDeviceFunc == nullptr); + UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifySourceCodeFunc == nullptr); + isActive = true; + } } SourceLevelDebugger::~SourceLevelDebugger() { - if (interface) { - delete interface; + if (sourceLevelDebuggerInterface) { + delete sourceLevelDebuggerInterface; } } @@ -75,11 +105,12 @@ bool SourceLevelDebugger::isDebuggerActive() { void SourceLevelDebugger::getFunctions() { UNRECOVERABLE_IF(debuggerLibrary.get() == nullptr); - interface->fNotifyNewDevice = reinterpret_cast(debuggerLibrary->getProcAddress(notifyNewDeviceSymbol)); - interface->fNotifySourceCode = reinterpret_cast(debuggerLibrary->getProcAddress(notifySourceCodeSymbol)); - interface->fGetDebuggerOption = reinterpret_cast(debuggerLibrary->getProcAddress(getDebuggerOptionSymbol)); - interface->fNotifyKernelDebugData = reinterpret_cast(debuggerLibrary->getProcAddress(notifyKernelDebugDataSymbol)); - interface->fInit = reinterpret_cast(debuggerLibrary->getProcAddress(initSymbol)); + sourceLevelDebuggerInterface->notifyNewDeviceFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyNewDeviceSymbol)); + sourceLevelDebuggerInterface->notifySourceCodeFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifySourceCodeSymbol)); + sourceLevelDebuggerInterface->getDebuggerOptionFunc = reinterpret_cast(debuggerLibrary->getProcAddress(getDebuggerOptionSymbol)); + sourceLevelDebuggerInterface->notifyKernelDebugDataFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyKernelDebugDataSymbol)); + sourceLevelDebuggerInterface->initFunc = reinterpret_cast(debuggerLibrary->getProcAddress(initSymbol)); + sourceLevelDebuggerInterface->isDebuggerActive = reinterpret_cast(debuggerLibrary->getProcAddress(isDebuggerActiveSymbol)); } void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const { @@ -88,7 +119,7 @@ void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const { newDevice.version = IGFXDBG_CURRENT_VERSION; newDevice.dh = reinterpret_cast(static_cast(deviceHandle)); newDevice.udh = GfxDeviceHandle(0); - interface->fNotifyNewDevice(&newDevice); + sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice); } } void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *source, size_t sourceSize) const { @@ -103,7 +134,7 @@ void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *so sourceCode.sourceName = &fileName[0]; sourceCode.sourceNameMaxLen = sizeof(fileName); - interface->fNotifySourceCode(&sourceCode); + sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode); } } @@ -116,7 +147,7 @@ bool SourceLevelDebugger::isOptimizationDisabled() const { option.valueLen = sizeof(value); option.value = &value; - int result = interface->fGetDebuggerOption(&option); + int result = sourceLevelDebuggerInterface->getDebuggerOptionFunc(&option); if (result == 1) { if (option.value[0] == '1') { return true; @@ -126,8 +157,33 @@ bool SourceLevelDebugger::isOptimizationDisabled() const { return false; } -void SourceLevelDebugger::notifyKernelDebugData() const { - GfxDbgKernelDebugData kernelDebugData; - interface->fNotifyKernelDebugData(&kernelDebugData); +void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const { + if (isActive) { + GfxDbgKernelDebugData kernelDebugData; + kernelDebugData.hDevice = reinterpret_cast(static_cast(deviceHandle)); + kernelDebugData.version = IGFXDBG_CURRENT_VERSION; + kernelDebugData.hProgram = reinterpret_cast(0); + + kernelDebugData.kernelName = kernelInfo->name.c_str(); + kernelDebugData.kernelBinBuffer = const_cast(kernelInfo->heapInfo.pKernelHeap); + kernelDebugData.KernelBinSize = kernelInfo->heapInfo.pKernelHeader->KernelHeapSize; + + kernelDebugData.dbgVisaBuffer = kernelInfo->debugData.vIsa; + kernelDebugData.dbgVisaSize = kernelInfo->debugData.vIsaSize; + kernelDebugData.dbgGenIsaBuffer = kernelInfo->debugData.genIsa; + kernelDebugData.dbgGenIsaSize = kernelInfo->debugData.genIsaSize; + + sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData); + } +} + +void SourceLevelDebugger::initialize(bool useLocalMemory) { + if (isActive) { + GfxDbgTargetCaps caps = {IGFXDBG_CURRENT_VERSION, useLocalMemory}; + int result = sourceLevelDebuggerInterface->initFunc(&caps); + if (static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS) { + isActive = false; + } + } } } // namespace OCLRT diff --git a/runtime/source_level_debugger/source_level_debugger.h b/runtime/source_level_debugger/source_level_debugger.h index 92dfa0c495..f8adc753cb 100644 --- a/runtime/source_level_debugger/source_level_debugger.h +++ b/runtime/source_level_debugger/source_level_debugger.h @@ -25,22 +25,26 @@ #include namespace OCLRT { +struct KernelInfo; + class SourceLevelDebugger { public: - SourceLevelDebugger(); + SourceLevelDebugger(OsLibrary *library); ~SourceLevelDebugger(); SourceLevelDebugger(const SourceLevelDebugger &ref) = delete; SourceLevelDebugger &operator=(const SourceLevelDebugger &) = delete; + static SourceLevelDebugger *create(); bool isDebuggerActive(); void notifyNewDevice(uint32_t deviceHandle) const; void notifySourceCode(uint32_t deviceHandle, const char *sourceCode, size_t size) const; bool isOptimizationDisabled() const; - void notifyKernelDebugData() const; + void notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const; + void initialize(bool useLocalMemory); protected: class SourceLevelDebuggerInterface; - SourceLevelDebuggerInterface *interface = nullptr; + SourceLevelDebuggerInterface *sourceLevelDebuggerInterface = nullptr; static OsLibrary *loadDebugger(); void getFunctions(); @@ -53,6 +57,7 @@ class SourceLevelDebugger { static const char *getDebuggerOptionSymbol; static const char *notifyKernelDebugDataSymbol; static const char *initSymbol; + static const char *isDebuggerActiveSymbol; // OS specific library name static const char *dllName; }; diff --git a/runtime/source_level_debugger/source_level_debugger_stubs.cpp b/runtime/source_level_debugger/source_level_debugger_stubs.cpp new file mode 100644 index 0000000000..db2b82de89 --- /dev/null +++ b/runtime/source_level_debugger/source_level_debugger_stubs.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "runtime/source_level_debugger/source_level_debugger.h" + +namespace OCLRT { + +SourceLevelDebugger::SourceLevelDebugger(OsLibrary *library) { + debuggerLibrary.reset(library); +} + +SourceLevelDebugger::~SourceLevelDebugger() { +} + +SourceLevelDebugger *SourceLevelDebugger::create() { + return nullptr; +} + +bool SourceLevelDebugger::isDebuggerActive() { + return false; +} + +void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const { +} +void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *sourceCode, size_t size) const { +} +bool SourceLevelDebugger::isOptimizationDisabled() const { + return false; +} +void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const { +} +void SourceLevelDebugger::initialize(bool useLocalMemory) { +} + +} // namespace OCLRT diff --git a/unit_tests/libult/source_level_debugger_library.cpp b/unit_tests/libult/source_level_debugger_library.cpp index 9e71ccbc2e..009b23ac43 100644 --- a/unit_tests/libult/source_level_debugger_library.cpp +++ b/unit_tests/libult/source_level_debugger_library.cpp @@ -25,7 +25,7 @@ using namespace OCLRT; -bool DebuggerLibrary::isDebuggerActive = false; +bool DebuggerLibrary::debuggerActive = false; bool DebuggerLibrary::isLibraryAvailable = false; DebuggerLibraryInterceptor *DebuggerLibrary::interceptor = nullptr; @@ -40,6 +40,8 @@ void *DebuggerLibrary::getProcAddress(const std::string &procName) { return reinterpret_cast(notifyKernelDebugData); } else if (procName == "init") { return reinterpret_cast(init); + } else if (procName == "isDebuggerActive") { + return reinterpret_cast(isDebuggerActive); } return nullptr; } @@ -55,16 +57,18 @@ int DebuggerLibrary::notifyNewDevice(GfxDbgNewDeviceData *newDevice) { if (interceptor) { interceptor->newDeviceArgIn = *newDevice; interceptor->newDeviceCalled = true; + return interceptor->newDeviceRetVal; } - return 0; + return IgfxdbgRetVal::IGFXDBG_SUCCESS; } int DebuggerLibrary::notifySourceCode(GfxDbgSourceCode *sourceCode) { if (interceptor) { interceptor->sourceCodeArgIn = *sourceCode; interceptor->sourceCodeCalled = true; + return interceptor->sourceCodeRetVal; } - return 0; + return IgfxdbgRetVal::IGFXDBG_SUCCESS; } int DebuggerLibrary::getDebuggerOption(GfxDbgOption *option) { @@ -77,21 +81,27 @@ int DebuggerLibrary::getDebuggerOption(GfxDbgOption *option) { } return interceptor->optionRetVal; } - return true; + return IgfxdbgRetVal::IGFXDBG_SUCCESS; } int DebuggerLibrary::notifyKernelDebugData(GfxDbgKernelDebugData *kernelDebugData) { if (interceptor) { interceptor->kernelDebugDataArgIn = *kernelDebugData; interceptor->kernelDebugDataCalled = true; + return interceptor->kernelDebugDataRetVal; } - return 0; + return IgfxdbgRetVal::IGFXDBG_SUCCESS; } int DebuggerLibrary::init(GfxDbgTargetCaps *targetCaps) { if (interceptor) { interceptor->targetCapsArgIn = *targetCaps; - interceptor->targetCapsCalled = true; + interceptor->initCalled = true; + return interceptor->initRetVal; } - return 0; + return IgfxdbgRetVal::IGFXDBG_SUCCESS; +} + +int DebuggerLibrary::isDebuggerActive(void) { + return debuggerActive ? 1 : 0; } diff --git a/unit_tests/libult/source_level_debugger_library.h b/unit_tests/libult/source_level_debugger_library.h index d2d858c413..1ffe734423 100644 --- a/unit_tests/libult/source_level_debugger_library.h +++ b/unit_tests/libult/source_level_debugger_library.h @@ -43,13 +43,13 @@ struct DebuggerLibraryInterceptor { bool sourceCodeCalled = false; bool optionCalled = false; bool kernelDebugDataCalled = false; - bool targetCapsCalled = false; + bool initCalled = false; int newDeviceRetVal = 0; int sourceCodeRetVal = 0; int optionRetVal = 0; int kernelDebugDataRetVal = 0; - int targetCapsRetVal = 0; + int initRetVal = 0; }; class DebuggerLibrary : public OCLRT::OsLibrary { @@ -64,11 +64,11 @@ class DebuggerLibrary : public OCLRT::OsLibrary { } static void setDebuggerActive(bool active) { - isDebuggerActive = active; + debuggerActive = active; } static bool getDebuggerActive() { - return isDebuggerActive; + return debuggerActive; } static void setLibraryAvailable(bool available) { @@ -95,7 +95,8 @@ class DebuggerLibrary : public OCLRT::OsLibrary { static int getDebuggerOption(GfxDbgOption *); static int notifyKernelDebugData(GfxDbgKernelDebugData *); static int init(GfxDbgTargetCaps *); + static int isDebuggerActive(void); static bool isLibraryAvailable; - static bool isDebuggerActive; + static bool debuggerActive; }; diff --git a/unit_tests/libult/ult_command_stream_receiver.h b/unit_tests/libult/ult_command_stream_receiver.h index 91c1bb85fa..0fe98ae768 100644 --- a/unit_tests/libult/ult_command_stream_receiver.h +++ b/unit_tests/libult/ult_command_stream_receiver.h @@ -21,7 +21,6 @@ */ #pragma once -#include "runtime/memory_manager/os_agnostic_memory_manager.h" #include "runtime/command_stream/command_stream_receiver_hw.h" #include "runtime/memory_manager/os_agnostic_memory_manager.h" #include diff --git a/unit_tests/mocks/mock_device.h b/unit_tests/mocks/mock_device.h index ffac548b3a..f4576d6e26 100644 --- a/unit_tests/mocks/mock_device.h +++ b/unit_tests/mocks/mock_device.h @@ -36,7 +36,9 @@ class MockMemoryManager; class MockDevice : public Device { public: using Device::commandStreamReceiver; + using Device::createDeviceImpl; using Device::initializeCaps; + using Device::sourceLevelDebugger; void setOSTime(OSTime *osTime); void setDriverInfo(DriverInfo *driverInfo); diff --git a/unit_tests/source_level_debugger/device_tests.cpp b/unit_tests/source_level_debugger/device_tests.cpp index 20650ec120..57e03dae43 100644 --- a/unit_tests/source_level_debugger/device_tests.cpp +++ b/unit_tests/source_level_debugger/device_tests.cpp @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include "runtime/source_level_debugger/source_level_debugger.h" #include "unit_tests/fixtures/device_fixture.h" #include "unit_tests/helpers/debug_manager_state_restore.h" #include "unit_tests/mocks/mock_builtins.h" @@ -32,7 +33,18 @@ using namespace OCLRT; class MockDeviceWithActiveDebugger : public MockDevice { public: - MockDeviceWithActiveDebugger(const HardwareInfo &hwInfo, bool isRootDevice = true) : MockDevice(hwInfo, isRootDevice) {} + class MockOsLibrary : public OsLibrary { + public: + void *getProcAddress(const std::string &procName) override { + return nullptr; + } + bool isLoaded() override { + return false; + } + }; + MockDeviceWithActiveDebugger(const HardwareInfo &hwInfo, bool isRootDevice = true) : MockDevice(hwInfo, isRootDevice) { + sourceLevelDebugger.reset(new SourceLevelDebugger(new MockOsLibrary)); + } void initializeCaps() override { MockDevice::initializeCaps(); diff --git a/unit_tests/source_level_debugger/source_level_debugger_tests.cpp b/unit_tests/source_level_debugger/source_level_debugger_tests.cpp index 63d84450e4..b5b414938f 100644 --- a/unit_tests/source_level_debugger/source_level_debugger_tests.cpp +++ b/unit_tests/source_level_debugger/source_level_debugger_tests.cpp @@ -20,12 +20,19 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include "runtime/device/device.h" +#include "runtime/os_interface/os_interface.h" +#include "runtime/program/kernel_info.h" #include "runtime/source_level_debugger/source_level_debugger.h" +#include "unit_tests/fixtures/device_fixture.h" #include "unit_tests/libult/source_level_debugger_library.h" +#include "unit_tests/libult/create_command_stream.h" #include +#include using namespace OCLRT; +using std::unique_ptr; class DebuggerLibraryRestorer { public: @@ -45,7 +52,7 @@ class DebuggerLibraryRestorer { class MockSourceLevelDebugger : public SourceLevelDebugger { public: using SourceLevelDebugger::debuggerLibrary; - MockSourceLevelDebugger() = default; + MockSourceLevelDebugger() : SourceLevelDebugger(SourceLevelDebugger::loadDebugger()) {} void setActive(bool active) { isActive = active; } @@ -59,7 +66,7 @@ TEST(SourceLevelDebugger, givenNoKernelDebuggerLibraryWhenSourceLevelDebuggerIsC EXPECT_EQ(nullptr, debugger.debuggerLibrary.get()); } -TEST(SourceLevelDebugger, givenKernelDebuggerLibraryAvailableWhenIsDebuggerActiveIsCalledThenLibraryIsLoadedAndFalseIsReturned) { +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryAvailableWhenSourceLevelDebuggerIsConstructedThenLibraryIsLoaded) { DebuggerLibraryRestorer restorer; DebuggerLibrary::setLibraryAvailable(true); @@ -67,10 +74,20 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryAvailableWhenIsDebuggerActiv EXPECT_NE(nullptr, debugger.debuggerLibrary.get()); } -TEST(SourceLevelDebugger, givenKernelDebuggerLibraryAvailableWhenIsDebuggerActiveIsCalledThenTrueIsReturned) { +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryAvailableWhenIsDebuggerActiveIsCalledThenFalseIsReturned) { DebuggerLibraryRestorer restorer; DebuggerLibrary::setLibraryAvailable(true); + MockSourceLevelDebugger debugger; + bool active = debugger.isDebuggerActive(); + EXPECT_FALSE(active); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenIsDebuggerActiveIsCalledThenTrueIsReturned) { + DebuggerLibraryRestorer restorer; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + MockSourceLevelDebugger debugger; bool active = debugger.isDebuggerActive(); EXPECT_TRUE(active); @@ -90,6 +107,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenNotifySourceCodeIs DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); MockSourceLevelDebugger debugger; @@ -110,6 +128,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifySourceCod DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(false); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); MockSourceLevelDebugger debugger; @@ -126,6 +145,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenNotifyNewDeviceIsC DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); MockSourceLevelDebugger debugger; @@ -140,6 +160,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifyNewDevice DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(false); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); MockSourceLevelDebugger debugger; @@ -154,6 +175,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenIsOptimizationDisa DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); MockSourceLevelDebugger debugger; @@ -186,6 +208,7 @@ TEST(SourceLevelDebugger, givenActiveDebuggerWhenGetDebuggerOptionReturnsZeroThe DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); char value = '1'; @@ -205,6 +228,7 @@ TEST(SourceLevelDebugger, givenActiveDebuggerAndOptDisabledWhenGetDebuggerOption DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); char value = '1'; @@ -224,6 +248,7 @@ TEST(SourceLevelDebugger, givenActiveDebuggerAndOptDisabledWhenGetDebuggerOption DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); char value = '0'; @@ -243,10 +268,178 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenNotifyKernelDebugD DebuggerLibraryInterceptor interceptor; DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); MockSourceLevelDebugger debugger; - debugger.notifyKernelDebugData(); + char isa[8]; + char dbgIsa[10]; + char visa[12]; + + KernelInfo info; + info.debugData.genIsa = dbgIsa; + info.debugData.vIsa = visa; + info.debugData.genIsaSize = sizeof(dbgIsa); + info.debugData.vIsaSize = sizeof(visa); + + info.name = "debugKernel"; + + SKernelBinaryHeaderCommon kernelHeader; + kernelHeader.KernelHeapSize = sizeof(isa); + info.heapInfo.pKernelHeader = &kernelHeader; + info.heapInfo.pKernelHeap = isa; + + debugger.notifyKernelDebugData(6, &info); EXPECT_TRUE(interceptor.kernelDebugDataCalled); -} \ No newline at end of file + + EXPECT_EQ(static_cast(IGFXDBG_CURRENT_VERSION), interceptor.kernelDebugDataArgIn.version); + EXPECT_EQ(reinterpret_cast(6), interceptor.kernelDebugDataArgIn.hDevice); + EXPECT_EQ(reinterpret_cast(0), interceptor.kernelDebugDataArgIn.hProgram); + + EXPECT_EQ(dbgIsa, interceptor.kernelDebugDataArgIn.dbgGenIsaBuffer); + EXPECT_EQ(sizeof(dbgIsa), interceptor.kernelDebugDataArgIn.dbgGenIsaSize); + EXPECT_EQ(visa, interceptor.kernelDebugDataArgIn.dbgVisaBuffer); + EXPECT_EQ(sizeof(visa), interceptor.kernelDebugDataArgIn.dbgVisaSize); + + EXPECT_EQ(kernelHeader.KernelHeapSize, interceptor.kernelDebugDataArgIn.KernelBinSize); + EXPECT_EQ(isa, interceptor.kernelDebugDataArgIn.kernelBinBuffer); + EXPECT_STREQ(info.name.c_str(), interceptor.kernelDebugDataArgIn.kernelName); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifyKernelDebugDataIsCalledThenDebuggerLibraryFunctionIsNotCalled) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(false); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + MockSourceLevelDebugger debugger; + + debugger.setActive(false); + KernelInfo info; + debugger.notifyKernelDebugData(6, &info); + EXPECT_FALSE(interceptor.kernelDebugDataCalled); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenInitializeIsCalledWithLocalMemoryUsageFalseThenDebuggerFunctionIsCalledWithCorrectArg) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + MockSourceLevelDebugger debugger; + + debugger.initialize(false); + EXPECT_TRUE(interceptor.initCalled); + EXPECT_FALSE(interceptor.targetCapsArgIn.supportsLocalMemory); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenInitializeReturnsErrorThenIsActiveIsSetToFalse) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + MockSourceLevelDebugger debugger; + + interceptor.initRetVal = IgfxdbgRetVal::IGFXDBG_FAILURE; + debugger.initialize(false); + EXPECT_TRUE(interceptor.initCalled); + EXPECT_FALSE(debugger.isDebuggerActive()); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenInitializeIsCalledWithLocalMemoryUsageTrueThenDebuggerFunctionIsCalledWithCorrectArg) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + MockSourceLevelDebugger debugger; + + debugger.initialize(true); + EXPECT_TRUE(interceptor.initCalled); + EXPECT_TRUE(interceptor.targetCapsArgIn.supportsLocalMemory); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenInitializeIsCalledThenDebuggerFunctionIsNotCalled) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(false); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + MockSourceLevelDebugger debugger; + + debugger.initialize(false); + EXPECT_FALSE(interceptor.initCalled); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenDeviceIsConstructedThenDebuggerIsInitialized) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + unique_ptr device(new MockDevice(*platformDevices[0])); + EXPECT_TRUE(interceptor.initCalled); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenDeviceImplIsCreatedThenDebuggerIsNotified) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + unique_ptr device(new MockDevice(*platformDevices[0])); + MockDevice::createDeviceImpl(platformDevices[0], true, *device.get()); + EXPECT_TRUE(interceptor.newDeviceCalled); + uint32_t deviceHandleExpected = device->getCommandStreamReceiver().getOSInterface() != nullptr ? device->getCommandStreamReceiver().getOSInterface()->getDeviceHandle() : 0; + EXPECT_EQ(reinterpret_cast(static_cast(deviceHandleExpected)), interceptor.newDeviceArgIn.dh); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenDeviceImplIsCreatedWithOsCsrThenDebuggerIsNotifiedWithCorrectDeviceHandle) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(true); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + overrideCommandStreamReceiverCreation = true; + + // Device::create must be used to create correct OS memory manager + unique_ptr device(Device::create(platformDevices[0])); + ASSERT_NE(nullptr, device->getCommandStreamReceiver().getOSInterface()); + + EXPECT_TRUE(interceptor.newDeviceCalled); + uint32_t deviceHandleExpected = device->getCommandStreamReceiver().getOSInterface()->getDeviceHandle(); + EXPECT_EQ(reinterpret_cast(static_cast(deviceHandleExpected)), interceptor.newDeviceArgIn.dh); +} + +TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenDeviceIsCreatedThenDebuggerIsNotCreatedInitializedAndNotNotified) { + DebuggerLibraryRestorer restorer; + + DebuggerLibraryInterceptor interceptor; + DebuggerLibrary::setLibraryAvailable(true); + DebuggerLibrary::setDebuggerActive(false); + DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor); + + unique_ptr device(DeviceHelper<>::create()); + + EXPECT_EQ(nullptr, device->sourceLevelDebugger.get()); + EXPECT_FALSE(interceptor.initCalled); + EXPECT_FALSE(interceptor.newDeviceCalled); +}