WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] xend: pass-through: Allow multi-function

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xend: pass-through: Allow multi-function device specifications to be parsed
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 29 Jun 2009 02:20:15 -0700
Delivery-date: Mon, 29 Jun 2009 02:20:26 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1246092836 -3600
# Node ID 6966404d2cb8fa8306de5a0ffa38f8c0b237693f
# Parent  4caca5bd2b174dc4c7c0ccd58d3c5da130bf3540
xend: pass-through: Allow multi-function device specifications to be parsed

The general format is as follows:

  Now: SEQ:BUS:DEV.FUNC[@VSLOT][,OPT...]
  New: SEQ:BUS:DEV.FUNC0-FUNCN[@VSLOT][,OPT...]
       SEQ:BUS:DEV.FUNC0,FUNCM,FUNCN[@VSLOT][,OPT...]
       SEQ:BUS:DEV.*[@VSLOT][,OPT...]

  In the case of unplug the VSLOT and OPT must be omitted.

  Xm expands this notation notation out and passes
  more conventional parameters to qemu-xen.

  E.g:
       0000:00:01.00-03 becomes:
         0000:00:01.00
         0000:00:01.01
         0000:00:01.02
         0000:00:01.03

       0000:00:01.00,03,05,07 becomes:
         0000:00:01.00
         0000:00:01.03
         0000:00:01.05
         0000:00:01.07

       For a device that has functions 0, 1, 2, 3, 5 and 7,
       0000:00:01.* becomes:
         0000:00:01.00
         0000:00:01.01
         0000:00:01.02
         0000:00:01.03
         0000:00:01.05
         0000:00:01.07

Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx>
Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
Cc: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
 tools/python/xen/util/pci.py            |  111 +++++++++++++++++++++++++-------
 tools/python/xen/xend/XendConfig.py     |    5 -
 tools/python/xen/xend/XendConstants.py  |    3 
 tools/python/xen/xend/XendDomainInfo.py |    2 
 tools/python/xen/xend/server/pciif.py   |    3 
 tools/python/xen/xm/create.py           |    4 -
 tools/python/xen/xm/main.py             |    4 -
 7 files changed, 97 insertions(+), 35 deletions(-)

diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py      Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/util/pci.py      Sat Jun 27 09:53:56 2009 +0100
@@ -16,7 +16,7 @@ from xen.util import utils
 from xen.util import utils
 from xen.xend import uuid
 from xen.xend import sxp
-from xen.xend.XendConstants import AUTO_PHP_DEVFN
+from xen.xend.XendConstants import AUTO_PHP_SLOT
 from xen.xend.XendSXPDev import dev_dict_to_sxp
 
 PROC_PCI_PATH = '/proc/bus/pci/devices'
@@ -227,11 +227,39 @@ def parse_hex(val):
     except ValueError:
         return None
 
+def pci_func_list_map_fn(key, func_str):
+    if func_str == "*":
+        return map(lambda x: int(x['func'], 16),
+                   filter(lambda x:
+                          pci_dict_cmp(x, key, ['domain', 'bus', 'slot']),
+                          get_all_pci_dict()))
+    l = map(int, func_str.split("-"))
+    if len(l) == 1:
+        return l
+    if len(l) == 2:
+        if l[0] < l[1]:
+            return range(l[0], l[1] + 1)
+        else:
+            x = range(l[1], l[0] + 1)
+            x.reverse()
+            return x
+    return []
+
+def pci_func_list_process(pci_dev_str, template, func_str):
+    l = reduce(lambda x, y: x + y,
+               (map(lambda x: pci_func_list_map_fn(template, x),
+                    func_str.split(","))))
+
+    if len(l) != len(set(l)):
+        raise PciDeviceParseError("Duplicate functions: %s" % pci_dev_str)
+
+    return l
+
 def parse_pci_name_extended(pci_dev_str):
     pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" +
                          r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" +
                          r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" +
-                         r"(?P<func>(\*|[0-7]))" +
+                         r"(?P<func>(\*|[0-7]([,-][0-7])*))" +
                          r"(@(?P<vslot>[01]?[0-9a-fA-F]))?" +
                          r"(,(?P<opts>.*))?$", pci_dev_str)
 
@@ -239,31 +267,65 @@ def parse_pci_name_extended(pci_dev_str)
         raise PciDeviceParseError("Failed to parse pci device: %s" %
                                   pci_dev_str)
 
