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 <[email protected]>
---
 pyjailhouse/sysfs_parser.py   | 35 +++++++++++++++++++++++++++++++----
 tools/root-cell-config.c.tmpl |  2 +-
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/pyjailhouse/sysfs_parser.py b/pyjailhouse/sysfs_parser.py
index 0a690186..a21690db 100644
--- a/pyjailhouse/sysfs_parser.py
+++ b/pyjailhouse/sysfs_parser.py
@@ -655,14 +655,41 @@ class PCICapability:
 
                 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,
diff --git a/tools/root-cell-config.c.tmpl b/tools/root-cell-config.c.tmpl
index 81d3a92b..512b9f0d 100644
--- a/tools/root-cell-config.c.tmpl
+++ b/tools/root-cell-config.c.tmpl
@@ -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
-- 
2.22.0

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/20190711200915.21217-1-ralf.ramsauer%40oth-regensburg.de.
For more options, visit https://groups.google.com/d/optout.

Reply via email to