zesSysmanDeviceReset: Reinitialize device after device reset

Before performing gpu device reset, first all level zero resources
and gpu device specific resources have to be cleaned up. Also as
after device reset, state of gpu device would be lost.
Hence after performing gpu device reset, level zero device have
to be reinitialized by querying gpu device again.
This change is aimed at reinitializing the level zero resources
after gpu device reset, so that user could continue using level zero
devices after device reset.

Related-To: LOCI-2627

Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2021-10-11 15:34:03 +00:00
committed by Compute-Runtime-Automation
parent 06eaef0352
commit 1186c1aae3
26 changed files with 373 additions and 44 deletions

View File

@ -32,9 +32,9 @@ class Engine : _zes_engine_handle_t {
struct EngineHandleContext {
EngineHandleContext(OsSysman *pOsSysman);
~EngineHandleContext();
MOCKABLE_VIRTUAL ~EngineHandleContext();
void init();
MOCKABLE_VIRTUAL void init();
void releaseEngines();
ze_result_t engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine);

View File

@ -7,6 +7,8 @@
#include "level_zero/tools/source/sysman/global_operations/linux/os_global_operations_imp.h"
#include "shared/source/os_interface/device_factory.h"
#include "level_zero/core/source/device/device_imp.h"
#include "level_zero/tools/source/sysman/global_operations/global_operations_imp.h"
#include "level_zero/tools/source/sysman/linux/fs_access.h"
@ -119,6 +121,44 @@ static void getPidFdsForOpenDevice(ProcfsAccess *pProcfsAccess, SysfsAccess *pSy
}
}
void LinuxGlobalOperationsImp::releaseSysmanDeviceResources() {
pLinuxSysmanImp->getSysmanDeviceImp()->pEngineHandleContext->releaseEngines();
pLinuxSysmanImp->getSysmanDeviceImp()->pRasHandleContext->releaseRasHandles();
pLinuxSysmanImp->releasePmtObject();
pLinuxSysmanImp->releaseLocalDrmHandle();
}
void LinuxGlobalOperationsImp::releaseDeviceResources() {
releaseSysmanDeviceResources();
auto device = static_cast<DeviceImp *>(getDevice());
device->releaseResources();
executionEnvironment->memoryManager->releaseDeviceSpecificMemResources(rootDeviceIndex);
executionEnvironment->releaseRootDeviceEnvironmentResources(executionEnvironment->rootDeviceEnvironments[rootDeviceIndex].get());
executionEnvironment->rootDeviceEnvironments[rootDeviceIndex].reset();
}
void LinuxGlobalOperationsImp::reInitSysmanDeviceResources() {
pLinuxSysmanImp->getSysmanDeviceImp()->updateSubDeviceHandlesLocally();
pLinuxSysmanImp->createPmtHandles();
pLinuxSysmanImp->getSysmanDeviceImp()->pRasHandleContext->init(pLinuxSysmanImp->getSysmanDeviceImp()->deviceHandles);
pLinuxSysmanImp->getSysmanDeviceImp()->pEngineHandleContext->init();
}
ze_result_t LinuxGlobalOperationsImp::initDevice() {
ze_result_t result = ZE_RESULT_SUCCESS;
auto device = static_cast<DeviceImp *>(getDevice());
auto neoDevice = NEO::DeviceFactory::createDevice(*executionEnvironment, devicePciBdf, rootDeviceIndex);
if (neoDevice == nullptr) {
return ZE_RESULT_ERROR_DEVICE_LOST;
}
static_cast<L0::DriverHandleImp *>(device->getDriverHandle())->updateRootDeviceBitFields(neoDevice);
static_cast<L0::DriverHandleImp *>(device->getDriverHandle())->enableRootDeviceDebugger(neoDevice);
Device::deviceReinit(device->getDriverHandle(), device, neoDevice, &result);
reInitSysmanDeviceResources();
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
std::string resetPath;
std::string resetName;
@ -159,10 +199,8 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
}
}
pLinuxSysmanImp->getSysmanDeviceImp()->pEngineHandleContext->releaseEngines();
pLinuxSysmanImp->getSysmanDeviceImp()->pRasHandleContext->releaseRasHandles();
pLinuxSysmanImp->releasePmtObject();
static_cast<DeviceImp *>(getDevice())->releaseResources();
ExecutionEnvironmentRefCountRestore restorer(executionEnvironment);
releaseDeviceResources();
for (auto &&fd : myPidFds) {
// Close open filedescriptors to the device
// before unbinding device.
@ -227,7 +265,7 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
return result;
}
return ZE_RESULT_SUCCESS;
return initDevice();
}
// Processes in the form of clients are present in sysfs like this:
@ -407,6 +445,10 @@ LinuxGlobalOperationsImp::LinuxGlobalOperationsImp(OsSysman *pOsSysman) {
pFsAccess = &pLinuxSysmanImp->getFsAccess();
pDevice = pLinuxSysmanImp->getDeviceHandle();
pFwInterface = pLinuxSysmanImp->getFwUtilInterface();
auto device = static_cast<DeviceImp *>(pDevice);
devicePciBdf = device->getNEODevice()->getRootDeviceEnvironment().osInterface->getDriverModel()->as<NEO::Drm>()->getPciPath();
executionEnvironment = device->getNEODevice()->getExecutionEnvironment();
rootDeviceIndex = device->getNEODevice()->getRootDeviceIndex();
}
OsGlobalOperations *OsGlobalOperations::create(OsSysman *pOsSysman) {

View File

@ -40,6 +40,10 @@ class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMo
FirmwareUtil *pFwInterface = nullptr;
int resetTimeout = 10000; // in milliseconds
void releaseSysmanDeviceResources();
void releaseDeviceResources();
ze_result_t initDevice();
void reInitSysmanDeviceResources();
private:
static const std::string deviceDir;
@ -50,6 +54,22 @@ class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMo
static const std::string srcVersionFile;
static const std::string agamaVersionFile;
static const std::string ueventWedgedFile;
std::string devicePciBdf = "";
NEO::ExecutionEnvironment *executionEnvironment = nullptr;
uint32_t rootDeviceIndex = 0u;
};
class ExecutionEnvironmentRefCountRestore {
public:
ExecutionEnvironmentRefCountRestore() = delete;
ExecutionEnvironmentRefCountRestore(NEO::ExecutionEnvironment *executionEnvironmentRecevied) {
executionEnvironment = executionEnvironmentRecevied;
executionEnvironment->incRefInternal();
}
~ExecutionEnvironmentRefCountRestore() {
executionEnvironment->decRefInternal();
}
NEO::ExecutionEnvironment *executionEnvironment = nullptr;
};
} // namespace L0

