mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
xend: pass-through: Common parse_pci_name()
Share some parsing code between different parts of xm. This has the side-effect that the device specification for hot-plug may now include the VSLOT and OPTS as per device specifictions in the domain configuration file. SEQ:BUS:DEV.FUNC[,OPT...] e.g. 0000:00:01.00@6 Signed-off-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
1 parent
60c32a612f
commit
5a6a2f7e9b
4 files changed
+126
-168
No files matched your search
@@ -15,6 +15,7 @@ import time
|
||||
import threading
|
||||
from xen.util import utils
|
||||
from xen.xend import sxp
|
||||
from xen.xend.XendConstants import AUTO_PHP_SLOT
|
||||
|
||||
PROC_PCI_PATH = '/proc/bus/pci/devices'
|
||||
PROC_PCI_NUM_RESOURCES = 7
|
||||
@@ -35,7 +36,6 @@ LSPCI_CMD = 'lspci'
|
||||
|
||||
PCI_DEV_REG_EXPRESS_STR = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}."+ \
|
||||
r"[0-9a-fA-F]{1}"
|
||||
PCI_DEV_FORMAT_STR = '%04x:%02x:%02x.%01x'
|
||||
|
||||
DEV_TYPE_PCIe_ENDPOINT = 0
|
||||
DEV_TYPE_PCIe_BRIDGE = 1
|
||||
@@ -148,22 +148,62 @@ def parse_hex(val):
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def parse_pci_name_extended(pci_dev_str):
|
||||
pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" +
|
||||
r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" +
|
||||
r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" +
|
||||
r"(?P<func>(\*|[0-7]))" +
|
||||
r"(@(?P<vslot>[01]?[0-9a-fA-F]))?" +
|
||||
r"(,(?P<opts>.*))?$", pci_dev_str)
|
||||
|
||||
if pci_match == None:
|
||||
raise PciDeviceParseError("Failed to parse pci device: %s" %
|
||||
pci_dev_str)
|
||||
|
||||
out = {}
|
||||
pci_dev_info = pci_match.groupdict('')
|
||||
if pci_dev_info['domain'] == '':
|
||||
domain = 0
|
||||
else:
|
||||
domain = int(pci_dev_info['domain'], 16)
|
||||
out['domain'] = "0x%04x" % domain
|
||||
out['bus'] = "0x%02x" % int(pci_dev_info['bus'], 16)
|
||||
out['slot'] = "0x%02x" % int(pci_dev_info['slot'], 16)
|
||||
out['func'] = "0x%x" % int(pci_dev_info['func'], 16)
|
||||
if pci_dev_info['vslot'] == '':
|
||||
vslot = AUTO_PHP_SLOT
|
||||
else:
|
||||
vslot = int(pci_dev_info['vslot'], 16)
|
||||
out['vslot'] = "0x%02x" % vslot
|
||||
if pci_dev_info['opts'] != '':
|
||||
out['opts'] = split_pci_opts(pci_dev_info['opts'])
|
||||
check_pci_opts(out['opts'])
|
||||
|
||||
return out
|
||||
|
||||
def parse_pci_name(pci_name_string):
|
||||
pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
|
||||
r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
|
||||
r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
|
||||
r"(?P<func>[0-7])$", pci_name_string)
|
||||
if pci_match is None:
|
||||
raise PciDeviceParseError(('Failed to parse pci device name: %s' %
|
||||
pci_name_string))
|
||||
pci_dev_info = pci_match.groupdict('0')
|
||||
pci = parse_pci_name_extended(pci_name_string)
|
||||
|
||||
domain = parse_hex(pci_dev_info['domain'])
|
||||
bus = parse_hex(pci_dev_info['bus'])
|
||||
slot = parse_hex(pci_dev_info['slot'])
|
||||
func = parse_hex(pci_dev_info['func'])
|
||||
if int(pci['vslot'], 16) != AUTO_PHP_SLOT:
|
||||
raise PciDeviceParseError(("Failed to parse pci device: %s: " +
|
||||
"vslot provided where prohibited: %s") %
|
||||
(pci_name_string, pci['vslot']))
|
||||
if 'opts' in pci:
|
||||
raise PciDeviceParseError(("Failed to parse pci device: %s: " +
|
||||
"options provided where prohibited: %s") %
|
||||
(pci_name_string, pci['opts']))
|
||||
|
||||
return (domain, bus, slot, func)
|
||||
return pci
|
||||
|
||||
def __pci_dict_to_fmt_str(fmt, dev):
|
||||
return fmt % (int(dev['domain'], 16), int(dev['bus'], 16),
|
||||
int(dev['slot'], 16), int(dev['func'], 16))
|
||||
|
||||
def pci_dict_to_bdf_str(dev):
|
||||
return __pci_dict_to_fmt_str('%04x:%02x:%02x.%01x', dev)
|
||||
|
||||
def pci_dict_to_xc_str(dev):
|
||||
return __pci_dict_to_fmt_str('0x%x, 0x%x, 0x%x, 0x%x', dev)
|
||||
|
||||
def extract_the_exact_pci_names(pci_names):
|
||||
result = []
|
||||
@@ -198,27 +238,7 @@ def get_all_pci_names():
|
||||
return pci_names
|
||||
|
||||
def get_all_pci_devices():
|
||||
pci_devs = []
|
||||
for pci_name in get_all_pci_names():
|
||||
pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
|
||||
r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
|
||||
r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
|
||||
r"(?P<func>[0-7])$", pci_name)
|
||||
if pci_match is None:
|
||||
raise PciDeviceParseError(('Failed to parse pci device name: %s' %
|
||||
pci_name))
|
||||
pci_dev_info = pci_match.groupdict('0')
|
||||
domain = parse_hex(pci_dev_info['domain'])
|
||||
bus = parse_hex(pci_dev_info['bus'])
|
||||
slot = parse_hex(pci_dev_info['slot'])
|
||||
func = parse_hex(pci_dev_info['func'])
|
||||
try:
|
||||
pci_dev = PciDevice(domain, bus, slot, func)
|
||||
except:
|
||||
continue
|
||||
pci_devs.append(pci_dev)
|
||||
|
||||
return pci_devs
|
||||
return map(PciDevice, map(parse_pci_name, get_all_pci_names()))
|
||||
|
||||
def _create_lspci_info():
|
||||
"""Execute 'lspci' command and parse the result.
|
||||
@@ -241,7 +261,7 @@ def _create_lspci_info():
|
||||
try:
|
||||
(opt, value) = line.split(':\t')
|
||||
if opt == 'Slot' or (opt == 'Device' and first_device):
|
||||
device_name = PCI_DEV_FORMAT_STR % parse_pci_name(value)
|
||||
device_name = pci_dict_to_bdf_str(parse_pci_name(value))
|
||||
first_device = False
|
||||
else:
|
||||
device_info[opt] = value
|
||||
@@ -292,8 +312,7 @@ def find_all_devices_owned_by_pciback():
|
||||
pci_list = extract_the_exact_pci_names(pci_names)
|
||||
dev_list = []
|
||||
for pci in pci_list:
|
||||
(dom, b, d, f) = parse_pci_name(pci)
|
||||
dev = PciDevice(dom, b, d, f)
|
||||
dev = PciDevice(parse_pci_name(pci))
|
||||
dev_list = dev_list + [dev]
|
||||
return dev_list
|
||||
|
||||
@@ -400,12 +419,12 @@ class PciDeviceVslotMissing(Exception):
|
||||
return 'pci: no vslot: ' + self.message
|
||||
|
||||
class PciDevice:
|
||||
def __init__(self, domain, bus, slot, func):
|
||||
self.domain = domain
|
||||
self.bus = bus
|
||||
self.slot = slot
|
||||
self.func = func
|
||||
self.name = PCI_DEV_FORMAT_STR % (domain, bus, slot, func)
|
||||
def __init__(self, dev):
|
||||
self.domain = int(dev['domain'], 16)
|
||||
self.bus = int(dev['bus'], 16)
|
||||
self.slot = int(dev['slot'], 16)
|
||||
self.func = int(dev['func'], 16)
|
||||
self.name = pci_dict_to_bdf_str(dev)
|
||||
self.cfg_space_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \
|
||||
self.name + SYSFS_PCI_DEV_CONFIG_PATH
|
||||
self.irq = 0
|
||||
@@ -447,14 +466,15 @@ class PciDevice:
|
||||
# We have reached the upmost one.
|
||||
return None
|
||||
else:
|
||||
dev = {}
|
||||
lst = parent.split(':')
|
||||
dom = int(lst[0], 16)
|
||||
bus = int(lst[1], 16)
|
||||
dev['domain'] = int(lst[0], 16)
|
||||
dev['bus'] = int(lst[1], 16)
|
||||
lst = lst[2]
|
||||
lst = lst.split('.')
|
||||
dev = int(lst[0], 16)
|
||||
func = int(lst[1], 16)
|
||||
return (dom, bus, dev, func)
|
||||
dev['slot'] = int(lst[0], 16)
|
||||
dev['func'] = int(lst[1], 16)
|
||||
return dev
|
||||
except OSError, (errno, strerr):
|
||||
raise PciDeviceParseError('Can not locate the parent of %s',
|
||||
self.name)
|
||||
@@ -464,15 +484,13 @@ class PciDevice:
|
||||
dev = self.find_parent()
|
||||
if dev is None:
|
||||
return None
|
||||
(dom, b, d, f) = dev
|
||||
dev = dev_parent = PciDevice(dom, b, d, f)
|
||||
dev = dev_parent = PciDevice(dev)
|
||||
while dev_parent.dev_type != DEV_TYPE_PCIe_BRIDGE:
|
||||
parent = dev_parent.find_parent()
|
||||
if parent is None:
|
||||
break
|
||||
(dom, b, d, f) = parent
|
||||
dev = dev_parent
|
||||
dev_parent = PciDevice(dom, b, d, f)
|
||||
dev_parent = PciDevice(parent)
|
||||
return dev
|
||||
|
||||
def find_all_devices_behind_the_bridge(self, ignore_bridge):
|
||||
@@ -483,8 +501,7 @@ class PciDevice:
|
||||
|
||||
list = [self.name]
|
||||
for pci_str in dev_list:
|
||||
(dom, b, d, f) = parse_pci_name(pci_str)
|
||||
dev = PciDevice(dom, b, d, f)
|
||||
dev = PciDevice(parse_pci_name(pci_str))
|
||||
if dev.dev_type == DEV_TYPE_PCI_BRIDGE or \
|
||||
dev.dev_type == DEV_TYPE_PCIe_BRIDGE:
|
||||
sub_list_including_self = \
|
||||
@@ -600,7 +617,7 @@ class PciDevice:
|
||||
|
||||
def find_all_the_multi_functions(self):
|
||||
sysfs_mnt = find_sysfs_mnt()
|
||||
parent = PCI_DEV_FORMAT_STR % self.find_parent()
|
||||
parent = pci_dict_to_bdf_str(self.find_parent())
|
||||
pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \
|
||||
parent + '/').read()
|
||||
funcs = extract_the_exact_pci_names(pci_names)
|
||||
@@ -758,8 +775,7 @@ class PciDevice:
|
||||
if len(devs) == 0:
|
||||
return
|
||||
for pci_dev in devs:
|
||||
(dom, b, d, f) = parse_pci_name(pci_dev)
|
||||
dev = PciDevice(dom, b, d, f)
|
||||
dev = PciDevice(parse_pci_name(pci_dev))
|
||||
if dev.driver == 'pciback':
|
||||
continue
|
||||
err_msg = 'pci: %s must be co-assigned to the same guest with %s' + \
|
||||
@@ -785,7 +801,7 @@ class PciDevice:
|
||||
funcs = self.find_all_the_multi_functions()
|
||||
self.devs_check_driver(funcs)
|
||||
|
||||
parent = '%04x:%02x:%02x.%01x' % self.find_parent()
|
||||
parent = pci_dict_to_bdf_str(self.find_parent())
|
||||
|
||||
# Do Secondary Bus Reset.
|
||||
self.do_secondary_bus_reset(parent, funcs)
|
||||
|
||||
@@ -39,7 +39,8 @@ from xen.util import asserts, auxbin
|
||||
from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
|
||||
import xen.util.xsm.xsm as security
|
||||
from xen.util import xsconstants
|
||||
from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp
|
||||
from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp, \
|
||||
pci_dict_to_bdf_str, pci_dict_to_xc_str
|
||||
|
||||
from xen.xend import balloon, sxp, uuid, image, arch
|
||||
from xen.xend import XendOptions, XendNode, XendConfig
|
||||
@@ -310,9 +311,8 @@ def do_FLR(domid):
|
||||
dev_str_list = get_assigned_pci_devices(domid)
|
||||
|
||||
for dev_str in dev_str_list:
|
||||
(dom, b, d, f) = parse_pci_name(dev_str)
|
||||
try:
|
||||
dev = PciDevice(dom, b, d, f)
|
||||
dev = PciDevice(parse_pci_name(dev_str))
|
||||
except Exception, e:
|
||||
raise VmError("pci: failed to locate device and "+
|
||||
"parse it's resources - "+str(e))
|
||||
@@ -652,23 +652,15 @@ class XendDomainInfo:
|
||||
raise VmError("device is already inserted")
|
||||
|
||||
# Test whether the devices can be assigned with VT-d
|
||||
pci_str = "%s, %s, %s, %s" % (new_dev['domain'],
|
||||
new_dev['bus'],
|
||||
new_dev['slot'],
|
||||
new_dev['func'])
|
||||
bdf = xc.test_assign_device(0, pci_str)
|
||||
bdf = xc.test_assign_device(0, pci_dict_to_xc_str(new_dev))
|
||||
if bdf != 0:
|
||||
if bdf == -1:
|
||||
raise VmError("failed to assign device: maybe the platform"
|
||||
" doesn't support VT-d, or VT-d isn't enabled"
|
||||
" properly?")
|
||||
bus = (bdf >> 16) & 0xff
|
||||
devfn = (bdf >> 8) & 0xff
|
||||
dev = (devfn >> 3) & 0x1f
|
||||
func = devfn & 0x7
|
||||
raise VmError("fail to assign device(%x:%x.%x): maybe it has"
|
||||
raise VmError("fail to assign device(%s): maybe it has"
|
||||
" already been assigned to other domain, or maybe"
|
||||
" it doesn't exist." % (bus, dev, func))
|
||||
" it doesn't exist." % pci_dict_to_bdf_str(new_dev))
|
||||
|
||||
# Here, we duplicate some checkings (in some cases, we mustn't allow
|
||||
# a device to be hot-plugged into an HVM guest) that are also done in
|
||||
@@ -680,12 +672,8 @@ class XendDomainInfo:
|
||||
# Test whether the device is owned by pciback. For instance, we can't
|
||||
# hotplug a device being used by Dom0 itself to an HVM guest.
|
||||
from xen.xend.server.pciif import PciDevice, parse_pci_name
|
||||
domain = int(new_dev['domain'],16)
|
||||
bus = int(new_dev['bus'],16)
|
||||
dev = int(new_dev['slot'],16)
|
||||
func = int(new_dev['func'],16)
|
||||
try:
|
||||
pci_device = PciDevice(domain, bus, dev, func)
|
||||
pci_device = PciDevice(new_dev)
|
||||
except Exception, e:
|
||||
raise VmError("pci: failed to locate device and "+
|
||||
"parse it's resources - "+str(e))
|
||||
@@ -710,9 +698,8 @@ class XendDomainInfo:
|
||||
pci_device.devs_check_driver(coassignment_list)
|
||||
assigned_pci_device_str_list = self._get_assigned_pci_devices()
|
||||
for pci_str in coassignment_list:
|
||||
(domain, bus, dev, func) = parse_pci_name(pci_str)
|
||||
dev_str = '0x%x,0x%x,0x%x,0x%x' % (domain, bus, dev, func)
|
||||
if xc.test_assign_device(0, dev_str) == 0:
|
||||
pci_dev = parse_pci_name(pci_str)
|
||||
if xc.test_assign_device(0, pci_dict_to_xc_str(pci_dev)) == 0:
|
||||
continue
|
||||
if not pci_str in assigned_pci_device_str_list:
|
||||
raise VmError(("pci: failed to pci-attach %s to domain %s" + \
|
||||
@@ -742,12 +729,9 @@ class XendDomainInfo:
|
||||
if new_dev.has_key('opts'):
|
||||
opts = ',' + serialise_pci_opts(new_dev['opts'])
|
||||
|
||||
bdf_str = "%s:%s:%s.%s@%s%s" % (new_dev['domain'],
|
||||
new_dev['bus'],
|
||||
new_dev['slot'],
|
||||
new_dev['func'],
|
||||
new_dev['vslot'],
|
||||
opts)
|
||||
bdf_str = "%s@%02x%s" % (pci_dict_to_bdf_str(new_dev),
|
||||
int(new_dev['vslot'], 16), opts)
|
||||
log.debug("XendDomainInfo.hvm_pci_device_insert_dev: %s" % bdf_str)
|
||||
self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str)
|
||||
|
||||
vslot = xstransact.Read("/local/domain/0/device-model/%i/parameter"
|
||||
@@ -864,9 +848,8 @@ class XendDomainInfo:
|
||||
vslot = x['vslot']
|
||||
break
|
||||
if vslot == "":
|
||||
raise VmError("Device %04x:%02x:%02x.%01x is not connected"
|
||||
% (int(dev['domain'],16), int(dev['bus'],16),
|
||||
int(dev['slot'],16), int(dev['func'],16)))
|
||||
raise VmError("Device %s is not connected" %
|
||||
pci_dict_to_bdf_str(dev))
|
||||
self.hvm_destroyPCIDevice(int(vslot, 16))
|
||||
# Update vslot
|
||||
dev['vslot'] = vslot
|
||||
@@ -1152,12 +1135,8 @@ class XendDomainInfo:
|
||||
# list of D's co-assignment devices, DD is not assigned (to domN).
|
||||
#
|
||||
from xen.xend.server.pciif import PciDevice
|
||||
domain = int(x['domain'],16)
|
||||
bus = int(x['bus'],16)
|
||||
dev = int(x['slot'],16)
|
||||
func = int(x['func'],16)
|
||||
try:
|
||||
pci_device = PciDevice(domain, bus, dev, func)
|
||||
pci_device = PciDevice(x)
|
||||
except Exception, e:
|
||||
raise VmError("pci: failed to locate device and "+
|
||||
"parse it's resources - "+str(e))
|
||||
@@ -1172,9 +1151,8 @@ class XendDomainInfo:
|
||||
)% (pci_device.name, self.info['name_label'], pci_str))
|
||||
|
||||
|
||||
bdf_str = "%s:%s:%s.%s" % (x['domain'], x['bus'], x['slot'], x['func'])
|
||||
bdf_str = pci_dict_to_bdf_str(x)
|
||||
log.info("hvm_destroyPCIDevice:%s:%s!", x, bdf_str)
|
||||
|
||||
if self.domid is not None:
|
||||
self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str)
|
||||
|
||||
@@ -1338,21 +1316,12 @@ class XendDomainInfo:
|
||||
if self.domid is not None:
|
||||
return get_assigned_pci_devices(self.domid)
|
||||
|
||||
dev_str_list = []
|
||||
dev_info = self._getDeviceInfo_pci(devid)
|
||||
if dev_info is None:
|
||||
return dev_str_list
|
||||
return []
|
||||
dev_uuid = sxp.child_value(dev_info, 'uuid')
|
||||
pci_conf = self.info['devices'][dev_uuid][1]
|
||||
pci_devs = pci_conf['devs']
|
||||
for pci_dev in pci_devs:
|
||||
domain = int(pci_dev['domain'], 16)
|
||||
bus = int(pci_dev['bus'], 16)
|
||||
slot = int(pci_dev['slot'], 16)
|
||||
func = int(pci_dev['func'], 16)
|
||||
dev_str = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
|
||||
dev_str_list = dev_str_list + [dev_str]
|
||||
return dev_str_list
|
||||
return map(pci_dict_to_bdf_str, pci_conf['devs'])
|
||||
|
||||
def setMemoryTarget(self, target):
|
||||
"""Set the memory target of this domain.
|
||||
@@ -3909,12 +3878,12 @@ class XendDomainInfo:
|
||||
target_dev = None
|
||||
new_pci_sxp = ['pci']
|
||||
for dev in sxp.children(old_pci_sxp, 'dev'):
|
||||
domain = int(sxp.child_value(dev, 'domain'), 16)
|
||||
bus = int(sxp.child_value(dev, 'bus'), 16)
|
||||
slot = int(sxp.child_value(dev, 'slot'), 16)
|
||||
func = int(sxp.child_value(dev, 'func'), 16)
|
||||
name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func)
|
||||
if ppci.get_name() == name:
|
||||
pci_dev = {}
|
||||
pci_dev['domain'] = sxp.child_value(dev, 'domain')
|
||||
pci_dev['bus'] = sxp.child_value(dev, 'bus')
|
||||
pci_dev['slot'] = sxp.child_value(dev, 'slot')
|
||||
pci_dev['func'] = sxp.child_value(dev, 'func')
|
||||
if ppci.get_name() == pci_dict_to_bdf_str(pci_dev):
|
||||
target_dev = dev
|
||||
else:
|
||||
new_pci_sxp.append(dev)
|
||||
|
||||
@@ -340,8 +340,7 @@ class XendNode:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
(domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
|
||||
pci_dev = PciUtil.PciDevice(domain, bus, slot, func)
|
||||
pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name))
|
||||
ppci_record = {
|
||||
'domain': pci_dev.domain,
|
||||
'bus': pci_dev.bus,
|
||||
|
||||
@@ -130,13 +130,7 @@ class PciController(DevController):
|
||||
log.debug('Reconfiguring PCI device %s.' % dev)
|
||||
attaching = False
|
||||
|
||||
(domain, bus, slotfunc) = dev.split(':')
|
||||
(slot, func) = slotfunc.split('.')
|
||||
domain = parse_hex(domain)
|
||||
bus = parse_hex(bus)
|
||||
slot = parse_hex(slot)
|
||||
func = parse_hex(func)
|
||||
self.setupOneDevice(domain, bus, slot, func)
|
||||
self.setupOneDevice(parse_pci_name(dev))
|
||||
|
||||
self.writeBackend(devid, 'dev-%i' % devno, dev)
|
||||
self.writeBackend(devid, 'state-%i' % devno,
|
||||
@@ -248,15 +242,13 @@ class PciController(DevController):
|
||||
return
|
||||
|
||||
#group string format xx:xx.x,xx:xx.x,
|
||||
devstr_len = group_str.find(',')
|
||||
for i in range(0, len(group_str), devstr_len + 1):
|
||||
(bus, slotfunc) = group_str[i:i + devstr_len].split(':')
|
||||
(slot, func) = slotfunc.split('.')
|
||||
b = parse_hex(bus)
|
||||
d = parse_hex(slot)
|
||||
f = parse_hex(func)
|
||||
for i in group_str.split(','):
|
||||
if i == '':
|
||||
continue
|
||||
pci_dev = parse_pci_name(i)
|
||||
pci_dev['domain'] = '%04x' % dev.domain
|
||||
try:
|
||||
sdev = PciDevice(dev.domain, b, d, f)
|
||||
sdev = PciDevice(pci_dev)
|
||||
except Exception, e:
|
||||
#no dom0 drivers bound to sdev
|
||||
continue
|
||||
@@ -270,13 +262,13 @@ class PciController(DevController):
|
||||
)%(sdev.name, dev.name))
|
||||
return
|
||||
|
||||
def setupOneDevice(self, domain, bus, slot, func):
|
||||
def setupOneDevice(self, pci_dev):
|
||||
""" Attach I/O resources for device to frontend domain
|
||||
"""
|
||||
fe_domid = self.getDomid()
|
||||
|
||||
try:
|
||||
dev = PciDevice(domain, bus, slot, func)
|
||||
dev = PciDevice(pci_dev)
|
||||
except Exception, e:
|
||||
raise VmError("pci: failed to locate device and "+
|
||||
"parse it's resources - "+str(e))
|
||||
@@ -305,12 +297,11 @@ class PciController(DevController):
|
||||
|
||||
if not self.vm.info.is_hvm():
|
||||
# Setup IOMMU device assignment
|
||||
pci_str = "0x%x, 0x%x, 0x%x, 0x%x" % (domain, bus, slot, func)
|
||||
bdf = xc.assign_device(fe_domid, pci_str)
|
||||
bdf = xc.assign_device(fe_domid, pci_dict_to_xc_str(pci_dev))
|
||||
pci_str = pci_dict_to_bdf_str(pci_dev)
|
||||
if bdf > 0:
|
||||
raise VmError("Failed to assign device to IOMMU (%x:%x.%x)"
|
||||
% (bus, slot, func))
|
||||
log.debug("pci: assign device %x:%x.%x" % (bus, slot, func))
|
||||
raise VmError("Failed to assign device to IOMMU (%s)" % pci_str)
|
||||
log.debug("pci: assign device %s" % pci_str)
|
||||
|
||||
for (start, size) in dev.ioports:
|
||||
log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size))
|
||||
@@ -366,23 +357,15 @@ class PciController(DevController):
|
||||
def setupDevice(self, config):
|
||||
"""Setup devices from config
|
||||
"""
|
||||
pci_str_list = []
|
||||
pci_dev_list = []
|
||||
for pci_config in config.get('devs', []):
|
||||
domain = parse_hex(pci_config.get('domain', 0))
|
||||
bus = parse_hex(pci_config.get('bus', 0))
|
||||
slot = parse_hex(pci_config.get('slot', 0))
|
||||
func = parse_hex(pci_config.get('func', 0))
|
||||
pci_str = '%04x:%02x:%02x.%01x' % (domain, bus, slot, func)
|
||||
pci_str_list = pci_str_list + [pci_str]
|
||||
pci_dev_list = pci_dev_list + [(domain, bus, slot, func)]
|
||||
pci_dev_list = config.get('devs', [])
|
||||
pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list)
|
||||
|
||||
if len(pci_str_list) != len(set(pci_str_list)):
|
||||
raise VmError('pci: duplicate devices specified in guest config?')
|
||||
|
||||
for (domain, bus, slot, func) in pci_dev_list:
|
||||
for pci_dev in pci_dev_list:
|
||||
try:
|
||||
dev = PciDevice(domain, bus, slot, func)
|
||||
dev = PciDevice(pci_dev)
|
||||
except Exception, e:
|
||||
raise VmError("pci: failed to locate device and "+
|
||||
"parse it's resources - "+str(e))
|
||||
@@ -427,9 +410,7 @@ class PciController(DevController):
|
||||
dev.devs_check_driver(devs_str)
|
||||
for s in devs_str:
|
||||
if not s in pci_str_list:
|
||||
(s_dom, s_bus, s_slot, s_func) = parse_pci_name(s)
|
||||
s_pci_str = '0x%x,0x%x,0x%x,0x%x' % \
|
||||
(s_dom, s_bus, s_slot, s_func)
|
||||
s_pci_str = pci_dict_to_bdf_str(parse_pci_name(s))
|
||||
# s has been assigned to other guest?
|
||||
if xc.test_assign_device(0, s_pci_str) != 0:
|
||||
err_msg = 'pci: %s must be co-assigned to the'+\
|
||||
@@ -453,13 +434,13 @@ class PciController(DevController):
|
||||
return True
|
||||
|
||||
|
||||
def cleanupOneDevice(self, domain, bus, slot, func):
|
||||
def cleanupOneDevice(self, pci_dev):
|
||||
""" Detach I/O resources for device from frontend domain
|
||||
"""
|
||||
fe_domid = self.getDomid()
|
||||
|
||||
try:
|
||||
dev = PciDevice(domain, bus, slot, func)
|
||||
dev = PciDevice(pci_dev)
|
||||
except Exception, e:
|
||||
raise VmError("pci: failed to locate device and "+
|
||||
"parse it's resources - "+str(e))
|
||||
@@ -476,12 +457,11 @@ class PciController(DevController):
|
||||
# DMA transaction, etc
|
||||
dev.do_FLR()
|
||||
|
||||
pci_str = "0x%x, 0x%x, 0x%x, 0x%x" % (domain, bus, slot, func)
|
||||
bdf = xc.deassign_device(fe_domid, pci_str)
|
||||
bdf = xc.deassign_device(fe_domid, pci_dict_to_xc_str(pci_dev))
|
||||
pci_str = pci_dict_to_bdf_str(pci_dev)
|
||||
if bdf > 0:
|
||||
raise VmError("Failed to deassign device from IOMMU (%x:%x.%x)"
|
||||
% (bus, slot, func))
|
||||
log.debug("pci: Deassign device %x:%x.%x" % (bus, slot, func))
|
||||
raise VmError("Failed to deassign device from IOMMU (%s)" % pci_str)
|
||||
log.debug("pci: Deassign device %s" % pci_str)
|
||||
|
||||
for (start, size) in dev.ioports:
|
||||
log.debug('pci: disabling ioport 0x%x/0x%x'%(start,size))
|
||||
@@ -530,15 +510,9 @@ class PciController(DevController):
|
||||
state = int(self.readBackend(devid, 'state-%i' % i))
|
||||
if state == xenbusState['Closing']:
|
||||
# Detach I/O resources.
|
||||
dev = self.readBackend(devid, 'dev-%i' % i)
|
||||
(domain, bus, slotfunc) = dev.split(':')
|
||||
(slot, func) = slotfunc.split('.')
|
||||
domain = parse_hex(domain)
|
||||
bus = parse_hex(bus)
|
||||
slot = parse_hex(slot)
|
||||
func = parse_hex(func)
|
||||
pci_dev = parse_pci_name(self.readBackend(devid, 'dev-%i' % i))
|
||||
# In HVM case, I/O resources are disabled in ioemu.
|
||||
self.cleanupOneDevice(domain, bus, slot, func)
|
||||
self.cleanupOneDevice(pci_dev)
|
||||
# Remove xenstore nodes.
|
||||
list = ['dev', 'vdev', 'state', 'uuid', 'vslot']
|
||||
if self.readBackend(devid, 'opts-%i' % i) is not None:
|
||||
|
||||