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: Parse command line fo

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xend: pass-through: Parse command line for multi-function hot-plug and unplug
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 29 Jun 2009 02:20:20 -0700
Delivery-date: Mon, 29 Jun 2009 02:20:59 -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 1246092975 -3600
# Node ID f5f5905e6e1c79ccc156fdc36c77a85cb11030c1
# Parent  7bbc4433f2ef5f79861821c0b40542694f5452e7
xend: pass-through: Parse command line for multi-function hot-plug and unplug

Hook things up to allow multi-function pass-through.

This includes making sure that request is valid.
In the case of pci-detach:

* All the functions requested must be attached to the same virtual
  slot * and;
* A request must include the functions attached to a virtual slot

Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx>
Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
 tools/python/xen/xend/XendDomainInfo.py |   54 ++++++++++++--
 tools/python/xen/xm/main.py             |  122 +++++++++++++++++++++++---------
 2 files changed, 136 insertions(+), 40 deletions(-)

diff -r 7bbc4433f2ef -r f5f5905e6e1c tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Sat Jun 27 09:55:42 2009 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Sat Jun 27 09:56:15 2009 +0100
@@ -42,7 +42,7 @@ from xen.util.pci import serialise_pci_o
 from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp, \
                          pci_dict_to_bdf_str, pci_dict_to_xc_str, \
                          pci_convert_sxp_to_dict, pci_convert_dict_to_sxp, \
-                         pci_dict_cmp, PCI_FUNC
+                         pci_dict_cmp, PCI_DEVFN, PCI_SLOT, PCI_FUNC
 
 from xen.xend import balloon, sxp, uuid, image, arch
 from xen.xend import XendOptions, XendNode, XendConfig
@@ -617,12 +617,52 @@ class XendDomainInfo:
         dev_uuid = sxp.child_value(dev_info, 'uuid')
         pci_conf = self.info['devices'][dev_uuid][1]
         pci_devs = pci_conf['devs']
