Skip to content
Permalink
Browse files

pyjailhouse: sysfs_parser: Add more precise length of some extended caps

I often run into situations where Linux tries to write to some extended
capabilities. E.g., Linux wants to clear Advanced Error Reporting (ERR)
registers when probing for a device.

At the moment, the crash dump of the cell is hard to interprete, as it
remains unclear if the access is inside a capability, or if the device
just accesses some PCI config space (e.g., accesses beyond PCI spec). At
the moment, all extended capabilities have a fixed length of 4, which
supports the confusion. Four bytes only cover the header of the
capability.

This patch calculates the correct length of PCI caps for the
configuration file -- at least of some capabilities. For some extended
caps this is pretty easy, as they have a fixed length.
  Nevertheless, other vary in their length. In some cases, it's pretty
easy (VNDR, ACS), in other cases it's not worth it (VC, VC9) due to
their complexity.

Caps that aren't handle still result in a length of 4.

Additionally, switch to a hexadecimal representation of the length of
PCI caps in config files.

Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
  • Loading branch information...
rralf authored and jan-kiszka committed Jul 11, 2019
1 parent 9f23389 commit f6fef92ffabab0772a6da1fd15cf12887a9600fa
Showing with 32 additions and 5 deletions.
  1. +31 −4 pyjailhouse/sysfs_parser.py
  2. +1 −1 tools/root-cell-config.c.tmpl
@@ -655,14 +655,41 @@ def parse_pcicaps(dir):

id = PCI_EXT_CAP_ID(id)
next = version_next >> 4
if id == PCI_EXT_CAP_ID.SRIOV:
# access side effects still need to be analyzed
flags = PCICapability.RD

if id == PCI_EXT_CAP_ID.VNDR:
(vsec_len,) = struct.unpack('<I', f.read(4))
len = 4 + (vsec_len >> 20)
elif id == PCI_EXT_CAP_ID.ACS:
len = 8
vector_size = 0

(acs_cap, acs_ctrl) = struct.unpack('<HH', f.read(4))
if acs_cap & (1 << 5) and acs_ctrl & (1 << 5):
vector_bits = acs_cap >> 8
if vector_bits == 0:
vector_bits = 256
vector_bytes = int((vector_bits + 31) / (8 * 4))
len += vector_bytes
elif id in [PCI_EXT_CAP_ID.VC, PCI_EXT_CAP_ID.VC9]:
# parsing is too complex, but we have at least 4 DWORDS
len = 4 * 4
elif id == PCI_EXT_CAP_ID.MFVC:
len = 4
elif id in [PCI_EXT_CAP_ID.LTR, PCI_EXT_CAP_ID.ARI, PCI_EXT_CAP_ID.PASID]:
len = 8
elif id in [PCI_EXT_CAP_ID.DSN, PCI_EXT_CAP_ID.PTM]:
len = 12
elif id in [PCI_EXT_CAP_ID.PWR, PCI_EXT_CAP_ID.SECPCI]:
len = 16
elif id == PCI_EXT_CAP_ID.MCAST:
len = 48
elif id in [PCI_EXT_CAP_ID.SRIOV, PCI_EXT_CAP_ID.ERR]:
len = 64
# access side effects still need to be analyzed
flags = PCICapability.RD
else:
# unknown/unhandled cap, mark its existence
len = 4
flags = PCICapability.RD
f.seek(cap + 4)
content = f.read(len - 4)
caps.append(PCICapability(id, True, cap, len, flags, content,
@@ -199,7 +199,7 @@ struct {
{
.id = ${c.gen_id_str()},
.start = ${hex(c.start)},
.len = ${c.len},
.len = ${hex(c.len)},
.flags = ${c.flags},
},
% endfor

0 comments on commit f6fef92

Please sign in to comment.
You can’t perform that action at this time.