diff --git a/level_zero/core/source/device/device_imp.cpp b/level_zero/core/source/device/device_imp.cpp index f39a7e9aa1..25a88154b7 100644 --- a/level_zero/core/source/device/device_imp.cpp +++ b/level_zero/core/source/device/device_imp.cpp @@ -789,13 +789,27 @@ Device *Device::create(DriverHandle *driverHandle, NEO::Device *neoDevice, bool device->cacheReservation = CacheReservation::create(*device); device->maxNumHwThreads = NEO::HwHelper::getMaxThreadsForVfe(neoDevice->getHardwareInfo()); + auto debugSurfaceSize = NEO::SipKernel::maxDbgSurfaceSize; + std::vector stateSaveAreaHeader; + + if (neoDevice->getCompilerInterface()) { + if (neoDevice->getPreemptionMode() == NEO::PreemptionMode::MidThread || neoDevice->getDebugger()) { + bool ret = NEO::SipKernel::initSipKernel(NEO::SipKernel::getSipKernelType(*neoDevice), *neoDevice); + UNRECOVERABLE_IF(!ret); + + stateSaveAreaHeader = NEO::SipKernel::getSipKernel(*neoDevice).getStateSaveAreaHeader(); + debugSurfaceSize = NEO::SipKernel::getSipKernel(*neoDevice).getStateSaveAreaSize(); + } + } else { + *returnValue = ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; + } + const bool allocateDebugSurface = (device->getL0Debugger() || neoDevice->getDeviceInfo().debuggerActive) && !isSubDevice; NEO::GraphicsAllocation *debugSurface = nullptr; - if (allocateDebugSurface) { debugSurface = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties( {device->getRootDeviceIndex(), true, - NEO::SipKernel::maxDbgSurfaceSize, + debugSurfaceSize, NEO::GraphicsAllocation::AllocationType::DEBUG_CONTEXT_SAVE_AREA, false, false, @@ -803,6 +817,14 @@ Device *Device::create(DriverHandle *driverHandle, NEO::Device *neoDevice, bool device->setDebugSurface(debugSurface); } + if (debugSurface && stateSaveAreaHeader.size() > 0) { + auto &hwInfo = neoDevice->getHardwareInfo(); + auto &hwHelper = NEO::HwHelper::get(hwInfo.platform.eRenderCoreFamily); + NEO::MemoryTransferHelper::transferMemoryToAllocation(hwHelper.isBlitCopyRequiredForLocalMemory(hwInfo, *debugSurface), + *neoDevice, debugSurface, 0, stateSaveAreaHeader.data(), + stateSaveAreaHeader.size()); + } + for (auto &neoSubDevice : device->neoDevice->getSubDevices()) { if (!neoSubDevice) { continue; @@ -820,24 +842,6 @@ Device *Device::create(DriverHandle *driverHandle, NEO::Device *neoDevice, bool } device->numSubDevices = static_cast(device->subDevices.size()); - if (neoDevice->getCompilerInterface()) { - auto &hwInfo = neoDevice->getHardwareInfo(); - if (neoDevice->getPreemptionMode() == NEO::PreemptionMode::MidThread || neoDevice->getDebugger()) { - bool ret = NEO::SipKernel::initSipKernel(NEO::SipKernel::getSipKernelType(*neoDevice), *neoDevice); - UNRECOVERABLE_IF(!ret); - - auto &stateSaveAreaHeader = NEO::SipKernel::getSipKernel(*neoDevice).getStateSaveAreaHeader(); - if (debugSurface && stateSaveAreaHeader.size() > 0) { - auto &hwHelper = NEO::HwHelper::get(hwInfo.platform.eRenderCoreFamily); - NEO::MemoryTransferHelper::transferMemoryToAllocation(hwHelper.isBlitCopyRequiredForLocalMemory(hwInfo, *debugSurface), - *neoDevice, debugSurface, 0, stateSaveAreaHeader.data(), - stateSaveAreaHeader.size()); - } - } - } else { - *returnValue = ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; - } - auto supportDualStorageSharedMemory = neoDevice->getMemoryManager()->isLocalMemorySupported(device->neoDevice->getRootDeviceIndex()); if (NEO::DebugManager.flags.AllocateSharedAllocationsWithCpuAndGpuStorage.get() != -1) { supportDualStorageSharedMemory = NEO::DebugManager.flags.AllocateSharedAllocationsWithCpuAndGpuStorage.get(); diff --git a/shared/source/built_ins/sip.cpp b/shared/source/built_ins/sip.cpp index 66f5012fd2..e11296866d 100644 --- a/shared/source/built_ins/sip.cpp +++ b/shared/source/built_ins/sip.cpp @@ -21,6 +21,8 @@ #include "shared/source/memory_manager/memory_manager.h" #include "shared/source/utilities/io_functions.h" +#include "common/StateSaveAreaHeader.h" + namespace NEO { const size_t SipKernel::maxDbgSurfaceSize = 0x1800000; // proper value should be taken from compiler when it's ready @@ -70,6 +72,28 @@ const std::vector &SipKernel::getStateSaveAreaHeader() const { return stateSaveAreaHeader; } +size_t SipKernel::getStateSaveAreaSize() const { + auto stateSaveAreaHeader = getStateSaveAreaHeader(); + if (stateSaveAreaHeader.empty()) { + return SipKernel::maxDbgSurfaceSize; + } + + if (strcmp(stateSaveAreaHeader.data(), "tssarea")) { + return SipKernel::maxDbgSurfaceSize; + } + + auto hdr = reinterpret_cast(stateSaveAreaHeader.data()); + DEBUG_BREAK_IF(hdr->versionHeader.size * 8 != sizeof(SIP::StateSaveAreaHeader)); + + auto stateSaveAreaSize = hdr->regHeader.num_slices * + hdr->regHeader.num_subslices_per_slice * + hdr->regHeader.num_eus_per_subslice * + hdr->regHeader.num_threads_per_eu * + hdr->regHeader.state_save_size + + hdr->versionHeader.size * 8 + hdr->regHeader.state_area_offset; + return alignUp(stateSaveAreaSize, MemoryConstants::pageSize); +} + SipKernelType SipKernel::getSipKernelType(Device &device) { bool debuggingEnabled = device.getDebugger() != nullptr || device.isDebuggerActive(); return getSipKernelType(device, debuggingEnabled); diff --git a/shared/source/built_ins/sip.h b/shared/source/built_ins/sip.h index 962780e69b..5c5d21e5ba 100644 --- a/shared/source/built_ins/sip.h +++ b/shared/source/built_ins/sip.h @@ -34,6 +34,7 @@ class SipKernel { MOCKABLE_VIRTUAL GraphicsAllocation *getSipAllocation() const; MOCKABLE_VIRTUAL const std::vector &getStateSaveAreaHeader() const; + MOCKABLE_VIRTUAL size_t getStateSaveAreaSize() const; static bool initSipKernel(SipKernelType type, Device &device); static void freeSipKernels(RootDeviceEnvironment *rootDeviceEnvironment, MemoryManager *memoryManager); diff --git a/shared/test/common/helpers/sip_init.cpp b/shared/test/common/helpers/sip_init.cpp index 194f7373bc..7d987eeb0b 100644 --- a/shared/test/common/helpers/sip_init.cpp +++ b/shared/test/common/helpers/sip_init.cpp @@ -9,6 +9,8 @@ #include "shared/source/memory_manager/os_agnostic_memory_manager.h" #include "shared/test/common/mocks/mock_sip.h" +#include "common/StateSaveAreaHeader.h" + #include namespace NEO { @@ -24,6 +26,54 @@ void clearUseFlags() { calledType = SipKernelType::COUNT; called = false; } + +std::vector createStateSaveAreaHeader() { + SIP::StateSaveAreaHeader stateSaveAreaHeader = { + { + // versionHeader + "tssarea", // magic + 0, // reserved1 + { // version + 1, // major + 0, // minor + 0}, // patch + 40, // size + {0, 0, 0}, // reserved2 + }, + { + // regHeader + 1, // num_slices + 6, // num_subslices_per_slice + 16, // num_eus_per_subslice + 7, // num_threads_per_eu + 0, // state_area_offset + 6144, // state_save_size + 0, // slm_area_offset + 0, // slm_bank_size + 0, // slm_bank_valid + 4740, // sr_magic_offset + {0, 128, 256, 32}, // grf + {4096, 1, 256, 32}, // addr + {4128, 2, 32, 4}, // flag + {4156, 1, 32, 4}, // emask + {4160, 2, 128, 16}, // sr + {4192, 1, 128, 16}, // cr + {4256, 1, 96, 12}, // notification + {4288, 1, 128, 16}, // tdr + {4320, 10, 256, 32}, // acc + {0, 0, 0, 0}, // mme + {4672, 1, 32, 4}, // ce + {4704, 1, 128, 16}, // sp + {0, 0, 0, 0}, // cmd + {4640, 1, 128, 16}, // tm + {0, 0, 0, 0}, // fc + {4736, 1, 32, 4}, // dbg + }, + }; + + char *begin = reinterpret_cast(&stateSaveAreaHeader); + return std::vector(begin, begin + sizeof(stateSaveAreaHeader)); +} } // namespace MockSipData bool SipKernel::initSipKernel(SipKernelType type, Device &device) { diff --git a/shared/test/common/mocks/mock_sip.h b/shared/test/common/mocks/mock_sip.h index e9d275624e..be5cdef017 100644 --- a/shared/test/common/mocks/mock_sip.h +++ b/shared/test/common/mocks/mock_sip.h @@ -46,5 +46,6 @@ extern bool returned; extern bool useMockSip; void clearUseFlags(); +std::vector createStateSaveAreaHeader(); } // namespace MockSipData } // namespace NEO diff --git a/shared/test/unit_test/built_ins/sip_tests.cpp b/shared/test/unit_test/built_ins/sip_tests.cpp index dffa5d3172..a33fe9ef0a 100644 --- a/shared/test/unit_test/built_ins/sip_tests.cpp +++ b/shared/test/unit_test/built_ins/sip_tests.cpp @@ -265,7 +265,6 @@ TEST_F(RawBinarySipTest, givenRawBinaryFileWhenInitSipKernelTwiceThenSipIsLoaded ASSERT_NE(nullptr, secondSipKernel); auto secondStoredAllocation = sipKernel->getSipAllocation(); EXPECT_NE(nullptr, secondStoredAllocation); - EXPECT_EQ(sipKernel, secondSipKernel); EXPECT_EQ(storedAllocation, secondStoredAllocation); } @@ -317,3 +316,23 @@ TEST_F(HexadecimalHeaderSipTest, whenInitHexadecimalArraySipKernelIsCalledTwiceT auto sipAllocation2 = sipKernel2.getSipAllocation(); EXPECT_EQ(sipAllocation, sipAllocation2); } + +using StateSaveAreaSipTest = Test; + +TEST_F(StateSaveAreaSipTest, givenEmptyStateSaveAreaHeaderWhenGetStateSaveAreaSizeCalledThenMaxDbgSurfaceSizeIsReturned) { + MockSipData::useMockSip = true; + MockSipData::mockSipKernel->mockStateSaveAreaHeader.clear(); + EXPECT_EQ(SipKernel::maxDbgSurfaceSize, SipKernel::getSipKernel(*pDevice).getStateSaveAreaSize()); +} + +TEST_F(StateSaveAreaSipTest, givenCorruptedStateSaveAreaHeaderWhenGetStateSaveAreaSizeCalledThenMaxDbgSurfaceSizeIsReturned) { + MockSipData::useMockSip = true; + MockSipData::mockSipKernel->mockStateSaveAreaHeader = {'g', 'a', 'r', 'b', 'a', 'g', 'e'}; + EXPECT_EQ(SipKernel::maxDbgSurfaceSize, SipKernel::getSipKernel(*pDevice).getStateSaveAreaSize()); +} + +TEST_F(StateSaveAreaSipTest, givenCorrectStateSaveAreaHeaderWhenGetStateSaveAreaSizeCalledThenCorrectDbgSurfaceSizeIsReturned) { + MockSipData::useMockSip = true; + MockSipData::mockSipKernel->mockStateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(); + EXPECT_EQ(0x3F1000u, SipKernel::getSipKernel(*pDevice).getStateSaveAreaSize()); +}