[PATCH] board_inspector: tolerate PCI functions with undefined header layout


Junjie Mao
 

While PCIe specification defines only type 0 and type 1 configuration space
headers, there can be cases where a PCI function has a different header
type. As an example, that device itself is under development or is a
special emulated device.

This patch makes the board inspector gracefully skips those PCIe functions
and continue scanning the rest in such cases, as the only impact of the
anomaly is the prevention of ACRN from passing through that PCIe function
to any VM. It is an overkill to crash the board inspector.

Signed-off-by: Junjie Mao <junjie.mao@...>
---
.../board_inspector/extractors/60-pci.py | 13 ++++++++++---
.../board_inspector/pcieparser/__init__.py | 2 +-
.../board_inspector/pcieparser/header.py | 2 +-
3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/misc/config_tools/board_inspector/extractors/60-pci.py b/misc/config_tools/board_inspector/extractors/60-pci.py
index b2f99f50c..1dec6b9ef 100644
--- a/misc/config_tools/board_inspector/extractors/60-pci.py
+++ b/misc/config_tools/board_inspector/extractors/60-pci.py
@@ -98,9 +98,16 @@ def parse_device(bus_node, device_path):
cfg = parse_config_space(device_path)
physfn_cfg = parse_config_space(os.path.join(device_path, "physfn"))

- # There are cases where Linux creates device-like nodes without a file named "config", e.g. when there is a PCIe
- # non-transparent bridge (NTB) on the physical platform.
- if cfg is None:
+ # The following kinds of PCIe functions are not supported by ACRN.
+ #
+ # 1. There are cases where Linux creates device-like nodes without a file named "config", e.g. when there is a PCIe
+ # non-transparent bridge (NTB) on the physical platform.
+ #
+ # 2. Some PCIe functions may have a configuration header type other than 0 or 1, which is not yet defined in PCIe
+ # specifications.
+ #
+ # Such PCIe functions are ignored by the board inspector and won't be able to passthrough to any VM.
+ if cfg is None or hasattr(cfg.header, "unparsed_data"):
return None

if device_name == "0000:00:00.0":
diff --git a/misc/config_tools/board_inspector/pcieparser/__init__.py b/misc/config_tools/board_inspector/pcieparser/__init__.py
index 202c915f1..f20482ae5 100644
--- a/misc/config_tools/board_inspector/pcieparser/__init__.py
+++ b/misc/config_tools/board_inspector/pcieparser/__init__.py
@@ -41,7 +41,7 @@ def parse_config_space(path):
try:
data = open(os.path.join(path, "config"), mode='rb').read()
hdr = header(data)
- caps = capabilities(data, hdr.capability_pointer)
+ caps = capabilities(data, hdr.capability_pointer) if hasattr(hdr, 'capability_pointer') else []
config_space = PCIConfigSpace(hdr, caps, [])
# While PCI Express specification requires that a PCIe endpoint must have an extended capability header at
# offset 100h of its configuration space, we do see real PCIe endpoints not meeting this requirement
diff --git a/misc/config_tools/board_inspector/pcieparser/header.py b/misc/config_tools/board_inspector/pcieparser/header.py
index fb8e6ea02..4be6f3ae1 100644
--- a/misc/config_tools/board_inspector/pcieparser/header.py
+++ b/misc/config_tools/board_inspector/pcieparser/header.py
@@ -173,7 +173,7 @@ def header_field_list(addr):
elif common_header.header_type == 0x01:
return header_type_1_field_list(addr + ctypes.sizeof(Common))
else:
- return [('data', ctypes.c_uint8 * 0x30)]
+ return [('unparsed_data', ctypes.c_uint8 * 0x30)]

def header_factory(field_list):
class Header(cdata.Struct):
--
2.30.2