ia64/xen-unstable

changeset 19776:9e36ef77f658

xend: pass-through: Common parse_pci_name()

Share some parsing code between different parts of xm.

This has the side-effect that the device specification for
hot-plug may now include the VSLOT and OPTS as per device
specifictions in the domain configuration file.

SEQ:BUS:DEV.FUNC[,OPT...]

e.g. 0000:00:01.00@6

Signed-off-by: Simon Horman <horms@verge.net.au>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 17 07:34:59 2009 +0100 (2009-06-17)
parents bda5ab0cb387
children 60588f1f055f
files tools/python/xen/util/pci.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/XendNode.py tools/python/xen/xend/server/pciif.py
line diff
     1.1 --- a/tools/python/xen/util/pci.py	Wed Jun 17 07:23:40 2009 +0100
     1.2 +++ b/tools/python/xen/util/pci.py	Wed Jun 17 07:34:59 2009 +0100
     1.3 @@ -15,6 +15,7 @@ import time
     1.4  import threading
     1.5  from xen.util import utils
     1.6  from xen.xend import sxp
     1.7 +from xen.xend.XendConstants import AUTO_PHP_SLOT
     1.8  
     1.9  PROC_PCI_PATH = '/proc/bus/pci/devices'
    1.10  PROC_PCI_NUM_RESOURCES = 7
    1.11 @@ -35,7 +36,6 @@ LSPCI_CMD = 'lspci'
    1.12  
    1.13  PCI_DEV_REG_EXPRESS_STR = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}."+ \
    1.14              r"[0-9a-fA-F]{1}"
    1.15 -PCI_DEV_FORMAT_STR = '%04x:%02x:%02x.%01x'
    1.16  
    1.17  DEV_TYPE_PCIe_ENDPOINT  = 0
    1.18  DEV_TYPE_PCIe_BRIDGE    = 1
    1.19 @@ -148,22 +148,62 @@ def parse_hex(val):
    1.20      except ValueError:
    1.21          return None
    1.22  
    1.23 +def parse_pci_name_extended(pci_dev_str):
    1.24 +    pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" +
    1.25 +                         r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" +
    1.26 +                         r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" +
    1.27 +                         r"(?P<func>(\*|[0-7]))" +
    1.28 +                         r"(@(?P<vslot>[01]?[0-9a-fA-F]))?" +
    1.29 +                         r"(,(?P<opts>.*))?$", pci_dev_str)
    1.30 +
    1.31 +    if pci_match == None:
    1.32 +        raise PciDeviceParseError("Failed to parse pci device: %s" %
    1.33 +                                  pci_dev_str)
    1.34 +
    1.35 +    out = {}
    1.36 +    pci_dev_info = pci_match.groupdict('')
    1.37 +    if pci_dev_info['domain'] == '':
    1.38 +        domain = 0
    1.39 +    else:
    1.40 +        domain = int(pci_dev_info['domain'], 16)
    1.41 +    out['domain'] = "0x%04x" % domain
    1.42 +    out['bus']    = "0x%02x" % int(pci_dev_info['bus'], 16)
    1.43 +    out['slot']   = "0x%02x" % int(pci_dev_info['slot'], 16)
    1.44 +    out['func']   = "0x%x"   % int(pci_dev_info['func'], 16)
    1.45 +    if pci_dev_info['vslot'] == '':
    1.46 +        vslot = AUTO_PHP_SLOT
    1.47 +    else:
    1.48 +        vslot = int(pci_dev_info['vslot'], 16)
    1.49 +    out['vslot'] = "0x%02x" % vslot
    1.50 +    if pci_dev_info['opts'] != '':
    1.51 +        out['opts'] = split_pci_opts(pci_dev_info['opts'])
    1.52 +        check_pci_opts(out['opts'])
    1.53 +
    1.54 +    return out
    1.55 +
    1.56  def parse_pci_name(pci_name_string):
    1.57 -    pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
    1.58 -            r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
    1.59 -            r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
    1.60 -            r"(?P<func>[0-7])$", pci_name_string)
    1.61 -    if pci_match is None:
    1.62 -        raise PciDeviceParseError(('Failed to parse pci device name: %s' %
    1.63 -            pci_name_string))
    1.64 -    pci_dev_info = pci_match.groupdict('0')
    1.65 +    pci = parse_pci_name_extended(pci_name_string)
    1.66  
    1.67 -    domain = parse_hex(pci_dev_info['domain'])
    1.68 -    bus = parse_hex(pci_dev_info['bus'])
    1.69 -    slot = parse_hex(pci_dev_info['slot'])
    1.70 -    func = parse_hex(pci_dev_info['func'])
    1.71 +    if int(pci['vslot'], 16) != AUTO_PHP_SLOT:
    1.72 +        raise PciDeviceParseError(("Failed to parse pci device: %s: " +
    1.73 +                                   "vslot provided where prohibited: %s") %
    1.74 +                                  (pci_name_string, pci['vslot']))
    1.75 +    if 'opts' in pci:
    1.76 +        raise PciDeviceParseError(("Failed to parse pci device: %s: " +
    1.77 +                                   "options provided where prohibited: %s") %
    1.78 +                                  (pci_name_string, pci['opts']))
    1.79  
    1.80 -    return (domain, bus, slot, func)
    1.81 +    return pci
    1.82 +
    1.83 +def __pci_dict_to_fmt_str(fmt, dev):
    1.84 +    return fmt % (int(dev['domain'], 16), int(dev['bus'], 16),
    1.85 +                  int(dev['slot'], 16), int(dev['func'], 16))
    1.86 +
    1.87 +def pci_dict_to_bdf_str(dev):
    1.88 +    return __pci_dict_to_fmt_str('%04x:%02x:%02x.%01x', dev)
    1.89 +
    1.90 +def pci_dict_to_xc_str(dev):
    1.91 +    return __pci_dict_to_fmt_str('0x%x, 0x%x, 0x%x, 0x%x', dev)
    1.92  
    1.93  def extract_the_exact_pci_names(pci_names):
    1.94      result = []
    1.95 @@ -198,27 +238,7 @@ def get_all_pci_names():
    1.96      return pci_names
    1.97  
    1.98  def get_all_pci_devices():
    1.99 -    pci_devs = []
   1.100 -    for pci_name in get_all_pci_names():
   1.101 -        pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
   1.102 -                r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
   1.103 -                r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
   1.104 -                r"(?P<func>[0-7])$", pci_name)
   1.105 -        if pci_match is None:
   1.106 -            raise PciDeviceParseError(('Failed to parse pci device name: %s' %
   1.107 -                pci_name))
   1.108 -        pci_dev_info = pci_match.groupdict('0')
   1.109 -        domain = parse_hex(pci_dev_info['domain'])
   1.110 -        bus = parse_hex(pci_dev_info['bus'])
   1.111 -        slot = parse_hex(pci_dev_info['slot'])
   1.112 -        func = parse_hex(pci_dev_info['func'])
   1.113 -        try:
   1.114 -            pci_dev = PciDevice(domain, bus, slot, func)
   1.115 -        except:
   1.116 -            continue
   1.117 -        pci_devs.append(pci_dev)
   1.118 -
   1.119 -    return pci_devs
   1.120 +    return map(PciDevice, map(parse_pci_name, get_all_pci_names()))
   1.121  
   1.122  def _create_lspci_info():
   1.123      """Execute 'lspci' command and parse the result.
   1.124 @@ -241,7 +261,7 @@ def _create_lspci_info():
   1.125              try:
   1.126                  (opt, value) = line.split(':\t')
   1.127                  if opt == 'Slot' or (opt == 'Device' and first_device):
   1.128 -                    device_name = PCI_DEV_FORMAT_STR % parse_pci_name(value)
   1.129 +                    device_name = pci_dict_to_bdf_str(parse_pci_name(value))
   1.130                      first_device = False
   1.131                  else:
   1.132                      device_info[opt] = value
   1.133 @@ -292,8 +312,7 @@ def find_all_devices_owned_by_pciback():
   1.134      pci_list = extract_the_exact_pci_names(pci_names)
   1.135      dev_list = []
   1.136      for pci in pci_list:
   1.137 -        (dom, b, d, f) = parse_pci_name(pci)
   1.138 -        dev = PciDevice(dom, b, d, f)
   1.139 +        dev = PciDevice(parse_pci_name(pci))
   1.140          dev_list = dev_list + [dev]
   1.141      return dev_list
   1.142  
   1.143 @@ -400,12 +419,12 @@ class PciDeviceVslotMissing(Exception):
   1.144          return 'pci: no vslot: ' + self.message
   1.145  
   1.146  class PciDevice:
   1.147 -    def __init__(self, domain, bus, slot, func):
   1.148 -        self.domain = domain
   1.149 -        self.bus = bus
   1.150 -        self.slot = slot
   1.151 -        self.func = func
   1.152 -        self.name = PCI_DEV_FORMAT_STR % (domain, bus, slot, func)
   1.153 +    def __init__(self, dev):
   1.154 +        self.domain = int(dev['domain'], 16)
   1.155 +        self.bus = int(dev['bus'], 16)
   1.156 +        self.slot = int(dev['slot'], 16)
   1.157 +        self.func = int(dev['func'], 16)
   1.158 +        self.name = pci_dict_to_bdf_str(dev)
   1.159          self.cfg_space_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \
   1.160              self.name + SYSFS_PCI_DEV_CONFIG_PATH 
   1.161          self.irq = 0
   1.162 @@ -447,14 +466,15 @@ class PciDevice:
   1.163                  # We have reached the upmost one.
   1.164                  return None
   1.165              else:
   1.166 +                dev = {}
   1.167                  lst = parent.split(':')
   1.168 -                dom = int(lst[0], 16)
   1.169 -                bus = int(lst[1], 16)
   1.170 +                dev['domain'] = int(lst[0], 16)
   1.171 +                dev['bus'] = int(lst[1], 16)
   1.172                  lst = lst[2]
   1.173                  lst = lst.split('.')
   1.174 -                dev =  int(lst[0], 16)
   1.175 -                func =  int(lst[1], 16)
   1.176 -            return (dom, bus, dev, func)
   1.177 +                dev['slot'] = int(lst[0], 16)
   1.178 +                dev['func'] = int(lst[1], 16)
   1.179 +            return dev
   1.180          except OSError, (errno, strerr):
   1.181              raise PciDeviceParseError('Can not locate the parent of %s',
   1.182                  self.name)
   1.183 @@ -464,15 +484,13 @@ class PciDevice:
   1.184          dev = self.find_parent()
   1.185          if dev is None:
   1.186              return None
   1.187 -        (dom, b, d, f) = dev
   1.188 -        dev = dev_parent = PciDevice(dom, b, d, f)
   1.189 +        dev = dev_parent = PciDevice(dev)
   1.190          while dev_parent.dev_type != DEV_TYPE_PCIe_BRIDGE:
   1.191              parent = dev_parent.find_parent()
   1.192              if parent is None:
   1.193                  break
   1.194 -            (dom, b, d, f) = parent
   1.195              dev = dev_parent
   1.196 -            dev_parent = PciDevice(dom, b, d, f)
   1.197 +            dev_parent = PciDevice(parent)
   1.198          return dev
   1.199  
   1.200      def find_all_devices_behind_the_bridge(self, ignore_bridge):
   1.201 @@ -483,8 +501,7 @@ class PciDevice:
   1.202  
   1.203          list = [self.name]
   1.204          for pci_str in dev_list:
   1.205 -            (dom, b, d, f) = parse_pci_name(pci_str)
   1.206 -            dev = PciDevice(dom, b, d, f)
   1.207 +            dev = PciDevice(parse_pci_name(pci_str))
   1.208              if dev.dev_type == DEV_TYPE_PCI_BRIDGE or \
   1.209                  dev.dev_type == DEV_TYPE_PCIe_BRIDGE:
   1.210                  sub_list_including_self = \
   1.211 @@ -600,7 +617,7 @@ class PciDevice:
   1.212  
   1.213      def find_all_the_multi_functions(self):
   1.214          sysfs_mnt = find_sysfs_mnt()
   1.215 -        parent = PCI_DEV_FORMAT_STR % self.find_parent()
   1.216 +        parent = pci_dict_to_bdf_str(self.find_parent())
   1.217          pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \
   1.218              parent + '/').read()
   1.219          funcs = extract_the_exact_pci_names(pci_names)
   1.220 @@ -758,8 +775,7 @@ class PciDevice:
   1.221          if len(devs) == 0:
   1.222              return
   1.223          for pci_dev in devs:
   1.224 -            (dom, b, d, f) = parse_pci_name(pci_dev)
   1.225 -            dev = PciDevice(dom, b, d, f)
   1.226 +            dev = PciDevice(parse_pci_name(pci_dev))
   1.227              if dev.driver == 'pciback':
   1.228                  continue
   1.229              err_msg = 'pci: %s must be co-assigned to the same guest with %s' + \
   1.230 @@ -785,7 +801,7 @@ class PciDevice:
   1.231                      funcs = self.find_all_the_multi_functions()
   1.232                      self.devs_check_driver(funcs)
   1.233  
   1.234 -                    parent = '%04x:%02x:%02x.%01x' % self.find_parent()
   1.235 +                    parent = pci_dict_to_bdf_str(self.find_parent())
   1.236  
   1.237                      # Do Secondary Bus Reset.
   1.238                      self.do_secondary_bus_reset(parent, funcs)
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed Jun 17 07:23:40 2009 +0100
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Wed Jun 17 07:34:59 2009 +0100
     2.3 @@ -39,7 +39,8 @@ from xen.util import asserts, auxbin
     2.4  from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
     2.5  import xen.util.xsm.xsm as security
     2.6  from xen.util import xsconstants
     2.7 -from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp
     2.8 +from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp, \
     2.9 +                         pci_dict_to_bdf_str, pci_dict_to_xc_str
    2.10  
    2.11  from xen.xend import balloon, sxp, uuid, image, arch
    2.12  from xen.xend import XendOptions, XendNode, XendConfig
    2.13 @@ -310,9 +311,8 @@ def do_FLR(domid):
    2.14      dev_str_list = get_assigned_pci_devices(domid)
    2.15  
    2.16      for dev_str in dev_str_list:
    2.17 -        (dom, b, d, f) = parse_pci_name(dev_str)
    2.18          try:
    2.19 -            dev = PciDevice(dom, b, d, f)
    2.20 +            dev = PciDevice(parse_pci_name(dev_str))
    2.21          except Exception, e:
    2.22              raise VmError("pci: failed to locate device and "+
    2.23                      "parse it's resources - "+str(e))
    2.24 @@ -652,23 +652,15 @@ class XendDomainInfo:
    2.25                      raise VmError("device is already inserted")
    2.26  
    2.27          # Test whether the devices can be assigned with VT-d
    2.28 -        pci_str = "%s, %s, %s, %s" % (new_dev['domain'],
    2.29 -                new_dev['bus'],
    2.30 -                new_dev['slot'],
    2.31 -                new_dev['func'])
    2.32 -        bdf = xc.test_assign_device(0, pci_str)
    2.33 +        bdf = xc.test_assign_device(0, pci_dict_to_xc_str(new_dev))
    2.34          if bdf != 0:
    2.35              if bdf == -1:
    2.36                  raise VmError("failed to assign device: maybe the platform"
    2.37                                " doesn't support VT-d, or VT-d isn't enabled"
    2.38                                " properly?")
    2.39 -            bus = (bdf >> 16) & 0xff
    2.40 -            devfn = (bdf >> 8) & 0xff
    2.41 -            dev = (devfn >> 3) & 0x1f
    2.42 -            func = devfn & 0x7
    2.43 -            raise VmError("fail to assign device(%x:%x.%x): maybe it has"
    2.44 +            raise VmError("fail to assign device(%s): maybe it has"
    2.45                            " already been assigned to other domain, or maybe"
    2.46 -                          " it doesn't exist." % (bus, dev, func))
    2.47 +                          " it doesn't exist." % pci_dict_to_bdf_str(new_dev))
    2.48  
    2.49          # Here, we duplicate some checkings (in some cases, we mustn't allow
    2.50          # a device to be hot-plugged into an HVM guest) that are also done in
    2.51 @@ -680,12 +672,8 @@ class XendDomainInfo:
    2.52          # Test whether the device is owned by pciback. For instance, we can't
    2.53          # hotplug a device being used by Dom0 itself to an HVM guest.
    2.54          from xen.xend.server.pciif import PciDevice, parse_pci_name
    2.55 -        domain = int(new_dev['domain'],16)
    2.56 -        bus    = int(new_dev['bus'],16)
    2.57 -        dev    = int(new_dev['slot'],16)
    2.58 -        func   = int(new_dev['func'],16)
    2.59          try:
    2.60 -            pci_device = PciDevice(domain, bus, dev, func)
    2.61 +            pci_device = PciDevice(new_dev)
    2.62          except Exception, e:
    2.63              raise VmError("pci: failed to locate device and "+
    2.64                      "parse it's resources - "+str(e))
    2.65 @@ -710,9 +698,8 @@ class XendDomainInfo:
    2.66          pci_device.devs_check_driver(coassignment_list)
    2.67          assigned_pci_device_str_list = self._get_assigned_pci_devices()
    2.68          for pci_str in coassignment_list:
    2.69 -            (domain, bus, dev, func) = parse_pci_name(pci_str) 
    2.70 -            dev_str =  '0x%x,0x%x,0x%x,0x%x' % (domain, bus, dev, func)
    2.71 -            if xc.test_assign_device(0, dev_str) == 0:
    2.72 +            pci_dev = parse_pci_name(pci_str)
    2.73 +            if xc.test_assign_device(0, pci_dict_to_xc_str(pci_dev)) == 0:
    2.74                  continue
    2.75              if not pci_str in assigned_pci_device_str_list:
    2.76                  raise VmError(("pci: failed to pci-attach %s to domain %s" + \
    2.77 @@ -742,12 +729,9 @@ class XendDomainInfo:
    2.78              if new_dev.has_key('opts'):
    2.79                  opts = ',' + serialise_pci_opts(new_dev['opts'])
    2.80  
    2.81 -            bdf_str = "%s:%s:%s.%s@%s%s" % (new_dev['domain'],
    2.82 -                new_dev['bus'],
    2.83 -                new_dev['slot'],
    2.84 -                new_dev['func'],
    2.85 -                new_dev['vslot'],
    2.86 -                opts)
    2.87 +            bdf_str = "%s@%02x%s" % (pci_dict_to_bdf_str(new_dev),
    2.88 +                                     int(new_dev['vslot'], 16), opts)
    2.89 +            log.debug("XendDomainInfo.hvm_pci_device_insert_dev: %s" % bdf_str)
    2.90              self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
    2.91  
    2.92              vslot = xstransact.Read("/local/domain/0/device-model/%i/parameter"
    2.93 @@ -864,9 +848,8 @@ class XendDomainInfo:
    2.94                          vslot = x['vslot']
    2.95                          break
    2.96                  if vslot == "":
    2.97 -                    raise VmError("Device %04x:%02x:%02x.%01x is not connected"
    2.98 -                                  % (int(dev['domain'],16), int(dev['bus'],16),
    2.99 -                                     int(dev['slot'],16), int(dev['func'],16)))
   2.100 +                    raise VmError("Device %s is not connected" %
   2.101 +                                  pci_dict_to_bdf_str(dev))
   2.102                  self.hvm_destroyPCIDevice(int(vslot, 16))
   2.103                  # Update vslot
   2.104                  dev['vslot'] = vslot
   2.105 @@ -1152,12 +1135,8 @@ class XendDomainInfo:
   2.106          # list of D's co-assignment devices, DD is not assigned (to domN).
   2.107          # 
   2.108          from xen.xend.server.pciif import PciDevice
   2.109 -        domain = int(x['domain'],16)
   2.110 -        bus    = int(x['bus'],16)
   2.111 -        dev    = int(x['slot'],16)
   2.112 -        func   = int(x['func'],16)
   2.113          try:
   2.114 -            pci_device = PciDevice(domain, bus, dev, func)
   2.115 +            pci_device = PciDevice(x)
   2.116          except Exception, e:
   2.117              raise VmError("pci: failed to locate device and "+
   2.118                      "parse it's resources - "+str(e))
   2.119 @@ -1172,9 +1151,8 @@ class XendDomainInfo:
   2.120                      )% (pci_device.name, self.info['name_label'], pci_str))
   2.121  
   2.122  
   2.123 -        bdf_str = "%s:%s:%s.%s" % (x['domain'], x['bus'], x['slot'], x['func'])
   2.124 +        bdf_str = pci_dict_to_bdf_str(x)
   2.125          log.info("hvm_destroyPCIDevice:%s:%s!", x, bdf_str)
   2.126 -
   2.127          if self.domid is not None:
   2.128              self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
   2.129  
   2.130 @@ -1338,21 +1316,12 @@ class XendDomainInfo:
   2.131          if self.domid is not None:
   2.132              return get_assigned_pci_devices(self.domid)
   2.133  
   2.134 -        dev_str_list = []
   2.135          dev_info = self._getDeviceInfo_pci(devid)
   2.136          if dev_info is None:
   2.137 -            return dev_str_list
   2.138 +            return []
   2.139          dev_uuid = sxp.child_value(dev_info, 'uuid')
   2.140          pci_conf = self.info['devices'][dev_uuid][1]
   2.141 -        pci_devs = pci_conf['devs']
   2.142 -        for pci_dev in pci_devs:
   2.143 -            domain = int(pci_dev['domain'], 16)
   2.144 -            bus = int(pci_dev['bus'], 16)
   2.145 -            slot = int(pci_dev['slot'], 16)
   2.146 -            func = int(pci_dev['func'], 16)
   2.147 -            dev_str = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
   2.148 -            dev_str_list = dev_str_list + [dev_str]
   2.149 -        return dev_str_list 
   2.150 +        return map(pci_dict_to_bdf_str, pci_conf['devs'])
   2.151  
   2.152      def setMemoryTarget(self, target):
   2.153          """Set the memory target of this domain.
   2.154 @@ -3909,12 +3878,12 @@ class XendDomainInfo:
   2.155          target_dev = None
   2.156          new_pci_sxp = ['pci']
   2.157          for dev in sxp.children(old_pci_sxp, 'dev'):
   2.158 -            domain = int(sxp.child_value(dev, 'domain'), 16)
   2.159 -            bus = int(sxp.child_value(dev, 'bus'), 16)
   2.160 -            slot = int(sxp.child_value(dev, 'slot'), 16)
   2.161 -            func = int(sxp.child_value(dev, 'func'), 16)
   2.162 -            name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
   2.163 -            if ppci.get_name() == name:
   2.164 +            pci_dev = {}
   2.165 +            pci_dev['domain'] = sxp.child_value(dev, 'domain')
   2.166 +            pci_dev['bus'] = sxp.child_value(dev, 'bus')
   2.167 +            pci_dev['slot'] = sxp.child_value(dev, 'slot')
   2.168 +            pci_dev['func'] = sxp.child_value(dev, 'func')
   2.169 +            if ppci.get_name() == pci_dict_to_bdf_str(pci_dev):
   2.170                  target_dev = dev
   2.171              else:
   2.172                  new_pci_sxp.append(dev)
     3.1 --- a/tools/python/xen/xend/XendNode.py	Wed Jun 17 07:23:40 2009 +0100
     3.2 +++ b/tools/python/xen/xend/XendNode.py	Wed Jun 17 07:34:59 2009 +0100
     3.3 @@ -340,8 +340,7 @@ class XendNode:
     3.4                  except KeyError:
     3.5                      pass
     3.6  
     3.7 -        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
     3.8 -        pci_dev = PciUtil.PciDevice(domain, bus, slot, func)
     3.9 +        pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
    3.10          ppci_record = {
    3.11              'domain':                   pci_dev.domain,
    3.12              'bus':                      pci_dev.bus,
     4.1 --- a/tools/python/xen/xend/server/pciif.py	Wed Jun 17 07:23:40 2009 +0100
     4.2 +++ b/tools/python/xen/xend/server/pciif.py	Wed Jun 17 07:34:59 2009 +0100
     4.3 @@ -130,13 +130,7 @@ class PciController(DevController):
     4.4                      log.debug('Reconfiguring PCI device %s.' % dev)
     4.5                      attaching = False
     4.6  
     4.7 -                (domain, bus, slotfunc) = dev.split(':')
     4.8 -                (slot, func) = slotfunc.split('.')
     4.9 -                domain = parse_hex(domain)
    4.10 -                bus = parse_hex(bus)
    4.11 -                slot = parse_hex(slot)
    4.12 -                func = parse_hex(func)
    4.13 -                self.setupOneDevice(domain, bus, slot, func)
    4.14 +                self.setupOneDevice(parse_pci_name(dev))
    4.15  
    4.16                  self.writeBackend(devid, 'dev-%i' % devno, dev)
    4.17                  self.writeBackend(devid, 'state-%i' % devno,
    4.18 @@ -248,15 +242,13 @@ class PciController(DevController):
    4.19              return
    4.20  
    4.21          #group string format xx:xx.x,xx:xx.x,
    4.22 -        devstr_len = group_str.find(',')
    4.23 -        for i in range(0, len(group_str), devstr_len + 1):
    4.24 -            (bus, slotfunc) = group_str[i:i + devstr_len].split(':')
    4.25 -            (slot, func) = slotfunc.split('.')
    4.26 -            b = parse_hex(bus)
    4.27 -            d = parse_hex(slot)
    4.28 -            f = parse_hex(func)
    4.29 +        for i in group_str.split(','):
    4.30 +            if i == '':
    4.31 +                continue
    4.32 +            pci_dev = parse_pci_name(i)
    4.33 +            pci_dev['domain'] = '%04x' % dev.domain
    4.34              try:
    4.35 -                sdev = PciDevice(dev.domain, b, d, f)
    4.36 +                sdev = PciDevice(pci_dev)
    4.37              except Exception, e:
    4.38                  #no dom0 drivers bound to sdev
    4.39                  continue
    4.40 @@ -270,13 +262,13 @@ class PciController(DevController):
    4.41                      )%(sdev.name, dev.name))
    4.42          return
    4.43  
    4.44 -    def setupOneDevice(self, domain, bus, slot, func):
    4.45 +    def setupOneDevice(self, pci_dev):
    4.46          """ Attach I/O resources for device to frontend domain
    4.47          """
    4.48          fe_domid = self.getDomid()
    4.49  
    4.50          try:
    4.51 -            dev = PciDevice(domain, bus, slot, func)
    4.52 +            dev = PciDevice(pci_dev)
    4.53          except Exception, e:
    4.54              raise VmError("pci: failed to locate device and "+
    4.55                      "parse it's resources - "+str(e))
    4.56 @@ -305,12 +297,11 @@ class PciController(DevController):
    4.57  
    4.58          if not self.vm.info.is_hvm():
    4.59              # Setup IOMMU device assignment
    4.60 -            pci_str = "0x%x, 0x%x, 0x%x, 0x%x" % (domain, bus, slot, func)
    4.61 -            bdf = xc.assign_device(fe_domid, pci_str)
    4.62 +            bdf = xc.assign_device(fe_domid, pci_dict_to_xc_str(pci_dev))
    4.63 +            pci_str = pci_dict_to_bdf_str(pci_dev)
    4.64              if bdf > 0:
    4.65 -                raise VmError("Failed to assign device to IOMMU (%x:%x.%x)"
    4.66 -                              % (bus, slot, func))
    4.67 -            log.debug("pci: assign device %x:%x.%x" % (bus, slot, func))
    4.68 +                raise VmError("Failed to assign device to IOMMU (%s)" % pci_str)
    4.69 +            log.debug("pci: assign device %s" % pci_str)
    4.70  
    4.71          for (start, size) in dev.ioports:
    4.72              log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
    4.73 @@ -366,23 +357,15 @@ class PciController(DevController):
    4.74      def setupDevice(self, config):
    4.75          """Setup devices from config
    4.76          """
    4.77 -        pci_str_list = []
    4.78 -        pci_dev_list = []
    4.79 -        for pci_config in config.get('devs', []):
    4.80 -            domain = parse_hex(pci_config.get('domain', 0))
    4.81 -            bus = parse_hex(pci_config.get('bus', 0))
    4.82 -            slot = parse_hex(pci_config.get('slot', 0))
    4.83 -            func = parse_hex(pci_config.get('func', 0))            
    4.84 -            pci_str = '%04x:%02x:%02x.%01x' % (domain, bus, slot, func)
    4.85 -            pci_str_list = pci_str_list + [pci_str]
    4.86 -            pci_dev_list = pci_dev_list + [(domain, bus, slot, func)]
    4.87 +        pci_dev_list = config.get('devs', [])
    4.88 +        pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list)
    4.89  
    4.90          if len(pci_str_list) != len(set(pci_str_list)):
    4.91              raise VmError('pci: duplicate devices specified in guest config?')
    4.92  
    4.93 -        for (domain, bus, slot, func) in pci_dev_list:
    4.94 +        for pci_dev in pci_dev_list:
    4.95              try:
    4.96 -                dev = PciDevice(domain, bus, slot, func)
    4.97 +                dev = PciDevice(pci_dev)
    4.98              except Exception, e:
    4.99                  raise VmError("pci: failed to locate device and "+
   4.100                          "parse it's resources - "+str(e))
   4.101 @@ -427,9 +410,7 @@ class PciController(DevController):
   4.102                      dev.devs_check_driver(devs_str)
   4.103                      for s in devs_str:
   4.104                          if not s in pci_str_list:
   4.105 -                            (s_dom, s_bus, s_slot, s_func) = parse_pci_name(s)
   4.106 -                            s_pci_str = '0x%x,0x%x,0x%x,0x%x' % \
   4.107 -                                (s_dom, s_bus, s_slot, s_func)
   4.108 +                            s_pci_str = pci_dict_to_bdf_str(parse_pci_name(s))
   4.109                              # s has been assigned to other guest?
   4.110                              if xc.test_assign_device(0, s_pci_str) != 0:
   4.111                                  err_msg = 'pci: %s must be co-assigned to the'+\
   4.112 @@ -453,13 +434,13 @@ class PciController(DevController):
   4.113          return True
   4.114  
   4.115  
   4.116 -    def cleanupOneDevice(self, domain, bus, slot, func):
   4.117 +    def cleanupOneDevice(self, pci_dev):
   4.118          """ Detach I/O resources for device from frontend domain
   4.119          """
   4.120          fe_domid = self.getDomid()
   4.121  
   4.122          try:
   4.123 -            dev = PciDevice(domain, bus, slot, func)
   4.124 +            dev = PciDevice(pci_dev)
   4.125          except Exception, e:
   4.126              raise VmError("pci: failed to locate device and "+
   4.127                      "parse it's resources - "+str(e))
   4.128 @@ -476,12 +457,11 @@ class PciController(DevController):
   4.129          # DMA transaction, etc
   4.130          dev.do_FLR()
   4.131  
   4.132 -        pci_str = "0x%x, 0x%x, 0x%x, 0x%x" % (domain, bus, slot, func)
   4.133 -        bdf = xc.deassign_device(fe_domid, pci_str)
   4.134 +        bdf = xc.deassign_device(fe_domid, pci_dict_to_xc_str(pci_dev))
   4.135 +        pci_str = pci_dict_to_bdf_str(pci_dev)
   4.136          if bdf > 0:
   4.137 -            raise VmError("Failed to deassign device from IOMMU (%x:%x.%x)"
   4.138 -                          % (bus, slot, func))
   4.139 -        log.debug("pci: Deassign device %x:%x.%x" % (bus, slot, func))
   4.140 +            raise VmError("Failed to deassign device from IOMMU (%s)" % pci_str)
   4.141 +        log.debug("pci: Deassign device %s" % pci_str)
   4.142  
   4.143          for (start, size) in dev.ioports:
   4.144              log.debug('pci: disabling ioport 0x%x/0x%x'%(start,size))
   4.145 @@ -530,15 +510,9 @@ class PciController(DevController):
   4.146              state = int(self.readBackend(devid, 'state-%i' % i))
   4.147              if state == xenbusState['Closing']:
   4.148                  # Detach I/O resources.
   4.149 -                dev = self.readBackend(devid, 'dev-%i' % i)
   4.150 -                (domain, bus, slotfunc) = dev.split(':')
   4.151 -                (slot, func) = slotfunc.split('.')
   4.152 -                domain = parse_hex(domain)
   4.153 -                bus = parse_hex(bus)
   4.154 -                slot = parse_hex(slot)
   4.155 -                func = parse_hex(func)            
   4.156 +                pci_dev = parse_pci_name(self.readBackend(devid, 'dev-%i' % i))
   4.157                  # In HVM case, I/O resources are disabled in ioemu.
   4.158 -                self.cleanupOneDevice(domain, bus, slot, func)
   4.159 +                self.cleanupOneDevice(pci_dev)
   4.160                  # Remove xenstore nodes.
   4.161                  list = ['dev', 'vdev', 'state', 'uuid', 'vslot']
   4.162                  if self.readBackend(devid, 'opts-%i' % i) is not None: