1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
|
/*
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "opencl/source/command_stream/aub_command_stream_receiver.h"
#include "shared/source/execution_environment/execution_environment.h"
#include "shared/source/execution_environment/root_device_environment.h"
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/hw_helper.h"
#include "shared/source/helpers/hw_info.h"
#include "shared/source/helpers/options.h"
#include "opencl/source/memory_manager/os_agnostic_memory_manager.h"
#include "opencl/source/os_interface/os_inc_base.h"
#include <algorithm>
#include <cstring>
#include <sstream>
namespace NEO {
AubCommandStreamReceiverCreateFunc aubCommandStreamReceiverFactory[IGFX_MAX_CORE] = {};
std::string AUBCommandStreamReceiver::createFullFilePath(const HardwareInfo &hwInfo, const std::string &filename) {
std::string hwPrefix = hardwarePrefix[hwInfo.platform.eProductFamily];
// Generate the full filename
const auto >SystemInfo = hwInfo.gtSystemInfo;
std::stringstream strfilename;
auto subDevicesCount = HwHelper::getSubDevicesCount(&hwInfo);
uint32_t subSlicesPerSlice = gtSystemInfo.SubSliceCount / gtSystemInfo.SliceCount;
strfilename << hwPrefix << "_";
if (subDevicesCount > 1) {
strfilename << subDevicesCount << "tx";
}
strfilename << gtSystemInfo.SliceCount << "x" << subSlicesPerSlice << "x" << gtSystemInfo.MaxEuPerSubSlice << "_" << filename << ".aub";
// clean-up any fileName issues because of the file system incompatibilities
auto fileName = strfilename.str();
for (char &i : fileName) {
i = i == '/' ? '_' : i;
}
std::string filePath(folderAUB);
filePath.append(Os::fileSeparator);
filePath.append(fileName);
return filePath;
}
CommandStreamReceiver *AUBCommandStreamReceiver::create(const std::string &baseName, bool standalone, ExecutionEnvironment &executionEnvironment, uint32_t rootDeviceIndex) {
auto hwInfo = executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo();
std::string filePath = AUBCommandStreamReceiver::createFullFilePath(*hwInfo, baseName);
if (DebugManager.flags.AUBDumpCaptureFileName.get() != "unk") {
filePath.assign(DebugManager.flags.AUBDumpCaptureFileName.get());
}
if (hwInfo->platform.eRenderCoreFamily >= IGFX_MAX_CORE) {
DEBUG_BREAK_IF(!false);
return nullptr;
}
auto pCreate = aubCommandStreamReceiverFactory[hwInfo->platform.eRenderCoreFamily];
return pCreate ? pCreate(filePath, standalone, executionEnvironment, rootDeviceIndex) : nullptr;
}
} // namespace NEO
namespace AubMemDump {
using CmdServicesMemTraceMemoryCompare = AubMemDump::CmdServicesMemTraceMemoryCompare;
using CmdServicesMemTraceMemoryWrite = AubMemDump::CmdServicesMemTraceMemoryWrite;
using CmdServicesMemTraceRegisterPoll = AubMemDump::CmdServicesMemTraceRegisterPoll;
using CmdServicesMemTraceRegisterWrite = AubMemDump::CmdServicesMemTraceRegisterWrite;
using CmdServicesMemTraceVersion = AubMemDump::CmdServicesMemTraceVersion;
static auto sizeMemoryWriteHeader = sizeof(CmdServicesMemTraceMemoryWrite) - sizeof(CmdServicesMemTraceMemoryWrite::data);
extern const size_t g_dwordCountMax;
void AubFileStream::open(const char *filePath) {
fileHandle.open(filePath, std::ofstream::binary);
fileName.assign(filePath);
}
void AubFileStream::close() {
fileHandle.close();
fileName.clear();
}
void AubFileStream::write(const char *data, size_t size) {
fileHandle.write(data, size);
}
void AubFileStream::flush() {
fileHandle.flush();
}
bool AubFileStream::init(uint32_t stepping, uint32_t device) {
CmdServicesMemTraceVersion header = {};
header.setHeader();
header.dwordCount = (sizeof(header) / sizeof(uint32_t)) - 1;
header.stepping = stepping;
header.metal = 0;
header.device = device;
header.csxSwizzling = CmdServicesMemTraceVersion::CsxSwizzlingValues::Disabled;
//Which recording method used:
// Phys is required for GGTT memory to be written directly to phys vs through aperture.
header.recordingMethod = CmdServicesMemTraceVersion::RecordingMethodValues::Phy;
header.pch = CmdServicesMemTraceVersion::PchValues::Default;
header.captureTool = CmdServicesMemTraceVersion::CaptureToolValues::GenKmdCapture;
header.primaryVersion = 0;
header.secondaryVersion = 0;
header.commandLine[0] = 'N';
header.commandLine[1] = 'E';
header.commandLine[2] = 'O';
header.commandLine[3] = 0;
write(reinterpret_cast<char *>(&header), sizeof(header));
return true;
}
void AubFileStream::writeMemory(uint64_t physAddress, const void *memory, size_t size, uint32_t addressSpace, uint32_t hint) {
writeMemoryWriteHeader(physAddress, size, addressSpace, hint);
// Copy the contents from source to destination.
write(reinterpret_cast<const char *>(memory), size);
auto sizeRemainder = size % sizeof(uint32_t);
if (sizeRemainder) {
//if input size is not 4 byte aligned, write extra zeros to AUB
uint32_t zero = 0;
write(reinterpret_cast<char *>(&zero), sizeof(uint32_t) - sizeRemainder);
}
}
void AubFileStream::writeMemoryWriteHeader(uint64_t physAddress, size_t size, uint32_t addressSpace, uint32_t hint) {
CmdServicesMemTraceMemoryWrite header = {};
auto alignedBlockSize = (size + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
auto dwordCount = (sizeMemoryWriteHeader + alignedBlockSize) / sizeof(uint32_t);
DEBUG_BREAK_IF(dwordCount > AubMemDump::g_dwordCountMax);
header.setHeader();
header.dwordCount = static_cast<uint32_t>(dwordCount - 1);
header.address = physAddress;
header.repeatMemory = CmdServicesMemTraceMemoryWrite::RepeatMemoryValues::NoRepeat;
header.tiling = CmdServicesMemTraceMemoryWrite::TilingValues::NoTiling;
header.dataTypeHint = hint;
header.addressSpace = addressSpace;
header.dataSizeInBytes = static_cast<uint32_t>(size);
write(reinterpret_cast<const char *>(&header), sizeMemoryWriteHeader);
}
void AubFileStream::writeGTT(uint32_t gttOffset, uint64_t entry) {
write(reinterpret_cast<char *>(&entry), sizeof(entry));
}
void AubFileStream::writePTE(uint64_t physAddress, uint64_t entry, uint32_t addressSpace) {
write(reinterpret_cast<char *>(&entry), sizeof(entry));
}
void AubFileStream::writeMMIOImpl(uint32_t offset, uint32_t value) {
CmdServicesMemTraceRegisterWrite header = {};
header.setHeader();
header.dwordCount = (sizeof(header) / sizeof(uint32_t)) - 1;
header.registerOffset = offset;
header.messageSourceId = MessageSourceIdValues::Ia;
header.registerSize = RegisterSizeValues::Dword;
header.registerSpace = RegisterSpaceValues::Mmio;
header.writeMaskLow = 0xffffffff;
header.writeMaskHigh = 0x00000000;
header.data[0] = value;
write(reinterpret_cast<char *>(&header), sizeof(header));
}
void AubFileStream::registerPoll(uint32_t registerOffset, uint32_t mask, uint32_t value, bool pollNotEqual, uint32_t timeoutAction) {
CmdServicesMemTraceRegisterPoll header = {};
header.setHeader();
header.registerOffset = registerOffset;
header.timeoutAction = timeoutAction;
header.pollNotEqual = pollNotEqual;
header.operationType = CmdServicesMemTraceRegisterPoll::OperationTypeValues::Normal;
header.registerSize = CmdServicesMemTraceRegisterPoll::RegisterSizeValues::Dword;
header.registerSpace = CmdServicesMemTraceRegisterPoll::RegisterSpaceValues::Mmio;
header.pollMaskLow = mask;
header.data[0] = value;
header.dwordCount = (sizeof(header) / sizeof(uint32_t)) - 1;
write(reinterpret_cast<char *>(&header), sizeof(header));
}
void AubFileStream::expectMMIO(uint32_t mmioRegister, uint32_t expectedValue) {
using AubMemDump::CmdServicesMemTraceRegisterCompare;
CmdServicesMemTraceRegisterCompare header;
memset(&header, 0, sizeof(header));
header.setHeader();
header.data[0] = expectedValue;
header.registerOffset = mmioRegister;
header.noReadExpect = CmdServicesMemTraceRegisterCompare::NoReadExpectValues::ReadExpect;
header.registerSize = CmdServicesMemTraceRegisterCompare::RegisterSizeValues::Dword;
header.registerSpace = CmdServicesMemTraceRegisterCompare::RegisterSpaceValues::Mmio;
header.readMaskLow = 0xffffffff;
header.readMaskHigh = 0xffffffff;
header.dwordCount = (sizeof(header) / sizeof(uint32_t)) - 1;
write(reinterpret_cast<char *>(&header), sizeof(header));
}
void AubFileStream::expectMemory(uint64_t physAddress, const void *memory, size_t sizeRemaining,
uint32_t addressSpace, uint32_t compareOperation) {
using CmdServicesMemTraceMemoryCompare = AubMemDump::CmdServicesMemTraceMemoryCompare;
CmdServicesMemTraceMemoryCompare header = {};
header.setHeader();
header.noReadExpect = CmdServicesMemTraceMemoryCompare::NoReadExpectValues::ReadExpect;
header.repeatMemory = CmdServicesMemTraceMemoryCompare::RepeatMemoryValues::NoRepeat;
header.tiling = CmdServicesMemTraceMemoryCompare::TilingValues::NoTiling;
header.crcCompare = CmdServicesMemTraceMemoryCompare::CrcCompareValues::NoCrc;
header.compareOperation = compareOperation;
header.dataTypeHint = CmdServicesMemTraceMemoryCompare::DataTypeHintValues::TraceNotype;
header.addressSpace = addressSpace;
auto headerSize = sizeof(CmdServicesMemTraceMemoryCompare) - sizeof(CmdServicesMemTraceMemoryCompare::data);
auto blockSizeMax = g_dwordCountMax * sizeof(uint32_t) - headerSize;
// We have to decompose memory into chunks that can be streamed per iteration
while (sizeRemaining > 0) {
AubMemDump::setAddress(header, physAddress);
auto sizeThisIteration = std::min(sizeRemaining, blockSizeMax);
// Round up to the number of dwords
auto dwordCount = Math::divideAndRoundUp(headerSize + sizeThisIteration, sizeof(uint32_t));
header.dwordCount = static_cast<uint32_t>(dwordCount - 1);
header.dataSizeInBytes = static_cast<uint32_t>(sizeThisIteration);
// Write the header
write(reinterpret_cast<char *>(&header), headerSize);
// Copy the contents from source to destination.
write(reinterpret_cast<const char *>(memory), sizeThisIteration);
sizeRemaining -= sizeThisIteration;
memory = (uint8_t *)memory + sizeThisIteration;
physAddress += sizeThisIteration;
auto remainder = sizeThisIteration & (sizeof(uint32_t) - 1);
if (remainder) {
//if size is not 4 byte aligned, write extra zeros to AUB
uint32_t zero = 0;
write(reinterpret_cast<char *>(&zero), sizeof(uint32_t) - remainder);
}
}
}
void AubFileStream::createContext(const AubPpgttContextCreate &cmd) {
write(reinterpret_cast<const char *>(&cmd), sizeof(cmd));
}
bool AubFileStream::addComment(const char *message) {
using CmdServicesMemTraceComment = AubMemDump::CmdServicesMemTraceComment;
CmdServicesMemTraceComment cmd = {};
cmd.setHeader();
cmd.syncOnComment = false;
cmd.syncOnSimulatorDisplay = false;
auto messageLen = strlen(message) + 1;
auto dwordLen = ((messageLen + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1)) / sizeof(uint32_t);
cmd.dwordCount = static_cast<uint32_t>(dwordLen + 1);
write(reinterpret_cast<char *>(&cmd), sizeof(cmd) - sizeof(cmd.comment));
write(message, messageLen);
auto remainder = messageLen & (sizeof(uint32_t) - 1);
if (remainder) {
//if size is not 4 byte aligned, write extra zeros to AUB
uint32_t zero = 0;
write(reinterpret_cast<char *>(&zero), sizeof(uint32_t) - remainder);
}
return true;
}
std::unique_lock<std::mutex> AubFileStream::lockStream() {
return std::unique_lock<std::mutex>(mutex);
}
} // namespace AubMemDump
|