Abstract the common property of the ioports from the
/proc/ioports as the super class named IOPortRegion,
using the region of ioports from the IOPortRegionTree,
this tree includes all of the ioport regions we could
use this regions generate the pio_bitmap.

Signed-off-by: Xuguo Wang <[email protected]>

This is the PATCH V4. All what I have done is follow the
Ralf's advice, add whitespace after comma.
---
 tools/jailhouse-config-create | 181 +++++++++++++++++++++++++++++++++---------
 1 file changed, 145 insertions(+), 36 deletions(-)

diff --git a/tools/jailhouse-config-create b/tools/jailhouse-config-create
index 4e61abc..727c87f 100755
--- a/tools/jailhouse-config-create
+++ b/tools/jailhouse-config-create
@@ -368,18 +368,27 @@ class PCIPCIBridge(PCIDevice):
         return (secondbus, subordinate)
 
 
-class MemRegion:
-    def __init__(self, start, stop, typestr, comments=None):
+# super class of IOMemRegion and IOPortRegion
+class IORegion:
+    def __init__(self, start, stop, typestr):
         self.start = start
         self.stop = stop
         self.typestr = typestr
+
+
+# Each IOMemRegion represents one of the /proc/iomem entry.
+# It extends IORegion by the typestr property.
+class IOMemRegion(IORegion):
+    def __init__(self, start, stop, typestr, comments=None):
+
         if comments is None:
             self.comments = []
         else:
             self.comments = comments
+        IORegion.__init__(self, start, stop, typestr)
 
     def __str__(self):
-        return 'MemRegion: %08x-%08x : %s' % \
+        return 'IOMemRegion: %08x-%08x : %s' % \
             (self.start, self.stop, self.typestr)
 
     def size(self):
@@ -400,6 +409,19 @@ class MemRegion:
         return 'JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE'
 
 
+# Each IOPortRegion represents one of the /proc/ioports entry.
+# It extends IORegion typestr priority.
+# the value == 0 means permit, 1 means intercept.
+class IOPortRegion(IORegion):
+    def __init__(self, start, stop, typestr, value=0):
+        self.value = value
+        IORegion.__init__(self, start, stop, typestr)
+
+    def size(self):
+        # The range is from start to stop including self.start
+        return self.stop - self.start + 1
+
+
 class IOAPIC:
     def __init__(self, id, address, gsi_base, iommu=0, bdf=0):
         self.id = id
@@ -416,7 +438,11 @@ class IOAPIC:
         return (self.iommu << 16) | self.bdf
 
 
-class IOMemRegionTree:
+# super class of IOMemRegionTree and IOPortRegionTree
+class IORegionTree:
+    # This regex matches entries in /proc/ioports, like
+    # '  0020-0021 : pic1'
+    IOEntry_Regex = re.compile('( *)([0-9a-f]*)-([0-9a-f]*) : (\w?.*)')
     def __init__(self, region, level):
         self.region = region
         self.level = level
@@ -434,6 +460,28 @@ class IOMemRegionTree:
             s += str(c)
         return s
 
+    @staticmethod
+    def parse_line(regionclass, line):
+        match = IORegionTree.IOEntry_Regex.match(line)
+        if not match:
+            raise ValueError('invalid entry')
+
+        # blank level
+        level = int(match.group(1).count(' ') / 2) + 1
+        # start address
+        start = match.group(2)
+        # end address
+        stop = match.group(3)
+        # comments
+        typestr = match.group(4)
+        return level, regionclass(int(start, 16), int(stop, 16), typestr)
+
+
+# parse the IOMemRegions to the tree structure.
+class IOMemRegionTree(IORegionTree):
+    def __init__(self, region, level):
+        IORegionTree.__init__(self, region, level)
+
     def regions_split_by_kernel(self):
         kernel = [x for x in self.children if
                   x.region.typestr.startswith('Kernel ')]
@@ -457,38 +505,30 @@ class IOMemRegionTree:
 
         # before Kernel if any
         if (r.start < kernel_start):
-            before_kernel = MemRegion(r.start, kernel_start - 1, s)
+            before_kernel = IOMemRegion(r.start, kernel_start - 1, s)
 
-        kernel_region = MemRegion(kernel_start, kernel_stop, "Kernel")
+        kernel_region = IOMemRegion(kernel_start, kernel_stop, "Kernel")
 
         # after Kernel if any
         if (r.stop > kernel_stop):