View File

@ -20,16 +20,13 @@ ze_result_t LinuxSysmanImp::init() {
}
DEBUG_BREAK_IF(nullptr == pProcfsAccess);
pDevice = Device::fromHandle(pParentSysmanDeviceImp->hCoreDevice);
DEBUG_BREAK_IF(nullptr == pDevice);
NEO::OSInterface &OsInterface = pDevice->getOsInterface();
if (OsInterface.getDriverModel()->getDriverModelType() != NEO::DriverModelType::DRM) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
auto result = initLocalDeviceAndDrmHandles();
if (ZE_RESULT_SUCCESS != result) {
return result;
}
pDrm = OsInterface.getDriverModel()->as<NEO::Drm>();
int myDeviceFd = pDrm->getFileDescriptor();
std::string myDeviceName;
ze_result_t result = pProcfsAccess->getFileName(pProcfsAccess->myProcessId(), myDeviceFd, myDeviceName);
result = pProcfsAccess->getFileName(pProcfsAccess->myProcessId(), myDeviceFd, myDeviceName);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
@ -39,22 +36,22 @@ ze_result_t LinuxSysmanImp::init() {
}
DEBUG_BREAK_IF(nullptr == pSysfsAccess);
pPmuInterface = PmuInterface::create(this);
DEBUG_BREAK_IF(nullptr == pPmuInterface);
pFwUtilInterface = FirmwareUtil::create(pDrm->getPciPath());
return createPmtHandles();
}
ze_result_t LinuxSysmanImp::createPmtHandles() {
std::string realRootPath;
result = pSysfsAccess->getRealPath("device", realRootPath);
auto result = pSysfsAccess->getRealPath("device", realRootPath);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
auto rootPciPathOfGpuDevice = getPciRootPortDirectoryPath(realRootPath);
PlatformMonitoringTech::create(pParentSysmanDeviceImp->deviceHandles, pFsAccess, rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject);
pPmuInterface = PmuInterface::create(this);
DEBUG_BREAK_IF(nullptr == pPmuInterface);
auto loc = realRootPath.find_last_of('/');
std::string pciBDF = realRootPath.substr(loc + 1, std::string::npos);
pFwUtilInterface = FirmwareUtil::create(pciBDF);
return ZE_RESULT_SUCCESS;
return result;
}
PmuInterface *LinuxSysmanImp::getPmuInterface() {
@ -80,11 +77,29 @@ SysfsAccess &LinuxSysmanImp::getSysfsAccess() {
return *pSysfsAccess;
}
ze_result_t LinuxSysmanImp::initLocalDeviceAndDrmHandles() {
pDevice = Device::fromHandle(pParentSysmanDeviceImp->hCoreDevice);
DEBUG_BREAK_IF(nullptr == pDevice);
NEO::OSInterface &OsInterface = pDevice->getOsInterface();
if (OsInterface.getDriverModel()->getDriverModelType() != NEO::DriverModelType::DRM) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
pDrm = OsInterface.getDriverModel()->as<NEO::Drm>();
return ZE_RESULT_SUCCESS;
}
NEO::Drm &LinuxSysmanImp::getDrm() {
if (pDrm == nullptr) {
initLocalDeviceAndDrmHandles();
}
UNRECOVERABLE_IF(nullptr == pDrm);
return *pDrm;
}
void LinuxSysmanImp::releaseLocalDrmHandle() {
pDrm = nullptr;
}
Device *LinuxSysmanImp::getDeviceHandle() {
return pDevice;
}

View File

@ -40,16 +40,19 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass {
SysmanDeviceImp *getSysmanDeviceImp();
std::string getPciRootPortDirectoryPath(std::string realPciPath);
void releasePmtObject();
ze_result_t createPmtHandles();
void releaseLocalDrmHandle();
protected:
FsAccess *pFsAccess = nullptr;
ProcfsAccess *pProcfsAccess = nullptr;
SysfsAccess *pSysfsAccess = nullptr;
NEO::Drm *pDrm = nullptr;
Device *pDevice = nullptr;
NEO::Drm *pDrm = nullptr;
PmuInterface *pPmuInterface = nullptr;
FirmwareUtil *pFwUtilInterface = nullptr;
std::map<uint32_t, L0::PlatformMonitoringTech *> mapOfSubDeviceIdToPmtObject;
ze_result_t initLocalDeviceAndDrmHandles();
private:
LinuxSysmanImp() = delete;

View File

@ -60,9 +60,9 @@ SysmanDeviceImp::~SysmanDeviceImp() {
freeResource(pOsSysman);
}
ze_result_t SysmanDeviceImp::init() {
void SysmanDeviceImp::updateSubDeviceHandlesLocally() {
uint32_t subDeviceCount = 0;
// We received a device handle. Check for subdevices in this device
deviceHandles.clear();
Device::fromHandle(hCoreDevice)->getSubDevices(&subDeviceCount, nullptr);
if (subDeviceCount == 0) {
deviceHandles.resize(1, hCoreDevice);
@ -70,6 +70,11 @@ ze_result_t SysmanDeviceImp::init() {
deviceHandles.resize(subDeviceCount, nullptr);
Device::fromHandle(hCoreDevice)->getSubDevices(&subDeviceCount, deviceHandles.data());
}
}
ze_result_t SysmanDeviceImp::init() {
// We received a device handle. Check for subdevices in this device
updateSubDeviceHandlesLocally();
auto result = pOsSysman->init();
if (ZE_RESULT_SUCCESS != result) {

View File

@ -68,6 +68,8 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass {
ze_result_t deviceEventRegister(zes_event_type_flags_t events) override;
bool deviceEventListen(zes_event_type_flags_t &pEvent, uint64_t timeout) override;
void updateSubDeviceHandlesLocally();
private:
template <typename T>
void inline freeResource(T *&resource) {

View File

@ -52,6 +52,16 @@ const std::string mockFunctionResetPath("/MOCK_FUNCTION_LEVEL_RESET_PATH");
const std::string mockDeviceDir("/MOCK_DEVICE_DIR");
const std::string mockDeviceName("/MOCK_DEVICE_NAME");
struct GlobalOperationsEngineHandleContext : public EngineHandleContext {
GlobalOperationsEngineHandleContext(OsSysman *pOsSysman) : EngineHandleContext(pOsSysman) {}
};
template <>
struct Mock<GlobalOperationsEngineHandleContext> : public GlobalOperationsEngineHandleContext {
void initMock() {}
Mock<GlobalOperationsEngineHandleContext>(OsSysman *pOsSysman) : GlobalOperationsEngineHandleContext(pOsSysman) {}
MOCK_METHOD(void, init, (), (override));
};
class GlobalOperationsSysfsAccess : public SysfsAccess {};
template <>

View File

@ -5,6 +5,8 @@
*
*/
#include "shared/test/common/helpers/ult_hw_config.h"
#include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h"
#include "mock_global_operations.h"
@ -40,9 +42,11 @@ constexpr uint32_t totalProcessStates = 5u; // Three process States for three pi
constexpr uint32_t totalProcessStatesForFaultyClients = 3u;
class SysmanGlobalOperationsFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<Mock<GlobalOperationsEngineHandleContext>> pEngineHandleContext;
std::unique_ptr<Mock<GlobalOperationsSysfsAccess>> pSysfsAccess;
std::unique_ptr<Mock<GlobalOperationsProcfsAccess>> pProcfsAccess;
std::unique_ptr<Mock<GlobalOperationsFsAccess>> pFsAccess;
EngineHandleContext *pEngineHandleContextOld = nullptr;
SysfsAccess *pSysfsAccessOld = nullptr;
ProcfsAccess *pProcfsAccessOld = nullptr;
FsAccess *pFsAccessOld = nullptr;
@ -53,15 +57,23 @@ class SysmanGlobalOperationsFixture : public SysmanDeviceFixture {
void SetUp() override {
SysmanDeviceFixture::SetUp();
pEngineHandleContextOld = pSysmanDeviceImp->pEngineHandleContext;
pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
pProcfsAccessOld = pLinuxSysmanImp->pProcfsAccess;
pFsAccessOld = pLinuxSysmanImp->pFsAccess;
pEngineHandleContext = std::make_unique<NiceMock<Mock<GlobalOperationsEngineHandleContext>>>(pOsSysman);
pSysfsAccess = std::make_unique<NiceMock<Mock<GlobalOperationsSysfsAccess>>>();
pProcfsAccess = std::make_unique<NiceMock<Mock<GlobalOperationsProcfsAccess>>>();
pFsAccess = std::make_unique<NiceMock<Mock<GlobalOperationsFsAccess>>>();
pSysmanDeviceImp->pEngineHandleContext = pEngineHandleContext.get();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
pLinuxSysmanImp->pProcfsAccess = pProcfsAccess.get();
pLinuxSysmanImp->pFsAccess = pFsAccess.get();
ON_CALL(*pEngineHandleContext.get(), init())
.WillByDefault(::testing::Invoke(pEngineHandleContext.get(), &Mock<GlobalOperationsEngineHandleContext>::initMock));
ON_CALL(*pSysfsAccess.get(), read(_, Matcher<std::string &>(_)))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<GlobalOperationsSysfsAccess>::getValString));
ON_CALL(*pSysfsAccess.get(), read(_, Matcher<uint64_t &>(_)))
@ -103,6 +115,7 @@ class SysmanGlobalOperationsFixture : public SysmanDeviceFixture {
}
pGlobalOperationsImp->pOsGlobalOperations = pOsGlobalOperationsPrev;
pGlobalOperationsImp = nullptr;
pSysmanDeviceImp->pEngineHandleContext = pEngineHandleContextOld;
SysmanDeviceFixture::TearDown();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
pLinuxSysmanImp->pProcfsAccess = pProcfsAccessOld;
@ -413,6 +426,26 @@ TEST_F(SysmanGlobalOperationsFixture, GivenProcessStartsMidResetWhenCallingReset
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenProcessStartsMidResetWhenCallingResetAndIfNeoDeviceCreateFailsThenErrorIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
EXPECT_CALL(*pProcfsAccess.get(), listProcesses(Matcher<std::vector<::pid_t> &>(_)))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceUnused))
.WillRepeatedly(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockProcessListDeviceInUse));
EXPECT_CALL(*pProcfsAccess.get(), kill(pProcfsAccess->ourDevicePid))
.WillOnce(::testing::Invoke(pProcfsAccess.get(), &Mock<GlobalOperationsProcfsAccess>::mockKill));
EXPECT_CALL(*pSysfsAccess.get(), bindDevice(_))
.WillOnce(::testing::Return(ZE_RESULT_SUCCESS));
pGlobalOperationsImp->init();
VariableBackup<UltHwConfig> backup{&ultHwConfig};
ultHwConfig.mockedPrepareDeviceEnvironmentsFuncResult = false;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_DEVICE_LOST, result);
}
TEST_F(SysmanGlobalOperationsFixture, GivenProcessStartsMidResetWhenCallingResetAndBindFailsThenFailureIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
@ -555,5 +588,23 @@ TEST_F(SysmanGlobalOperationsFixture, GivenProcessStartsMidResetWhenCallingReset
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST(SysmanGlobalOperationsTest, GivenValidDevicePciPathWhenPreparingDeviceEnvironmentThenPrepareDeviceEnvironmentReturnsTrue) {
auto device1 = std::unique_ptr<MockDevice>{MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get())};
std::string pciPath1 = "0000:00:02.0";
EXPECT_TRUE(DeviceFactory::prepareDeviceEnvironment(*device1->getExecutionEnvironment(), pciPath1, 0u));
}
TEST(SysmanGlobalOperationsTest, GivenValidDevicePciPathWhoseFileDescriptorOpenFailedThenPrepareDeviceEnvironmentReturnsFalse) {
auto device2 = std::unique_ptr<MockDevice>{MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get())};
std::string pciPath2 = "0000:00:03.0";
EXPECT_FALSE(DeviceFactory::prepareDeviceEnvironment(*device2->getExecutionEnvironment(), pciPath2, 0u));
}
TEST(SysmanGlobalOperationsTest, GivenNotExisitingPciPathWhenPrepareDeviceEnvironmentIsCalledThenFalseIsReturned) {
auto device3 = std::unique_ptr<MockDevice>{MockDevice::createWithNewExecutionEnvironment<MockDevice>(defaultHwInfo.get())};
std::string pciPath3 = "0000:00:04.0";
EXPECT_FALSE(DeviceFactory::prepareDeviceEnvironment(*device3->getExecutionEnvironment(), pciPath3, 0u));
}
} // namespace ult
} // namespace L0

View File

@ -311,6 +311,11 @@ TEST_F(SysmanDeviceFixture, GivenValidPciPathWhileGettingRootPciPortThenReturned
EXPECT_EQ(pciRootPort2, "device");
}
TEST_F(SysmanDeviceFixture, GivenNullDrmHandleWhenGettingDrmHandleThenValidDrmHandleIsReturned) {
pLinuxSysmanImp->releaseLocalDrmHandle();
EXPECT_NO_THROW(pLinuxSysmanImp->getDrm());
}
TEST_F(SysmanMultiDeviceFixture, GivenValidDeviceHandleHavingSubdevicesWhenValidatingSysmanHandlesForSubdevicesThenSysmanHandleForSubdeviceWillBeSameAsSysmanHandleForDevice) {
ze_device_handle_t hSysman = device->toHandle();
auto pSysmanDeviceOriginal = static_cast<DeviceImp *>(device)->getSysmanHandle();

View File

@ -28,6 +28,58 @@ bool operator==(const HardwareInfo &hwInfoIn, const HardwareInfo &hwInfoOut) {
return result;
}
TEST(PrepareDeviceEnvironmentTest, givenPrepareDeviceEnvironmentWhenCsrIsSetToVariousTypesThenFunctionReturnsExpectedValueOfHardwareInfo) {
const HardwareInfo *hwInfo = nullptr;
VariableBackup<UltHwConfig> backup{&ultHwConfig};
DebugManagerStateRestore stateRestorer;
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
uint32_t expectedDevices = 1;
DebugManager.flags.CreateMultipleRootDevices.set(expectedDevices);
for (int productFamilyIndex = 0; productFamilyIndex < IGFX_MAX_PRODUCT; productFamilyIndex++) {
const char *hwPrefix = hardwarePrefix[productFamilyIndex];
auto hwInfoConfig = hwInfoConfigFactory[productFamilyIndex];
if (hwPrefix == nullptr || hwInfoConfig == nullptr) {
continue;
}
const std::string productFamily(hwPrefix);
for (int csrTypes = -1; csrTypes <= CSR_TYPES_NUM; csrTypes++) {
CommandStreamReceiverType csrType;
if (csrTypes != -1) {
csrType = static_cast<CommandStreamReceiverType>(csrTypes);
DebugManager.flags.SetCommandStreamReceiver.set(csrType);
} else {
csrType = CSR_HW;
DebugManager.flags.SetCommandStreamReceiver.set(-1);
}
DebugManager.flags.ProductFamilyOverride.set(productFamily);
platformsImpl->clear();
ExecutionEnvironment *exeEnv = constructPlatform()->peekExecutionEnvironment();
std::string pciPath = "0000:00:02.0";
exeEnv->rootDeviceEnvironments.resize(1u);
const auto ret = prepareDeviceEnvironment(*exeEnv, pciPath, 0u);
EXPECT_EQ(expectedDevices, exeEnv->rootDeviceEnvironments.size());
for (auto i = 0u; i < expectedDevices; i++) {
hwInfo = exeEnv->rootDeviceEnvironments[i]->getHardwareInfo();
switch (csrType) {
case CSR_HW:
case CSR_HW_WITH_AUB:
case CSR_TYPES_NUM:
EXPECT_TRUE(ret);
EXPECT_NE(nullptr, hwInfo);
break;
default:
EXPECT_FALSE(ret);
break;
}
}
}
}
}
struct PrepareDeviceEnvironmentsTest : ::testing::Test {
void SetUp() override {
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;

View File

@ -59,4 +59,11 @@ bool prepareDeviceEnvironmentsImpl(ExecutionEnvironment &executionEnvironment) {
return DeviceFactory::prepareDeviceEnvironmentsForProductFamilyOverride(executionEnvironment);
}
bool prepareDeviceEnvironmentImpl(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex) {
if (DeviceFactory::isHwModeSelected()) {
return DeviceFactory::prepareDeviceEnvironment(executionEnvironment, osPciPath, rootDeviceIndex);
}
return false;
}
} // namespace NEO

View File

@ -14,4 +14,5 @@ extern CommandStreamReceiver *createCommandStreamImpl(ExecutionEnvironment &exec
uint32_t rootDeviceIndex,
const DeviceBitfield deviceBitfield);
extern bool prepareDeviceEnvironmentsImpl(ExecutionEnvironment &executionEnvironment);
extern bool prepareDeviceEnvironmentImpl(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex);
} // namespace NEO

View File

@ -11,8 +11,13 @@
namespace NEO {
bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment) {
auto returnValue = prepareDeviceEnvironmentsImpl(executionEnvironment);
bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex) {
bool returnValue = false;
if (osPciPath.empty()) {
returnValue = prepareDeviceEnvironmentsImpl(executionEnvironment);
} else {
returnValue = prepareDeviceEnvironmentImpl(executionEnvironment, osPciPath, rootDeviceIndex);
}
if (DebugManager.flags.Force32BitDriverSupport.get() != -1) {
return returnValue;
@ -39,4 +44,13 @@ bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment) {
return returnValue && executionEnvironment.rootDeviceEnvironments.size() > 0;
}
bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment) {
std::string path = "";
return prepareDeviceEnvironments(executionEnvironment, path, 0u);
}
bool prepareDeviceEnvironment(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex) {
return prepareDeviceEnvironments(executionEnvironment, osPciPath, rootDeviceIndex);
}
} // namespace NEO

View File

@ -25,14 +25,21 @@ ExecutionEnvironment::ExecutionEnvironment() {
WaitUtils::init();
}
void ExecutionEnvironment::releaseRootDeviceEnvironmentResources(RootDeviceEnvironment *rootDeviceEnvironment) {
if (rootDeviceEnvironment == nullptr) {
return;
}
SipKernel::freeSipKernels(rootDeviceEnvironment, memoryManager.get());
if (rootDeviceEnvironment->builtins.get()) {
rootDeviceEnvironment->builtins.get()->freeSipKernels(memoryManager.get());
}
}
ExecutionEnvironment::~ExecutionEnvironment() {
if (memoryManager) {
memoryManager->commonCleanup();
for (const auto &rootDeviceEnvironment : this->rootDeviceEnvironments) {
SipKernel::freeSipKernels(rootDeviceEnvironment.get(), memoryManager.get());
if (rootDeviceEnvironment->builtins.get()) {
rootDeviceEnvironment->builtins.get()->freeSipKernels(memoryManager.get());
}
releaseRootDeviceEnvironmentResources(rootDeviceEnvironment.get());
}
}
rootDeviceEnvironments.clear();
@ -111,6 +118,10 @@ void ExecutionEnvironment::prepareRootDeviceEnvironments(uint32_t numRootDevices
}
}
void ExecutionEnvironment::prepareRootDeviceEnvironment(const uint32_t rootDeviceIndexForReInit) {
rootDeviceEnvironments[rootDeviceIndexForReInit] = std::make_unique<RootDeviceEnvironment>(*this);
}
void ExecutionEnvironment::parseAffinityMask() {
const auto &affinityMaskString = DebugManager.flags.ZE_AFFINITY_MASK.get();

View File

@ -25,6 +25,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject<ExecutionEnvironment>
MOCKABLE_VIRTUAL bool initializeMemoryManager();
void calculateMaxOsContextCount();
virtual void prepareRootDeviceEnvironments(uint32_t numRootDevices);
void prepareRootDeviceEnvironment(const uint32_t rootDeviceIndexForReInit);
void parseAffinityMask();
void sortNeoDevices();
void setDebuggingEnabled() {
@ -37,6 +38,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject<ExecutionEnvironment>
std::unique_ptr<DirectSubmissionController> directSubmissionController;
std::unique_ptr<OsEnvironment> osEnvironment;
std::vector<std::unique_ptr<RootDeviceEnvironment>> rootDeviceEnvironments;
void releaseRootDeviceEnvironmentResources(RootDeviceEnvironment *rootDeviceEnvironment);
protected:
bool debuggingEnabled = false;

View File

@ -95,6 +95,24 @@ bool DeviceFactory::isHwModeSelected() {
}
}
static bool initHwDeviceIdResources(ExecutionEnvironment &executionEnvironment,
std::unique_ptr<NEO::HwDeviceId> &&hwDeviceId, uint32_t rootDeviceIndex) {
if (!executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->initOsInterface(std::move(hwDeviceId), rootDeviceIndex)) {
return false;
}
if (DebugManager.flags.OverrideGpuAddressSpace.get() != -1) {
executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->getMutableHardwareInfo()->capabilityTable.gpuAddressSpace =
maxNBitValue(static_cast<uint64_t>(DebugManager.flags.OverrideGpuAddressSpace.get()));
}
if (DebugManager.flags.OverrideRevision.get() != -1) {
executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->getMutableHardwareInfo()->platform.usRevId =
static_cast<unsigned short>(DebugManager.flags.OverrideRevision.get());
}
return true;
}
bool DeviceFactory::prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment) {
using HwDeviceIds = std::vector<std::unique_ptr<HwDeviceId>>;
@ -108,20 +126,10 @@ bool DeviceFactory::prepareDeviceEnvironments(ExecutionEnvironment &executionEnv
uint32_t rootDeviceIndex = 0u;
for (auto &hwDeviceId : hwDeviceIds) {
if (!executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->initOsInterface(std::move(hwDeviceId), rootDeviceIndex)) {
if (initHwDeviceIdResources(executionEnvironment, std::move(hwDeviceId), rootDeviceIndex) == false) {
return false;
}
if (DebugManager.flags.OverrideGpuAddressSpace.get() != -1) {
executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->getMutableHardwareInfo()->capabilityTable.gpuAddressSpace =
maxNBitValue(static_cast<uint64_t>(DebugManager.flags.OverrideGpuAddressSpace.get()));
}
if (DebugManager.flags.OverrideRevision.get() != -1) {
executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->getMutableHardwareInfo()->platform.usRevId =
static_cast<unsigned short>(DebugManager.flags.OverrideRevision.get());
}
rootDeviceIndex++;
}
@ -132,6 +140,34 @@ bool DeviceFactory::prepareDeviceEnvironments(ExecutionEnvironment &executionEnv
return true;
}
bool DeviceFactory::prepareDeviceEnvironment(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex) {
using HwDeviceIds = std::vector<std::unique_ptr<HwDeviceId>>;
HwDeviceIds hwDeviceIds = OSInterface::discoverDevice(executionEnvironment, osPciPath);
if (hwDeviceIds.empty()) {
return false;
}
executionEnvironment.prepareRootDeviceEnvironment(rootDeviceIndex);
// HwDeviceIds should contain only one entry corresponding to osPciPath
UNRECOVERABLE_IF(hwDeviceIds.size() > 1);
return initHwDeviceIdResources(executionEnvironment, std::move(hwDeviceIds[0]), rootDeviceIndex);
}
std::unique_ptr<Device> DeviceFactory::createDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex) {
std::unique_ptr<Device> device;
if (!NEO::prepareDeviceEnvironment(executionEnvironment, osPciPath, rootDeviceIndex)) {
return device;
}
executionEnvironment.memoryManager->createDeviceSpecificMemResources(rootDeviceIndex);
executionEnvironment.memoryManager->reInitLatestContextId();
device = createRootDeviceFunc(executionEnvironment, rootDeviceIndex);
return device;
}
std::vector<std::unique_ptr<Device>> DeviceFactory::createDevices(ExecutionEnvironment &executionEnvironment) {
std::vector<std::unique_ptr<Device>> devices;

View File

@ -8,6 +8,7 @@
#pragma once
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>
namespace NEO {
@ -15,11 +16,14 @@ namespace NEO {
class ExecutionEnvironment;
class Device;
bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment);
bool prepareDeviceEnvironment(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex);
class DeviceFactory {
public:
static bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment);
static bool prepareDeviceEnvironment(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex);
static bool prepareDeviceEnvironmentsForProductFamilyOverride(ExecutionEnvironment &executionEnvironment);
static std::vector<std::unique_ptr<Device>> createDevices(ExecutionEnvironment &executionEnvironment);
static std::unique_ptr<Device> createDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex);
static bool isHwModeSelected();
static std::unique_ptr<Device> (*createRootDeviceFunc)(ExecutionEnvironment &executionEnvironment, uint32_t rootDeviceIndex);

View File

@ -14,4 +14,8 @@ std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionE
return Drm::discoverDevices(executionEnvironment);
}
std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath) {
return Drm::discoverDevice(executionEnvironment, osPciPath);
}
} // namespace NEO

View File

@ -19,4 +19,8 @@ std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionE
return devices;
}
std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath) {
return Drm::discoverDevice(executionEnvironment, osPciPath);
}
} // namespace NEO

