/* * Copyright (C) 2018-2024 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/built_ins/sip.h" #include "shared/source/built_ins/built_ins.h" #include "shared/source/debug_settings/debug_settings_manager.h" #include "shared/source/debugger/debugger.h" #include "shared/source/debugger/debugger_l0.h" #include "shared/source/device/device.h" #include "shared/source/execution_environment/execution_environment.h" #include "shared/source/execution_environment/root_device_environment.h" #include "shared/source/helpers/aligned_memory.h" #include "shared/source/helpers/debug_helpers.h" #include "shared/source/helpers/gfx_core_helper.h" #include "shared/source/helpers/hw_info.h" #include "shared/source/helpers/string.h" #include "shared/source/memory_manager/allocation_properties.h" #include "shared/source/memory_manager/graphics_allocation.h" #include "shared/source/memory_manager/memory_manager.h" #include "shared/source/utilities/io_functions.h" #include "common/StateSaveAreaHeader.h" namespace NEO { SipClassType SipKernel::classType = SipClassType::init; std::vector readFile(const std::string &fileName, size_t &retSize) { std::vector retBuf; FILE *fileDescriptor = nullptr; long int size = 0; size_t bytesRead = 0u; retSize = 0; fileDescriptor = IoFunctions::fopenPtr(fileName.c_str(), "rb"); if (fileDescriptor == NULL) { return retBuf; } IoFunctions::fseekPtr(fileDescriptor, 0, SEEK_END); size = IoFunctions::ftellPtr(fileDescriptor); UNRECOVERABLE_IF(size == -1); IoFunctions::rewindPtr(fileDescriptor); retBuf.resize(size); bytesRead = IoFunctions::freadPtr(retBuf.data(), 1, size, fileDescriptor); IoFunctions::fclosePtr(fileDescriptor); if (static_cast(bytesRead) != size || bytesRead == 0u) { retBuf.clear(); } else { retSize = bytesRead; } return retBuf; } SipKernel::~SipKernel() = default; SipKernel::SipKernel(SipKernelType type, GraphicsAllocation *sipAlloc, std::vector ssah) : stateSaveAreaHeader(std::move(ssah)), sipAllocation(sipAlloc), type(type) { } SipKernel::SipKernel(SipKernelType type, GraphicsAllocation *sipAlloc, std::vector ssah, std::vector binary) : stateSaveAreaHeader(std::move(ssah)), binary(std::move(binary)), sipAllocation(sipAlloc), type(type) { } GraphicsAllocation *SipKernel::getSipAllocation() const { return sipAllocation; } const std::vector &SipKernel::getStateSaveAreaHeader() const { return stateSaveAreaHeader; } const std::vector &SipKernel::getBinary() const { return binary; } size_t SipKernel::getStateSaveAreaSize(Device *device) const { auto &hwInfo = device->getHardwareInfo(); auto &gfxCoreHelper = device->getGfxCoreHelper(); auto maxDbgSurfaceSize = gfxCoreHelper.getSipKernelMaxDbgSurfaceSize(hwInfo); const auto &stateSaveAreaHeader = getStateSaveAreaHeader(); if (stateSaveAreaHeader.empty()) { return maxDbgSurfaceSize; } if (strcmp(stateSaveAreaHeader.data(), "tssarea")) { return maxDbgSurfaceSize; } auto hdr = reinterpret_cast(stateSaveAreaHeader.data()); auto numSlices = NEO::GfxCoreHelper::getHighestEnabledSlice(hwInfo); size_t stateSaveAreaSize = 0; if (hdr->versionHeader.version.major >= 3) { stateSaveAreaSize = numSlices * hdr->regHeaderV3.num_subslices_per_slice * hdr->regHeaderV3.num_eus_per_subslice * hdr->regHeaderV3.num_threads_per_eu * hdr->regHeaderV3.state_save_size + hdr->versionHeader.size * 8 + hdr->regHeaderV3.state_area_offset; stateSaveAreaSize += hdr->regHeaderV3.fifo_size * sizeof(SIP::fifo_node); } else { stateSaveAreaSize = numSlices * 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) { if (device.getDebugger() != nullptr) { return SipKernelType::dbgBindless; } bool debuggingEnabled = device.getDebugger() != nullptr; return getSipKernelType(device, debuggingEnabled); } SipKernelType SipKernel::getSipKernelType(Device &device, bool debuggingEnabled) { auto &gfxCoreHelper = device.getGfxCoreHelper(); return gfxCoreHelper.getSipKernelType(debuggingEnabled); } bool SipKernel::initBuiltinsSipKernel(SipKernelType type, Device &device, OsContext *context) { if (context) { device.getBuiltIns()->getSipKernel(device, context); } else { device.getBuiltIns()->getSipKernel(type, device); } return true; } bool SipKernel::initRawBinaryFromFileKernel(SipKernelType type, Device &device, std::string &fileName) { uint32_t sipIndex = static_cast(type); uint32_t rootDeviceIndex = device.getRootDeviceIndex(); auto &rootDeviceEnvironment = device.getRootDeviceEnvironment(); if (rootDeviceEnvironment.sipKernels[sipIndex].get() != nullptr) { return true; } size_t bytesRead = 0u; auto fileData = readFile(fileName, bytesRead); if (bytesRead) { void *alignedBuffer = alignedMalloc(bytesRead, MemoryConstants::pageSize); memcpy_s(alignedBuffer, bytesRead, fileData.data(), bytesRead); const auto allocType = AllocationType::kernelIsaInternal; AllocationProperties properties = {rootDeviceIndex, bytesRead, allocType, device.getDeviceBitfield()}; properties.flags.use32BitFrontWindow = false; auto sipAllocation = device.getMemoryManager()->allocateGraphicsMemoryWithProperties(properties); if (sipAllocation == nullptr) { alignedFree(alignedBuffer); return false; } auto &productHelper = device.getProductHelper(); MemoryTransferHelper::transferMemoryToAllocation(productHelper.isBlitCopyRequiredForLocalMemory(rootDeviceEnvironment, *sipAllocation), device, sipAllocation, 0, alignedBuffer, bytesRead); alignedFree(alignedBuffer); auto headerFilename = createHeaderFilename(fileName); std::vector stateSaveAreaHeader = readStateSaveAreaHeaderFromFile(headerFilename); device.getExecutionEnvironment()->rootDeviceEnvironments[rootDeviceIndex]->sipKernels[sipIndex] = std::make_unique(type, sipAllocation, std::move(stateSaveAreaHeader)); return true; } return false; } std::vector SipKernel::readStateSaveAreaHeaderFromFile(const std::string &fileName) { std::vector data; size_t bytesRead = 0u; data = readFile(fileName, bytesRead); return data; } std::string SipKernel::createHeaderFilename(const std::string &fileName) { std::string_view coreName(fileName); auto extensionPos = coreName.find('.'); std::string ext = ""; if (extensionPos != coreName.npos) { ext = coreName.substr(extensionPos, coreName.size() - extensionPos); coreName.remove_suffix(coreName.size() - extensionPos); } std::string headerFilename(coreName); headerFilename += "_header" + ext; return headerFilename; } bool SipKernel::initHexadecimalArraySipKernel(SipKernelType type, Device &device) { uint32_t sipIndex = static_cast(type); uint32_t rootDeviceIndex = device.getRootDeviceIndex(); auto sipKenel = device.getExecutionEnvironment()->rootDeviceEnvironments[rootDeviceIndex]->sipKernels[sipIndex].get(); if (sipKenel != nullptr) { return true; } uint32_t *sipKernelBinary = nullptr; size_t kernelBinarySize = 0u; auto &rootDeviceEnvironment = device.getRootDeviceEnvironment(); auto &gfxCoreHelper = device.getGfxCoreHelper(); gfxCoreHelper.setSipKernelData(sipKernelBinary, kernelBinarySize, rootDeviceEnvironment); const auto allocType = AllocationType::kernelIsaInternal; AllocationProperties properties = {rootDeviceIndex, kernelBinarySize, allocType, device.getDeviceBitfield()}; properties.flags.use32BitFrontWindow = false; auto sipAllocation = device.getMemoryManager()->allocateGraphicsMemoryWithProperties(properties); if (sipAllocation == nullptr) { return false; } auto &productHelper = device.getProductHelper(); MemoryTransferHelper::transferMemoryToAllocation(productHelper.isBlitCopyRequiredForLocalMemory(rootDeviceEnvironment, *sipAllocation), device, sipAllocation, 0, sipKernelBinary, kernelBinarySize); std::vector emptyStateSaveAreaHeader; device.getExecutionEnvironment()->rootDeviceEnvironments[rootDeviceIndex]->sipKernels[sipIndex] = std::make_unique(type, sipAllocation, std::move(emptyStateSaveAreaHeader)); return true; } void SipKernel::freeSipKernels(RootDeviceEnvironment *rootDeviceEnvironment, MemoryManager *memoryManager) { for (auto &sipKernel : rootDeviceEnvironment->sipKernels) { if (sipKernel.get()) { memoryManager->freeGraphicsMemory(sipKernel->getSipAllocation()); sipKernel.reset(); } } } void SipKernel::selectSipClassType(std::string &fileName, Device &device) { const GfxCoreHelper &gfxCoreHelper = device.getGfxCoreHelper(); const std::string unknown("unk"); if (fileName.compare(unknown) == 0) { bool debuggingEnabled = device.getDebugger() != nullptr; if (debuggingEnabled) { SipKernel::classType = SipClassType::builtins; } else { SipKernel::classType = gfxCoreHelper.isSipKernelAsHexadecimalArrayPreferred() ? SipClassType::hexadecimalHeaderFile : SipClassType::builtins; } } else { SipKernel::classType = SipClassType::rawBinaryFromFile; } if (debugManager.flags.ForceSipClass.get() != -1) { SipKernel::classType = static_cast(debugManager.flags.ForceSipClass.get()); } } bool SipKernel::initSipKernelImpl(SipKernelType type, Device &device, OsContext *context) { std::string fileName = debugManager.flags.LoadBinarySipFromFile.get(); SipKernel::selectSipClassType(fileName, device); switch (SipKernel::classType) { case SipClassType::rawBinaryFromFile: return SipKernel::initRawBinaryFromFileKernel(type, device, fileName); case SipClassType::hexadecimalHeaderFile: return SipKernel::initHexadecimalArraySipKernel(type, device); default: return SipKernel::initBuiltinsSipKernel(type, device, context); } } const SipKernel &SipKernel::getSipKernelImpl(Device &device) { auto sipType = SipKernel::getSipKernelType(device); switch (SipKernel::classType) { case SipClassType::rawBinaryFromFile: case SipClassType::hexadecimalHeaderFile: return *device.getRootDeviceEnvironment().sipKernels[static_cast(sipType)].get(); default: return device.getBuiltIns()->getSipKernel(sipType, device); } } const SipKernel &SipKernel::getBindlessDebugSipKernel(Device &device) { auto debugSipType = SipKernelType::dbgBindless; SipKernel::initSipKernelImpl(debugSipType, device, nullptr); switch (SipKernel::classType) { case SipClassType::rawBinaryFromFile: return *device.getRootDeviceEnvironment().sipKernels[static_cast(debugSipType)].get(); default: return device.getBuiltIns()->getSipKernel(debugSipType, device); } } const SipKernel &SipKernel::getBindlessDebugSipKernel(Device &device, OsContext *context) { auto debugSipType = SipKernelType::dbgBindless; SipKernel::initSipKernelImpl(debugSipType, device, context); switch (SipKernel::classType) { case SipClassType::rawBinaryFromFile: return *device.getRootDeviceEnvironment().sipKernels[static_cast(debugSipType)].get(); default: return device.getBuiltIns()->getSipKernel(device, context); } } void SipKernel::parseBinaryForContextId() { const int pattern = 0xCAFEBEAD; auto memory = reinterpret_cast(binary.data()); const auto sizeInDwords = binary.size() / sizeof(int); for (size_t i = 1; i < sizeInDwords; i++) { auto currentDword = memory + i; if (*currentDword == pattern) { for (size_t j = 1; (j < 16) && (i + j < sizeInDwords); j++) { if (*(currentDword + j) == pattern) { contextIdOffsets[0] = i; contextIdOffsets[1] = i + j; break; } } break; } } } } // namespace NEO