1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "level_zero/tools/source/sysman/linux/os_sysman_imp.h"
9 
10 #include "level_zero/tools/source/sysman/linux/fs_access.h"
11 
12 #include "sysman/linux/firmware_util/firmware_util.h"
13 
14 namespace L0 {
15 
init()16 ze_result_t LinuxSysmanImp::init() {
17     pFsAccess = FsAccess::create();
18     DEBUG_BREAK_IF(nullptr == pFsAccess);
19 
20     if (pProcfsAccess == nullptr) {
21         pProcfsAccess = ProcfsAccess::create();
22     }
23     DEBUG_BREAK_IF(nullptr == pProcfsAccess);
24 
25     auto result = initLocalDeviceAndDrmHandles();
26     if (ZE_RESULT_SUCCESS != result) {
27         return result;
28     }
29     int myDeviceFd = pDrm->getFileDescriptor();
30     std::string myDeviceName;
31     result = pProcfsAccess->getFileName(pProcfsAccess->myProcessId(), myDeviceFd, myDeviceName);
32     if (ZE_RESULT_SUCCESS != result) {
33         return result;
34     }
35 
36     if (pSysfsAccess == nullptr) {
37         pSysfsAccess = SysfsAccess::create(myDeviceName);
38     }
39     DEBUG_BREAK_IF(nullptr == pSysfsAccess);
40 
41 #ifdef __linux__
42     pPmuInterface = PmuInterface::create(this);
43 
44     DEBUG_BREAK_IF(nullptr == pPmuInterface);
45 #endif
46 
47     return createPmtHandles();
48 }
49 
createFwUtilInterface()50 void LinuxSysmanImp::createFwUtilInterface() {
51     std::string realRootPath;
52     auto result = pSysfsAccess->getRealPath("device", realRootPath);
53     if (ZE_RESULT_SUCCESS != result) {
54         return;
55     }
56     auto rootPciPathOfGpuDevice = getPciRootPortDirectoryPath(realRootPath);
57     auto loc = realRootPath.find_last_of('/');
58     pFwUtilInterface = FirmwareUtil::create(realRootPath.substr(loc + 1, std::string::npos));
59 }
60 
createPmtHandles()61 ze_result_t LinuxSysmanImp::createPmtHandles() {
62     std::string realRootPath;
63     auto result = pSysfsAccess->getRealPath("device", realRootPath);
64     if (ZE_RESULT_SUCCESS != result) {
65         return result;
66     }
67     auto rootPciPathOfGpuDevice = getPciRootPortDirectoryPath(realRootPath);
68     PlatformMonitoringTech::create(pParentSysmanDeviceImp->deviceHandles, pFsAccess, rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject);
69     return result;
70 }
71 
getPmuInterface()72 PmuInterface *LinuxSysmanImp::getPmuInterface() {
73     return pPmuInterface;
74 }
75 
getFwUtilInterface()76 FirmwareUtil *LinuxSysmanImp::getFwUtilInterface() {
77     if (pFwUtilInterface == nullptr) {
78         createFwUtilInterface();
79     }
80     return pFwUtilInterface;
81 }
82 
getProductFamily()83 PRODUCT_FAMILY LinuxSysmanImp::getProductFamily() {
84     return pDevice->getNEODevice()->getHardwareInfo().platform.eProductFamily;
85 }
86 
getFsAccess()87 FsAccess &LinuxSysmanImp::getFsAccess() {
88     UNRECOVERABLE_IF(nullptr == pFsAccess);
89     return *pFsAccess;
90 }
91 
getProcfsAccess()92 ProcfsAccess &LinuxSysmanImp::getProcfsAccess() {
93     UNRECOVERABLE_IF(nullptr == pProcfsAccess);
94     return *pProcfsAccess;
95 }
96 
getSysfsAccess()97 SysfsAccess &LinuxSysmanImp::getSysfsAccess() {
98     UNRECOVERABLE_IF(nullptr == pSysfsAccess);
99     return *pSysfsAccess;
100 }
101 
initLocalDeviceAndDrmHandles()102 ze_result_t LinuxSysmanImp::initLocalDeviceAndDrmHandles() {
103     pDevice = Device::fromHandle(pParentSysmanDeviceImp->hCoreDevice);
104     DEBUG_BREAK_IF(nullptr == pDevice);
105     NEO::OSInterface &OsInterface = pDevice->getOsInterface();
106     if (OsInterface.getDriverModel()->getDriverModelType() != NEO::DriverModelType::DRM) {
107         return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
108     }
109     pDrm = OsInterface.getDriverModel()->as<NEO::Drm>();
110     return ZE_RESULT_SUCCESS;
111 }
112 
getDrm()113 NEO::Drm &LinuxSysmanImp::getDrm() {
114     if (pDrm == nullptr) {
115         initLocalDeviceAndDrmHandles();
116     }
117     UNRECOVERABLE_IF(nullptr == pDrm);
118     return *pDrm;
119 }
120 
releaseLocalDrmHandle()121 void LinuxSysmanImp::releaseLocalDrmHandle() {
122     pDrm = nullptr;
123 }
124 
getDeviceHandle()125 Device *LinuxSysmanImp::getDeviceHandle() {
126     return pDevice;
127 }
128 
getSysmanDeviceImp()129 SysmanDeviceImp *LinuxSysmanImp::getSysmanDeviceImp() {
130     return pParentSysmanDeviceImp;
131 }
132 
getPciRootPortDirectoryPath(std::string realPciPath)133 std::string LinuxSysmanImp::getPciRootPortDirectoryPath(std::string realPciPath) {
134     size_t loc;
135     // we need to change the absolute path to two levels up to get
136     // the Discrete card's root port.
137     // the root port is always at a fixed distance as defined in HW
138     uint8_t nLevel = 2;
139     while (nLevel > 0) {
140         loc = realPciPath.find_last_of('/');
141         if (loc == std::string::npos) {
142             break;
143         }
144         realPciPath = realPciPath.substr(0, loc);
145         nLevel--;
146     }
147     return realPciPath;
148 }
149 
getPlatformMonitoringTechAccess(uint32_t subDeviceId)150 PlatformMonitoringTech *LinuxSysmanImp::getPlatformMonitoringTechAccess(uint32_t subDeviceId) {
151     auto subDeviceIdToPmtEntry = mapOfSubDeviceIdToPmtObject.find(subDeviceId);
152     if (subDeviceIdToPmtEntry == mapOfSubDeviceIdToPmtObject.end()) {
153         return nullptr;
154     }
155     return subDeviceIdToPmtEntry->second;
156 }
157 
LinuxSysmanImp(SysmanDeviceImp * pParentSysmanDeviceImp)158 LinuxSysmanImp::LinuxSysmanImp(SysmanDeviceImp *pParentSysmanDeviceImp) {
159     this->pParentSysmanDeviceImp = pParentSysmanDeviceImp;
160 }
161 
releasePmtObject()162 void LinuxSysmanImp::releasePmtObject() {
163     for (auto &subDeviceIdToPmtEntry : mapOfSubDeviceIdToPmtObject) {
164         if (subDeviceIdToPmtEntry.second) {
165             delete subDeviceIdToPmtEntry.second;
166             subDeviceIdToPmtEntry.second = nullptr;
167         }
168     }
169     mapOfSubDeviceIdToPmtObject.clear();
170 }
releaseFwUtilInterface()171 void LinuxSysmanImp::releaseFwUtilInterface() {
172     if (nullptr != pFwUtilInterface) {
173         delete pFwUtilInterface;
174         pFwUtilInterface = nullptr;
175     }
176 }
177 
~LinuxSysmanImp()178 LinuxSysmanImp::~LinuxSysmanImp() {
179     if (nullptr != pSysfsAccess) {
180         delete pSysfsAccess;
181         pSysfsAccess = nullptr;
182     }
183     if (nullptr != pProcfsAccess) {
184         delete pProcfsAccess;
185         pProcfsAccess = nullptr;
186     }
187     if (nullptr != pFsAccess) {
188         delete pFsAccess;
189         pFsAccess = nullptr;
190     }
191     if (nullptr != pPmuInterface) {
192         delete pPmuInterface;
193         pPmuInterface = nullptr;
194     }
195     releaseFwUtilInterface();
196     releasePmtObject();
197 }
198 
create(SysmanDeviceImp * pParentSysmanDeviceImp)199 OsSysman *OsSysman::create(SysmanDeviceImp *pParentSysmanDeviceImp) {
200     LinuxSysmanImp *pLinuxSysmanImp = new LinuxSysmanImp(pParentSysmanDeviceImp);
201     return static_cast<OsSysman *>(pLinuxSysmanImp);
202 }
203 
204 } // namespace L0
205