2016-07-19 21:11 GMT+08:00 Ralf Ramsauer <[email protected]>:
>
>
> On 07/06/2016 06:23 AM, Xuguo Wang wrote:
>> 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.
>>
>> v6:
>> - add all the commit messages and the changes info
>> - modify error comments
>> - modify self.comments to self.comments = comments or [] to avoid merging 
>> conflict
>> - refactor error message more verbose
>> - modify f.read() to the f.read().splitlines() to void trailing '\n'
>> - remove pep8 warnings
>> - refactor parse_ioport_tree to non-static method
>> - add the docstring to new introduced classes and functions
>>
>> Signed-off-by: Xuguo Wang <[email protected]>
>> ---
>>  tools/jailhouse-config-create | 421 
>> +++++++++++++++++++++++++++++++++++++-----
>>  1 file changed, 374 insertions(+), 47 deletions(-)
>>
>> diff --git a/tools/jailhouse-config-create b/tools/jailhouse-config-create
>> index 4e61abc..dfe98db 100755
>> --- a/tools/jailhouse-config-create
>> +++ b/tools/jailhouse-config-create
>> @@ -368,22 +368,62 @@ class PCIPCIBridge(PCIDevice):
>>          return (secondbus, subordinate)
>>
>>
>> -class MemRegion:
>> -    def __init__(self, start, stop, typestr, comments=None):
>> +class IORegion:
>> +    """
>> +    The super class of the IOPortRegion and IOMemRegion.
>> +
>> +    The IORegion means a region of a /proc/io{mem,ports} entry,
>> +    which starts from param start, ends of the param stop.
>> +
>> +    - ** attributes **:
> Is this standard docstring style or do you want to highlight something?

Sorry, this docstring style from a python document, it is not a standard
style, is there standard docstring style?

>> +        :param arg1: start      start address
>> +        :param arg2: stop       stop address
>> +        :param arg3: typestr    region type description
>> +    - ** type **:
>> +        :type arg1: long
>> +        :type arg2: long
>> +        :type arg3: str
>> +    - ** example **:
>> +        /proc/ioports:
>> +            region = IORegion(0x0, 0x1f, "dma1")
>> +        /proc/iomem:
>> +            region = IORegion(0x0000, 0xfff, "reserved")
>> +    """
>> +
>> +    def __init__(self, start, stop, typestr):
>>          self.start = start
>>          self.stop = stop
>>          self.typestr = typestr
>> -        if comments is None:
>> -            self.comments = []
>> -        else:
>> -            self.comments = comments
>> +
>> +
>> +class IOMemRegion(IORegion):
>> +    """
>> +    Each IOMemRegion represents one of the /proc/iomem entries.
>> +    It extends IORegion by the comments property.
>> +
>> +    - ** attributes **:
>> +        :param arg1: start      region start address
>> +        :param arg2: stop       region stop address
>> +        :param arg3: typestr    region type description
>> +        :param arg4: comments   region specified description
>> +    - ** type **:
>> +        :type arg1: long
>> +        :type arg2: long
>> +        :type arg3: str
>> +        :type arg4: str
>> +    - ** example **:
>> +        memregion = IOMemRegion(0x0000, 0xfff, "reserved", NULL)
>> +    """
>> +
>> +    def __init__(self, start, stop, typestr, comments=None):
>> +        self.comments = comments or []
>> +        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):
>> -        # round up to full PAGE_SIZE
>>          return int((self.stop - self.start + 0xfff) / 0x1000) * 0x1000
>>
>>      def flagstr(self, p=''):
>> @@ -400,6 +440,68 @@ class MemRegion:
>>          return 'JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE'
>>
>>
>> +class IOPortRegion(IORegion):
>> +    """
>> +    Each IOPortRegion represents one of the /proc/ioports entries.
>> +    The value == 0 means permit, 1 means intercept.
>> +
>> +    - ** attributes **:
>> +        :param arg1: start      region start address
>> +        :param arg2: stop       region stop address
>> +        :param arg3: typestr    region type description
>> +        :param arg4: value      region value description
>> +    - ** type **:
>> +        :type arg1: long
>> +        :type arg2: long
>> +        :type arg3: str
>> +        :type arg4: int
>> +    - ** example **:
>> +        portRegion = IOPortRegion(0x0, 0x1f, "dma1", -0x1)
>> +    """
>> +
>> +    def __init__(self, start, stop, typestr, value=0):
>> +        self.value = value
>> +        IORegion.__init__(self, start, stop, typestr)
>> +
>> +    def size(self):
>> +        return self.stop - self.start + 1
>> +
>> +    def alignment(self):
>> +        """
>> +        Return the region alignment.
>> +
>> +        - ** parameters **:
>> +            no.
>> +        - ** type **:
>> +            no.
> I'd remove those lines, parameters and type.
Since the docstring style file has this infomation, I will remove these lines.

>> +        - ** return type **:
>> +            int: the return value type.
>> +        - ** return value **:
>> +            0 means both are aligned
>> +            1 means both head and tail are both not aligned
>> +            2 means head not aligned but the tail is
>> +            3 means tail not aligned but the head is
>> +        - ** example **:
>> +            alignment = {$IOPortRegion}.alignment()
>> +        """
>> +        # region head bit and tail bit are both aligned
>> +        t = 0
>> +        # region head bit and tail bit are both not aligned
>> +        if self.start % 8 != 0 \
>> +                and (self.stop % 8 + 1) % 8 != 0:
>> +            t = 1
>> +        # region head bit is not aligned but tail do
>> +        elif self.start % 8 != 0 \
>> +                and (self.stop % 8 + 1) % 8 == 0:
>> +            t = 2
>> +        # region head bit is aligned but tail bit not
>> +        elif self.start % 8 == 0 \
>> +                and (self.stop % 8 + 1) % 8 != 0:
>> +            t = 3
>> +
>> +        return t
>> +
>> +
>>  class IOAPIC:
>>      def __init__(self, id, address, gsi_base, iommu=0, bdf=0):
>>          self.id = id
>> @@ -416,7 +518,26 @@ class IOAPIC:
>>          return (self.iommu << 16) | self.bdf
>>
>>
>> -class IOMemRegionTree:
>> +class IORegionTree:
>> +    """
>> +    Super class of IOMemRegionTree and IOPortRegionTree.
>> +
>> +    - ** attributes **:
>> +        :param arg1: region     region of a /proc/io{mem, ports} entry
>> +        :param arg2: level      the level of region
>> +    - ** type **:
>> +        :type arg1: IO{Port, Mem}Region
>> +        :type arg2: int
>> +    - ** example **:
>> +        level, r = IOMemRegionTree.parse_line(IOMemRegion, line)
>> +        or
>> +        level, r = IOPortRegionTree.parse_line(IOPortRegion, line)
>> +    """
>> +
>> +    # This regex matches entries in /proc/ioports or /proc/iomem, 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 +555,65 @@ class IOMemRegionTree:
>>              s += str(c)
>>          return s
>>
>> +    @staticmethod
>> +    def parse_line(RegionClass, line):
>> +        """
>> +        Parse an entry of /proc/iomem or /proc/ioports to an object
>> +        of region, this region type is specified by the regionclass.
>> +
>> +        The parse regex is "( *)([0-9a-f]*)-([0-9a-f]*) : (\w?.*)".
> Sure, it is :-)
> I'd drop this line as well.

OK, accepted.
>> +
>> +        - ** parameters **:
>> +            :param arg1: regionclass    region type
>> +            :param arg2: line           an entry of /proc/iomem or
>> +                                        /proc/ioports content
>> +        - ** type **:
>> +            :type arg1: IO{Port, Mem}Region
>> +            :type arg2: str
>> +        - ** return type **:
>> +            list: a list node contains tree node level and the region of 
>> entry
>> +        - ** return value **:
>> +            list = [level, region]
>> +        - ** example **:
>> +            level, r = IOMemRegionTree.parse_line(IOMemRegion, line)
>> +            or
>> +            level, r = IOPortRegionTree.parse_line(IOPortRegion, line)
>> +        """
>> +        match = IORegionTree.IOEntry_Regex.match(line)
>> +        if not match:
>> +            raise ValueError('invalid entry: %s' % line)
>> +
>> +        # 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)
>> +
>> +
>> +class IOMemRegionTree(IORegionTree):
>> +    """
>> +    This class parses the /proc/iomem file to the tree structure and parse 
>> the
>> +    tree structure to a list contains all regions.
>> +
>> +    - ** attributes **:
>> +        :param arg1: region     region of a /proc/iomem entry
>> +        :param arg2: level      the level of region
>> +    - ** type **:
>> +        :type arg1: IOMemRegion
>> +        :type arg2: int
>> +    - ** example **:
>> +        level, r = IOMemRegionTree.parse_line(IOMemRegion, line)
>> +        or
>> +        level, r = IOPortRegionTree.parse_line(IOPortRegion, line)
>> +    """
>> +
>> +    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 +637,44 @@ 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():
>> +        """
>> +        This function parses the file of /proc/iomem to a tree structure.
>> +
>> +        - ** parameters **:
>> +            no.
>> +        - ** type **:
>> +            no.
> drop those lines
OK, accepted.

>> +        - ** return type **:
>> +            IOMemRegionTree: /proc/iomem all entries' tree root node.
>> +        - ** return value **:
>> +            Return the tree root node.
>> +        - ** example **:
>> +            regions = IOMemRegionTree.parse_iomem_file().parse_iomem_tree()
>> +        """
>>          root = IOMemRegionTree(None, 0)
>>          f = input_open('/proc/iomem')
>>          lastlevel = 0
>>          lastnode = root
>> -        for line in f:
>> -            (level, r) = IOMemRegionTree.parse_iomem_line(line)
>> +        for line in f.read().splitlines():
>> +            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:
> Your patch still introduces non-functional cosmetic changes...
These above lines are original code, so I am afraid the author has
his own meanings. I will refactor these lines.