-            after_kernel = MemRegion(kernel_stop + 1, r.stop, s)
+            after_kernel = IOMemRegion(kernel_stop + 1, r.stop, s)
 
         return [before_kernel, kernel_region, after_kernel]
 
     @staticmethod
-    def parse_iomem_line(line):
-        a = line.split(':', 1)
-        level = int(a[0].count(' ') / 2) + 1
-        region = a[0].split('-', 1)
-        a[1] = a[1].strip()
-        return level, MemRegion(int(region[0], 16), int(region[1], 16), a[1])
-
-    @staticmethod
     def parse_iomem_file():
         root = IOMemRegionTree(None, 0)
         f = input_open('/proc/iomem')
         lastlevel = 0
         lastnode = root
         for line in f:
-            (level, r) = IOMemRegionTree.parse_iomem_line(line)
+            level, r = IOMemRegionTree.parse_line(IOMemRegion, line)
             t = IOMemRegionTree(r, level)
-            if (t.level > lastlevel):
+            if t.level > lastlevel:
                 t.parent = lastnode
-            if (t.level == lastlevel):
+            if t.level == lastlevel:
                 t.parent = lastnode.parent
-            if (t.level < lastlevel):
+            if t.level < lastlevel:
                 p = lastnode.parent
                 while(t.level < p.level):
                     p = p.parent
@@ -510,11 +550,11 @@ class IOMemRegionTree:
             r = tree.region
             s = r.typestr
 
-            if (s.find('HPET') >= 0):
+            if s.find('HPET') >= 0:
                 regions.append(r)
 
             # if the tree continues recurse further down ...
-            if (len(tree.children) > 0):
+            if len(tree.children) > 0:
                 regions.extend(IOMemRegionTree.find_hpet_regions(tree))
 
         return regions
@@ -543,12 +583,12 @@ class IOMemRegionTree:
                 continue
 
             # generally blacklisted, unless we find an HPET behind it
-            if (s == 'reserved'):
+            if s == 'reserved':
                 regions.extend(IOMemRegionTree.find_hpet_regions(tree))
                 continue
 
             # if the tree continues recurse further down ...
-            if (len(tree.children) > 0):
+            if len(tree.children) > 0:
                 regions.extend(IOMemRegionTree.parse_iomem_tree(tree))
                 continue
 
@@ -558,6 +598,73 @@ class IOMemRegionTree:
         return regions
 
 
+# parse the IOPortRegion to the tree structure.
+class IOPortRegionTree(IORegionTree):
+    def __init__(self, region, level):
+        IORegionTree.__init__(self, region, level)
+
+    @staticmethod
+    def parse_ioport_file():
+        root = IOPortRegionTree(None, 0)
+        f = input_open('/proc/ioports')
+        lastlevel = 0
+        lastnode = root
+        for line in f:
+            level, r = IOPortRegionTree.parse_line(IOPortRegion, line)
+            t = IOPortRegionTree(r, level)
+            if t.level > lastlevel:
+                t.parent = lastnode
+            if t.level == lastlevel:
+                t.parent = lastnode.parent
+            if t.level < lastlevel:
+                p = lastnode.parent
+                while(t.level < p.level):
+                    p = p.parent
+                t.parent = p.parent
+
+            t.parent.children.append(t)
+            lastnode = t
+            lastlevel = t.level
+        f.close()
+
+        return root
+
+    # recurse down the tree
+    @staticmethod
+    def parse_ioport_tree(tree):
+        regions = []
+
+        for tree in tree.children:
+            r = tree.region
+            c = r.typestr
+
+            # Intercept keyboard and PCI conf1
+            if (c is not None and (c == 'keyboard' or c == 'PCI conf1')):
+                r.value = IOPortRegionTree.get_first_ioport_byte(
+                            r.start, r.stop)
+
+            # if the tree continues recurse further down ...
+            if len(tree.children) > 0:
+                regions.extend(IOPortRegionTree.parse_ioport_tree(tree))
+                continue
+
+            # add all remaining leaves
+            regions.append(r)
+
+        return regions
+
+    # get a byte of ioport region mask from start_permitted, end
+    # at the last_permitted bit.
+    @staticmethod
+    def get_first_ioport_byte(start_permitted, last_permitted):
+        byte_head = start_permitted % 8
+        byte_tail = last_permitted % 8
+        byte = (1 << byte_head) - 1
+        byte |= (~((1 << (byte_tail + 1)) - 1) & 0xff)
+        byte &= 0xff
+        return int(byte)
+
+
 class IOMMUConfig(object):
     def __init__(self, props):
         self.base_addr = props['base_addr']
