ia64/xen-unstable

view tools/python/xen/xend/server/pciquirk.py @ 10844:8cd577110904

[PCI] xend parses the user-space PCI backend policy files and sends
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.

Signed-off-by: Chris Bookholt <hap10@tycho.ncsc.mil>
author kfraser@localhost.localdomain
date Fri Jul 28 12:57:55 2006 +0100 (2006-07-28)
parents
children e58bf6e0572e
line source
1 from xen.xend.XendLogging import log
2 from xen.xend.XendError import XendError
3 import sys
4 import os.path
5 from xen.xend.sxp import *
7 QUIRK_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/quirks"
8 QUIRK_CONFIG_FILE = "/etc/xen/xend-pci-quirks.sxp"
9 PERMISSIVE_CONFIG_FILE = "/etc/xen/xend-pci-permissive.sxp"
10 PERMISSIVE_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/permissive"
12 class PCIQuirk:
13 def __init__( self, vendor, device, subvendor, subdevice, domain, bus, slot, func):
14 self.vendor = vendor
15 self.device = device
16 self.subvendor = subvendor
17 self.subdevice = subdevice
18 self.domain = domain
19 self.bus = bus
20 self.slot = slot
21 self.func = func
23 self.devid = "%04x:%04x:%04x:%04x" % (vendor, device, subvendor, subdevice)
24 self.pciid = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
26 self.quirks = self.__getQuirksByID( )
28 self.__sendQuirks( )
29 self.__sendPermDevs( )
31 def __matchPCIdev( self, list ):
32 ret = False
33 if list == None:
34 return False
35 for id in list:
36 if id.startswith( self.devid[:9] ): # id's vendor and device ID match
37 skey = id.split(':')
38 size = len(skey)
39 if (size == 2): # subvendor/subdevice not suplied
40 ret = True
41 break
42 elif (size == 4): # check subvendor/subdevice
43 # check subvendor
44 subven = '%04x' % self.subvendor
45 if ((skey[2] != 'FFFF') and
46 (skey[2] != 'ffff') and
47 (skey[2] != subven)):
48 continue
49 # check subdevice
50 subdev = '%04x' % self.subdevice
51 if ((skey[3] != 'FFFF') and
52 (skey[3] != 'ffff') and
53 (skey[3] != subdev)):
54 continue
55 ret = True
56 break
57 else:
58 log.debug("WARNING: invalid configuration entry: %s" % id)
59 ret = False
60 break
61 return ret
63 def __getQuirksByID( self ):
64 if os.path.exists(QUIRK_CONFIG_FILE):
65 try:
66 fin = file(QUIRK_CONFIG_FILE, 'rb')
67 try:
68 pci_quirks_config = parse(fin)
69 finally:
70 fin.close()
71 if pci_quirks_config is None:
72 pci_quirks_config = ['xend-pci-quirks']
73 else:
74 pci_quirks_config.insert(0, 'xend-pci-quirks')
75 self.pci_quirks_config = pci_quirks_config
76 except Exception, ex:
77 raise XendError("Reading config file %s: %s" %
78 (QUIRK_CONFIG_FILE, str(ex)))
79 else:
80 log.info("Config file does not exist: %s" % QUIRK_CONFIG_FILE)
81 self.pci_quirks_config = ['xend-pci-quirks']
83 devices = children(self.pci_quirks_config)
84 for dev in devices:
85 ids = child_at(child(dev,'pci_ids'),0)
86 fields = child_at(child(dev,'pci_config_space_fields'),0)
87 if self.__matchPCIdev( ids ):
88 log.info("Quirks found for PCI device [%s]" % self.devid)
89 return fields
91 log.info("NO quirks found for PCI device [%s]" % self.devid)
92 return []
94 def __sendQuirks(self):
95 for quirk in self.quirks:
96 log.debug("Quirk Info: %04x:%02x:%02x.%1x-%s" % (self.domain,
97 self.bus, self.slot, self.func, quirk))
98 try:
99 f = file(QUIRK_SYSFS_NODE ,"w")
100 f.write( "%04x:%02x:%02x.%1x-%s" % (self.domain, self.bus,
101 self.slot, self.func, quirk) )
102 f.close()
103 except Exception, e:
104 raise VmError("pci: failed to open/write/close quirks sysfs " + \
105 "node - " + str(e))
107 def __devIsUnconstrained( self ):
108 if os.path.exists(PERMISSIVE_CONFIG_FILE):
109 try:
110 fin = file(PERMISSIVE_CONFIG_FILE, 'rb')
111 try:
112 pci_perm_dev_config = parse(fin)
113 finally:
114 fin.close()
115 if pci_perm_dev_config is None:
116 pci_perm_dev_config = ['']
117 else:
118 pci_perm_dev_config.insert(0, '')
119 self.pci_perm_dev_config = pci_perm_dev_config
120 except Exception, ex:
121 raise XendError("Reading config file %s: %s" %
122 (PERMISSIVE_CONFIG_FILE,str(ex)))
123 else:
124 log.info("Config file does not exist: %s" % PERMISSIVE_CONFIG_FILE)
125 self.pci_perm_dev_config = ['xend-pci-perm-devs']
127 devices = child_at(child(pci_perm_dev_config, 'unconstrained_dev_ids'),0)
128 if self.__matchPCIdev( devices ):
129 log.debug("Permissive mode enabled for PCI device [%s]" % self.devid)
130 return True
131 log.debug("Permissive mode NOT enabled for PCI device [%s]" % self.devid)
132 return False
134 def __sendPermDevs(self):
135 if self.__devIsUnconstrained( ):
136 log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % (self.domain,
137 self.bus, self.slot, self.func))
138 try:
139 f = file(PERMISSIVE_SYSFS_NODE ,"w")
140 f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus,
141 self.slot, self.func) )
142 f.close()
143 except Exception, e:
144 raise VmError("pci: failed to open/write/close permissive " + \
145 "sysfs node: " + str(e))