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 | 150 ++++++++++++++++++++++++++++++++++ tools/jailhouse-config-create | 26 ++---- tools/root-cell-config.c.tmpl | 31 ++++--- 3 files changed, 176 insertions(+), 31 deletions(-) diff --git a/pyjailhouse/sysfs_parser.py b/pyjailhouse/sysfs_parser.py index d612c6d3..ce490236 100644 --- a/pyjailhouse/sysfs_parser.py +++ b/pyjailhouse/sysfs_parser.py @@ -141,6 +141,52 @@ 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, comments=["HACK!"]), # NMI status/control + PortRegion(0x64, 0x64, 'NMI', allowed=True, comments=["HACK!"]), # 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 + + 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 @@ -772,6 +818,85 @@ 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): + # as in MemRegion this method is purely for C comment generation + + # remove consecutive duplicates + neighbor = self.neighbor + stop = self.stop + ns = '' + while neighbor: + if self.typestr != neighbor.typestr \ + or self.comments != neighbor.comments: + ns += ', ' + str(neighbor) + break + + stop = neighbor.stop + neighbor = neighbor.neighbor + + s = '' + # pretty print single ports + if self.start == stop: + s += '%5s' % '' + else: + s += '%04x-' % self.start + + s += '%04x' % stop + + + if self.typestr: + s += ' : ' + self.typestr + + if self.comments: + s += ' (' + ', '.join(c for c in self.comments) + ')' + + s += ns + return s + + # used in root-cell-config.c.tmpl + def is_combined(self): + neighbor = self.neighbor + while neighbor: + if self.typestr != neighbor.typestr: + return True + + neighbor = neighbor.neighbor + + return False + + 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 = disallowed, + # in config: 0 = allowed + 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 + + class IOAPIC: def __init__(self, id, address, gsi_base, iommu=0, bdf=0): self.id = id @@ -935,6 +1060,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..d154ec44 100755 --- a/tools/jailhouse-config-create +++ b/tools/jailhouse-config-create @@ -162,18 +162,6 @@ def count_cpus(): count += 1 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 @@ -269,7 +257,7 @@ product = [input_readline('/sys/class/dmi/id/sys_vendor', inmatemem = kmg_multiply_str(options.mem_inmates) hvmem = [0, kmg_multiply_str(options.mem_hv)] -(regions, dmar_regions) = sysfs_parser.parse_iomem(pcidevices) +(mem_regions, dmar_regions) = sysfs_parser.parse_iomem(pcidevices) ourmem = parse_kernel_cmdline() total = hvmem[1] + inmatemem @@ -283,11 +271,11 @@ if vendor == 'GenuineIntel': dmar_regions) else: (iommu_units, extra_memregs) = sysfs_parser.parse_ivrs(pcidevices, ioapics) -regions += extra_memregs +mem_regions += extra_memregs # kernel does not have memmap region, pick one if ourmem is None: - ourmem = alloc_mem(regions, total) + ourmem = alloc_mem(mem_regions, total) elif (total > ourmem[1]): raise RuntimeError('Your memmap reservation is too small you need >="' + hex(total) + '". Hint: your kernel cmd line needs ' @@ -298,20 +286,20 @@ hvmem[0] = ourmem[0] inmatereg = sysfs_parser.MemRegion(ourmem[0] + hvmem[1], ourmem[0] + hvmem[1] + inmatemem - 1, 'JAILHOUSE Inmate Memory') -regions.append(inmatereg) +mem_regions.append(inmatereg) cpucount = count_cpus() -pm_timer_base = parse_ioports() +(port_regions, pm_timer_base) = sysfs_parser.parse_ioports() debug_console = DebugConsole(options.console) - f = open(options.file, 'w') tmpl = Template(filename=os.path.join(options.template_dir, 'root-cell-config.c.tmpl')) kwargs = { - 'regions': regions, + 'mem_regions': mem_regions, + 'port_regions': port_regions, '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..9f65a72a 100644 --- a/tools/root-cell-config.c.tmpl +++ b/tools/root-cell-config.c.tmpl @@ -45,7 +45,7 @@ struct { struct jailhouse_system header; __u64 cpus[${int((cpucount + 63) / 64)}]; - struct jailhouse_memory mem_regions[${len(regions)}]; + struct jailhouse_memory mem_regions[${len(mem_regions)}]; struct jailhouse_irqchip irqchips[${len(irqchips)}]; __u8 pio_bitmap[0x2000]; struct jailhouse_pci_device pci_devices[${len(pcidevices)}]; @@ -125,7 +125,7 @@ struct { }, .mem_regions = { - % for r in regions: + % for r in mem_regions: /* ${str(r)} */ % for c in r.comments: /* ${c} */ @@ -153,18 +153,25 @@ 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 r in port_regions: + % if r.is_combined(): + + % for c in str(r).split(', '): + /* ${c} */ + % endfor + % endif + [${ + '%6s' % hex(r.aligned_start())}/8 ... ${ + '%6s' % hex(r.aligned_stop())}/8] = ${ + '%4s' % ('0' if r.bits() == 0 else \ + '-1' if r.bits() == 0xff else \ + hex(r.bits()))}, ${ + ('/* %s */' % str(r)) if not r.is_combined() else '\n' + } + % endfor }, + .pci_devices = { % for d in pcidevices: /* ${str(d)} */ -- 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 jailhouse-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/jailhouse-dev/20190620220614.23450-2-andrej.utz%40st.oth-regensburg.de. For more options, visit https://groups.google.com/d/optout.