They may not be used right now but will certainly ease the usage of the
parser API in the future.

Besides I already had written them long ago, so it would be a pity to
withehld them.

Signed-off-by: Andrej Utz <andrej....@st.oth-regensburg.de>
---
 pyjailhouse/config_parser.py | 178 ++++++++++++++++++++++++++++++++---
 1 file changed, 166 insertions(+), 12 deletions(-)

diff --git a/pyjailhouse/config_parser.py b/pyjailhouse/config_parser.py
index 2a0e6ec9..75e22fad 100644
--- a/pyjailhouse/config_parser.py
+++ b/pyjailhouse/config_parser.py
@@ -190,31 +190,77 @@ class PIORegion(CStruct):
         self.length = 0
 
 
+class PciDevice(CStruct):
+    __slots__ = 'type', 'iommu', 'domain', 'bdf', 'bar_mask', '_caps_start', \
+                '_caps_num', 'num_msi_vectors', 'msi_bits', \
+                'num_msix_vectors', 'msix_region_size', 'msix_address', \
+                'shmem_regions_start', 'shmem_dev_id', 'shmem_peers', \
+                'shmem_protocol'
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT_BAR_MASK = struct.Struct('6I')
+    _BIN_FMT = struct.Struct('BBHH%usHHBBHHQIBBH' % _BIN_FMT_BAR_MASK.size)
+
+    # constructed fields
+    __slots__ += 'caps',
+
+    TYPE_DEVICE = 1
+    TYPE_BRIDGE = 2
+    TYPE_IVSHMEM = 3
+
+    @classmethod
+    def parse(cls, stream):
+        self = cls.parse_class(cls, stream)
+        self.bar_mask = cls._BIN_FMT_BAR_MASK.unpack_from(self.bar_mask)
+        return self
+
+
+class PciCapability(CStruct):
+    __slots__ = 'id', 'start', 'len', 'flags'
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=HHHH')
+
+
+class Console(CStruct):
+    __slots__ = 'address', 'size', 'type', 'flags', 'divider', 'gate_nr', \
+                'clock_reg'
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=QIHHIIQ')
+
+
 class CellConfig(CStruct):
     # slots with a '_' prefix in name are private
-    __slots__ = 'name', '_flags', 'cpu_set', \
+    __slots__ = 'name', 'flags', 'cpu_set', \
                 'memory_regions', 'cache_regions', 'irqchips', 'pio_regions', \
-                '_pci_devices', '_pci_caps', '_stream_ids', \
+                'pci_devices', '_pci_caps', 'stream_ids', \
                 'vpci_irq_base', 'cpu_reset_address',
     _BIN_FIELD_NUM = len(__slots__)
-    _BIN_FMT = struct.Struct('=32s4xIIIIIIIIIIQ8x32x')
+    _BIN_FMT = struct.Struct('=32s4xIIIIIIIIIIQ8x')
     _BIN_FMT_HDR = struct.Struct('=6sH')
-    _BIN_FMT_CPU = struct.Struct('=Q')
+    _BIN_FMT_CPU = struct.Struct('Q')
+    _BIN_FMT_STREAM_ID = struct.Struct('I')
     _BIN_SIGNATURE = b'JHCELL'
 
+    # constructed fields
+    __slots__ += 'console',
+
     def __init__(self):
         self.name = ""
+        self.flags = 0
         self.cpu_set = set()
         self.memory_regions = []
         self.irqchips = []
         self.pio_regions = []
+        self.pci_devices = []
+        self.stream_ids = []
         self.vpci_irq_base = 0
         self.cpu_reset_address = 0
+        self.console = Console()
 
     @classmethod
     def parse(cls, stream):
         self = cls.parse_class(cls, stream)
         self.name = self.name.decode().strip('\0')
+        self.console = Console.parse(stream)
 
         cpu_fmt = cls._BIN_FMT_CPU
         cpu_set_num = int(self.cpu_set / cpu_fmt.size)
@@ -233,30 +279,138 @@ class CellConfig(CStruct):
         self.pio_regions = \
             cls.parse_array(PIORegion, self.pio_regions, stream)
 
