board_inspector: parse SR-IOV capability structure properly

This patch adds the logic needed to fully parse an SR-IOV extended
capability structure. Such information will later be used to extract all
information about physical and virtual functions.

Tracked-On: #7301
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Junjie Mao 2022-04-16 00:19:28 +08:00 committed by acrnsi-robot
parent 0a77891f1c
commit 93ccc0f473

View File

@ -6,6 +6,9 @@
import ctypes
import copy
import inspectorlib.cdata as cdata
from .header import MemoryBar32, MemoryBar64, IOBar, \
PCIE_BAR_SPACE_MASK, PCIE_BAR_MEMORY_SPACE, PCIE_BAR_IO_SPACE, \
PCIE_BAR_TYPE_MASK, PCIE_BAR_TYPE_32_BIT, PCIE_BAR_TYPE_64_BIT
class ExtendedCapability:
# Capability names from PCI Express Base Specification, mostly Table 9-23
@ -62,6 +65,11 @@ class ExtendedCapability:
else:
return f"Reserved Extended ({hex(self.id)})"
@property
def next_cap_ptr(self):
# Classes inherit ExtendedCapability must implement the attribute next_cap_ptr_raw
return self.next_cap_ptr_raw & 0xffc
class ExtendedCapabilityListRegister(cdata.Struct, ExtendedCapability):
_pack_ = 1
_fields_ = [
@ -70,12 +78,90 @@ class ExtendedCapabilityListRegister(cdata.Struct, ExtendedCapability):
('next_cap_ptr_raw', ctypes.c_uint32, 12),
]
@property
def next_cap_ptr(self):
return self.next_cap_ptr_raw & 0xffc
# SR-IOV (0x10)
class SRIOVBase(cdata.Struct, ExtendedCapability):
_pack_ = 1
_fields_ = copy.copy(ExtendedCapabilityListRegister._fields_) + [
# SR-IOV Capabilities Register
('vf_migration_capable', ctypes.c_uint32, 1),
('ari_capable_hierarchy_preserved', ctypes.c_uint32, 1),
('vf_10_bit_tag_requester_supported', ctypes.c_uint32, 1),
('reserved1', ctypes.c_uint32, 18),
('vf_migration_interrupt_message_number', ctypes.c_uint32, 11),
# SR-IOV Control Register
('vf_enable', ctypes.c_uint32, 1),
('vf_migration_enable', ctypes.c_uint32, 1),
('vf_migration_interrupt_enable', ctypes.c_uint32, 1),
('vf_mse', ctypes.c_uint32, 1),
('ari_capable_hierarchy', ctypes.c_uint32, 1),
('vf_10_bit_tag_requester_enable', ctypes.c_uint32, 1),
('reserved2', ctypes.c_uint32, 10),
# SR-IOV Status Register
('vf_migration_status', ctypes.c_uint32, 1),
('reserved3', ctypes.c_uint32, 15),
('initial_vfs', ctypes.c_uint16),
('total_vfs', ctypes.c_uint16),
('num_vfs', ctypes.c_uint16),
('function_dependency_link', ctypes.c_uint8),
('reserved4', ctypes.c_uint8),
('first_vf_offset', ctypes.c_uint16),
('vf_stride', ctypes.c_uint16),
('reserved5', ctypes.c_uint16),
('vf_device_id', ctypes.c_uint16),
('supported_page_sizes', ctypes.c_uint32),
('system_page_size', ctypes.c_uint32),
]
def SRIOV_factory(addr):
vf_bars_list = list()
bar_base = addr + ctypes.sizeof(SRIOVBase)
bar_addr = bar_base
bar_end = bar_base + 0x18
while bar_addr < bar_end:
bar = ctypes.c_uint32.from_address(bar_addr).value
idx = int((bar_addr - bar_base) / 4)
if (bar & PCIE_BAR_SPACE_MASK) == PCIE_BAR_MEMORY_SPACE:
if (bar & PCIE_BAR_TYPE_MASK) == PCIE_BAR_TYPE_64_BIT:
vf_bars_list.append((f"vf_bar{idx}", MemoryBar64))
bar_addr += 0x8
else:
vf_bars_list.append((f"vf_bar{idx}", MemoryBar32))
bar_addr += 0x4
else:
vf_bars_list.append((f"vf_bar{idx}", IOBar))
bar_addr += 0x4
class SRIOV(cdata.Struct, ExtendedCapability):
class VFBars(cdata.Struct):
_pack_ = 1
_fields_ = vf_bars_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
_pack_ = 1
_fields_ = copy.copy(SRIOVBase._fields_) + [
('vf_bars', VFBars),
('vf_migration_state_array_offset', ctypes.c_uint32),
]
return SRIOV
def parse_sriov(buf, cap_ptr):
return SRIOV_factory(ctypes.addressof(buf) + cap_ptr).from_buffer_copy(buf, cap_ptr)
# Module API
capability_parsers = {
0x10: parse_sriov,
}
def extended_capabilities(data):
buf = ctypes.create_string_buffer(data, len(data))
cap_ptr = 0x100
@ -83,7 +169,9 @@ def extended_capabilities(data):
acc = list()
while cap_ptr != 0:
caplist = ExtendedCapabilityListRegister.from_buffer_copy(buf, cap_ptr)
if caplist.id != 0:
if caplist.id in capability_parsers.keys():
acc.append(capability_parsers[caplist.id](buf, cap_ptr))
elif caplist.id != 0:
acc.append(caplist)
cap_ptr = caplist.next_cap_ptr