[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [rfc 7/9] 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> --- Wed, 20 May 2009 18:14:38 +1000 * Update for cset 19626:145e49b8574c Fri, 22 May 2009 14:49:21 +1000 * Update for for bdf6->bdf4 changes in previous patches * Remove bogus bdf6_to_bdf_string() hunk * Move bdf6_to_sxp_request() call out of parse_pci_configuration() - This saves subsequently reversing the conversion * Refactor bdf6_find_attached_devfn() to work on attached being a list of sprs - This saves a to bdf6 format * Rename bdf6_find_attached_devfn bdf4_find_attached_devfn * Move parse_pci_configuration() to main.py - It is only ever used in main.py Fri, 29 May 2009 09:18:15 +1000 * Remove "from xen.xend import sxp" hunk from tools/python/xen/util/pci.py. It is present in an earlier patch by Kanno-san. Index: xen-unstable.hg/tools/python/xen/xm/main.py =================================================================== --- xen-unstable.hg.orig/tools/python/xen/xm/main.py 2009-06-14 23:55:05.000000000 +1000 +++ xen-unstable.hg/tools/python/xen/xm/main.py 2009-06-14 23:55:09.000000000 +1000 @@ -2222,8 +2222,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: @@ -2501,7 +2502,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: @@ -2510,11 +2511,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 = [] @@ -2531,19 +2532,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) + (dom, dev) = parse_pci_configuration(params, 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) + 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): @@ -2555,13 +2568,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): @@ -2704,20 +2718,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: + (dom, dev) = parse_pci_configuration(args) + attached = attached_pci_dict(dom) - 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) + 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) @@ -2729,6 +2784,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): Index: xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-unstable.hg.orig/tools/python/xen/xend/XendDomainInfo.py 2009-06-14 23:55:05.000000000 +1000 +++ xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py 2009-06-14 23:55:09.000000000 +1000 @@ -42,7 +42,7 @@ from xen.util import xsconstants 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" -- _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |