debuggers.hg

view tools/python/xen/xend/server/pciif.py @ 16702:9fe92a88912b

Fix xend xenstore handling.

xend can get into a situation where two processes are attempting to
interact with the xenstore socket, with disastrous results. Fix the
two bad users of xstransact, add a big warning, and fix the destructor
so future mistakes will be detected earlier.

Signed-off-by: John Levon <john.levon@sun.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Dec 27 12:27:34 2007 +0000 (2007-12-27)
parents ca461349620a
children c6eeb71a85cf
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.server.DevController import DevController
28 import xen.lowlevel.xc
30 from xen.util.pci import PciDevice
31 import resource
32 import re
34 from xen.xend.server.pciquirk import *
36 xc = xen.lowlevel.xc.xc()
38 #Calculate PAGE_SHIFT: number of bits to shift an address to get the page number
39 PAGE_SIZE = resource.getpagesize()
40 PAGE_SHIFT = 0
41 t = PAGE_SIZE
42 while not (t&1):
43 t>>=1
44 PAGE_SHIFT+=1
46 class PciController(DevController):
48 def __init__(self, vm):
49 DevController.__init__(self, vm)
52 def getDeviceDetails(self, config):
53 """@see DevController.getDeviceDetails"""
54 def parse_hex(val):
55 try:
56 if isinstance(val, types.StringTypes):
57 return int(val, 16)
58 else:
59 return val
60 except ValueError:
61 return None
63 back = {}
64 pcidevid = 0
65 for pci_config in config.get('devs', []):
66 domain = parse_hex(pci_config.get('domain', 0))
67 bus = parse_hex(pci_config.get('bus', 0))
68 slot = parse_hex(pci_config.get('slot', 0))
69 func = parse_hex(pci_config.get('func', 0))
70 self.setupDevice(domain, bus, slot, func)
71 back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%02x" % \
72 (domain, bus, slot, func)
73 pcidevid += 1
75 back['num_devs']=str(pcidevid)
76 back['uuid'] = config.get('uuid','')
77 return (0, back, {})
79 def getDeviceConfiguration(self, devid, transaction = None):
80 result = DevController.getDeviceConfiguration(self, devid, transaction)
81 num_devs = self.readBackend(devid, 'num_devs')
82 pci_devs = []
84 for i in range(int(num_devs)):
85 dev_config = self.readBackend(devid, 'dev-%d' % i)
87 pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" +
88 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" +
89 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" +
90 r"(?P<func>[0-9a-fA-F]{1,2})", dev_config)
92 if pci_match!=None:
93 pci_dev_info = pci_match.groupdict()
94 pci_devs.append({'domain': '0x%(domain)s' % pci_dev_info,
95 'bus': '0x%(bus)s' % pci_dev_info,
96 'slot': '0x%(slot)s' % pci_dev_info,
97 'func': '0x%(func)s' % pci_dev_info})
99 result['devs'] = pci_devs
100 result['uuid'] = self.readBackend(devid, 'uuid')
101 return result
103 def configuration(self, devid, transaction = None):
104 """Returns SXPR for devices on domain.
106 @note: we treat this dict especially to convert to
107 SXP because it is not a straight dict of strings."""
109 configDict = self.getDeviceConfiguration(devid, transaction)
110 sxpr = [self.deviceClass]
112 # remove devs
113 devs = configDict.pop('devs', [])
115 for dev in devs:
116 dev_sxpr = ['dev']
117 for dev_item in dev.items():
118 dev_sxpr.append(list(dev_item))
119 sxpr.append(dev_sxpr)
121 for key, val in configDict.items():
122 if type(val) == type(list()):
123 for v in val:
124 sxpr.append([key, v])
125 else:
126 sxpr.append([key, val])
128 return sxpr
130 def setupDevice(self, domain, bus, slot, func):
131 """ Attach I/O resources for device to frontend domain
132 """
133 fe_domid = self.getDomid()
135 try:
136 dev = PciDevice(domain, bus, slot, func)
137 except Exception, e:
138 raise VmError("pci: failed to locate device and "+
139 "parse it's resources - "+str(e))
141 if dev.driver!='pciback':
142 raise VmError(("pci: PCI Backend does not own device "+ \
143 "%s\n"+ \
144 "See the pciback.hide kernel "+ \
145 "command-line parameter or\n"+ \
146 "bind your slot/device to the PCI backend using sysfs" \
147 )%(dev.name))
149 PCIQuirk(dev.vendor, dev.device, dev.subvendor, dev.subdevice, domain,
150 bus, slot, func)
152 for (start, size) in dev.ioports:
153 log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
154 rc = xc.domain_ioport_permission(domid = fe_domid, first_port = start,
155 nr_ports = size, allow_access = True)
156 if rc<0:
157 raise VmError(('pci: failed to configure I/O ports on device '+
158 '%s - errno=%d')%(dev.name,rc))
160 for (start, size) in dev.iomem:
161 # Convert start/size from bytes to page frame sizes
162 start_pfn = start>>PAGE_SHIFT
163 # Round number of pages up to nearest page boundary (if not on one)
164 nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT
166 log.debug('pci: enabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \
167 (start,size,start_pfn,nr_pfns))
168 rc = xc.domain_iomem_permission(domid = fe_domid,
169 first_pfn = start_pfn,
170 nr_pfns = nr_pfns,
171 allow_access = True)
172 if rc<0:
173 raise VmError(('pci: failed to configure I/O memory on device '+
174 '%s - errno=%d')%(dev.name,rc))
176 if dev.irq>0:
177 log.debug('pci: enabling irq %d'%dev.irq)
178 rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq,
179 allow_access = True)
180 if rc<0:
181 raise VmError(('pci: failed to configure irq on device '+
182 '%s - errno=%d')%(dev.name,rc))
184 def waitForBackend(self,devid):
185 return (0, "ok - no hotplug")
187 def migrate(self, config, network, dst, step, domName):
188 raise XendError('Migration not permitted with assigned PCI device.')