This replaces the old static port list with actual port regions from
'/proc/ioports'. The static regions from said list are kept and override
the data in case of region overlap to retain compability.
The generated port list is virtually identicall to the old one but eases
manual configuration.

Signed-off-by: Andrej Utz <andrej....@st.oth-regensburg.de>
---
 pyjailhouse/sysfs_parser.py   | 135 ++++++++++++++++++++++++++++++++++
 tools/jailhouse-config-create |  14 +---
 tools/root-cell-config.c.tmpl |  15 ++--
 3 files changed, 142 insertions(+), 22 deletions(-)

diff --git a/pyjailhouse/sysfs_parser.py b/pyjailhouse/sysfs_parser.py
index 56265fb5..d06a476a 100644
--- a/pyjailhouse/sysfs_parser.py
+++ b/pyjailhouse/sysfs_parser.py
@@ -142,6 +142,57 @@ def parse_iomem(pcidevices):
     return ret, dmar_regions
 
 
+def parse_ioports():
+    regions = IOMapTree.parse_ioports_tree(
+        IOMapTree.parse_iomap_file('/proc/ioports', PortRegion))
+
+    tmp = [
+        # static regions
+        PortRegion(0x0, 0x3f, ''),
+        PortRegion(0x40, 0x43, 'PIT', allowed=True),
+        PortRegion(0x60, 0x61, 'NMI', allowed=True), # NMI status/control
+        PortRegion(0x64, 0x64, 'NMI', allowed=True), # ditto
+        PortRegion(0x70, 0x71, 'RTC', allowed=True),
+        PortRegion(0x3b0, 0x3df, 'VGA', allowed=True),
+        PortRegion(0xd00, 0xffff, 'PCI bus', allowed=True),
+    ]
+
+    pm_timer_base = None
+    for r in regions:
+        if r.typestr == 'ACPI PM_TMR':
+            pm_timer_base = r.start
+
+        if r.typestr.startswith('ACPI'):
+            r.allowed = True
+
+        tmp.append(r)
+
+    tmp.sort(key=lambda r: r.start)
+    ret = [ tmp[0] ]
+
+    # adjust overlapping regions
+    for r in tmp[1:]:
+        prev = ret[-1]
+
+        # combine multiple regions under the same bit mask
+        if prev.aligned_stop() >= r.aligned_start():
+            if r.stop > prev.stop:
+                n = prev
+                while n.neighbor != None:
+                    n = n.neighbor
+                n.neighbor = r
+            continue
+
+        # forbid access to unrecognized regions
+        if prev.aligned_stop() - r.aligned_start() > 0:
+            ret.append(
+                PortRegion(prev.aligned_stop() + 1, r.aligned_start() - 1, ''))
+
+        ret.append(r)
+
+    return (ret, pm_timer_base)
+
+
 def parse_pcidevices():
     int_src_cnt = 0
     devices = []
@@ -769,6 +820,65 @@ class MemRegion:
         return 'JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE'
 
 
+class PortRegion:
+    def __init__(self, start, stop, typestr, comments=None, allowed=False):
+        self.start = start
+        self.stop = stop
+        self.typestr = typestr or ''
+        self.comments = comments or []
+        self.allowed = allowed
+        self.neighbor = None
+
+    def __str__(self, chained=False):
+        # as in MemRegion this method is purely for C comment generation
+
+        # deviceless region
+        if self.typestr == '':
+            return ''
+
+        s = ''
+        if chained == False:
+            s += 'PortRegion: %04x-%04x : ' % (self.start, self.stop)
+
+        s += self.typestr
+        if self.neighbor:
+            s += ' +' + self.neighbor.__str__(True)
+
+        return s
+
+    def size(self):
+        return self.stop - self.start
+
+    def aligned_start(self):
+        return self.start - self.start % 8
+
+    def aligned_stop(self):
+        return self.stop + (7 - self.stop % 8)
+
+    def bits(self):
+        # in this method: 0 = allowed,
+        # outside: 0 = disallowed
+        if self.allowed:
+            bits = ((1 << (self.size() + 1)) - 1) << \
+                (self.start - self.aligned_start())
+        else:
+            bits = 0
+
+        if self.neighbor:
+            bits |= ~self.neighbor.bits()
+
+        return ~bits & 0xFF
+
+    def bits_str(self):
+        b = self.bits()
+        if b == 0:
+            return '0'
+        elif b == 0xff:
+            return '-1'
+        else:
+            return hex(b)
+
+
 class IOAPIC:
     def __init__(self, id, address, gsi_base, iommu=0, bdf=0):
         self.id = id
