[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] xend: pass-through: Parse command line for multi-function hot-plug and unplug



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.