@@ -577,7 +684,7 @@ def parse_iomem(pcidevices):
     regions = IOMemRegionTree.parse_iomem_tree(
         IOMemRegionTree.parse_iomem_file())
 
-    rom_region = MemRegion(0xc0000, 0xdffff, 'ROMs')
+    rom_region = IOMemRegion(0xc0000, 0xdffff, 'ROMs')
     add_rom_region = False
 
     ret = []
@@ -588,12 +695,12 @@ def parse_iomem(pcidevices):
         for d in pcidevices:
             if d.msix_address >= r.start and d.msix_address <= r.stop:
                 if d.msix_address > r.start:
-                    head_r = MemRegion(r.start, d.msix_address - 1,
-                                       r.typestr, r.comments)
+                    head_r = IOMemRegion(r.start, d.msix_address - 1,
+                                         r.typestr, r.comments)
                     ret.append(head_r)
                 if d.msix_address + d.msix_region_size < r.stop:
-                    tail_r = MemRegion(d.msix_address + d.msix_region_size,
-                                       r.stop, r.typestr, r.comments)
+                    tail_r = IOMemRegion(d.msix_address + d.msix_region_size,
+                                         r.stop, r.typestr, r.comments)
                     ret.append(tail_r)
                 append_r = False
                 break
@@ -667,11 +774,12 @@ def alloc_mem(regions, size):
             r.stop + 1 >= mem[0] + mem[1]
         ):
             if r.start < mem[0]:
-                head_r = MemRegion(r.start, mem[0] - 1, r.typestr, r.comments)
+                head_r = IOMemRegion(r.start, mem[0] - 1,
+                                     r.typestr, r.comments)
                 regions.insert(regions.index(r), head_r)
             if r.stop + 1 > mem[0] + mem[1]:
-                tail_r = MemRegion(mem[0] + mem[1], r.stop, r.typestr,
-                                   r.comments)
+                tail_r = IOMemRegion(mem[0] + mem[1], r.stop,
+                                     r.typestr, r.comments)
                 regions.insert(regions.index(r), tail_r)
             regions.remove(r)
             return mem
@@ -826,7 +934,7 @@ def parse_dmar(pcidevices, ioapics, dmar_regions):
                     comments.append('DMAR parser could not decode device path')
                 offset += scope_len
 
-            reg = MemRegion(base, limit, 'ACPI DMAR RMRR', comments)
+            reg = IOMemRegion(base, limit, 'ACPI DMAR RMRR', comments)
             regions.append(reg)
 
         f.seek(struct_len - offset, os.SEEK_CUR)
@@ -1003,7 +1111,8 @@ def parse_ivrs(pcidevices, ioapics):
                       'regions. The memory at 0x%x will be mapped accessible '
                       'to all devices.' % mem_addr)
 
-            regions.append(MemRegion(mem_addr, mem_len, 'ACPI IVRS', comment))
+            regions.append(IOMemRegion(mem_addr, mem_len,
+                                       'ACPI IVRS', comment))
         elif type == 0x40:
             raise RuntimeError(
                 'You board uses IVRS Rev. 2 feature Jailhouse doesn\'t '
@@ -1135,9 +1244,9 @@ elif (total > ourmem[1]):
 
 hvmem[0] = ourmem[0]
 
-inmatereg = MemRegion(ourmem[0] + hvmem[1],
-                      ourmem[0] + hvmem[1] + inmatemem - 1,
-                      'JAILHOUSE Inmate Memory')
+inmatereg = IOMemRegion(ourmem[0] + hvmem[1],
+                        ourmem[0] + hvmem[1] + inmatemem - 1,
+                        'JAILHOUSE Inmate Memory')
 regions.append(inmatereg)
 
 cpucount = count_cpus()
-- 
2.5.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].
For more options, visit https://groups.google.com/d/optout.

Reply via email to