ia64/xen-unstable

view tools/python/xen/xend/server/pciif.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 4b4d16fe0b05
children 0ae1d493f37c
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005 XenSource Ltd
17 #============================================================================
20 import types
22 from xen.xend import sxp
23 from xen.xend.XendError import VmError
24 from xen.xend.XendLogging import log
26 from xen.xend.xenstore.xstransact import xstransact
28 from xen.xend.server.DevController import DevController
30 import xen.lowlevel.xc
32 from xen.util.pci import PciDevice
33 import resource
34 import re
36 from xen.xend.server.pciquirk import *
38 xc = xen.lowlevel.xc.xc()
40 #Calculate PAGE_SHIFT: number of bits to shift an address to get the page number
41 PAGE_SIZE = resource.getpagesize()
42 PAGE_SHIFT = 0
43 t = PAGE_SIZE
44 while not (t&1):
45 t>>=1
46 PAGE_SHIFT+=1
48 class PciController(DevController):
50 def __init__(self, vm):
51 DevController.__init__(self, vm)
54 def getDeviceDetails(self, config):
55 """@see DevController.getDeviceDetails"""
56 #log.debug('pci config='+sxp.to_string(config))
58 def get_param(config, field, default=None):
59 try:
60 val = sxp.child_value(config, field)
62 if not val:
63 if default==None:
64 raise VmError('pci: Missing %s config setting' % field)
65 else:
66 return default
68 if isinstance(val, types.StringType):
69 return int(val, 16)
70 else:
71 return val
72 except:
73 if default==None:
74 raise VmError('pci: Invalid config setting %s: %s' %
75 (field, val))
76 else:
77 return default
79 back = {}
81 val = sxp.child_value(config, 'dev')
82 if isinstance(val, list):
83 pcidevid = 0
84 for dev_config in sxp.children(config, 'dev'):
85 domain = get_param(dev_config, 'domain', 0)
86 bus = get_param(dev_config,'bus')
87 slot = get_param(dev_config,'slot')
88 func = get_param(dev_config,'func')
90 self.setupDevice(domain, bus, slot, func)
92 back['dev-%i'%(pcidevid)]="%04x:%02x:%02x.%02x"% \
93 (domain, bus, slot, func)
94 pcidevid+=1
96 back['num_devs']=str(pcidevid)
98 else:
99 # Xen 2.0 configuration compatibility
100 domain = get_param(config, 'domain', 0)
101 bus = get_param(config, 'bus')
102 slot = get_param(config, 'dev')
103 func = get_param(config, 'func')
105 self.setupDevice(domain, bus, slot, func)
107 back['dev-0']="%04x:%02x:%02x.%02x"%(domain, bus, slot, func)
108 back['num_devs']=str(1)
110 return (0, back, {})
112 def configuration(self, devid):
113 """@see DevController.configuration"""
115 result = DevController.configuration(self, devid)
117 (num_devs) = self.readBackend(devid, 'num_devs')
119 for i in range(int(num_devs)):
120 (dev_config) = self.readBackend(devid, 'dev-%d'%(i))
122 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
123 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
124 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
125 r"(?P<func>[0-9a-fA-F]{1,2})", dev_config)
126 if pci_match!=None:
127 pci_dev_info = pci_match.groupdict('0')
128 result.append( ['dev', \
129 ['domain', '0x'+pci_dev_info['domain']], \
130 ['bus', '0x'+pci_dev_info['bus']], \
131 ['slot', '0x'+pci_dev_info['slot']], \
132 ['func', '0x'+pci_dev_info['func']]])
134 return result
136 def setupDevice(self, domain, bus, slot, func):
137 """ Attach I/O resources for device to frontend domain
138 """
139 fe_domid = self.getDomid()
141 try:
142 dev = PciDevice(domain, bus, slot, func)
143 except Exception, e:
144 raise VmError("pci: failed to locate device and "+
145 "parse it's resources - "+str(e))
147 if dev.driver!='pciback':
148 raise VmError(("pci: PCI Backend does not own device "+ \
149 "%s\n"+ \
150 "See the pciback.hide kernel "+ \
151 "command-line parameter or\n"+ \
152 "bind your slot/device to the PCI backend using sysfs" \
153 )%(dev.name))
155 PCIQuirk(dev.vendor, dev.device, dev.subvendor, dev.subdevice, domain,
156 bus, slot, func)
158 for (start, size) in dev.ioports:
159 log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
160 rc = xc.domain_ioport_permission(dom = fe_domid, first_port = start,
161 nr_ports = size, allow_access = True)
162 if rc<0:
163 raise VmError(('pci: failed to configure I/O ports on device '+
164 '%s - errno=%d')%(dev.name,rc))
166 for (start, size) in dev.iomem:
167 # Convert start/size from bytes to page frame sizes
168 start_pfn = start>>PAGE_SHIFT
169 # Round number of pages up to nearest page boundary (if not on one)
170 nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT
172 log.debug('pci: enabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \
173 (start,size,start_pfn,nr_pfns))
174 rc = xc.domain_iomem_permission(dom = fe_domid,
175 first_pfn = start_pfn,
176 nr_pfns = nr_pfns,
177 allow_access = True)
178 if rc<0:
179 raise VmError(('pci: failed to configure I/O memory on device '+
180 '%s - errno=%d')%(dev.name,rc))
182 if dev.irq>0:
183 log.debug('pci: enabling irq %d'%dev.irq)
184 rc = xc.domain_irq_permission(dom = fe_domid, pirq = dev.irq,
185 allow_access = True)
186 if rc<0:
187 raise VmError(('pci: failed to configure irq on device '+
188 '%s - errno=%d')%(dev.name,rc))
190 def waitForBackend(self,devid):
191 return (0, "ok - no hotplug")