>>                  p = lastnode.parent
>>                  while(t.level < p.level):
>>                      p = p.parent
>> @@ -510,18 +696,32 @@ 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
>>
>>      # recurse down the tree
>> -    @staticmethod
>>      def parse_iomem_tree(tree):
>> +        """
>> +        This function parses the IOMemRegionTree tree nodes to regions,
>> +        and return the list contains all regions.
>> +
>> +        - ** parameters **:
>> +            :param arg1: tree           IOMemRegionTree tree root node
>> +        - ** type **:
>> +            :type arg1: IOMemRegionTree
>> +        - ** return type **:
>> +            list: contains all /proc/iomem tree nodes.
>> +        - ** return value **:
>> +            Return the list regions of /proc/iomem.
>> +        - ** example **:
>> +            regions = IOMemRegionTree.parse_iomem_file().parse_iomem_tree()
>> +        """
>>          regions = []
>>
>>          for tree in tree.children:
>> @@ -543,13 +743,13 @@ 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):
>> -                regions.extend(IOMemRegionTree.parse_iomem_tree(tree))
>> +            if len(tree.children) > 0:
>> +                regions.extend(tree.parse_iomem_tree())
>>                  continue
>>
>>              # add all remaining leaves
>> @@ -558,6 +758,132 @@ class IOMemRegionTree:
>>          return regions
>>
>>
>> +class IOPortRegionTree(IORegionTree):
>> +    """
>> +    This class parses the /proc/ioports file to the tree structure and parse
>> +    the tree structure to a list contains all regions.
>> +
>> +    - ** attributes **:
>> +        :param arg1: region     region of a /proc/ioports entry
>> +        :param arg2: level      the level of region tree node
>> +    - ** type **:
>> +        :type arg1: IOPortRegion
>> +        :type arg2: int
>> +    - ** example **:
>> +        level, r = IOMemRegionTree.parse_line(IOMemRegion, line)
>> +        or
>> +        level, r = IOPortRegionTree.parse_line(IOPortRegion, line)
>> +    """
>> +
>> +    def __init__(self, region, level):
>> +        IORegionTree.__init__(self, region, level)
>> +
>> +    @staticmethod
>> +    def parse_ioport_file():
>> +        """
>> +        This function parses the file of /proc/ioports to a tree structure.
>> +
>> +        - ** parameters **:
>> +            no.
>> +        - ** type **:
>> +            no.
>> +        - ** return type **:
>> +            IOPortRegionTree: contains /proc/ioports tree structure.
>> +        - ** return value **:
>> +            Return the tree root node.
>> +        - ** example **:
>> +            regions = 
>> IOPortRegionTree.parse_ioport_file().parse_ioport_tree()
>> +        """
>> +        root = IOPortRegionTree(None, 0)
>> +        f = input_open('/proc/ioports')
>> +        lastlevel = 0
>> +        lastnode = root
>> +        for line in f.read().splitlines():
>> +            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
>> +    def parse_ioport_tree(tree):
>> +        """
>> +        This function parses the IOPortRegionTree tree nodes to regions,
>> +        and return the list contains all regions.
>> +
>> +        - ** parameters **:
>> +            :param arg1: tree           IOPortRegionTree tree root node
>> +        - ** type **:
>> +            :type arg1: IOPortRegionTree
>> +        - ** return type **:
>> +            list: contains all /proc/ioports tree nodes.
>> +        - ** return value **:
>> +            Return the list regions of /proc/ioports.
>> +        - ** example **:
>> +            regions = 
>> IOPortRegionTree.parse_ioport_file().parse_ioport_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(tree.parse_ioport_tree())
>> +                continue
>> +
>> +            # add all remaining leaves
>> +            regions.append(r)
>> +
>> +        return regions
>> +
>> +    @staticmethod
>> +    def get_first_ioport_byte(start_permitted, last_permitted):
>> +        """
>> +        Get a byte of ioport region mask from start_permitted, end
>> +        at the last_permitted bit.
>> +
>> +        - ** parameters **:
>> +            :param arg1: start_permitted    first permitted bit
>> +            :param arg2: last_permitted     last permitted bit
>> +        - ** type **:
>> +            :type arg1: int
>> +            :type arg2: int
>> +        - ** return type **:
>> +            int:
>> +        - ** return value **:
>> +            a bitwise mask start from start_permitted to last_permitted
>> +        - ** example **:
>> +            value_head = IOPortRegionTree.get_first_ioport_byte(
>> +                                        region.start, region.stop)
>> +        """
>> +        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']
>> @@ -574,10 +900,9 @@ class IOMMUConfig(object):
>>
>>
>>  def parse_iomem(pcidevices):
>> -    regions = IOMemRegionTree.parse_iomem_tree(
>> -        IOMemRegionTree.parse_iomem_file())
>> +    regions = IOMemRegionTree.parse_iomem_file().parse_iomem_tree()
>>
>> -    rom_region = MemRegion(0xc0000, 0xdffff, 'ROMs')
>> +    rom_region = IOMemRegion(0xc0000, 0xdffff, 'ROMs')
>>      add_rom_region = False
>>
>>      ret = []
>> @@ -588,12 +913,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 +992,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 +1152,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 +1329,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 '
>> @@ -1064,7 +1391,7 @@ def get_cpu_vendor():
>>      if cpuvendor is not None:
>>          return cpuvendor
>>      with input_open('/proc/cpuinfo', 'r') as f:
>> -        for line in f:
>> +        for line in f.read().splitlines():
>>              if not line.strip():
>>                  continue
>>              key, value = line.split(':')
>> @@ -1135,9 +1462,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()
>>
>
> --
> Ralf Ramsauer
> PGP: 0x8F10049B

-- 
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