@@ -932,6 +1042,31 @@ class IOMapTree:
 
         return regions, dmar_regions
 
+    # recurse down the tree
+    @staticmethod
+    def parse_ioports_tree(tree):
+        regions = []
+
+        for tree in tree.children:
+            r = tree.region
+            s = r.typestr
+
+            if len(tree.children) > 0:
+                regions.extend(IOMapTree.parse_ioports_tree(tree))
+                continue
+
+            # split in byte sized regions
+            while r.size() > 8:
+                # byte-align r.stop
+                sub = PortRegion(r.start, r.start + 7 - r.start % 8, r.typestr)
+                regions.append(sub)
+                r.start = sub.stop + 1
+
+            # add all remaining leaves
+            regions.append(r)
+
+        return regions
+
 
 class IOMMUConfig:
     def __init__(self, props):
diff --git a/tools/jailhouse-config-create b/tools/jailhouse-config-create
index 55601a6d..d25071ce 100755
--- a/tools/jailhouse-config-create
+++ b/tools/jailhouse-config-create
@@ -163,17 +163,6 @@ def count_cpus():
     return count
 
 
-def parse_ioports():
-    pm_timer_base = None
-    f = sysfs_parser.input_open('/proc/ioports')
-    for line in f:
-        if line.endswith('ACPI PM_TMR\n'):
-            pm_timer_base = int(line.split('-')[0], 16)
-            break
-    f.close()
-    return pm_timer_base
-
-
 class MMConfig:
     def __init__(self, base, end_bus):
         self.base = base
@@ -302,7 +291,7 @@ regions.append(inmatereg)
 
 cpucount = count_cpus()
 
-pm_timer_base = parse_ioports()
+(ports, pm_timer_base) = sysfs_parser.parse_ioports()
 
 debug_console = DebugConsole(options.console)
 
@@ -312,6 +301,7 @@ tmpl = Template(filename=os.path.join(options.template_dir,
                                       'root-cell-config.c.tmpl'))
 kwargs = {
     'regions': regions,
+    'ports': ports,
     'ourmem': ourmem,
     'argstr': ' '.join(sys.argv),
     'hvmem': hvmem,
diff --git a/tools/root-cell-config.c.tmpl b/tools/root-cell-config.c.tmpl
index b6ac8637..c85a671c 100644
--- a/tools/root-cell-config.c.tmpl
+++ b/tools/root-cell-config.c.tmpl
@@ -153,16 +153,11 @@ struct {
        },
 
        .pio_bitmap = {
-               [     0/8 ...   0x3f/8] = -1,
-               [  0x40/8 ...   0x47/8] = 0xf0, /* PIT */
-               [  0x48/8 ...   0x5f/8] = -1,
-               [  0x60/8 ...   0x67/8] = 0xec, /* HACK: NMI status/control */
-               [  0x68/8 ...   0x6f/8] = -1,
-               [  0x70/8 ...   0x77/8] = 0xfc, /* RTC */
-               [  0x78/8 ...  0x3af/8] = -1,
-               [ 0x3b0/8 ...  0x3df/8] = 0x00, /* VGA */
-               [ 0x3e0/8 ...  0xcff/8] = -1,
-               [ 0xd00/8 ... 0xffff/8] = 0, /* HACK: PCI bus */
+               % for p in ports:
+               [${ '%6s' % hex(p.aligned_start()).strip('L')}/8 ... ${
+                   '%6s' % hex(p.aligned_stop()).strip('L')}/8] = ${'%4s' %  
p.bits_str()}, ${
+                   ('/* %s */' % (str(p).split(':', 2)[2].strip())) if 
len(str(p)) else '' }
+               % endfor
        },
 
        .pci_devices = {
-- 
2.21.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/20190605161745.2389-2-andrej.utz%40st.oth-regensburg.de.
For more options, visit https://groups.google.com/d/optout.

Reply via email to