+        self.pci_devices = cls.parse_array(PciDevice, self.pci_devices, stream)
+        pci_caps = cls.parse_array(PciCapability, self._pci_caps, stream)
+        for pci_dev in self.pci_devices:
+            start = pci_dev._caps_start
+            end = start + pci_dev._caps_num
+            pci_dev.caps = pci_caps[start:end]
+
+        sid_fmt = cls._BIN_FMT_STREAM_ID
+        sid_num = self.stream_ids
+        self.stream_ids = []
+        for i in range(sid_num):
+            self.stream_ids += [sid_fmt.unpack_from(stream.read(sid_fmt.size))]
+
+        return self
+
+
+class IommuAmd(CStruct):
+    __slots__ = 'bdf', 'base_cap', 'msi_cap', 'features'
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=HBBI')
+
+
+class IommuPvu(CStruct):
+    __slots__ = 'tlb_base', 'tlb_size'
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=QI')
+
+
+class Iommu(CStruct):
+    __slots__ = 'type', 'base', 'size',
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=IQI')
+
+    # constructed fields
+    __slots__ += 'subtype',
+
+    _MAX_UNITS = 8
+
+    TYPE_AMD = 1
+    TYPE_INTEL = 2
+    TYPE_SMMUV3 = 3
+    TYPE_PVU = 4
+
+    @classmethod
+    def parse(cls, stream):
+        self = cls.parse_class(cls, stream)
+        sub_cls = None
+        if self.type == cls.TYPE_AMD:
+            sub_cls = IommuAmd
+        elif self.type == cls.TYPE_PVU:
+            sub_cls = IommuPvu
+
+        if sub_cls:
+            self.subtype = sub_cls.parse(stream)
+
+        # skip rest of the C union, if needed
+        skip = max(IommuAmd._BIN_FMT.size, IommuPvu._BIN_FMT.size) \
+            - (sub_cls._BIN_FMT.size if sub_cls else 0)
+        stream.seek(skip, io.SEEK_CUR)
+        return self
+
+
+class PlattformInfoArm(CStruct):
+    __slots__ = 'maintenance_irq', 'gic_version', \
+                'gicd_base', 'gicc_base', 'gich_base', 'gicv_base', 
'gicr_base',
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=BB2xQQQQQ')
+
+
+class PlattformInfoX86(CStruct):
+    __slots__ = 'pm_timer_address', 'vtd_interrupt_limit', 'apic_mode', \
+                'tsc_khz', 'apic_khz',
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=HIB1xII')
+
+
+class PlattformInfo(CStruct):
+    __slots__ = 'pci_mmconfig_base', 'pci_mmconfig_end_bus', \
+                'pci_is_virtual', 'pci_domain',
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('=QBBH')
+
+    # constructed fields
+    __slots__ += 'iommus', 'arch_info',
+
+    def __init__(self, arch_info_cls=PlattformInfoX86):
+        self.pci_mmconfig_base = 0
+        self.pci_mmconfig_end_bus = 0
+        self.pci_is_virtual = 0
+        self.pci_domain = 0
+        self.iommus = []
+        self.arch_info = arch_info_cls()
+
+    @classmethod
+    def parse(cls, stream, arch_info_cls=PlattformInfoX86):
+        self = cls.parse_class(cls, stream)
+        self.iommus = cls.parse_array(Iommu, Iommu._MAX_UNITS, stream)
+        self.arch_info = arch_info_cls.parse(stream)
+
+        # skip rest of the C union, if needed
+        skip = \
+            max(PlattformInfoArm._BIN_FMT.size, 
PlattformInfoX86._BIN_FMT.size)\
+            - arch_info_cls._BIN_FMT.size
+        stream.seek(skip, io.SEEK_CUR)
         return self
 
 
 class SystemConfig(CStruct):
-    _BIN_FMT = struct.Struct('=4x')
-    # ...followed by MemRegion as hypervisor memory
-    _BIN_FMT_CONSOLE_AND_PLATFORM = struct.Struct('32x12x224x44x')
+    __slots__ = 'flags',
+    _BIN_FIELD_NUM = len(__slots__)
+    _BIN_FMT = struct.Struct('I')
     _BIN_SIGNATURE = b'JHSYST'
 
     # constructed fields
-    __slots__ = 'hypervisor_memory', 'root_cell',
+    __slots__ += 'hypervisor_memory', 'debug_console', 'platform_info', \
+                 'root_cell',
 
     def __init__(self):
+        self.flags = 0
         self.hypervisor_memory = MemRegion()
+        self.debug_console = Console()
+        self.platform_info = PlattformInfo()
         self.root_cell = CellConfig()
 
     @classmethod
     def parse(cls, stream):
         self = cls.parse_class(cls, stream)
         self.hypervisor_memory = MemRegion.parse(stream)
-
-        offs = cls._BIN_FMT_CONSOLE_AND_PLATFORM.size
-        offs += CellConfig._BIN_FMT_HDR.size # skip header inside rootcell
-        stream.seek(offs, io.SEEK_CUR)
+        self.debug_console = Console.parse(stream)
+        self.platform_info = PlattformInfo.parse(stream)
+        # skip header inside rootcell
+        stream.seek(CellConfig._BIN_FMT_HDR.size, io.SEEK_CUR)
         self.root_cell = CellConfig.parse(stream)
         return self
 
-- 
2.27.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 jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/20200630064730.7210-1-andrej.utz%40st.oth-regensburg.de.

Reply via email to