View File

@ -14,4 +14,8 @@ std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionE
return Wddm::discoverDevices(executionEnvironment);
}
std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath) {
return Wddm::discoverDevices(executionEnvironment);
}
} // namespace NEO

View File

@ -512,6 +512,15 @@ void appendHwDeviceId(std::vector<std::unique_ptr<HwDeviceId>> &hwDeviceIds, int
}
std::vector<std::unique_ptr<HwDeviceId>> Drm::discoverDevices(ExecutionEnvironment &executionEnvironment) {
std::string str = "";
return Drm::discoverDevices(executionEnvironment, str);
}
std::vector<std::unique_ptr<HwDeviceId>> Drm::discoverDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath) {
return Drm::discoverDevices(executionEnvironment, osPciPath);
}
std::vector<std::unique_ptr<HwDeviceId>> Drm::discoverDevices(ExecutionEnvironment &executionEnvironment, std::string &osPciPath) {
std::vector<std::unique_ptr<HwDeviceId>> hwDeviceIds;
executionEnvironment.osEnvironment = std::make_unique<OsEnvironment>();
size_t numRootDevices = 0u;
@ -559,6 +568,13 @@ std::vector<std::unique_ptr<HwDeviceId>> Drm::discoverDevices(ExecutionEnvironme
}
std::string pciPath(devicePathView.substr(rdsPos - 12, 12));
if (!osPciPath.empty()) {
if (osPciPath.compare(pciPath) != 0) {
// if osPciPath is non-empty, then interest is only in discovering device having same bdf as ocPciPath. Skip all other devices.
continue;
}
}
if (DebugManager.flags.ForceDeviceId.get() != "unk") {
if (devicePathView.find(DebugManager.flags.ForceDeviceId.get().c_str()) == std::string::npos) {
continue;

View File

@ -234,6 +234,8 @@ class Drm : public DriverModel {
const TopologyMap &getTopologyMap();
static std::vector<std::unique_ptr<HwDeviceId>> discoverDevices(ExecutionEnvironment &executionEnvironment);
static std::vector<std::unique_ptr<HwDeviceId>> discoverDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath);
static std::vector<std::unique_ptr<HwDeviceId>> discoverDevices(ExecutionEnvironment &executionEnvironment, std::string &osPciPath);
std::unique_lock<std::mutex> lockBindFenceMutex();

View File

@ -108,6 +108,7 @@ class OSInterface : public NonCopyableClass {
static bool gpuIdleImplicitFlush;
static bool requiresSupportForWddmTrimNotification;
static std::vector<std::unique_ptr<HwDeviceId>> discoverDevices(ExecutionEnvironment &executionEnvironment);
static std::vector<std::unique_ptr<HwDeviceId>> discoverDevice(ExecutionEnvironment &executionEnvironment, std::string &osPciPath);
protected:
std::unique_ptr<DriverModel> driverModel = nullptr;

View File

@ -51,4 +51,20 @@ bool prepareDeviceEnvironments(ExecutionEnvironment &executionEnvironment) {
return prepareDeviceEnvironmentsImpl(executionEnvironment);
}
bool prepareDeviceEnvironment(ExecutionEnvironment &executionEnvironment, std::string &osPciPath, const uint32_t rootDeviceIndex) {
executionEnvironment.prepareRootDeviceEnvironment(rootDeviceIndex);
auto currentHwInfo = executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo();
if (currentHwInfo->platform.eProductFamily == IGFX_UNKNOWN && currentHwInfo->platform.eRenderCoreFamily == IGFX_UNKNOWN_CORE) {
executionEnvironment.rootDeviceEnvironments[rootDeviceIndex]->setHwInfo(defaultHwInfo.get());
}
if (ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc) {
uint32_t numRootDevices = DebugManager.flags.CreateMultipleRootDevices.get() != 0 ? DebugManager.flags.CreateMultipleRootDevices.get() : 1u;
UltDeviceFactory::prepareDeviceEnvironments(executionEnvironment, numRootDevices);
return ultHwConfig.mockedPrepareDeviceEnvironmentsFuncResult;
}
return prepareDeviceEnvironmentImpl(executionEnvironment, osPciPath, rootDeviceIndex);
}
} // namespace NEO

View File

@ -17,6 +17,8 @@ std::vector<std::string> Directory::getFiles(const std::string &path) {
if (path == "./test_files/linux/by-path") {
files.push_back("./test_files/linux/by-path/pci-0000:00:02.0-card");
files.push_back("./test_files/linux/by-path/pci-0000:00:02.0-render");
files.push_back("./test_files/linux/by-path/pci-0000:00:03.0-card");
files.push_back("./test_files/linux/by-path/pci-0000:00:03.0-render");
return files;
}
if (path == "./test_files/linux/devices/device/drm") {