[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>
This commit is contained in:
kfraser@localhost.localdomain committed 2006-07-28 12:57:55 +01:00
1 parent 4c975eb710
commit 2b9c0e336c
3 files changed
+193 -46

No files matched your search

+42 -45
View File
@@ -16,6 +16,10 @@ SYSFS_PCI_DEVS_PATH = '/bus/pci/devices'
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)))
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!")
path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \
self.name+SYSFS_PCI_DEV_VENDOR_PATH
try:
proc_pci_file = open(PROC_PCI_PATH,'r')
self.vendor = int(open(path,'r').readline(), 16)
except IOError, (errno, strerr):
raise PciDeviceParseError(('Failed to open %s: %s (%d)' %
(PROC_PCI_PATH, strerr, errno)))
raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' %
(path, strerr, errno)))
for line in proc_pci_file:
sline = line.split()
if len(sline)<(PROC_PCI_NUM_RESOURCES*2+3):
continue
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)))
if sline[0]==bus_devfn:
self.dissect_proc_pci_line(sline)
break
else:
raise PciDeviceNotFoundError(self.domain, self.bus,
self.slot, self.func)
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)))
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) )
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)))
# detect driver module name
driver_idx = PROC_PCI_NUM_RESOURCES*2+3
if len(sline)>driver_idx:
self.driver = sline[driver_idx]
return True
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():
+6 -1
View File
@@ -33,6 +33,8 @@ from xen.util.pci import PciDevice
import resource
import re
from xen.xend.server.pciquirk import *
xc = xen.lowlevel.xc.xc()
#Calculate PAGE_SHIFT: number of bits to shift an address to get the page number
@@ -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)
+145
View File
@@ -0,0 +1,145 @@
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 __matchPCIdev( self, list ):
ret = False
if list == None:
return False
for id in list:
if id.startswith( self.devid[:9] ): # id's vendor and device ID match
skey = id.split(':')
size = len(skey)
if (size == 2): # subvendor/subdevice not suplied
ret = True
break
elif (size == 4): # check subvendor/subdevice
# check subvendor
subven = '%04x' % self.subvendor
if ((skey[2] != 'FFFF') and
(skey[2] != 'ffff') and
(skey[2] != subven)):
continue
# check subdevice
subdev = '%04x' % self.subdevice
if ((skey[3] != 'FFFF') and
(skey[3] != 'ffff') and
(skey[3] != subdev)):
continue
ret = True
break
else:
log.debug("WARNING: invalid configuration entry: %s" % id)
ret = False
break
return ret
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)
if self.__matchPCIdev( ids ):
log.info("Quirks found for PCI device [%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 ):
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 self.__matchPCIdev( devices ):
log.debug("Permissive mode enabled for PCI device [%s]" % self.devid)
return True
log.debug("Permissive mode NOT enabled for PCI device [%s]" % self.devid)
return False
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))
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.