[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 3/5] pciback: xend support for user-space PCI quirks
The attached patch augments xend to parse the user-space PCI backend policy files (see next email) and send the corresponding fields to the PCI bus manager via sysfs nodes: /sys/bus/pci/drivers/pciback/quirks /sys/bus/pci/drivers/pciback/permissive xend reads the policy file every time it creates a new domain that was assigned a PCI device. NB: This patch assumes the per-device permissive flag patch has been applied. Signed-off-by: Chris Bookholt <hap10@xxxxxxxxxxxxxx> diff -r b20580cf7fc1 -r 94a0a82c91d1 tools/python/xen/util/pci.py --- a/tools/python/xen/util/pci.py Wed Jul 12 16:34:39 2006 +0100 +++ b/tools/python/xen/util/pci.py Thu Jul 13 13:38:57 2006 -0400 @@ -16,6 +16,10 @@ SYSFS_PCI_DEV_RESOURCE_PATH = '/resource SYSFS_PCI_DEV_RESOURCE_PATH = '/resource' SYSFS_PCI_DEV_IRQ_PATH = '/irq' SYSFS_PCI_DEV_DRIVER_DIR_PATH = '/driver' +SYSFS_PCI_DEV_VENDOR_PATH = '/vendor' +SYSFS_PCI_DEV_DEVICE_PATH = '/device' +SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor' +SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device' PCI_BAR_IO = 0x01 PCI_BAR_IO_MASK = ~0x03 @@ -66,9 +70,12 @@ class PciDevice: self.iomem = [] self.ioports = [] self.driver = None + self.vendor = None + self.device = None + self.subvendor = None + self.subdevice = None - if not self.get_info_from_sysfs(): - self.get_info_from_proc() + self.get_info_from_sysfs() def get_info_from_sysfs(self): try: @@ -85,7 +92,7 @@ class PciDevice: try: resource_file = open(path,'r') - for i in range(7): + for i in range(PROC_PCI_NUM_RESOURCES): line = resource_file.readline() sline = line.split() if len(sline)<3: @@ -122,53 +129,39 @@ class PciDevice: raise PciDeviceParseError(('Failed to read %s: %s (%d)' % (path, strerr, errno))) + path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ + self.name+SYSFS_PCI_DEV_VENDOR_PATH + try: + self.vendor = int(open(path,'r').readline(), 16) + except IOError, (errno, strerr): + raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % + (path, strerr, errno))) + + path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ + self.name+SYSFS_PCI_DEV_DEVICE_PATH + try: + self.device = int(open(path,'r').readline(), 16) + except IOError, (errno, strerr): + raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % + (path, strerr, errno))) + + path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ + self.name+SYSFS_PCI_DEV_SUBVENDOR_PATH + try: + self.subvendor = int(open(path,'r').readline(), 16) + except IOError, (errno, strerr): + raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % + (path, strerr, errno))) + + path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ + self.name+SYSFS_PCI_DEV_SUBDEVICE_PATH + try: + self.subdevice = int(open(path,'r').readline(), 16) + except IOError, (errno, strerr): + raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % + (path, strerr, errno))) + return True - - def get_info_from_proc(self): - bus_devfn = '%02x%02x' % (self.bus,PCI_DEVFN(self.slot,self.func)) - - # /proc/bus/pci/devices doesn't expose domains - if self.domain!=0: - raise PciDeviceParseError("Can't yet detect resource usage by "+ - "devices in other domains through proc!") - - try: - proc_pci_file = open(PROC_PCI_PATH,'r') - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open %s: %s (%d)' % - (PROC_PCI_PATH, strerr, errno))) - - for line in proc_pci_file: - sline = line.split() - if len(sline)<(PROC_PCI_NUM_RESOURCES*2+3): - continue - - if sline[0]==bus_devfn: - self.dissect_proc_pci_line(sline) - break - else: - raise PciDeviceNotFoundError(self.domain, self.bus, - self.slot, self.func) - - def dissect_proc_pci_line(self, sline): - self.irq = int(sline[2],16) - start_idx = 3 - for i in range(PROC_PCI_NUM_RESOURCES): - flags = int(sline[start_idx+i],16) - size = int(sline[start_idx+i+PROC_PCI_NUM_RESOURCES],16) - if flags&PCI_BAR_IO: - start = flags&PCI_BAR_IO_MASK - if start!=0: - self.ioports.append( (start,size) ) - else: - start = flags&PCI_BAR_MEM_MASK - if start!=0: - self.iomem.append( (start,size) ) - - # detect driver module name - driver_idx = PROC_PCI_NUM_RESOURCES*2+3 - if len(sline)>driver_idx: - self.driver = sline[driver_idx] def __str__(self): str = "PCI Device %s\n" % (self.name) @@ -176,7 +169,11 @@ class PciDevice: str = str + "IO Port 0x%02x [size=%d]\n"%(start,size) for (start,size) in self.iomem: str = str + "IO Mem 0x%02x [size=%d]\n"%(start,size) - str = str + "IRQ %d"%(self.irq) + str = str + "IRQ %d\n"%(self.irq) + str = str + "Vendor ID 0x%04x\n"%(self.vendor) + str = str + "Device ID 0x%04x\n"%(self.device) + str = str + "Sybsystem Vendor ID 0x%04x\n"%(self.subvendor) + str = str + "Subsystem Device ID 0x%04x"%(self.subdevice) return str def main(): diff -r b20580cf7fc1 -r 94a0a82c91d1 tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Wed Jul 12 16:34:39 2006 +0100 +++ b/tools/python/xen/xend/server/pciif.py Thu Jul 13 13:38:57 2006 -0400 @@ -32,6 +32,8 @@ from xen.util.pci import PciDevice from xen.util.pci import PciDevice import resource import re + +from xen.xend.server.pciquirk import * xc = xen.lowlevel.xc.xc() @@ -150,7 +152,10 @@ class PciController(DevController): "bind your slot/device to the PCI backend using sysfs" \ )%(dev.name)) - for (start, size) in dev.ioports: + PCIQuirk(dev.vendor, dev.device, dev.subvendor, dev.subdevice, domain, + bus, slot, func) + + for (start, size) in dev.ioports: log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size)) rc = xc.domain_ioport_permission(dom = fe_domid, first_port = start, nr_ports = size, allow_access = True) diff -r b20580cf7fc1 tools/python/xen/xend/server/pciquirk.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/server/pciquirk.py Thu Jul 13 15:13:53 2006 -0400 @@ -0,0 +1,126 @@ +from xen.xend.XendLogging import log +from xen.xend.XendError import XendError +import sys +import os.path +from xen.xend.sxp import * + +QUIRK_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/quirks" +QUIRK_CONFIG_FILE = "/etc/xen/xend-pci-quirks.sxp" +PERMISSIVE_CONFIG_FILE = "/etc/xen/xend-pci-permissive.sxp" +PERMISSIVE_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/permissive" + +class PCIQuirk: + def __init__( self, vendor, device, subvendor, subdevice, domain, bus, slot, func): + self.vendor = vendor + self.device = device + self.subvendor = subvendor + self.subdevice = subdevice + self.domain = domain + self.bus = bus + self.slot = slot + self.func = func + + self.devid = "%04x:%04x:%04x:%04x" % (vendor, device, subvendor, subdevice) + self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func) + + self.quirks = self.__getQuirksByID( ) + + self.__sendQuirks( ) + self.__sendPermDevs( ) + + def __getQuirksByID( self ): + if os.path.exists(QUIRK_CONFIG_FILE): + try: + fin = file(QUIRK_CONFIG_FILE, 'rb') + try: + pci_quirks_config = parse(fin) + finally: + fin.close() + if pci_quirks_config is None: + pci_quirks_config = ['xend-pci-quirks'] + else: + pci_quirks_config.insert(0, 'xend-pci-quirks') + self.pci_quirks_config = pci_quirks_config + except Exception, ex: + raise XendError("Reading config file %s: %s" % + (QUIRK_CONFIG_FILE, str(ex))) + else: + log.info("Config file does not exist: %s" % QUIRK_CONFIG_FILE) + self.pci_quirks_config = ['xend-pci-quirks'] + + devices = children(self.pci_quirks_config) + for dev in devices: + ids = child_at(child(dev,'pci_ids'),0) + fields = child_at(child(dev,'pci_config_space_fields'),0) + for id in ids: + if id.startswith( self.devid[:9] ): # id's vendor and device ID match + skey = id.split(':') + if ((skey[2] != 'FFFF') and + (skey[2] != 'ffff') and + (self.subvendor != skey[2])): + continue + if ((skey[3] != 'FFFF') and + (skey[3] != 'ffff') and + (self.subdevice != skey[3])): + continue + log.info("Quirky device detected: %s" % self.devid) + return fields + log.info("No quirks found for PCI device [%s]" % self.devid) + return [] + + def __sendQuirks(self): + for quirk in self.quirks: + log.debug("Quirk Info: %04x:%02x:%02x.%1x-%s" % (self.domain, + self.bus, self.slot, self.func, quirk)) + try: + f = file(QUIRK_SYSFS_NODE ,"w") + f.write( "%04x:%02x:%02x.%1x-%s" % (self.domain, self.bus, + self.slot, self.func, quirk) ) + f.close() + except Exception, e: + raise VmError("pci: failed to open/write/close quirks sysfs " + \ + "node - " + str(e)) + + def __devIsUnconstrained( self ): + ret = False + if os.path.exists(PERMISSIVE_CONFIG_FILE): + try: + fin = file(PERMISSIVE_CONFIG_FILE, 'rb') + try: + pci_perm_dev_config = parse(fin) + finally: + fin.close() + if pci_perm_dev_config is None: + pci_perm_dev_config = [''] + else: + pci_perm_dev_config.insert(0, '') + self.pci_perm_dev_config = pci_perm_dev_config + except Exception, ex: + raise XendError("Reading config file %s: %s" % + (PERMISSIVE_CONFIG_FILE,str(ex))) + else: + log.info("Config file does not exist: %s" % PERMISSIVE_CONFIG_FILE) + self.pci_perm_dev_config = ['xend-pci-perm-devs'] + + devices = child_at(child(pci_perm_dev_config, 'unconstrained_dev_ids'),0) + if devices != None: + for id in devices: + if (id != self.pciid): + continue + log.debug("Permissive device found: %s" % id) + ret = True + break + return ret + + def __sendPermDevs(self): + if self.__devIsUnconstrained( ): + log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % (self.domain, + self.bus, self.slot, self.func)) + try: + f = file(PERMISSIVE_SYSFS_NODE ,"w") + f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus, + self.slot, self.func) ) + f.close() + except Exception, e: + raise VmError("pci: failed to open/write/close permissive " + \ + "sysfs node: " + str(e)) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |