[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] tools: Add PV passthrough PCI device hotplug support.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1205840361 0 # Node ID 3f407392da492ebaa30764406f69549bc11ae791 # Parent e678b42c36c45bc301d365d4d234216301fb11cc tools: Add PV passthrough PCI device hotplug support. Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@xxxxxxxxxxxxx> --- tools/python/xen/xend/XendConfig.py | 17 + tools/python/xen/xend/XendDomainInfo.py | 221 +++++++++++++++++-------- tools/python/xen/xend/server/DevController.py | 50 +++++ tools/python/xen/xend/server/pciif.py | 229 ++++++++++++++++++++++---- tools/python/xen/xm/main.py | 53 +++--- 5 files changed, 452 insertions(+), 118 deletions(-) diff -r e678b42c36c4 -r 3f407392da49 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Tue Mar 18 11:34:44 2008 +0000 +++ b/tools/python/xen/xend/XendConfig.py Tue Mar 18 11:39:21 2008 +0000 @@ -1461,6 +1461,23 @@ class XendConfig(dict): config = cfg_sxp dev_type, dev_info = self['devices'][dev_uuid] + + if dev_type == 'pci': # Special case for pci + pci_devs = [] + for pci_dev in sxp.children(config, 'dev'): + pci_dev_info = {} + for opt_val in pci_dev[1:]: + try: + opt, val = opt_val + pci_dev_info[opt] = val + except TypeError: + pass + pci_devs.append(pci_dev_info) + self['devices'][dev_uuid] = (dev_type, + {'devs': pci_devs, + 'uuid': dev_uuid}) + return True + for opt_val in config[1:]: try: opt, val = opt_val diff -r e678b42c36c4 -r 3f407392da49 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Mar 18 11:34:44 2008 +0000 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Mar 18 11:39:21 2008 +0000 @@ -558,18 +558,17 @@ class XendDomainInfo: count += 1 - def pci_device_create(self, dev_config): - log.debug("XendDomainInfo.pci_device_create: %s" % scrub_password(dev_config)) + def hvm_pci_device_create(self, dev_config): + log.debug("XendDomainInfo.hvm_pci_device_create: %s" + % scrub_password(dev_config)) if not self.info.is_hvm(): - raise VmError("only HVM guest support pci attach") + raise VmError("hvm_pci_device_create called on non-HVM guest") #all the PCI devs share one conf node devid = '0' - dev_type = sxp.name(dev_config) - new_devs = sxp.child_value(dev_config, 'devs') - new_dev = new_devs[0] + new_dev = dev_config['devs'][0] dev_info = self._getDeviceInfo_pci(devid)#from self.info['devices'] #check conflict before trigger hotplug event @@ -611,35 +610,6 @@ class XendDomainInfo: new_dev['vslt']) self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str) - # update the virtual pci slot - vslt = xstransact.Read("/local/domain/0/device-model/%i/parameter" - % self.getDomid()) - new_dev['vslt'] = vslt - - if dev_info is None: - # create a new one from scrach - dev_cfg_sxp = [dev_type, - ['dev', - ['domain', new_dev['domain']], - ['bus', new_dev['bus']], - ['slot', new_dev['slot']], - ['func', new_dev['func']], - ['vslt', new_dev['vslt']] - ]] - dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_cfg_sxp) - dev_config_dict = self.info['devices'][dev_uuid][1] - try: - dev_config_dict['devid'] = devid = \ - self._createDevice(dev_type, dev_config_dict) - self._waitForDevice(dev_type, devid) - except VmError, ex: - raise ex - else: - # update the pci config to add the new dev - pci_devs.extend(new_devs) - self._reconfigureDevice('pci', devid, pci_conf) - - return self.getDeviceController('pci').sxpr(devid) def device_create(self, dev_config): """Create a new device. @@ -649,11 +619,6 @@ class XendDomainInfo: """ log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config)) dev_type = sxp.name(dev_config) - - if dev_type == 'pci': - rc = self.pci_device_create(dev_config) - return rc - dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config) dev_config_dict = self.info['devices'][dev_uuid][1] log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict)) @@ -676,6 +641,151 @@ class XendDomainInfo: xen.xend.XendDomain.instance().managed_config_save(self) return self.getDeviceController(dev_type).sxpr(devid) + def pci_convert_sxp_to_dict(self, dev_sxp): + """Convert pci device sxp to dict + @param dev_sxp: device configuration + @type dev_sxp: SXP object (parsed config) + @return: dev_config + @rtype: dictionary + """ + # In reconfigure phase, config of PCI device looks like below: + # + # sxp: + # [device, [pci, [dev, [domain, '0x0'], [bus, '0x0'], [slot, '0x0'], + # [func, '0x0'], [vslt, '0x0']], + # [state, 'Initialising']]] + # + # dict: + # {devs: [{domain: '0x0', bus: '0x0', slot: '0x0', func: '0x0', + # vslt: '0x0'}], + # states: ['Initialising']} + # + # state 'Initialising' means the device is being attached. + # state 'Closing' means the device is being detached. + + dev_config = {} + pci_devs = [] + for pci_dev in sxp.children(dev_sxp, 'dev'): + pci_dev_info = {} + for opt_val in pci_dev[1:]: + try: + opt, val = opt_val + pci_dev_info[opt] = val + except TypeError: + pass + pci_devs.append(pci_dev_info) + dev_config['devs'] = pci_devs + pci_states = [] + for pci_state in sxp.children(dev_sxp, 'state'): + try: + pci_states.append(pci_state[1]) + except IndexError: + raise XendError("Error reading state while parsing pci sxp") + dev_config['states'] = pci_states + + return dev_config + + def pci_device_configure(self, dev_sxp, devid = 0): + """Configure an existing pci device. + + @param dev_sxp: device configuration + @type dev_sxp: SXP object (parsed config) + @param devid: device id + @type devid: int + @return: Returns True if successfully updated device + @rtype: boolean + """ + log.debug("XendDomainInfo.pci_device_configure: %s" + % scrub_password(dev_sxp)) + + dev_class = sxp.name(dev_sxp) + + if dev_class != 'pci': + return False + + pci_state = sxp.child_value(dev_sxp, 'state') + existing_dev_info = self._getDeviceInfo_pci(devid) + + if existing_dev_info is None and pci_state != 'Initialising': + raise XendError("Cannot detach when pci platform does not exist") + + pci_dev = sxp.children(dev_sxp, 'dev')[0] + dev_config = self.pci_convert_sxp_to_dict(dev_sxp) + dev = dev_config['devs'][0] + + # Do HVM specific processing + if self.info.is_hvm(): + if pci_state == 'Initialising': + # HVM PCI device attachment + self.hvm_pci_device_create(dev_config) + # Update vslt + vslt = xstransact.Read("/local/domain/0/device-model/%i/parameter" + % self.getDomid()) + dev['vslt'] = vslt + for n in sxp.children(pci_dev): + if(n[0] == 'vslt'): + n[1] = vslt + else: + # HVM PCI device detachment + existing_dev_uuid = sxp.child_value(existing_dev_info, 'uuid') + existing_pci_conf = self.info['devices'][existing_dev_uuid][1] + existing_pci_devs = existing_pci_conf['devs'] + vslt = '0x0' + for x in existing_pci_devs: + if ( int(x['domain'], 16) == int(dev['domain'], 16) and + int(x['bus'], 16) == int(dev['bus'], 16) and + int(x['slot'], 16) == int(dev['slot'], 16) and + int(x['func'], 16) == int(dev['func'], 16) ): + vslt = x['vslt'] + break + if vslt == '0x0': + raise VmError("Device %04x:%02x:%02x.%02x is not connected" + % (int(dev['domain'],16), int(dev['bus'],16), + int(dev['slot'],16), int(dev['func'],16))) + self.hvm_destroyPCIDevice(int(vslt, 16)) + # Update vslt + dev['vslt'] = vslt + for n in sxp.children(pci_dev): + if(n[0] == 'vslt'): + n[1] = vslt + + # If pci platform does not exist, create and exit. + if existing_dev_info is None: + self.device_create(dev_sxp) + return True + + # use DevController.reconfigureDevice to change device config + dev_control = self.getDeviceController(dev_class) + dev_uuid = dev_control.reconfigureDevice(devid, dev_config) + if not self.info.is_hvm(): + # in PV case, wait until backend state becomes connected. + dev_control.waitForDevice_reconfigure(devid) + num_devs = dev_control.cleanupDevice(devid) + + # update XendConfig with new device info + if dev_uuid: + new_dev_sxp = dev_control.configuration(devid) + self.info.device_update(dev_uuid, new_dev_sxp) + + # If there is no device left, destroy pci and remove config. + if num_devs == 0: + if self.info.is_hvm(): + self.destroyDevice('pci', devid, True) + del self.info['devices'][dev_uuid] + platform = self.info['platform'] + orig_dev_num = len(platform['pci']) + # TODO: can use this to keep some info to ask high level + # management tools to hot insert a new passthrough dev + # after migration + if orig_dev_num != 0: + #platform['pci'] = ["%dDEVs" % orig_dev_num] + platform['pci'] = [] + else: + self.destroyDevice('pci', devid) + del self.info['devices'][dev_uuid] + + return True + def device_configure(self, dev_sxp, devid = None): """Configure an existing device. @@ -690,6 +800,10 @@ class XendDomainInfo: # convert device sxp to a dict dev_class = sxp.name(dev_sxp) dev_config = {} + + if dev_class == 'pci': + return self.pci_device_configure(dev_sxp) + for opt_val in dev_sxp[1:]: try: dev_config[opt_val[0]] = opt_val[1] @@ -714,11 +828,11 @@ class XendDomainInfo: for devclass in XendDevices.valid_devices(): self.getDeviceController(devclass).waitForDevices() - def destroyPCIDevice(self, vslot): - log.debug("destroyPCIDevice called %s", vslot) + def hvm_destroyPCIDevice(self, vslot): + log.debug("hvm_destroyPCIDevice called %s", vslot) if not self.info.is_hvm(): - raise VmError("only HVM guest support pci detach") + raise VmError("hvm_destroyPCIDevice called on non-HVM guest") #all the PCI devs share one conf node devid = '0' @@ -744,34 +858,15 @@ class XendDomainInfo: raise VmError("Device @ vslot 0x%x do not support hotplug." % (vslot)) bdf_str = "%s:%s:%s.%s" % (x['domain'], x['bus'], x['slot'], x['func']) - log.info("destroyPCIDevice:%s:%s!", x, bdf_str) + log.info("hvm_destroyPCIDevice:%s:%s!", x, bdf_str) self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str) - - if pci_len > 1: - del pci_conf['devs'][devnum] - self._reconfigureDevice('pci', devid, pci_conf) - else: - self.getDeviceController('pci').destroyDevice(devid, True) - del self.info['devices'][dev_uuid] - platform = self.info['platform'] - orig_dev_num = len(platform['pci']) - - #need remove the pci config - #TODO:can use this to keep some info to ask high level management tools to hot insert a new passthrough dev after migration - if orig_dev_num != 0: -# platform['pci'] = ["%dDEVs" % orig_dev_num] - platform['pci'] = [] return 0 def destroyDevice(self, deviceClass, devid, force = False, rm_cfg = False): log.debug("XendDomainInfo.destroyDevice: deviceClass = %s, device = %s", deviceClass, devid) - - if deviceClass == 'dpci': - rc = self.destroyPCIDevice(devid) - return rc if rm_cfg: # Convert devid to device number. A device number is diff -r e678b42c36c4 -r 3f407392da49 tools/python/xen/xend/server/DevController.py --- a/tools/python/xen/xend/server/DevController.py Tue Mar 18 11:34:44 2008 +0000 +++ b/tools/python/xen/xend/server/DevController.py Tue Mar 18 11:39:21 2008 +0000 @@ -51,6 +51,8 @@ xenbusState = { 'Connected' : 4, 'Closing' : 5, 'Closed' : 6, + 'Reconfiguring': 7, + 'Reconfigured' : 8, } xoptions = XendOptions.instance() @@ -88,6 +90,8 @@ class DevController: (devid, back, front) = self.getDeviceDetails(config) if devid is None: return 0 + + self.setupDevice(config) (backpath, frontpath) = self.addStoreEntries(config, devid, back, front) @@ -198,6 +202,15 @@ class DevController: if status == Timeout: raise VmError("Device %s (%s) could not be disconnected. " % + (devid, self.deviceClass)) + + def waitForDevice_reconfigure(self, devid): + log.debug("Waiting for %s - reconfigureDevice.", devid) + + (status, err) = self.waitForBackend_reconfigure(devid) + + if status == Timeout: + raise VmError("Device %s (%s) could not be reconfigured. " % (devid, self.deviceClass)) @@ -325,6 +338,11 @@ class DevController: """ raise NotImplementedError() + + def setupDevice(self, config): + """ Setup device from config. + """ + return def migrate(self, deviceConfig, network, dst, step, domName): """ Migration of a device. The 'network' parameter indicates @@ -569,6 +587,22 @@ class DevController: return result['status'] + def waitForBackend_reconfigure(self, devid): + frontpath = self.frontendPath(devid) + backpath = xstransact.Read(frontpath, "backend") + if backpath: + statusPath = backpath + '/' + "state" + ev = Event() + result = { 'status': Timeout } + + xswatch(statusPath, xenbusStatusCallback, ev, result) + + ev.wait(DEVICE_CREATE_TIMEOUT) + + return (result['status'], None) + else: + return (Missing, None) + def backendPath(self, backdom, devid): """Construct backend path given the backend domain and device id. @@ -634,3 +668,19 @@ def deviceDestroyCallback(statusPath, ev ev.set() return 0 + + +def xenbusStatusCallback(statusPath, ev, result): + log.debug("xenbusStatusCallback %s.", statusPath) + + status = xstransact.Read(statusPath) + + if status == str(xenbusState['Connected']): + result['status'] = Connected + else: + return 1 + + log.debug("xenbusStatusCallback %d.", result['status']) + + ev.set() + return 0 diff -r e678b42c36c4 -r 3f407392da49 tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Tue Mar 18 11:34:44 2008 +0000 +++ b/tools/python/xen/xend/server/pciif.py Tue Mar 18 11:39:21 2008 +0000 @@ -24,7 +24,7 @@ from xen.xend.XendError import VmError from xen.xend.XendError import VmError from xen.xend.XendLogging import log -from xen.xend.server.DevController import DevController +from xen.xend.server.DevController import DevController, xenbusState import xen.lowlevel.xc @@ -44,6 +44,15 @@ while not (t&1): t>>=1 PAGE_SHIFT+=1 +def parse_hex(val): + try: + if isinstance(val, types.StringTypes): + return int(val, 16) + else: + return val + except ValueError: + return None + class PciController(DevController): def __init__(self, vm): @@ -52,15 +61,6 @@ class PciController(DevController): def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" - def parse_hex(val): - try: - if isinstance(val, types.StringTypes): - return int(val, 16) - else: - return val - except ValueError: - return None - back = {} pcidevid = 0 vslots = "" @@ -74,7 +74,6 @@ class PciController(DevController): if vslt is not None: vslots = vslots + vslt + ";" - self.setupDevice(domain, bus, slot, func) back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%02x" % \ (domain, bus, slot, func) pcidevid += 1 @@ -86,27 +85,80 @@ class PciController(DevController): back['uuid'] = config.get('uuid','') return (0, back, {}) + def reconfigureDevice(self, _, config): """@see DevController.reconfigureDevice""" - #currently only support config changes by hot insert/remove pass-through dev - #delete all the devices in xenstore - (devid, new_back, new_front) = self.getDeviceDetails(config) - num_devs = self.readBackend(devid, 'num_devs') - for i in range(int(num_devs)): - self.removeBackend(devid, 'dev-%d' % i) - self.removeBackend(devid, 'num_devs') - - #create new devices config - num_devs = new_back['num_devs'] - for i in range(int(num_devs)): - dev_no = 'dev-%d' % i - self.writeBackend(devid, dev_no, new_back[dev_no]) - self.writeBackend(devid, 'num_devs', num_devs) - - if new_back['vslots'] is not None: - self.writeBackend(devid, 'vslots', new_back['vslots']) - - return new_back.get('uuid') + (devid, back, front) = self.getDeviceDetails(config) + num_devs = int(back['num_devs']) + states = config.get('states', []) + + old_vslots = self.readBackend(devid, 'vslots') + if old_vslots is None: + old_vslots = '' + num_olddevs = int(self.readBackend(devid, 'num_devs')) + + for i in range(num_devs): + try: + dev = back['dev-%i' % i] + state = states[i] + except: + raise XendError('Error reading config') + + if state == 'Initialising': + # PCI device attachment + for j in range(num_olddevs): + if dev == self.readBackend(devid, 'dev-%i' % j): + raise XendError('Device %s is already connected.' % dev) + log.debug('Attaching PCI device %s.' % dev) + (domain, bus, slotfunc) = dev.split(':') + (slot, func) = slotfunc.split('.') + domain = parse_hex(domain) + bus = parse_hex(bus) + slot = parse_hex(slot) + func = parse_hex(func) + self.setupOneDevice(domain, bus, slot, func) + + self.writeBackend(devid, 'dev-%i' % (num_olddevs + i), dev) + self.writeBackend(devid, 'state-%i' % (num_olddevs + i), + str(xenbusState['Initialising'])) + self.writeBackend(devid, 'num_devs', str(num_olddevs + i + 1)) + + # Update vslots + if back['vslots'] is not None: + vslots = old_vslots + back['vslots'] + self.writeBackend(devid, 'vslots', vslots) + + elif state == 'Closing': + # PCI device detachment + found = False + for j in range(num_olddevs): + if dev == self.readBackend(devid, 'dev-%i' % j): + found = True + log.debug('Detaching device %s' % dev) + self.writeBackend(devid, 'state-%i' % j, + str(xenbusState['Closing'])) + if not found: + raise XendError('Device %s is not connected' % dev) + + # Update vslots + if back['vslots'] is not None: + vslots = old_vslots + for vslt in back['vslots'].split(';'): + if vslt != '': + vslots = vslots.replace(vslt + ';', '', 1) + if vslots == '': + self.removeBackend(devid, 'vslots') + else: + self.writeBackend(devid, 'vslots', vslots) + + else: + raise XendError('Error configuring device %s: invalid state %s' + % (dev,state)) + + self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring'])) + + return self.readBackend(devid, 'uuid') + def getDeviceConfiguration(self, devid, transaction = None): result = DevController.getDeviceConfiguration(self, devid, transaction) @@ -136,7 +188,10 @@ class PciController(DevController): #append vslot info if vslots is not None: - dev_dict['vslt'] = slot_list[i] + try: + dev_dict['vslt'] = slot_list[i] + except IndexError: + dev_dict['vslt'] = '0x0' pci_devs.append(dev_dict) @@ -171,7 +226,7 @@ class PciController(DevController): return sxpr - def setupDevice(self, domain, bus, slot, func): + def setupOneDevice(self, domain, bus, slot, func): """ Attach I/O resources for device to frontend domain """ fe_domid = self.getDomid() @@ -225,6 +280,116 @@ class PciController(DevController): raise VmError(('pci: failed to configure irq on device '+ '%s - errno=%d')%(dev.name,rc)) + def setupDevice(self, config): + """Setup devices from config + """ + for pci_config in config.get('devs', []): + domain = parse_hex(pci_config.get('domain', 0)) + bus = parse_hex(pci_config.get('bus', 0)) + slot = parse_hex(pci_config.get('slot', 0)) + func = parse_hex(pci_config.get('func', 0)) + self.setupOneDevice(domain, bus, slot, func) + + return + + def cleanupOneDevice(self, domain, bus, slot, func): + """ Detach I/O resources for device from frontend domain + """ + fe_domid = self.getDomid() + + try: + dev = PciDevice(domain, bus, slot, func) + except Exception, e: + raise VmError("pci: failed to locate device and "+ + "parse it's resources - "+str(e)) + + if dev.driver!='pciback': + raise VmError(("pci: PCI Backend does not own device "+ \ + "%s\n"+ \ + "See the pciback.hide kernel "+ \ + "command-line parameter or\n"+ \ + "bind your slot/device to the PCI backend using sysfs" \ + )%(dev.name)) + + for (start, size) in dev.ioports: + log.debug('pci: disabling ioport 0x%x/0x%x'%(start,size)) + rc = xc.domain_ioport_permission(domid = fe_domid, first_port = start, + nr_ports = size, allow_access = False) + if rc<0: + raise VmError(('pci: failed to configure I/O ports on device '+ + '%s - errno=%d')%(dev.name,rc)) + + for (start, size) in dev.iomem: + # Convert start/size from bytes to page frame sizes + start_pfn = start>>PAGE_SHIFT + # Round number of pages up to nearest page boundary (if not on one) + nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT + + log.debug('pci: disabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \ + (start,size,start_pfn,nr_pfns)) + rc = xc.domain_iomem_permission(domid = fe_domid, + first_pfn = start_pfn, + nr_pfns = nr_pfns, + allow_access = False) + if rc<0: + raise VmError(('pci: failed to configure I/O memory on device '+ + '%s - errno=%d')%(dev.name,rc)) + + if dev.irq>0: + log.debug('pci: disabling irq %d'%dev.irq) + rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq, + allow_access = False) + if rc<0: + raise VmError(('pci: failed to configure irq on device '+ + '%s - errno=%d')%(dev.name,rc)) + + def cleanupDevice(self, devid): + """ Detach I/O resources for device and cleanup xenstore nodes + after reconfigure. + + @param devid: The device ID + @type devid: int + @return: Return the number of devices connected + @rtype: int + """ + num_devs = int(self.readBackend(devid, 'num_devs')) + new_num_devs = 0 + for i in range(num_devs): + state = int(self.readBackend(devid, 'state-%i' % i)) + if state == xenbusState['Closing']: + # Detach I/O resources. + dev = self.readBackend(devid, 'dev-%i' % i) + (domain, bus, slotfunc) = dev.split(':') + (slot, func) = slotfunc.split('.') + domain = parse_hex(domain) + bus = parse_hex(bus) + slot = parse_hex(slot) + func = parse_hex(func) + # In HVM case, I/O resources are disabled in ioemu. + self.cleanupOneDevice(domain, bus, slot, func) + # Remove xenstore nodes. + self.removeBackend(devid, 'dev-%i' % i) + self.removeBackend(devid, 'vdev-%i' % i) + self.removeBackend(devid, 'state-%i' % i) + else: + if new_num_devs != i: + tmpdev = self.readBackend(devid, 'dev-%i' % i) + self.writeBackend(devid, 'dev-%i' % new_num_devs, tmpdev) + self.removeBackend(devid, 'dev-%i' % i) + tmpvdev = self.readBackend(devid, 'vdev-%i' % i) + if tmpvdev is not None: + self.writeBackend(devid, 'vdev-%i' % new_num_devs, + tmpvdev) + self.removeBackend(devid, 'vdev-%i' % i) + tmpstate = self.readBackend(devid, 'state-%i' % i) + self.writeBackend(devid, 'state-%i' % new_num_devs, tmpstate) + self.removeBackend(devid, 'state-%i' % i) + new_num_devs = new_num_devs + 1 + + self.writeBackend(devid, 'num_devs', str(new_num_devs)) + + return new_num_devs + def waitForBackend(self,devid): return (0, "ok - no hotplug") diff -r e678b42c36c4 -r 3f407392da49 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Tue Mar 18 11:34:44 2008 +0000 +++ b/tools/python/xen/xm/main.py Tue Mar 18 11:39:21 2008 +0000 @@ -175,11 +175,11 @@ SUBCOMMAND_HELP = { 'vnet-delete' : ('<VnetId>', 'Delete a Vnet.'), 'vnet-list' : ('[-l|--long]', 'List Vnets.'), 'vtpm-list' : ('<Domain> [--long]', 'List virtual TPM devices.'), - 'pci-attach ' : ('<Domain> <dom> <bus> <slot> <func> [virtual slot]', + 'pci-attach' : ('<Domain> <domain:bus:slot.func> [virtual slot]', 'Insert a new pass-through pci device.'), - 'pci-detach ' : ('<Domain> <virtual slot>', + 'pci-detach' : ('<Domain> <domain:bus:slot.func>', 'Remove a domain\'s pass-through pci device.'), - 'pci-list' : ('<Domain>', + 'pci-list' : ('<Domain>', 'List pass-through pci devices for a domain.'), # security @@ -2232,29 +2232,37 @@ def xm_network_attach(args): vif.append(vif_param) server.xend.domain.device_create(dom, vif) -def parse_pci_configuration(args): +def parse_pci_configuration(args, state): dom = args[0] - - if len(args) == 6: - vslt = args[5] + pci_dev_str = args[1] + if len(args) == 3: + vslt = args[2] else: vslt = '0x0' #chose a free virtual PCI slot - - pci = ['pci', - ['devs', - [{'domain': "0x%x" % int(args[1], 16), - 'bus': "0x%x" % int(args[2], 16), - 'slot': "0x%x" % int(args[3], 16), - 'func': "0x%x" % int(args[4], 16), - 'vslt': "0x%x" % int(vslt, 16)}] - ]] + pci=['pci'] + 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])$", pci_dev_str) + if pci_match == None: + raise OptionError("Invalid argument: %s %s" % (pci_dev_str,vslt)) + pci_dev_info = pci_match.groupdict('0') + try: + pci.append(['dev', ['domain', '0x'+ pci_dev_info['domain']], \ + ['bus', '0x'+ pci_dev_info['bus']], + ['slot', '0x'+ pci_dev_info['slot']], + ['func', '0x'+ pci_dev_info['func']], + ['vslt', '0x%x' % int(vslt, 16)]]) + except: + raise OptionError("Invalid argument: %s %s" % (pci_dev_str,vslt)) + pci.append(['state', state]) return (dom, pci) def xm_pci_attach(args): - arg_check(args, 'pci-attach', 5, 6) - (dom, pci) = parse_pci_configuration(args) - server.xend.domain.device_create(dom, pci) + arg_check(args, 'pci-attach', 2, 3) + (dom, pci) = parse_pci_configuration(args, 'Initialising') + server.xend.domain.device_configure(dom, pci) def detach(args, deviceClass): rm_cfg = True @@ -2319,12 +2327,11 @@ def xm_network_detach(args): arg_check(args, 'network-detach', 2, 3) detach(args, 'vif') - def xm_pci_detach(args): arg_check(args, 'pci-detach', 2) - dom = args[0] - dev = args[1] - server.xend.domain.destroyDevice(dom, 'dpci', dev) + (dom, pci) = parse_pci_configuration(args, 'Closing') + server.xend.domain.device_configure(dom, pci) + def xm_vnet_list(args): xenapi_unsupported() _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |