pciif.py
来自「xen虚拟机源代码安装包」· Python 代码 · 共 567 行 · 第 1/2 页
PY
567 行
#============================================================================# This library is free software; you can redistribute it and/or# modify it under the terms of version 2.1 of the GNU Lesser General Public# License as published by the Free Software Foundation.## This library is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU# Lesser General Public License for more details.## You should have received a copy of the GNU Lesser General Public# License along with this library; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#============================================================================# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com># Copyright (C) 2005 XenSource Ltd#============================================================================import typesimport timefrom xen.xend import sxpfrom xen.xend import archfrom xen.xend.XendError import VmErrorfrom xen.xend.XendLogging import logfrom xen.xend.server.DevController import DevController, xenbusStateimport xen.lowlevel.xcfrom xen.util.pci import *import resourceimport refrom xen.xend.server.pciquirk import *xc = xen.lowlevel.xc.xc()#Calculate PAGE_SHIFT: number of bits to shift an address to get the page numberPAGE_SIZE = resource.getpagesize()PAGE_SHIFT = 0t = PAGE_SIZEwhile not (t&1): t>>=1 PAGE_SHIFT+=1def parse_hex(val): try: if isinstance(val, types.StringTypes): return int(val, 16) else: return val except ValueError: return Noneclass PciController(DevController): def __init__(self, vm): DevController.__init__(self, vm) def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" back = {} pcidevid = 0 vslots = "" 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)) vslt = pci_config.get('vslt') if vslt is not None: vslots = vslots + vslt + ";" back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%01x" % \ (domain, bus, slot, func) back['uuid-%i' % pcidevid] = pci_config.get('uuid', '') pcidevid += 1 if vslots != "": back['vslots'] = vslots back['num_devs']=str(pcidevid) back['uuid'] = config.get('uuid','') return (0, back, {}) def reconfigureDevice(self, _, config): """@see DevController.reconfigureDevice""" (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] uuid = back['uuid-%i' %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, 'uuid-%i' % (num_olddevs + i), uuid) 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.get('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) num_devs = self.readBackend(devid, 'num_devs') pci_devs = [] vslots = self.readBackend(devid, 'vslots') if vslots is not None: if vslots[-1] == ";": vslots = vslots[:-1] slot_list = vslots.split(';') for i in range(int(num_devs)): dev_config = self.readBackend(devid, 'dev-%d' % i) 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]{1,2})$", dev_config) if pci_match!=None: pci_dev_info = pci_match.groupdict() dev_dict = {'domain': '0x%(domain)s' % pci_dev_info, 'bus': '0x%(bus)s' % pci_dev_info, 'slot': '0x%(slot)s' % pci_dev_info, 'func': '0x%(func)s' % pci_dev_info} # Per device uuid info dev_dict['uuid'] = self.readBackend(devid, 'uuid-%d' % i) #append vslot info if vslots is not None: try: dev_dict['vslt'] = slot_list[i] except IndexError: dev_dict['vslt'] = '0x0' pci_devs.append(dev_dict) result['devs'] = pci_devs result['uuid'] = self.readBackend(devid, 'uuid') return result def configuration(self, devid, transaction = None): """Returns SXPR for devices on domain. @note: we treat this dict especially to convert to SXP because it is not a straight dict of strings.""" configDict = self.getDeviceConfiguration(devid, transaction) sxpr = [self.deviceClass] # remove devs devs = configDict.pop('devs', []) for dev in devs: dev_sxpr = ['dev'] for dev_item in dev.items(): dev_sxpr.append(list(dev_item)) sxpr.append(dev_sxpr) for key, val in configDict.items(): if type(val) == type(list()): for v in val: sxpr.append([key, v]) else: sxpr.append([key, val]) return sxpr def CheckSiblingDevices(self, domid, dev): """ Check if all sibling devices of dev are owned by pciback """ if not self.vm.info.is_hvm(): return group_str = xc.get_device_group(domid, dev.domain, dev.bus, dev.slot, dev.func) if group_str == "": return #group string format xx:xx.x,xx:xx.x, devstr_len = group_str.find(',') for i in range(0, len(group_str), devstr_len + 1): (bus, slotfunc) = group_str[i:i + devstr_len].split(':') (slot, func) = slotfunc.split('.') b = parse_hex(bus) d = parse_hex(slot) f = parse_hex(func) try: sdev = PciDevice(dev.domain, b, d, f) except Exception, e: #no dom0 drivers bound to sdev continue if sdev.driver!='pciback': raise VmError(("pci: PCI Backend does not own\n "+ \ "sibling device %s of device %s\n"+ \ "See the pciback.hide kernel "+ \ "command-line parameter or\n"+ \ "bind your slot/device to the PCI backend using sysfs" \ )%(sdev.name, dev.name)) return def setupOneDevice(self, domain, bus, slot, func): """ Attach I/O resources for device to 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"+ \
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?