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
|