-    out = {}
     pci_dev_info = pci_match.groupdict('')
-    if pci_dev_info['domain'] == '':
+
+    template = {}
+    if pci_dev_info['domain'] != '':
+        domain = int(pci_dev_info['domain'], 16)
+    else:
         domain = 0
-    else:
-        domain = int(pci_dev_info['domain'], 16)
-    out['domain'] = "0x%04x" % domain
-    out['bus']    = "0x%02x" % int(pci_dev_info['bus'], 16)
-    out['slot']   = "0x%02x" % int(pci_dev_info['slot'], 16)
-    out['func']   = "0x%x"   % int(pci_dev_info['func'], 16)
-    if pci_dev_info['vslot'] == '':
-        vslot = AUTO_PHP_DEVFN
-    else:
-        vslot = PCI_DEVFN(int(pci_dev_info['vslot'], 16), 0)
-    out['vslot'] = "0x%02x" % vslot
+    template['domain'] = "0x%04x" % domain
+    template['bus']    = "0x%02x" % int(pci_dev_info['bus'], 16)
+    template['slot']   = "0x%02x" % int(pci_dev_info['slot'], 16)
+    template['func']   = "0x%x"   % int(pci_dev_info['func'], 16)
     if pci_dev_info['opts'] != '':
-        out['opts'] = split_pci_opts(pci_dev_info['opts'])
-        check_pci_opts(out['opts'])
-
-    return out
+        template['opts'] = split_pci_opts(pci_dev_info['opts'])
+        check_pci_opts(template['opts'])
+
+    # This is where virtual function assignment takes place
+    # Virtual slot assignment takes place here if specified in the bdf,
+    # else it is done inside qemu-xen, as it knows which slots are free
+    pci = []
+    func_list = pci_func_list_process(pci_dev_str, template,
+                                      pci_dev_info['func'])
+    for func in func_list:
+        pci_dev = template.copy()
+
+        if len(func_list) == 1:
+            # For single-function devices vfunc must be 0
+            vfunc = 0
+        else:
+            # For multi-function virtual devices,
+            # identity map the func to vfunc
+            vfunc = func
+        if pci_dev_info['vslot'] == '':
+            vslot = AUTO_PHP_SLOT | vfunc
+        else:
+            vslot = PCI_DEVFN(int(pci_dev_info['vslot'], 16), vfunc)
+        pci_dev['vslot'] = "0x%02x" % vslot
+
+        pci.append(pci_dev)
+
+    # For pci attachment and detachment is it important that virtual
+    # function 0 is done last. This is because is virtual function 0 that
+    # is used to singnal changes to the guest using ACPI
+    #
+    # By arranging things so that virtual function 0 is first,
+    # attachemnt can use the returned list as is. And detachment
+    # can just reverse the list.
+    pci.sort(None, lambda x: int(x['vslot'], 16), 1)
+    return pci
 
 def parse_pci_name(pci_name_string):
