fix(debugger): use per-context fences for vm_bind operations

- vm_bind with user fence updates fence value independently for every
VM hence with per-context VMs, every context needs its unique fence
address. This prevents 2 contexts from updating value possibly
writing lower value than the one that was already stored

Resolves: NEO-8004

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2023-05-23 16:06:03 +00:00
committed by Compute-Runtime-Automation
parent af4fd337c5
commit 7d82b690e4
6 changed files with 133 additions and 5 deletions

View File

@@ -1399,8 +1399,19 @@ int changeBufferObjectBinding(Drm *drm, OsContext *osContext, uint32_t vmHandleI
if (!drm->hasPageFaultSupport() || bo->isExplicitResidencyRequired()) {
auto nextExtension = vmBind.extensions;
auto address = castToUint64(drm->getFenceAddr(vmHandleId));
auto value = drm->getNextFenceVal(vmHandleId);
uint64_t address = 0;
uint64_t value = 0;
if (drm->isPerContextVMRequired()) {
auto osContextLinux = static_cast<OsContextLinux *>(osContext);
address = castToUint64(osContextLinux->getFenceAddr(vmHandleId));
value = osContextLinux->getNextFenceVal(vmHandleId);
} else {
address = castToUint64(drm->getFenceAddr(vmHandleId));
value = drm->getNextFenceVal(vmHandleId);
}
incrementFenceValue = true;
ioctlHelper->fillVmBindExtUserFence(vmBindExtUserFence, address, value, nextExtension);
vmBind.extensions = castToUint64(vmBindExtUserFence);
@@ -1422,7 +1433,12 @@ int changeBufferObjectBinding(Drm *drm, OsContext *osContext, uint32_t vmHandleI
}
}
if (incrementFenceValue) {
drm->incFenceVal(vmHandleId);
if (drm->isPerContextVMRequired()) {
auto osContextLinux = static_cast<OsContextLinux *>(osContext);
osContextLinux->incFenceVal(vmHandleId);
} else {
drm->incFenceVal(vmHandleId);
}
}
}

View File

@@ -12,6 +12,7 @@
#include "shared/source/execution_environment/root_device_environment.h"
#include "shared/source/helpers/engine_node_helper.h"
#include "shared/source/helpers/hw_info.h"
#include "shared/source/helpers/ptr_math.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/source/os_interface/os_context.h"
@@ -30,7 +31,10 @@ OsContext *OsContextLinux::create(OSInterface *osInterface, uint32_t rootDeviceI
OsContextLinux::OsContextLinux(Drm &drm, uint32_t rootDeviceIndex, uint32_t contextId, const EngineDescriptor &engineDescriptor)
: OsContext(rootDeviceIndex, contextId, engineDescriptor),
drm(drm) {}
drm(drm) {
pagingFence.fill(0u);
fenceVal.fill(0u);
}
bool OsContextLinux::initializeContext() {
auto hwInfo = drm.getRootDeviceEnvironment().getHardwareInfo();
@@ -88,11 +92,28 @@ Drm &OsContextLinux::getDrm() const {
void OsContextLinux::waitForPagingFence() {
for (auto drmIterator = 0u; drmIterator < this->deviceBitfield.size(); drmIterator++) {
if (this->deviceBitfield.test(drmIterator)) {
drm.waitForBind(drmIterator);
this->waitForBind(drmIterator);
}
}
}
void OsContextLinux::waitForBind(uint32_t drmIterator) {
if (drm.isPerContextVMRequired()) {
if (pagingFence[drmIterator] >= fenceVal[drmIterator]) {
return;
}
auto lock = drm.lockBindFenceMutex();
auto fenceAddress = castToUint64(&this->pagingFence[drmIterator]);
auto fenceValue = this->fenceVal[drmIterator];
lock.unlock();
drm.waitUserFence(0u, fenceAddress, fenceValue, Drm::ValueWidth::U64, -1, drm.getIoctlHelper()->getWaitUserFenceSoftFlag());
} else {
drm.waitForBind(drmIterator);
}
}
void OsContextLinux::reInitializeContext() {}
uint64_t OsContextLinux::getOfflineDumpContextId(uint32_t deviceIndex) const {

View File

@@ -8,8 +8,10 @@
#pragma once
#include "shared/source/helpers/mt_helpers.h"
#include "shared/source/memory_manager/definitions/engine_limits.h"
#include "shared/source/os_interface/os_context.h"
#include <array>
#include <atomic>
#include <vector>
@@ -52,6 +54,11 @@ class OsContextLinux : public OsContext {
uint64_t getOfflineDumpContextId(uint32_t deviceIndex) const override;
uint64_t getNextFenceVal(uint32_t deviceIndex) { return fenceVal[deviceIndex] + 1; }
void incFenceVal(uint32_t deviceIndex) { fenceVal[deviceIndex]++; }
uint64_t *getFenceAddr(uint32_t deviceIndex) { return &pagingFence[deviceIndex]; }
void waitForBind(uint32_t drmIterator);
protected:
bool initializeContext() override;
@@ -60,6 +67,10 @@ class OsContextLinux : public OsContext {
unsigned int engineFlag = 0;
std::vector<uint32_t> drmContextIds;
std::vector<uint32_t> drmVmIds;
std::array<uint64_t, EngineLimits::maxHandleCount> pagingFence;
std::array<uint64_t, EngineLimits::maxHandleCount> fenceVal;
Drm &drm;
bool contextHangDetected = false;
};