Files
compute-runtime/shared/test/unit_test/debugger/test_l0_debugger.cpp
Filip Hazubski 0d61860af6 fix: Reset builtins pointer after its resources are freed
Add resetBuiltins helper function to MockRootDeviceEnvironment.
Update tests to use the new function whenever builtins unique pointer
is reset to ensure that sip kernels are properly freed.

Related-To: HSD-18038645398, HSD-18038819112

Signed-off-by: Filip Hazubski <filip.hazubski@intel.com>
2024-06-20 10:49:56 +02:00

644 lines
29 KiB
C++

/*
* Copyright (C) 2020-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/built_ins/sip.h"
#include "shared/source/gen_common/reg_configs_common.h"
#include "shared/source/helpers/blit_helper.h"
#include "shared/source/helpers/gfx_core_helper.h"
#include "shared/source/helpers/preamble.h"
#include "shared/source/indirect_heap/heap_size.h"
#include "shared/source/memory_manager/allocation_properties.h"
#include "shared/source/os_interface/device_factory.h"
#include "shared/test/common/cmd_parse/gen_cmd_parse.h"
#include "shared/test/common/fixtures/device_fixture.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/default_hw_info.h"
#include "shared/test/common/mocks/mock_builtins.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/mock_gmm_helper.h"
#include "shared/test/common/mocks/mock_l0_debugger.h"
#include "shared/test/common/mocks/mock_memory_operations_handler.h"
#include "shared/test/common/test_macros/hw_test.h"
using namespace NEO;
TEST(Debugger, givenL0DebuggerWhenGettingL0DebuggerThenCorrectObjectIsReturned) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->setDebuggingMode(NEO::DebuggingMode::online);
auto hwInfo = *NEO::defaultHwInfo.get();
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo);
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->initializeMemoryManager();
std::unique_ptr<NEO::MockDevice> neoDevice(NEO::MockDevice::create<NEO::MockDevice>(executionEnvironment, 0u));
auto mockDebugger = new MockDebuggerL0(neoDevice.get());
executionEnvironment->rootDeviceEnvironments[0]->debugger.reset(mockDebugger);
auto debugger = neoDevice->getL0Debugger();
ASSERT_NE(nullptr, debugger);
EXPECT_EQ(mockDebugger, debugger);
}
TEST(Debugger, givenL0DebuggerOFFWhenGettingStateSaveAreaHeaderThenValidSipTypeIsReturned) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
executionEnvironment->prepareRootDeviceEnvironments(1);
auto hwInfo = *NEO::defaultHwInfo.get();
hwInfo.featureTable.flags.ftrLocalMemory = true;
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo);
auto &gfxCoreHelper = executionEnvironment->rootDeviceEnvironments[0]->getHelper<GfxCoreHelper>();
auto isHexadecimalArrayPreferred = gfxCoreHelper.isSipKernelAsHexadecimalArrayPreferred();
if (!isHexadecimalArrayPreferred) {
auto mockBuiltIns = new NEO::MockBuiltins();
MockRootDeviceEnvironment::resetBuiltins(executionEnvironment->rootDeviceEnvironments[0].get(), mockBuiltIns);
}
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->initializeMemoryManager();
std::unique_ptr<NEO::MockDevice> neoDevice(NEO::MockDevice::create<NEO::MockDevice>(executionEnvironment, 0u));
auto sipType = SipKernel::getSipKernelType(*neoDevice);
if (isHexadecimalArrayPreferred) {
SipKernel::initSipKernel(sipType, *neoDevice);
}
auto &stateSaveAreaHeader = SipKernel::getSipKernel(*neoDevice, nullptr).getStateSaveAreaHeader();
if (isHexadecimalArrayPreferred) {
auto sipKernel = neoDevice->getRootDeviceEnvironment().sipKernels[static_cast<uint32_t>(sipType)].get();
ASSERT_NE(sipKernel, nullptr);
auto &expectedStateSaveAreaHeader = sipKernel->getStateSaveAreaHeader();
EXPECT_EQ(expectedStateSaveAreaHeader, stateSaveAreaHeader);
} else {
auto &expectedStateSaveAreaHeader = neoDevice->getBuiltIns()->getSipKernel(sipType, *neoDevice).getStateSaveAreaHeader();
EXPECT_EQ(expectedStateSaveAreaHeader, stateSaveAreaHeader);
}
}
TEST(Debugger, givenDebuggingEnabledInExecEnvWhenAllocatingIsaThenSingleBankIsUsed) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->setDebuggingMode(NEO::DebuggingMode::online);
auto hwInfo = *NEO::defaultHwInfo.get();
hwInfo.featureTable.flags.ftrLocalMemory = true;
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo);
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->initializeMemoryManager();
std::unique_ptr<NEO::MockDevice> neoDevice(NEO::MockDevice::create<NEO::MockDevice>(executionEnvironment, 0u));
auto allocation = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{neoDevice->getRootDeviceIndex(), 4096, NEO::AllocationType::kernelIsa, neoDevice->getDeviceBitfield()});
if (allocation->getMemoryPool() == MemoryPool::localMemory) {
EXPECT_EQ(1u, allocation->storageInfo.getMemoryBanks());
} else {
EXPECT_EQ(0u, allocation->storageInfo.getMemoryBanks());
}
neoDevice->getMemoryManager()->freeGraphicsMemory(allocation);
}
TEST(Debugger, givenTileAttachAndDebuggingEnabledInExecEnvWhenAllocatingIsaThenMultipleBanksAreUsed) {
DebugManagerStateRestore restorer;
NEO::debugManager.flags.ExperimentalEnableTileAttach.set(1);
auto executionEnvironment = new NEO::ExecutionEnvironment();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->setDebuggingMode(NEO::DebuggingMode::online);
auto hwInfo = *NEO::defaultHwInfo.get();
hwInfo.featureTable.flags.ftrLocalMemory = true;
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo);
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->initializeMemoryManager();
std::unique_ptr<NEO::MockDevice> neoDevice(NEO::MockDevice::create<NEO::MockDevice>(executionEnvironment, 0u));
auto allocation = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{neoDevice->getRootDeviceIndex(), 4096, NEO::AllocationType::kernelIsa, DeviceBitfield{3}});
if (allocation->getMemoryPool() == MemoryPool::localMemory) {
EXPECT_EQ(3u, allocation->storageInfo.getMemoryBanks());
} else {
EXPECT_EQ(0u, allocation->storageInfo.getMemoryBanks());
}
neoDevice->getMemoryManager()->freeGraphicsMemory(allocation);
}
TEST(Debugger, WhenInitializingDebuggerL0ThenCapabilitiesAreAdjustedAndDebuggerIsCreated) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
executionEnvironment->incRefInternal();
executionEnvironment->prepareRootDeviceEnvironments(1);
auto hwInfo = *NEO::defaultHwInfo.get();
executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo);
executionEnvironment->rootDeviceEnvironments[0]->initGmm();
executionEnvironment->initializeMemoryManager();
executionEnvironment->setDebuggingMode(NEO::DebuggingMode::online);
auto neoDevice = std::unique_ptr<MockDevice>(MockDevice::create<MockDevice>(executionEnvironment, 0u));
executionEnvironment->rootDeviceEnvironments[0]->initDebuggerL0(neoDevice.get());
EXPECT_FALSE(executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo()->capabilityTable.fusedEuEnabled);
EXPECT_FALSE(executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo()->capabilityTable.ftrRenderCompressedBuffers);
EXPECT_FALSE(executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo()->capabilityTable.ftrRenderCompressedImages);
EXPECT_NE(nullptr, executionEnvironment->rootDeviceEnvironments[0]->debugger);
executionEnvironment->decRefInternal();
}
using L0DebuggerTest = Test<DeviceFixture>;
HWTEST_F(L0DebuggerTest, GivenDeviceWhenAllocateCalledThenDebuggerIsCreated) {
auto debugger = DebuggerL0Hw<FamilyType>::allocate(pDevice);
EXPECT_NE(nullptr, debugger);
delete debugger;
}
HWTEST_F(L0DebuggerTest, givenDebuggerWithoutMemoryOperationsHandlerWhenNotifyingModuleAllocationsThenNoAllocationIsResident) {
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(pDevice);
StackVec<NEO::GraphicsAllocation *, 32> allocs;
NEO::GraphicsAllocation alloc(0, 1u /*num gmms*/, NEO::AllocationType::internalHostMemory,
reinterpret_cast<void *>(0x1234), 0x1000, 0, sizeof(uint32_t),
MemoryPool::system4KBPages, MemoryManager::maxOsContextCount);
allocs.push_back(&alloc);
debugger->notifyModuleLoadAllocations(pDevice, allocs);
}
HWTEST_F(L0DebuggerTest, givenDebuggerWhenCreatedThenModuleHeapDebugAreaIsCreated) {
auto mockBlitMemoryToAllocation = [](const NEO::Device &device, NEO::GraphicsAllocation *memory, size_t offset, const void *hostPtr,
Vec3<size_t> size) -> NEO::BlitOperationResult {
memcpy(memory->getUnderlyingBuffer(), hostPtr, size.x);
return BlitOperationResult::success;
};
VariableBackup<NEO::BlitHelperFunctions::BlitMemoryToAllocationFunc> blitMemoryToAllocationFuncBackup(
&NEO::BlitHelperFunctions::blitMemoryToAllocation, mockBlitMemoryToAllocation);
auto memoryOperationsHandler = new NEO::MockMemoryOperations();
memoryOperationsHandler->makeResidentCalledCount = 0;
pDevice->executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface.reset(memoryOperationsHandler);
auto neoDevice = pDevice;
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(neoDevice);
auto debugArea = debugger->getModuleDebugArea();
EXPECT_EQ(1, memoryOperationsHandler->makeResidentCalledCount);
auto allocation = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
{neoDevice->getRootDeviceIndex(), 4096, NEO::AllocationType::kernelIsa, neoDevice->getDeviceBitfield()});
EXPECT_EQ(allocation->storageInfo.getMemoryBanks(), debugArea->storageInfo.getMemoryBanks());
DebugAreaHeader *header = reinterpret_cast<DebugAreaHeader *>(debugArea->getUnderlyingBuffer());
EXPECT_EQ(1u, header->pgsize);
uint64_t isShared = debugArea->storageInfo.getNumBanks() == 1 ? 1 : 0;
EXPECT_EQ(isShared, header->isShared);
EXPECT_STREQ("dbgarea", header->magic);
EXPECT_EQ(sizeof(DebugAreaHeader), header->size);
EXPECT_EQ(sizeof(DebugAreaHeader), header->scratchBegin);
EXPECT_EQ(MemoryConstants::pageSize64k - sizeof(DebugAreaHeader), header->scratchEnd);
neoDevice->getMemoryManager()->freeGraphicsMemory(allocation);
}
HWTEST_F(L0DebuggerTest, givenBindlessSipWhenModuleHeapDebugAreaIsCreatedThenReservedFieldIsSet) {
DebugManagerStateRestore restorer;
NEO::debugManager.flags.UseBindlessDebugSip.set(1);
auto mockBlitMemoryToAllocation = [](const NEO::Device &device, NEO::GraphicsAllocation *memory, size_t offset, const void *hostPtr,
Vec3<size_t> size) -> NEO::BlitOperationResult {
memcpy(memory->getUnderlyingBuffer(), hostPtr, size.x);
return BlitOperationResult::success;
};
VariableBackup<NEO::BlitHelperFunctions::BlitMemoryToAllocationFunc> blitMemoryToAllocationFuncBackup(
&NEO::BlitHelperFunctions::blitMemoryToAllocation, mockBlitMemoryToAllocation);
auto memoryOperationsHandler = new NEO::MockMemoryOperations();
pDevice->executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface.reset(memoryOperationsHandler);
memoryOperationsHandler->makeResidentCalledCount = 0;
auto neoDevice = pDevice;
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(neoDevice);
auto debugArea = debugger->getModuleDebugArea();
DebugAreaHeader *header = reinterpret_cast<DebugAreaHeader *>(debugArea->getUnderlyingBuffer());
EXPECT_EQ(1u, header->reserved1);
}
HWTEST_F(L0DebuggerTest, givenUseBindlessDebugSipZeroWhenModuleHeapDebugAreaIsCreatedThenReservedFieldIsSet) {
DebugManagerStateRestore restorer;
NEO::debugManager.flags.UseBindlessDebugSip.set(0);
auto mockBlitMemoryToAllocation = [](const NEO::Device &device, NEO::GraphicsAllocation *memory, size_t offset, const void *hostPtr,
Vec3<size_t> size) -> NEO::BlitOperationResult {
memcpy(memory->getUnderlyingBuffer(), hostPtr, size.x);
return BlitOperationResult::success;
};
VariableBackup<NEO::BlitHelperFunctions::BlitMemoryToAllocationFunc> blitMemoryToAllocationFuncBackup(
&NEO::BlitHelperFunctions::blitMemoryToAllocation, mockBlitMemoryToAllocation);
auto memoryOperationsHandler = new NEO::MockMemoryOperations();
pDevice->executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface.reset(memoryOperationsHandler);
memoryOperationsHandler->makeResidentCalledCount = 0;
auto neoDevice = pDevice;
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(neoDevice);
auto debugArea = debugger->getModuleDebugArea();
DebugAreaHeader *header = reinterpret_cast<DebugAreaHeader *>(debugArea->getUnderlyingBuffer());
EXPECT_EQ(1u, header->reserved1);
}
HWTEST_F(L0DebuggerTest, givenProgramDebuggingWhenGettingDebuggingModeThenCorrectModeIsReturned) {
DebuggingMode mode = NEO::getDebuggingMode(0);
EXPECT_TRUE(DebuggingMode::disabled == mode);
mode = NEO::getDebuggingMode(1);
EXPECT_TRUE(DebuggingMode::online == mode);
mode = NEO::getDebuggingMode(2);
EXPECT_TRUE(DebuggingMode::offline == mode);
mode = NEO::getDebuggingMode(3);
EXPECT_TRUE(DebuggingMode::disabled == mode);
}
using PerContextAddressSpaceL0DebuggerTest = L0DebuggerTest;
HWTEST_F(PerContextAddressSpaceL0DebuggerTest, givenCanonizedGpuVasWhenProgrammingSbaTrackingThenNonCanonicalAddressesAreStored) {
using MI_STORE_DATA_IMM = typename FamilyType::MI_STORE_DATA_IMM;
DebugManagerStateRestore restorer;
NEO::debugManager.flags.DebuggerForceSbaTrackingMode.set(0);
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(pDevice);
debugger->sbaTrackingGpuVa.address = 0x45670000;
auto expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, generalStateBaseAddress);
StackVec<char, 4096> buffer(4096);
NEO::LinearStream cmdStream(buffer.begin(), buffer.size());
uint64_t gsba = 0xffff800000060000;
uint64_t ssba = 0xffff801234567000;
uint64_t iba = 0xffff8000fff80000;
uint64_t ioba = 0xffff800008100000;
uint64_t dsba = 0xffff8000aaaa0000;
NEO::Debugger::SbaAddresses sbaAddresses = {};
sbaAddresses.generalStateBaseAddress = gsba;
sbaAddresses.surfaceStateBaseAddress = ssba;
sbaAddresses.instructionBaseAddress = iba;
sbaAddresses.indirectObjectBaseAddress = ioba;
sbaAddresses.dynamicStateBaseAddress = dsba;
sbaAddresses.bindlessSurfaceStateBaseAddress = ssba;
debugger->captureStateBaseAddress(cmdStream, sbaAddresses, false);
GenCmdList cmdList;
ASSERT_TRUE(FamilyType::Parse::parseCommandBuffer(cmdList, cmdStream.getCpuBase(), cmdStream.getUsed()));
EXPECT_EQ(6 * sizeof(MI_STORE_DATA_IMM), cmdStream.getUsed());
auto sdiItor = find<MI_STORE_DATA_IMM *>(cmdList.begin(), cmdList.end());
ASSERT_NE(cmdList.end(), sdiItor);
auto cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
EXPECT_EQ(static_cast<uint32_t>(gsba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(gsba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, surfaceStateBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(ssba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(ssba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, dynamicStateBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(dsba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(dsba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, indirectObjectBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(ioba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(ioba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, instructionBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(iba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(iba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, bindlessSurfaceStateBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(ssba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(ssba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
}
HWTEST_F(PerContextAddressSpaceL0DebuggerTest, givenNonZeroGpuVasWhenProgrammingSbaTrackingThenCorrectCmdsAreAddedToStream) {
using MI_STORE_DATA_IMM = typename FamilyType::MI_STORE_DATA_IMM;
DebugManagerStateRestore restorer;
NEO::debugManager.flags.DebuggerForceSbaTrackingMode.set(0);
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(pDevice);
debugger->singleAddressSpaceSbaTracking = 0;
debugger->sbaTrackingGpuVa.address = 0x45670000;
auto expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, generalStateBaseAddress);
StackVec<char, 4096> buffer(4096);
NEO::LinearStream cmdStream(buffer.begin(), buffer.size());
uint64_t gsba = 0x60000;
uint64_t ssba = 0x1234567000;
uint64_t iba = 0xfff80000;
uint64_t ioba = 0x8100000;
uint64_t dsba = 0xffffffffaaaa0000;
NEO::Debugger::SbaAddresses sbaAddresses = {};
sbaAddresses.generalStateBaseAddress = gsba;
sbaAddresses.surfaceStateBaseAddress = ssba;
sbaAddresses.instructionBaseAddress = iba;
sbaAddresses.indirectObjectBaseAddress = ioba;
sbaAddresses.dynamicStateBaseAddress = dsba;
sbaAddresses.bindlessSurfaceStateBaseAddress = ssba;
debugger->captureStateBaseAddress(cmdStream, sbaAddresses, false);
GenCmdList cmdList;
ASSERT_TRUE(FamilyType::Parse::parseCommandBuffer(cmdList, cmdStream.getCpuBase(), cmdStream.getUsed()));
EXPECT_EQ(6 * sizeof(MI_STORE_DATA_IMM), cmdStream.getUsed());
auto sdiItor = find<MI_STORE_DATA_IMM *>(cmdList.begin(), cmdList.end());
ASSERT_NE(cmdList.end(), sdiItor);
auto cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
EXPECT_EQ(static_cast<uint32_t>(gsba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(gsba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, surfaceStateBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(ssba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(ssba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, dynamicStateBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(dsba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(dsba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, indirectObjectBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(ioba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(ioba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, instructionBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(iba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(iba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
sdiItor++;
cmdSdi = genCmdCast<MI_STORE_DATA_IMM *>(*sdiItor);
expectedGpuVa = debugger->sbaTrackingGpuVa.address + offsetof(NEO::SbaTrackedAddresses, bindlessSurfaceStateBaseAddress);
EXPECT_EQ(static_cast<uint32_t>(ssba & 0x0000FFFFFFFFULL), cmdSdi->getDataDword0());
EXPECT_EQ(static_cast<uint32_t>(ssba >> 32), cmdSdi->getDataDword1());
EXPECT_EQ(expectedGpuVa, cmdSdi->getAddress());
EXPECT_TRUE(cmdSdi->getStoreQword());
}
using L0DebuggerMultiSubDeviceTest = L0DebuggerTest;
HWTEST_F(L0DebuggerMultiSubDeviceTest, givenMultiSubDevicesWhenSbaTrackingBuffersAllocatedThenThereIsSeparatePhysicalStorageForEveryContext) {
if (is32bit) {
GTEST_SKIP();
}
DebugManagerStateRestore restorer;
debugManager.flags.CreateMultipleRootDevices.set(1);
constexpr auto numSubDevices = 2u;
debugManager.flags.CreateMultipleSubDevices.set(2);
auto executionEnvironment = new NEO::ExecutionEnvironment;
auto devices = NEO::DeviceFactory::createDevices(*executionEnvironment);
auto neoDevice = devices[0].get();
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(neoDevice);
const auto &engines = neoDevice->getAllEngines();
EXPECT_LE(1u, engines.size());
for (auto &engine : engines) {
auto contextId = engine.osContext->getContextId();
const auto &storageInfo = debugger->perContextSbaAllocations[contextId]->storageInfo;
EXPECT_FALSE(storageInfo.cloningOfPageTables);
EXPECT_EQ(DeviceBitfield{maxNBitValue(numSubDevices)}, storageInfo.memoryBanks);
EXPECT_EQ(DeviceBitfield{maxNBitValue(numSubDevices)}, storageInfo.pageTablesVisibility);
EXPECT_EQ(engine.osContext->getDeviceBitfield().to_ulong(), storageInfo.memoryBanks.to_ulong());
EXPECT_TRUE(storageInfo.tileInstanced);
for (uint32_t i = 0; i < numSubDevices; i++) {
auto sbaHeader = reinterpret_cast<NEO::SbaTrackedAddresses *>(ptrOffset(debugger->perContextSbaAllocations[contextId]->getUnderlyingBuffer(),
debugger->perContextSbaAllocations[contextId]->getUnderlyingBufferSize() * i));
EXPECT_STREQ("sbaarea", sbaHeader->magic);
EXPECT_EQ(0u, sbaHeader->bindlessSamplerStateBaseAddress);
EXPECT_EQ(0u, sbaHeader->bindlessSurfaceStateBaseAddress);
EXPECT_EQ(0u, sbaHeader->dynamicStateBaseAddress);
EXPECT_EQ(0u, sbaHeader->generalStateBaseAddress);
EXPECT_EQ(0u, sbaHeader->indirectObjectBaseAddress);
EXPECT_EQ(0u, sbaHeader->instructionBaseAddress);
EXPECT_EQ(0u, sbaHeader->surfaceStateBaseAddress);
EXPECT_EQ(0u, sbaHeader->version);
}
if (!debugger->singleAddressSpaceSbaTracking) {
EXPECT_EQ(debugger->sbaTrackingGpuVa.address, debugger->perContextSbaAllocations[contextId]->getGpuAddress());
} else {
EXPECT_NE(debugger->sbaTrackingGpuVa.address, debugger->perContextSbaAllocations[contextId]->getGpuAddress());
}
}
const auto &subDevice0Engines = neoDevice->getSubDevice(0)->getAllEngines();
const auto &subDevice1Engines = neoDevice->getSubDevice(1)->getAllEngines();
auto subDeviceEngineSets = {subDevice0Engines, subDevice1Engines};
uint64_t subDeviceIndex = 0;
for (const auto &subDeviceEngines : subDeviceEngineSets) {
for (auto &engine : subDeviceEngines) {
auto contextId = engine.osContext->getContextId();
const auto &storageInfo = debugger->perContextSbaAllocations[contextId]->storageInfo;
EXPECT_FALSE(storageInfo.cloningOfPageTables);
EXPECT_EQ(DeviceBitfield{1llu << subDeviceIndex}, storageInfo.memoryBanks);
EXPECT_EQ(DeviceBitfield{1llu << subDeviceIndex}, storageInfo.pageTablesVisibility);
EXPECT_EQ(engine.osContext->getDeviceBitfield().to_ulong(), storageInfo.memoryBanks.to_ulong());
EXPECT_FALSE(storageInfo.tileInstanced);
if (!debugger->singleAddressSpaceSbaTracking) {
EXPECT_EQ(debugger->sbaTrackingGpuVa.address, debugger->perContextSbaAllocations[contextId]->getGpuAddress());
} else {
EXPECT_NE(debugger->sbaTrackingGpuVa.address, debugger->perContextSbaAllocations[contextId]->getGpuAddress());
}
}
subDeviceIndex++;
}
}
struct L0DebuggerSimpleParameterizedTest : public ::testing::TestWithParam<int>, DeviceFixture {
void SetUp() override {
NEO::debugManager.flags.DebuggerForceSbaTrackingMode.set(GetParam());
DeviceFixture::setUp();
}
void TearDown() override {
DeviceFixture::tearDown();
}
DebugManagerStateRestore restorer;
};
using Gen12Plus = IsAtLeastGfxCore<IGFX_GEN12_CORE>;
HWTEST2_P(L0DebuggerSimpleParameterizedTest, givenZeroGpuVasWhenProgrammingSbaTrackingThenStreamIsNotUsed, Gen12Plus) {
using MI_STORE_DATA_IMM = typename FamilyType::MI_STORE_DATA_IMM;
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(pDevice);
debugger->sbaTrackingGpuVa.address = 0x45670000;
StackVec<char, 4096> buffer(4096);
NEO::LinearStream cmdStream(buffer.begin(), buffer.size());
uint64_t gsba = 0;
uint64_t ssba = 0;
NEO::Debugger::SbaAddresses sbaAddresses = {};
sbaAddresses.generalStateBaseAddress = gsba;
sbaAddresses.surfaceStateBaseAddress = ssba;
debugger->captureStateBaseAddress(cmdStream, sbaAddresses, false);
EXPECT_EQ(0u, cmdStream.getUsed());
}
HWTEST2_P(L0DebuggerSimpleParameterizedTest, givenNotChangedSurfaceStateWhenCapturingSBAThenNoTrackingCmdsAreAdded, Gen12Plus) {
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(pDevice);
debugger->sbaTrackingGpuVa.address = 0x45670000;
NEO::CommandContainer container;
container.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
NEO::Debugger::SbaAddresses sba = {};
sba.surfaceStateBaseAddress = 0x123456000;
debugger->captureStateBaseAddress(*container.getCommandStream(), sba, false);
auto sizeUsed = container.getCommandStream()->getUsed();
EXPECT_NE(0u, sizeUsed);
sba.surfaceStateBaseAddress = 0;
debugger->captureStateBaseAddress(*container.getCommandStream(), sba, false);
auto sizeUsed2 = container.getCommandStream()->getUsed();
EXPECT_EQ(sizeUsed, sizeUsed2);
}
HWTEST2_P(L0DebuggerSimpleParameterizedTest, givenChangedBaseAddressesWhenCapturingSBAThenTrackingCmdsAreAdded, Gen12Plus) {
auto debugger = std::make_unique<MockDebuggerL0Hw<FamilyType>>(pDevice);
debugger->sbaTrackingGpuVa.address = 0x45670000;
{
NEO::CommandContainer container;
container.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
NEO::Debugger::SbaAddresses sba = {};
sba.surfaceStateBaseAddress = 0x123456000;
debugger->captureStateBaseAddress(*container.getCommandStream(), sba, false);
auto sizeUsed = container.getCommandStream()->getUsed();
EXPECT_NE(0u, sizeUsed);
}
{
NEO::CommandContainer container;
container.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
NEO::Debugger::SbaAddresses sba = {};
sba.generalStateBaseAddress = 0x123456000;
debugger->captureStateBaseAddress(*container.getCommandStream(), sba, false);
auto sizeUsed = container.getCommandStream()->getUsed();
EXPECT_NE(0u, sizeUsed);
}
{
NEO::CommandContainer container;
container.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, true, false);
NEO::Debugger::SbaAddresses sba = {};
sba.bindlessSurfaceStateBaseAddress = 0x123456000;
debugger->captureStateBaseAddress(*container.getCommandStream(), sba, false);
auto sizeUsed = container.getCommandStream()->getUsed();
EXPECT_NE(0u, sizeUsed);
}
}
INSTANTIATE_TEST_SUITE_P(SBAModesForDebugger, L0DebuggerSimpleParameterizedTest, ::testing::Values(0, 1));