WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 3/5] pciback: xend support for user-space PCI quirks

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 3/5] pciback: xend support for user-space PCI quirks
From: Chris <hap10@xxxxxxxxxxxxxx>
Date: Mon, 17 Jul 2006 15:15:40 -0400
Delivery-date: Mon, 17 Jul 2006 12:17:53 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5.0.4 (X11/20060614)
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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 3/5] pciback: xend support for user-space PCI quirks, Chris <=