-    pci = parse_pci_name_extended(pci_name_string)
-
-    if int(pci['vslot'], 16) != AUTO_PHP_DEVFN:
+    dev = parse_pci_name_extended(pci_name_string)
+
+    if len(dev) != 1:
+        raise PciDeviceParseError(("Failed to parse pci device: %s: "
+                                   "multiple functions specified prohibited") %
+                                    pci_name_string)
+
+    pci = dev[0]
+    if not int(pci['vslot'], 16) & AUTO_PHP_SLOT:
         raise PciDeviceParseError(("Failed to parse pci device: %s: " +
                                    "vslot provided where prohibited: 0x%02x") %
                                   (pci_name_string,
@@ -321,8 +383,11 @@ def get_all_pci_names():
     pci_names = os.popen('ls ' + sysfs_mnt + 
SYSFS_PCI_DEVS_PATH).read().split()
     return pci_names
 
+def get_all_pci_dict():
+    return map(parse_pci_name, get_all_pci_names())
+
 def get_all_pci_devices():
-    return map(PciDevice, map(parse_pci_name, get_all_pci_names()))
+    return map(PciDevice, get_all_pci_dict())
 
 def _create_lspci_info():
     """Execute 'lspci' command and parse the result.
diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Sat Jun 27 09:53:56 2009 +0100
@@ -32,7 +32,7 @@ from xen.xend.XendError import VmError
 from xen.xend.XendError import VmError
 from xen.xend.XendDevices import XendDevices
 from xen.xend.PrettyPrint import prettyprintstring
-from xen.xend.XendConstants import DOM_STATE_HALTED, AUTO_PHP_DEVFN_STR
+from xen.xend.XendConstants import DOM_STATE_HALTED, AUTO_PHP_SLOT
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.server.BlktapController import blktap_disk_types
 from xen.xend.server.netif import randomMAC
@@ -1249,8 +1249,7 @@ class XendConfig(dict):
             dpci_record = {
                 'VM': self['uuid'],
                 'PPCI': ppci_uuid,
-                'hotplug_slot': pci_dev.get('vslot',
-                                            '0x' + AUTO_PHP_DEVFN_STR)
+                'hotplug_slot': pci_dev.get('vslot', '0x%02x' % AUTO_PHP_SLOT)
             }
 
             dpci_opts = pci_dev.get('opts')
diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/xend/XendConstants.py
--- a/tools/python/xen/xend/XendConstants.py    Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/xend/XendConstants.py    Sat Jun 27 09:53:56 2009 +0100
@@ -141,8 +141,7 @@ NR_PCI_FUNC = 8
 NR_PCI_FUNC = 8
 NR_PCI_DEV = 32
 NR_PCI_DEVFN = NR_PCI_FUNC * NR_PCI_DEV
-AUTO_PHP_DEVFN = NR_PCI_DEVFN
-AUTO_PHP_DEVFN_STR = "%02x" % NR_PCI_DEVFN
+AUTO_PHP_SLOT = 0x100
 
 #
 # tmem
diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Sat Jun 27 09:53:56 2009 +0100
@@ -644,7 +644,7 @@ class XendDomainInfo:
             pci_devs = pci_conf['devs']
             for x in pci_devs:
                 if (int(x['vslot'], 16) == int(new_dev['vslot'], 16) and
-                   int(x['vslot'], 16) != AUTO_PHP_DEVFN):
+                    not int(x['vslot'], 16) & AUTO_PHP_SLOT):
                     raise VmError("vslot %s already have a device." % 
(new_dev['vslot']))
 
                 if (pci_dict_cmp(x, new_dev)):
diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py     Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/xend/server/pciif.py     Sat Jun 27 09:53:56 2009 +0100
@@ -74,8 +74,7 @@ class PciController(DevController):
             bus = parse_hex(pci_config.get('bus', 0))
             slot = parse_hex(pci_config.get('slot', 0))
             func = parse_hex(pci_config.get('func', 0))            
-            vslot = parse_hex(pci_config.get('vslot',
-                                             '0x' + AUTO_PHP_DEVFN_STR))
+            vslot = parse_hex(pci_config.get('vslot', '0x%02x' % 
AUTO_PHP_SLOT))
 
             if pci_config.has_key('opts'):
                 opts = serialise_pci_opts(pci_config['opts'])
diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/xm/create.py     Sat Jun 27 09:53:56 2009 +0100
@@ -1090,8 +1090,8 @@ def preprocess_pci(vals):
     if not vals.pci:
         return
     try:
-        vals.pci = map(pci_dict_to_tuple,
-                       map(parse_pci_name_extended, vals.pci))
+        vals.pci = map(pci_dict_to_tuple, reduce(lambda x, y: x + y,
+                       map(parse_pci_name_extended, vals.pci)))
     except PciDeviceParseError, ex:
         err(str(ex))
 
diff -r 4caca5bd2b17 -r 6966404d2cb8 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Sat Jun 27 09:53:19 2009 +0100
+++ b/tools/python/xen/xm/main.py       Sat Jun 27 09:53:56 2009 +0100
@@ -2214,7 +2214,7 @@ def xm_pci_list(args):
 
     has_vslot = False
     for x in devs:
-        if x['vslot'] == AUTO_PHP_DEVFN:
+        if x['vslot'] & AUTO_PHP_SLOT:
             x['show_vslot'] = '-'
             x['show_vfunc'] = '-'
         else:
@@ -2497,7 +2497,7 @@ def parse_pci_configuration(args, state,
         pci_dev_str += ',' + serialise_pci_opts(opts)
 
     try:
-        pci_dev = parse_pci_name_extended(pci_dev_str)
+        pci_dev = parse_pci_name_extended(pci_dev_str)[0]
     except PciDeviceParseError, ex:
         raise OptionError(str(ex))
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] xend: pass-through: Allow multi-function device specifications to be parsed, Xen patchbot-unstable <=