Skip to content

Commit f9703f2

Browse files
feature(sysman): Added support for PCI APIs
Added support for PCI APIs in the new sysman design Added ULTs for the PCI APIs in the new sysman design Related-To: LOCI-4319 Signed-off-by: Bari, Pratik <[email protected]>
1 parent 7b27d7c commit f9703f2

20 files changed

+1646
-4
lines changed

level_zero/api/sysman/zes_sysman_api_entrypoints.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,26 +171,42 @@ ze_result_t zesDeviceReset(
171171
ze_result_t zesDevicePciGetProperties(
172172
zes_device_handle_t hDevice,
173173
zes_pci_properties_t *pProperties) {
174-
return L0::SysmanDevice::pciGetProperties(hDevice, pProperties);
174+
if (L0::sysmanInitFromCore) {
175+
return L0::SysmanDevice::pciGetProperties(hDevice, pProperties);
176+
} else {
177+
return L0::Sysman::SysmanDevice::pciGetProperties(hDevice, pProperties);
178+
}
175179
}
176180

177181
ze_result_t zesDevicePciGetState(
178182
zes_device_handle_t hDevice,
179183
zes_pci_state_t *pState) {
180-
return L0::SysmanDevice::pciGetState(hDevice, pState);
184+
if (L0::sysmanInitFromCore) {
185+
return L0::SysmanDevice::pciGetState(hDevice, pState);
186+
} else {
187+
return L0::Sysman::SysmanDevice::pciGetState(hDevice, pState);
188+
}
181189
}
182190

183191
ze_result_t zesDevicePciGetBars(
184192
zes_device_handle_t hDevice,
185193
uint32_t *pCount,
186194
zes_pci_bar_properties_t *pProperties) {
187-
return L0::SysmanDevice::pciGetBars(hDevice, pCount, pProperties);
195+
if (L0::sysmanInitFromCore) {
196+
return L0::SysmanDevice::pciGetBars(hDevice, pCount, pProperties);
197+
} else {
198+
return L0::Sysman::SysmanDevice::pciGetBars(hDevice, pCount, pProperties);
199+
}
188200
}
189201

190202
ze_result_t zesDevicePciGetStats(
191203
zes_device_handle_t hDevice,
192204
zes_pci_stats_t *pStats) {
193-
return L0::SysmanDevice::pciGetStats(hDevice, pStats);
205+
if (L0::sysmanInitFromCore) {
206+
return L0::SysmanDevice::pciGetStats(hDevice, pStats);
207+
} else {
208+
return L0::Sysman::SysmanDevice::pciGetStats(hDevice, pStats);
209+
}
194210
}
195211

196212
ze_result_t zesDeviceEnumPowerDomains(
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Copyright (C) 2023 Intel Corporation
3+
#
4+
# SPDX-License-Identifier: MIT
5+
#
6+
7+
target_sources(${L0_STATIC_LIB_NAME}
8+
PRIVATE
9+
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
10+
${CMAKE_CURRENT_SOURCE_DIR}/pci.h
11+
${CMAKE_CURRENT_SOURCE_DIR}/pci_imp.cpp
12+
${CMAKE_CURRENT_SOURCE_DIR}/pci_imp.h
13+
${CMAKE_CURRENT_SOURCE_DIR}/os_pci.h
14+
)
15+
16+
add_subdirectories()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#
2+
# Copyright (C) 2023 Intel Corporation
3+
#
4+
# SPDX-License-Identifier: MIT
5+
#
6+
7+
if(UNIX)
8+
target_sources(${L0_STATIC_LIB_NAME}
9+
PRIVATE
10+
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
11+
${CMAKE_CURRENT_SOURCE_DIR}/os_pci_imp.cpp
12+
${CMAKE_CURRENT_SOURCE_DIR}/os_pci_imp.h
13+
)
14+
endif()
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/*
2+
* Copyright (C) 2023 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "level_zero/sysman/source/pci/linux/os_pci_imp.h"
9+
10+
#include "shared/source/debug_settings/debug_settings_manager.h"
11+
#include "shared/source/utilities/directory.h"
12+
13+
#include "level_zero/sysman/source/pci/pci_imp.h"
14+
#include "level_zero/sysman/source/sysman_const.h"
15+
16+
#include <linux/pci_regs.h>
17+
18+
namespace L0 {
19+
namespace Sysman {
20+
21+
const std::string LinuxPciImp::deviceDir("device");
22+
const std::string LinuxPciImp::resourceFile("device/resource");
23+
24+
ze_result_t LinuxPciImp::getProperties(zes_pci_properties_t *properties) {
25+
properties->haveBandwidthCounters = false;
26+
properties->havePacketCounters = false;
27+
properties->haveReplayCounters = false;
28+
return ZE_RESULT_SUCCESS;
29+
}
30+
ze_result_t LinuxPciImp::getPciBdf(zes_pci_properties_t &pciProperties) {
31+
std::string bdfDir;
32+
ze_result_t result = pSysfsAccess->readSymLink(deviceDir, bdfDir);
33+
if (ZE_RESULT_SUCCESS != result) {
34+
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): readSymLink() failed to retrive BDF from %s and returning error:0x%x \n", __FUNCTION__, deviceDir.c_str(), result);
35+
return result;
36+
}
37+
const auto loc = bdfDir.find_last_of('/');
38+
std::string bdf = bdfDir.substr(loc + 1);
39+
uint16_t domain = 0;
40+
uint8_t bus = 0, device = 0, function = 0;
41+
NEO::parseBdfString(bdf.c_str(), domain, bus, device, function);
42+
pciProperties.address.domain = static_cast<uint32_t>(domain);
43+
pciProperties.address.bus = static_cast<uint32_t>(bus);
44+
pciProperties.address.device = static_cast<uint32_t>(device);
45+
pciProperties.address.function = static_cast<uint32_t>(function);
46+
return ZE_RESULT_SUCCESS;
47+
}
48+
49+
void LinuxPciImp::getMaxLinkCaps(double &maxLinkSpeed, int32_t &maxLinkWidth) {
50+
uint16_t linkCaps = 0;
51+
auto linkCapPos = getLinkCapabilityPos();
52+
if (!linkCapPos) {
53+
maxLinkSpeed = 0;
54+
maxLinkWidth = -1;
55+
return;
56+
}
57+
58+
linkCaps = getWordFromConfig(linkCapPos, (!(isIntegratedDevice)) ? uspConfigMemory.get() : configMemory.get());
59+
maxLinkSpeed = convertPciGenToLinkSpeed(BITS(linkCaps, 0, 4));
60+
maxLinkWidth = BITS(linkCaps, 4, 6);
61+
62+
return;
63+
}
64+
65+
void getBarBaseAndSize(std::string readBytes, uint64_t &baseAddr, uint64_t &barSize, uint64_t &barFlags) {
66+
unsigned long long start, end, flags;
67+
std::stringstream sStreamReadBytes;
68+
sStreamReadBytes << readBytes;
69+
sStreamReadBytes >> std::hex >> start;
70+
sStreamReadBytes >> end;
71+
sStreamReadBytes >> flags;
72+
73+
flags &= 0xf;
74+
barFlags = flags;
75+
baseAddr = start;
76+
barSize = end - start + 1;
77+
}
78+
79+
ze_result_t LinuxPciImp::initializeBarProperties(std::vector<zes_pci_bar_properties_t *> &pBarProperties) {
80+
std::vector<std::string> readBytes;
81+
ze_result_t result = pSysfsAccess->read(resourceFile, readBytes);
82+
if (result != ZE_RESULT_SUCCESS) {
83+
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): read() failed to read %s and returning error:0x%x \n", __FUNCTION__, resourceFile.c_str(), result);
84+
return result;
85+
}
86+
for (uint32_t i = 0; i <= maxPciBars; i++) {
87+
uint64_t baseAddr, barSize, barFlags;
88+
getBarBaseAndSize(readBytes[i], baseAddr, barSize, barFlags);
89+
if (baseAddr && !(barFlags & 0x1)) { // we do not update for I/O ports
90+
zes_pci_bar_properties_t *pBarProp = new zes_pci_bar_properties_t;
91+
memset(pBarProp, 0, sizeof(zes_pci_bar_properties_t));
92+
pBarProp->index = i;
93+
pBarProp->base = baseAddr;
94+
pBarProp->size = barSize;
95+
// Bar Flags Desc.
96+
// Bit-0 - Value 0x0 -> MMIO type BAR
97+
// Bit-0 - Value 0x1 -> I/O type BAR
98+
if (i == 0) { // GRaphics MMIO is at BAR0, and is a 64-bit
99+
pBarProp->type = ZES_PCI_BAR_TYPE_MMIO;
100+
}
101+
if (i == 2) {
102+
pBarProp->type = ZES_PCI_BAR_TYPE_MEM; // device memory is always at BAR2
103+
}
104+
if (i == 6) { // the 7th entry of resource file is expected to be ROM BAR
105+
pBarProp->type = ZES_PCI_BAR_TYPE_ROM;
106+
}
107+
pBarProperties.push_back(pBarProp);
108+
}
109+
}
110+
if (pBarProperties.size() == 0) {
111+
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): BarProperties = %d and returning error:0x%x \n", __FUNCTION__, pBarProperties.size(), result);
112+
result = ZE_RESULT_ERROR_UNKNOWN;
113+
}
114+
return result;
115+
}
116+
117+
uint32_t LinuxPciImp::getRebarCapabilityPos() {
118+
uint32_t pos = PCI_CFG_SPACE_SIZE;
119+
uint32_t header = 0;
120+
121+
if (!configMemory) {
122+
return 0;
123+
}
124+
125+
// Minimum 8 bytes per capability. Hence maximum capabilities that
126+
// could be present in PCI extended configuration space are
127+
// represented by loopCount.
128+
auto loopCount = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
129+
header = getDwordFromConfig(pos);
130+
if (!header) {
131+
return 0;
132+
}
133+
134+
while (loopCount-- > 0) {
135+
if (PCI_EXT_CAP_ID(header) == PCI_EXT_CAP_ID_REBAR) {
136+
return pos;
137+
}
138+
pos = PCI_EXT_CAP_NEXT(header);
139+
if (pos < PCI_CFG_SPACE_SIZE) {
140+
return 0;
141+
}
142+
header = getDwordFromConfig(pos);
143+
}
144+
return 0;
145+
}
146+
147+
uint16_t LinuxPciImp::getLinkCapabilityPos() {
148+
uint16_t pos = PCI_CAPABILITY_LIST;
149+
uint8_t id, type = 0;
150+
uint16_t capRegister = 0;
151+
uint8_t *configMem = (!(isIntegratedDevice)) ? uspConfigMemory.get() : configMemory.get();
152+
153+
if ((!configMem) || (!(getByteFromConfig(PCI_STATUS, configMem) & PCI_STATUS_CAP_LIST))) {
154+
return 0;
155+
}
156+
157+
// Minimum 8 bytes per capability. Hence maximum capabilities that
158+
// could be present in PCI configuration space are
159+
// represented by loopCount.
160+
auto loopCount = (PCI_CFG_SPACE_SIZE) / 8;
161+
162+
// Bottom two bits of capability pointer register are reserved and
163+
// software should mask these bits to get pointer to capability list.
164+
165+
pos = getByteFromConfig(pos, configMem) & 0xfc;
166+
while (loopCount-- > 0) {
167+
id = getByteFromConfig(pos + PCI_CAP_LIST_ID, configMem);
168+
if (id == PCI_CAP_ID_EXP) {
169+
capRegister = getWordFromConfig(pos + PCI_CAP_FLAGS, configMem);
170+
type = BITS(capRegister, 4, 4);
171+
172+
// Root Complex Integrated end point and
173+
// Root Complex Event collector will not implement link capabilities
174+
175+
if ((type != PCI_EXP_TYPE_RC_END) && (type != PCI_EXP_TYPE_RC_EC)) {
176+
return pos + PCI_EXP_LNKCAP;
177+
}
178+
}
179+
180+
pos = getByteFromConfig(pos + PCI_CAP_LIST_NEXT, configMem) & 0xfc;
181+
if (!pos) {
182+
break;
183+
}
184+
}
185+
return 0;
186+
}
187+
188+
// Parse PCIe configuration space to see if resizable Bar is supported
189+
bool LinuxPciImp::resizableBarSupported() {
190+
return (getRebarCapabilityPos() > 0);
191+
}
192+
193+
bool LinuxPciImp::resizableBarEnabled(uint32_t barIndex) {
194+
bool isBarResizable = false;
195+
uint32_t capabilityRegister = 0, controlRegister = 0;
196+
uint32_t nBars = 1;
197+
auto rebarCapabilityPos = getRebarCapabilityPos();
198+
199+
// If resizable Bar is not supported then return false.
200+
if (!rebarCapabilityPos) {
201+
return false;
202+
}
203+
204+
// As per PCI spec, resizable BAR's capability structure's 52 byte length could be represented as:
205+
// --------------------------------------------------------------
206+
// | byte offset | Description of register |
207+
// -------------------------------------------------------------|
208+
// | +000h | PCI Express Extended Capability Header |
209+
// -------------------------------------------------------------|
210+
// | +004h | Resizable BAR Capability Register (0) |
211+
// -------------------------------------------------------------|
212+
// | +008h | Resizable BAR Control Register (0) |
213+
// -------------------------------------------------------------|
214+
// | +00Ch | Resizable BAR Capability Register (1) |
215+
// -------------------------------------------------------------|
216+
// | +010h | Resizable BAR Control Register (1) |
217+
// -------------------------------------------------------------|
218+
// | +014h | --- |
219+
// -------------------------------------------------------------|
220+
221+
// Only first Control register(at offset 008h, as shown above), could tell about number of resizable Bars
222+
controlRegister = getDwordFromConfig(rebarCapabilityPos + PCI_REBAR_CTRL);
223+
nBars = BITS(controlRegister, 5, 3); // control register's bits 5,6 and 7 contain number of resizable bars information
224+
for (auto barNumber = 0u; barNumber < nBars; barNumber++) {
225+
uint32_t barId = 0;
226+
controlRegister = getDwordFromConfig(rebarCapabilityPos + PCI_REBAR_CTRL);
227+
barId = BITS(controlRegister, 0, 3); // Control register's bit 0,1,2 tells the index of bar
228+
if (barId == barIndex) {
229+
isBarResizable = true;
230+
break;
231+
}
232+
rebarCapabilityPos += 8;
233+
}
234+
235+
if (isBarResizable == false) {
236+
return false;
237+
}
238+
239+
capabilityRegister = getDwordFromConfig(rebarCapabilityPos + PCI_REBAR_CAP);
240+
// Capability register's bit 4 to 31 indicates supported Bar sizes.
241+
// In possibleBarSizes, position of each set bit indicates supported bar size. Example, if set bit
242+
// position of possibleBarSizes is from 0 to n, then this indicates BAR size from 2^0 MB to 2^n MB
243+
auto possibleBarSizes = (capabilityRegister & PCI_REBAR_CAP_SIZES) >> 4; // First 4 bits are reserved
244+
uint32_t largestPossibleBarSize = 0;
245+
while (possibleBarSizes >>= 1) { // most significant set bit position of possibleBarSizes would tell larget possible bar size
246+
largestPossibleBarSize++;
247+
}
248+
249+
// Control register's bit 8 to 13 indicates current BAR size in encoded form.
250+
// Example, real value of current size could be 2^currentSize MB
251+
auto currentSize = BITS(controlRegister, 8, 6);
252+
253+
// If current size is equal to larget possible BAR size, it indicates resizable BAR is enabled.
254+
return (currentSize == largestPossibleBarSize);
255+
}
256+
257+
ze_result_t LinuxPciImp::getState(zes_pci_state_t *state) {
258+
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s() returning UNSUPPORTED_FEATURE \n", __FUNCTION__);
259+
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
260+
}
261+
262+
void LinuxPciImp::pciExtendedConfigRead() {
263+
std::string pciConfigNode;
264+
pSysfsAccess->getRealPath("device/config", pciConfigNode);
265+
266+
int fdConfig = -1;
267+
fdConfig = this->openFunction(pciConfigNode.c_str(), O_RDONLY);
268+
if (fdConfig < 0) {
269+
return;
270+
}
271+
configMemory = std::make_unique<uint8_t[]>(PCI_CFG_SPACE_EXP_SIZE);
272+
memset(configMemory.get(), 0, PCI_CFG_SPACE_EXP_SIZE);
273+
this->preadFunction(fdConfig, configMemory.get(), PCI_CFG_SPACE_EXP_SIZE, 0);
274+
this->closeFunction(fdConfig);
275+
}
276+
277+
void LinuxPciImp::pciCardBusConfigRead() {
278+
std::string pciConfigNode;
279+
std::string rootPortPath;
280+
pSysfsAccess->getRealPath(deviceDir, pciConfigNode);
281+
rootPortPath = pLinuxSysmanImp->getPciCardBusDirectoryPath(pciConfigNode);
282+
pciConfigNode = rootPortPath + "/config";
283+
int fdConfig = -1;
284+
fdConfig = this->openFunction(pciConfigNode.c_str(), O_RDONLY);
285+
if (fdConfig < 0) {
286+
return;
287+
}
288+
uspConfigMemory = std::make_unique<uint8_t[]>(PCI_CFG_SPACE_SIZE);
289+
memset(uspConfigMemory.get(), 0, PCI_CFG_SPACE_SIZE);
290+
this->preadFunction(fdConfig, uspConfigMemory.get(), PCI_CFG_SPACE_SIZE, 0);
291+
this->closeFunction(fdConfig);
292+
}
293+
294+
LinuxPciImp::LinuxPciImp(OsSysman *pOsSysman) {
295+
pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
296+
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
297+
isIntegratedDevice = pLinuxSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironment().getHardwareInfo()->capabilityTable.isIntegratedDevice;
298+
299+
if (pSysfsAccess->isRootUser()) {
300+
pciExtendedConfigRead();
301+
pciCardBusConfigRead();
302+
}
303+
}
304+
305+
OsPci *OsPci::create(OsSysman *pOsSysman) {
306+
LinuxPciImp *pLinuxPciImp = new LinuxPciImp(pOsSysman);
307+
return static_cast<OsPci *>(pLinuxPciImp);
308+
}
309+
310+
} // namespace Sysman
311+
} // namespace L0

0 commit comments

Comments
 (0)