From 87f0dcda36b0170f7685d4f3c635f996f81da17e Mon Sep 17 00:00:00 2001 From: "Hoppe, Mateusz" Date: Fri, 13 Apr 2018 11:50:57 +0200 Subject: [PATCH] Source Level Debugger - add MI_LOAD_REG debug cmds - add 2 MI_LOAD_REGISTER_IMM cmds in preamble when debugger is active Change-Id: I4dd46a3c01fc95feadf8a12728ce801efe506e05 --- runtime/gen9/preamble.cpp | 4 +- runtime/helpers/preamble.h | 12 ++++ runtime/helpers/preamble.inl | 28 +++++++- unit_tests/gen9/preamble_tests.cpp | 14 ++++ unit_tests/preamble/preamble_tests.cpp | 92 ++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 2 deletions(-) diff --git a/runtime/gen9/preamble.cpp b/runtime/gen9/preamble.cpp index a89316820b..46fd7bd3f0 100644 --- a/runtime/gen9/preamble.cpp +++ b/runtime/gen9/preamble.cpp @@ -88,7 +88,9 @@ void PreambleHelper::programThreadArbitration(LinearStream *pCommandS template <> size_t PreambleHelper::getAdditionalCommandsSize(const Device &device) { - return PreemptionHelper::getRequiredPreambleSize(device) + sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL); + size_t totalSize = PreemptionHelper::getRequiredPreambleSize(device) + sizeof(MI_LOAD_REGISTER_IMM) + sizeof(PIPE_CONTROL); + totalSize += getKernelDebuggingCommandsSize(device.isSourceLevelDebuggerActive()); + return totalSize; } template struct PreambleHelper; diff --git a/runtime/helpers/preamble.h b/runtime/helpers/preamble.h index ef449efad2..8019dcfc86 100644 --- a/runtime/helpers/preamble.h +++ b/runtime/helpers/preamble.h @@ -50,8 +50,10 @@ struct PreambleHelper { static void programVFEState(LinearStream *pCommandStream, const HardwareInfo &hwInfo, int scratchSize, uint64_t scratchAddress); static void programPreamble(LinearStream *pCommandStream, Device &device, uint32_t l3Config, uint32_t requiredThreadArbitrationPolicy, GraphicsAllocation *preemptionCsr); + static void programKernelDebugging(LinearStream *pCommandStream); static uint32_t getL3Config(const HardwareInfo &hwInfo, bool useSLM); static size_t getAdditionalCommandsSize(const Device &device); + static size_t getKernelDebuggingCommandsSize(bool debuggingActive); static void programGenSpecificPreambleWorkArounds(LinearStream *pCommandStream, const HardwareInfo &hwInfo); static uint32_t getUrbEntryAllocationSize(); }; @@ -78,4 +80,14 @@ struct L3CNTLRegisterOffset { static const uint32_t registerOffset; }; +namespace DebugModeRegisterOffset { +static constexpr uint32_t registerOffset = 0x20ec; +static constexpr uint32_t debugEnabledValue = (1 << 6) | (1 << 22); +}; // namespace DebugModeRegisterOffset + +namespace TdDebugControlRegisterOffset { +static constexpr uint32_t registerOffset = 0xe400; +static constexpr uint32_t debugEnabledValue = (1 << 4) | (1 << 7); +}; // namespace TdDebugControlRegisterOffset + } // namespace OCLRT diff --git a/runtime/helpers/preamble.inl b/runtime/helpers/preamble.inl index 10c6773dc9..0e45bf5817 100644 --- a/runtime/helpers/preamble.inl +++ b/runtime/helpers/preamble.inl @@ -47,7 +47,8 @@ void PreambleHelper::programGenSpecificPreambleWorkArounds(LinearStre template size_t PreambleHelper::getAdditionalCommandsSize(const Device &device) { - return 0; + size_t totalSize = getKernelDebuggingCommandsSize(device.isSourceLevelDebuggerActive()); + return totalSize; } template @@ -84,6 +85,9 @@ void PreambleHelper::programPreamble(LinearStream *pCommandStream, De programL3(pCommandStream, l3Config); programThreadArbitration(pCommandStream, requiredThreadArbitrationPolicy); programPreemption(pCommandStream, device, preemptionCsr); + if (device.isSourceLevelDebuggerActive()) { + programKernelDebugging(pCommandStream); + } programGenSpecificPreambleWorkArounds(pCommandStream, device.getHardwareInfo()); } @@ -96,4 +100,26 @@ template uint32_t PreambleHelper::getUrbEntryAllocationSize() { return 0x782; } + +template +void PreambleHelper::programKernelDebugging(LinearStream *pCommandStream) { + auto pCmd = reinterpret_cast(pCommandStream->getSpace(sizeof(MI_LOAD_REGISTER_IMM))); + *pCmd = MI_LOAD_REGISTER_IMM::sInit(); + pCmd->setRegisterOffset(DebugModeRegisterOffset::registerOffset); + pCmd->setDataDword(DebugModeRegisterOffset::debugEnabledValue); + + auto pCmd2 = reinterpret_cast(pCommandStream->getSpace(sizeof(MI_LOAD_REGISTER_IMM))); + *pCmd2 = MI_LOAD_REGISTER_IMM::sInit(); + pCmd2->setRegisterOffset(TdDebugControlRegisterOffset::registerOffset); + pCmd2->setDataDword(TdDebugControlRegisterOffset::debugEnabledValue); +} + +template +size_t PreambleHelper::getKernelDebuggingCommandsSize(bool debuggingActive) { + if (debuggingActive) { + return 2 * sizeof(MI_LOAD_REGISTER_IMM); + } + return 0; +} + } // namespace OCLRT diff --git a/unit_tests/gen9/preamble_tests.cpp b/unit_tests/gen9/preamble_tests.cpp index 71aa0823cf..568cc1ffca 100644 --- a/unit_tests/gen9/preamble_tests.cpp +++ b/unit_tests/gen9/preamble_tests.cpp @@ -57,3 +57,17 @@ GEN9TEST_F(PreambleTestGen9, givenMidThreadPreemptionAndDisabledDebuggingWhenPre GEN9TEST_F(PreambleTestGen9, givenDisabledPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturned) { SourceLevelDebuggerPreambleTest::givenDisabledPreemptionAndDisabledDebuggingWhenPreambleSizeIsQueriedThenCorrecrSizeIsReturnedTest(); } + +GEN9TEST_F(PreambleTestGen9, givenKernelDebuggingActiveAndDisabledPreemptionWhenGetAdditionalCommandsSizeIsCalledThen2MiLoadRegisterImmCmdsAndStateSipAreInlcuded) { + auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); + + mockDevice->setSourceLevelDebuggerActive(false); + size_t withoutDebugging = PreambleHelper::getAdditionalCommandsSize(*mockDevice); + mockDevice->setSourceLevelDebuggerActive(true); + size_t withDebugging = PreambleHelper::getAdditionalCommandsSize(*mockDevice); + EXPECT_LT(withoutDebugging, withDebugging); + + size_t diff = withDebugging - withoutDebugging; + size_t sizeExpected = sizeof(typename FamilyType::STATE_SIP) + 2 * sizeof(typename FamilyType::MI_LOAD_REGISTER_IMM); + EXPECT_EQ(sizeExpected, diff); +} diff --git a/unit_tests/preamble/preamble_tests.cpp b/unit_tests/preamble/preamble_tests.cpp index 6a9bf8817d..b6c687ac4c 100644 --- a/unit_tests/preamble/preamble_tests.cpp +++ b/unit_tests/preamble/preamble_tests.cpp @@ -24,6 +24,7 @@ #include "runtime/helpers/preamble.h" #include "runtime/utilities/stackvec.h" #include "unit_tests/gen_common/test.h" +#include "unit_tests/helpers/hw_parse.h" #include "unit_tests/mocks/mock_device.h" #include "unit_tests/mocks/mock_graphics_allocation.h" @@ -74,3 +75,94 @@ HWTEST_F(PreambleTest, PreemptionIsTakenIntoAccountWhenProgrammingPreamble) { &preemptionBuffer[0], &preemptionBuffer[preemptionStream.getUsed()]); EXPECT_NE(&preambleBuffer[preambleStream.getUsed()], it); } + +HWTEST_F(PreambleTest, givenActiveKernelDebuggingWhenPreambleKernelDebuggingCommandsSizeIsQueriedThenCorrectSizeIsReturned) { + typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM; + auto size = PreambleHelper::getKernelDebuggingCommandsSize(true); + auto sizeExpected = 2 * sizeof(MI_LOAD_REGISTER_IMM); + EXPECT_EQ(sizeExpected, size); +} + +HWTEST_F(PreambleTest, givenInactiveKernelDebuggingWhenPreambleKernelDebuggingCommandsSizeIsQueriedThenZeroIsReturned) { + auto size = PreambleHelper::getKernelDebuggingCommandsSize(false); + EXPECT_EQ(0u, size); +} + +HWTEST_F(PreambleTest, whenKernelDebuggingCommandsAreProgrammedThenCorrectCommandsArePlacedIntoStream) { + typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM; + + auto bufferSize = PreambleHelper::getKernelDebuggingCommandsSize(true); + auto buffer = std::unique_ptr(new char[bufferSize]); + + LinearStream stream(buffer.get(), bufferSize); + PreambleHelper::programKernelDebugging(&stream); + + HardwareParse hwParser; + hwParser.parseCommands(stream); + auto cmdList = hwParser.getCommandsList(); + + ASSERT_EQ(2u, cmdList.size()); + + auto it = cmdList.begin(); + + MI_LOAD_REGISTER_IMM *pCmd = reinterpret_cast(*it); + EXPECT_EQ(DebugModeRegisterOffset::registerOffset, pCmd->getRegisterOffset()); + EXPECT_EQ(DebugModeRegisterOffset::debugEnabledValue, pCmd->getDataDword()); + + it++; + + pCmd = reinterpret_cast(*it); + EXPECT_EQ(TdDebugControlRegisterOffset::registerOffset, pCmd->getRegisterOffset()); + EXPECT_EQ(TdDebugControlRegisterOffset::debugEnabledValue, pCmd->getDataDword()); +} + +HWTEST_F(PreambleTest, givenKernelDebuggingActiveWhenPreambleIsProgrammedThenProgramKernelDebuggingIsCalled) { + typedef typename FamilyType::MI_LOAD_REGISTER_IMM MI_LOAD_REGISTER_IMM; + + auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); + + mockDevice->setPreemptionMode(PreemptionMode::Disabled); + mockDevice->setSourceLevelDebuggerActive(false); + + StackVec preambleBuffer(8192); + LinearStream preambleStream(&*preambleBuffer.begin(), preambleBuffer.size()); + + PreambleHelper::programPreamble(&preambleStream, *mockDevice, 0U, + ThreadArbitrationPolicy::RoundRobin, nullptr); + + HardwareParse hwParser; + hwParser.parseCommands(preambleStream); + auto cmdList = hwParser.getCommandsList(); + + auto miLoadRegImmCountWithoutDebugging = cmdList.size(); + + mockDevice->setSourceLevelDebuggerActive(true); + + StackVec preambleBuffer2(8192); + preambleStream.replaceBuffer(&*preambleBuffer2.begin(), preambleBuffer2.size()); + PreambleHelper::programPreamble(&preambleStream, *mockDevice, 0U, + ThreadArbitrationPolicy::RoundRobin, nullptr); + + HardwareParse hwParser2; + hwParser2.parseCommands(preambleStream); + cmdList = hwParser2.getCommandsList(); + + auto miLoadRegImmCountWithDebugging = cmdList.size(); + ASSERT_LT(miLoadRegImmCountWithoutDebugging, miLoadRegImmCountWithDebugging); + EXPECT_EQ(2u, miLoadRegImmCountWithDebugging - miLoadRegImmCountWithoutDebugging); +} + +HWTEST_F(PreambleTest, givenKernelDebuggingActiveAndMidThreadPreemptionWhenGetAdditionalCommandsSizeIsCalledThen2MiLoadRegisterImmCmdsAreAdded) { + auto mockDevice = std::unique_ptr(MockDevice::create(nullptr)); + mockDevice->setPreemptionMode(PreemptionMode::MidThread); + + mockDevice->setSourceLevelDebuggerActive(false); + size_t withoutDebugging = PreambleHelper::getAdditionalCommandsSize(*mockDevice); + mockDevice->setSourceLevelDebuggerActive(true); + size_t withDebugging = PreambleHelper::getAdditionalCommandsSize(*mockDevice); + EXPECT_LT(withoutDebugging, withDebugging); + + size_t diff = withDebugging - withoutDebugging; + size_t sizeExpected = 2 * sizeof(typename FamilyType::MI_LOAD_REGISTER_IMM); + EXPECT_EQ(sizeExpected, diff); +}