-        request = map(lambda x:
-                      pci_convert_dict_to_sxp(x, 'Initialising', 'Booting'),
-                      pci_devs)
-
-        for i in request:
-                self.pci_device_configure(i)
+
+        # Keep a set of keys that are done rather than
+        # just itterating through set(map(..., pci_devs))
+        # to preserve any order information present.
+        done = set()
+        for key in map(lambda x: x['key'], pci_devs):
+            if key in done:
+                continue
+            done |= set([key])
+            dev = filter(lambda x: x['key'] == key, pci_devs)
+
+            head_dev = dev.pop()
+            dev_sxp = pci_convert_dict_to_sxp(head_dev, 'Initialising',
+                                              'Booting')
+            self.pci_device_configure(dev_sxp)
+
+            # That is all for single-function virtual devices
+            if len(dev) == 0:
+                continue
+
+            if int(head_dev['vslot'], 16) & AUTO_PHP_SLOT:
+                new_dev_info = self._getDeviceInfo_pci(devid)
+                if new_dev_info is None:
+                    continue
+                new_dev_uuid = sxp.child_value(new_dev_info, 'uuid')
+                new_pci_conf = self.info['devices'][new_dev_uuid][1]
+                new_pci_devs = new_pci_conf['devs']
+
+                new_head_dev = filter(lambda x: pci_dict_cmp(x, head_dev),
+                                      new_pci_devs)[0]
+
+                if int(new_head_dev['vslot'], 16) & AUTO_PHP_SLOT:
+                    continue
+
+                vslot = PCI_SLOT(int(new_head_dev['vslot'], 16))
+                new_dev = []
+                for i in dev:
+                    i['vslot'] = '0x%02x' % \
+                                 PCI_DEVFN(vslot, PCI_FUNC(int(i['vslot'], 
16)))
+                    new_dev.append(i)
+
+                dev = new_dev
+
+            for i in dev:
+                dev_sxp = pci_convert_dict_to_sxp(i, 'Initialising', 'Booting')
+                self.pci_device_configure(dev_sxp)
 
     def hvm_pci_device_create(self, dev_config):
         log.debug("XendDomainInfo.hvm_pci_device_create: %s"
diff -r 7bbc4433f2ef -r f5f5905e6e1c tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Sat Jun 27 09:55:42 2009 +0100
+++ b/tools/python/xen/xm/main.py       Sat Jun 27 09:56:15 2009 +0100
@@ -2226,8 +2226,9 @@ def xm_pci_list(args):
     if len(devs) == 0:
         return
 
-    devs.sort(None, lambda x: x['vslot'] << 32 | PCI_BDF(x['domain'], x['bus'],
-                                                         x['slot'], x['func']))
+    devs.sort(None,
+              lambda x: (x['vslot'] - PCI_FUNC(x['vslot'])) << 32 |
+                        PCI_BDF(x['domain'], x['bus'], x['slot'], x['func']))
 
     has_vslot = False
     for x in devs:
@@ -2505,7 +2506,7 @@ def xm_network_attach(args):
             vif.append(vif_param)
         server.xend.domain.device_create(dom, vif)
 
-def parse_pci_configuration(args, state, opts = ''):
+def parse_pci_configuration(args, opts = ''):
     dom = args[0]
     pci_dev_str = args[1]
     if len(args) == 3:
@@ -2514,11 +2515,11 @@ def parse_pci_configuration(args, state,
         pci_dev_str += ',' + serialise_pci_opts(opts)
 
     try:
-        pci_dev = parse_pci_name_extended(pci_dev_str)[0]
+        pci_dev = parse_pci_name_extended(pci_dev_str)
     except PciDeviceParseError, ex:
         raise OptionError(str(ex))
 
-    return (dom, pci_convert_dict_to_sxp(pci_dev, state))
+    return (dom, pci_dev)
 
 def xm_pci_attach(args):
     config_pci_opts = []
@@ -2535,19 +2536,31 @@ def xm_pci_attach(args):
         err("Invalid argument for 'xm pci-attach'")
         usage('pci-attach')
 
-    (dom, pci) = parse_pci_configuration(params, 'Initialising',
-                     config_pci_opts)
-
-    if serverType == SERVER_XEN_API:
-        pci_dev = sxp.children(pci, 'dev')[0]
-        domain = int(sxp.child_value(pci_dev, 'domain'), 16)
-        bus = int(sxp.child_value(pci_dev, 'bus'), 16)
-        slot = int(sxp.child_value(pci_dev, 'slot'), 16)
-        func = int(sxp.child_value(pci_dev, 'func'), 16)
-        vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
-        key = sxp.child_value(pci_dev, 'key')
-        name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
-
+    (dom, dev) = parse_pci_configuration(params, config_pci_opts)
+
+    head_dev = dev.pop(0)
+    xm_pci_attach_one(dom, head_dev)
+
+    # That is all for single-function virtual devices
+    if len(dev) == 0:
+        return
+
+    # If the slot wasn't spefified in the args then use the slot
+    # assigned to the head by qemu-xen for the rest of the functions
+    if int(head_dev['vslot'], 16) & AUTO_PHP_SLOT:
+        vdevfn = int(find_attached_devfn(attached_pci_dict(dom), head_dev), 16)
+        if not vdevfn & AUTO_PHP_SLOT:
+            vslot = PCI_SLOT(vdevfn)
+            for i in dev:
+                i['vslot'] = '0x%02x' % \
+                            PCI_DEVFN(vslot, PCI_FUNC(int(i['vslot'], 16)))
+
+    for i in dev:
+        xm_pci_attach_one(dom, i)
+
+def xm_pci_attach_one(dom, pci_dev):
+    if serverType == SERVER_XEN_API:
+        name = pci_dict_to_bdf_str(pci_dev)
         target_ref = None
         for ppci_ref in server.xenapi.PPCI.get_all():
             if name == server.xenapi.PPCI.get_name(ppci_ref):
@@ -2559,13 +2572,14 @@ def xm_pci_attach(args):
         dpci_record = {
             "VM":           get_single_vm(dom),
             "PPCI":         target_ref,
-            "hotplug_slot": vslot,
-            "options":      dict(config_pci_opts),
-            "key":          key
+            "hotplug_slot": int(pci_dev['vslot'], 16),
+            "options":      dict(pci_dev.get('opts', [])),
+            "key":          pci_dev['key']
         }
         server.xenapi.DPCI.create(dpci_record)
 
     else:
+        pci = pci_convert_dict_to_sxp(pci_dev, 'Initialising')
         server.xend.domain.device_configure(dom, pci)
 
 def parse_scsi_configuration(p_scsi, v_hctl, state):
@@ -2708,20 +2722,61 @@ def xm_network_detach(args):
         arg_check(args, 'network-detach', 2, 3)
         detach(args, 'vif')
 
+def find_attached(attached, key):
+    l = filter(lambda dev: pci_dict_cmp(dev, key), attached)
+
+    if len(l) == 0:
+         raise OptionError("pci: device is not attached: " +
+                           pci_dict_to_bdf_str(key))
+
+    # There shouldn't ever be more than one match,
+    # but perhaps an exception should be thrown if there is
+    return l[0]
+
+def find_attached_devfn(attached, key):
+    pci_dev = find_attached(attached, key)
+    return pci_dev['vslot']
+
 def xm_pci_detach(args):
     arg_check(args, 'pci-detach', 2)
-    (dom, pci) = parse_pci_configuration(args, 'Closing')
-
-    if serverType == SERVER_XEN_API:
-
-        pci_dev = sxp.children(pci, 'dev')[0]
-        domain = int(sxp.child_value(pci_dev, 'domain'), 16)
-        bus = int(sxp.child_value(pci_dev, 'bus'), 16)
-        slot = int(sxp.child_value(pci_dev, 'slot'), 16)
-        func = int(sxp.child_value(pci_dev, 'func'), 16)
-        vslot = int(sxp.child_value(pci_dev, 'vslot'), 16)
-        name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
-
+
+    (dom, dev) = parse_pci_configuration(args)
+    attached = attached_pci_dict(dom)
+
+    attached_dev = map(lambda x: find_attached(attached, x), dev)
+
+    def f(pci_dev):
+        vdevfn = int(pci_dev['vslot'], 16)
+        return PCI_SLOT(vdevfn) | (vdevfn & AUTO_PHP_SLOT)
+    vslots = map(f, attached_dev)
+    if len(set(vslots)) > 1:
+        err_str = map(lambda x: "\t%s is in slot 0x%02x\n" %
+                                (pci_dict_to_bdf_str(x),
+                                 PCI_SLOT(int(x['vslot'], 16))), dev)
+        raise OptionError("More than one slot used by specified devices\n"
+                          + ''.join(err_str))
+
+    attached_to_slot = filter(lambda x:
+                              f(x) == vslots[0] and
+                              attached_dev[0]["key"] ==
+                                      x["key"], attached_dev)
+
+    if len(attached_to_slot) != len(dev):
+        err_str_ = map(lambda x: '\t%s\n' % pci_dict_to_bdf_str(x), dev)
+        err_str = "Requested:\n" + ''.join(err_str_)
+        err_str_ = map(lambda x: '\t%s (%s)\n' %
+                       (pci_dict_to_bdf_str(x), x['key']),
+                       attached_to_slot)
+        err_str += "Present:\n" + ''.join(err_str_)
+        raise OptionError(("Not all functions in slot 0x%02x have had "
+                           "detachment requested.\n" % vslots[0]) + err_str)
+
+    for i in dev:
+        xm_pci_detach_one(dom, i)
+
+def xm_pci_detach_one(dom, pci_dev):
+    if serverType == SERVER_XEN_API:
+        name = pci_dict_to_bdf_str(pci_dev)
         target_ref = None
         for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)):
             ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref)
@@ -2733,6 +2788,7 @@ def xm_pci_detach(args):
             raise OptionError("Device %s not assigned" % name)
 
     else:
+        pci = pci_convert_dict_to_sxp(pci_dev, 'Closing')
         server.xend.domain.device_configure(dom, pci)
 
 def xm_scsi_detach(args):

_______________________________________________
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: Parse command line for multi-function hot-plug and unplug, Xen patchbot-unstable <=