# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1248795732 -3600
# Node ID 7faf35a248c0cffa133347bae01a22e92345fd28
# Parent 5bb626155123eab4dbe81f15a3b6e4746da63982
xend: pass-through: fix "xm pci-list-assignable-devices' for pv_guest
xc.test_assign_device(dev) can only tell us if dev is assigned to hvm
guest; if a device is assigned to pv guest, xc.test_assign_device()
still tells us the device is not assigned yet, as a result, the device
still appears in the output of "xm pci-list-assignable-devices", and
xend would not prevent us from assigning the device to a new pv or hvm
guest.
To judge if a device has been assigned to guest, we have to scan
xenstore.
Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
tools/python/xen/xend/XendConfig.py | 3 -
tools/python/xen/xend/XendDomainInfo.py | 52 +++++++++++++++-----------------
tools/python/xen/xend/XendNode.py | 9 ++---
tools/python/xen/xend/server/pciif.py | 27 ++++++++++++----
4 files changed, 50 insertions(+), 41 deletions(-)
diff -r 5bb626155123 -r 7faf35a248c0 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Tue Jul 28 16:41:13 2009 +0100
+++ b/tools/python/xen/xend/XendConfig.py Tue Jul 28 16:42:12 2009 +0100
@@ -2059,9 +2059,6 @@ class XendConfig(dict):
return self['platform'].get('hap', 0)
def update_platform_pci(self):
- if not self.is_hvm():
- return
-
pci = []
for dev_type, dev_info in self.all_devices_sxpr():
if dev_type != 'pci':
diff -r 5bb626155123 -r 7faf35a248c0 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Tue Jul 28 16:41:13 2009 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py Tue Jul 28 16:42:12 2009 +0100
@@ -42,7 +42,7 @@ from xen.util.pci import serialise_pci_o
from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp, \
pci_dict_to_bdf_str, pci_dict_to_xc_str, \
pci_convert_sxp_to_dict, pci_convert_dict_to_sxp, \
- pci_dict_cmp, PCI_DEVFN, PCI_SLOT, PCI_FUNC
+ pci_dict_cmp, PCI_DEVFN, PCI_SLOT, PCI_FUNC, parse_hex
from xen.xend import balloon, sxp, uuid, image, arch
from xen.xend import XendOptions, XendNode, XendConfig
@@ -296,20 +296,11 @@ def dom_get(dom):
log.trace("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
return None
-def get_assigned_pci_devices(domid):
- dev_str_list = []
- path = '/local/domain/0/backend/pci/%u/0/' % domid
- num_devs = xstransact.Read(path + 'num_devs');
- if num_devs is None or num_devs == "":
- return dev_str_list
- num_devs = int(num_devs);
- for i in range(num_devs):
- dev_str = xstransact.Read(path + 'dev-%i' % i)
- dev_str_list = dev_str_list + [dev_str]
- return dev_str_list
+from xen.xend.server.pciif import parse_pci_name, PciDevice,\
+ get_assigned_pci_devices, get_all_assigned_pci_devices
+
def do_FLR(domid):
- from xen.xend.server.pciif import parse_pci_name, PciDevice
dev_str_list = get_assigned_pci_devices(domid)
for dev_str in dev_str_list:
@@ -686,15 +677,14 @@ class XendDomainInfo:
raise VmError("device is already inserted")
# Test whether the devices can be assigned with VT-d
- 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?")
- raise VmError("fail to assign device(%s): maybe it has"
- " already been assigned to other domain, or maybe"
- " it doesn't exist." % pci_dict_to_bdf_str(new_dev))
+ pci_name = '%04x:%02x:%02x.%x' % \
+ (parse_hex(new_dev['domain']),\
+ parse_hex(new_dev['bus']),\
+ parse_hex(new_dev['slot']),\
+ parse_hex(new_dev['func']))
+ if pci_name in get_all_assigned_pci_devices():
+ raise VmError("failed to assign device %s that has"
+ " already been assigned to other domain." % pci_str)
# 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
@@ -732,8 +722,7 @@ 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:
- pci_dev = parse_pci_name(pci_str)
- if xc.test_assign_device(0, pci_dict_to_xc_str(pci_dev)) == 0:
+ if not (pci_str in get_all_assigned_pci_devices()):
continue
if not pci_str in assigned_pci_device_str_list:
raise VmError(("pci: failed to pci-attach %s to domain %s" + \
@@ -859,7 +848,7 @@ class XendDomainInfo:
pci_dev = sxp.children(dev_sxp, 'dev')[0]
dev_config = pci_convert_sxp_to_dict(dev_sxp)
dev = dev_config['devs'][0]
-
+
# Do HVM specific processing
if self.info.is_hvm():
if pci_state == 'Initialising':
@@ -2454,7 +2443,8 @@ class XendDomainInfo:
if pci and len(pci) > 0:
pci = map(lambda x: x[0:4], pci) # strip options
pci_str = str(pci)
- if hvm and pci_str:
+
+ if hvm and pci_str != '':
bdf = xc.test_assign_device(0, pci_str)
if bdf != 0:
if bdf == -1:
@@ -2465,9 +2455,17 @@ class XendDomainInfo:
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("failed to assign device(%x:%x.%x): maybe it has"
" already been assigned to other domain, or
maybe"
" it doesn't exist." % (bus, dev, func))
+
+ # This test is done for both pv and hvm guest.
+ for p in pci:
+ pci_name = '%04x:%02x:%02x.%x' % \
+ (parse_hex(p[0]), parse_hex(p[1]), parse_hex(p[2]),
parse_hex(p[3]))
+ if pci_name in get_all_assigned_pci_devices():
+ raise VmError("failed to assign device %s that has"
+ " already been assigned to other domain." %
pci_name)
# register the domain in the list
from xen.xend import XendDomain
diff -r 5bb626155123 -r 7faf35a248c0 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Tue Jul 28 16:41:13 2009 +0100
+++ b/tools/python/xen/xend/XendNode.py Tue Jul 28 16:42:12 2009 +0100
@@ -834,6 +834,9 @@ class XendNode:
def pciinfo(self):
+ from xen.xend.server.pciif import get_all_assigned_pci_devices
+ assigned_devs = get_all_assigned_pci_devices()
+
# Each element of dev_list is a PciDevice
dev_list = PciUtil.find_all_assignable_devices()
@@ -847,11 +850,7 @@ class XendNode:
for dev_list in devs_list:
available = True
for d in dev_list:
- pci_str = '0x%x,0x%x,0x%x,0x%x' %(d.domain, d.bus, d.slot,
d.func)
- # Xen doesn't care what the domid is, so we pass 0 here...
- domid = 0
- bdf = self.xc.test_assign_device(domid, pci_str)
- if bdf != 0:
+ if d.name in assigned_devs:
available = False
break
if available:
diff -r 5bb626155123 -r 7faf35a248c0 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py Tue Jul 28 16:41:13 2009 +0100
+++ b/tools/python/xen/xend/server/pciif.py Tue Jul 28 16:42:12 2009 +0100
@@ -57,6 +57,25 @@ def parse_hex(val):
return val
except ValueError:
return None
+
+def get_assigned_pci_devices(domid):
+ dev_str_list = []
+ path = '/local/domain/0/backend/pci/%u/0/' % domid
+ num_devs = xstransact.Read(path + 'num_devs');
+ if num_devs is None or num_devs == "":
+ return dev_str_list
+ num_devs = int(num_devs)
+ for i in range(num_devs):
+ dev_str = xstransact.Read(path + 'dev-%i' % i)
+ dev_str_list = dev_str_list + [dev_str]
+ return dev_str_list
+
+def get_all_assigned_pci_devices():
+ dom_list = xstransact.List('/local/domain')
+ pci_str_list = []
+ for d in dom_list:
+ pci_str_list = pci_str_list + get_assigned_pci_devices(int(d))
+ return pci_str_list
class PciController(DevController):
@@ -368,11 +387,8 @@ class PciController(DevController):
dev.devs_check_driver(funcs)
for f in funcs:
if not f in pci_str_list:
- (f_dom, f_bus, f_slot, f_func) = parse_pci_name(f)
- f_pci_str = '0x%x,0x%x,0x%x,0x%x' % \
- (f_dom, f_bus, f_slot, f_func)
# f has been assigned to other guest?
- if xc.test_assign_device(0, f_pci_str) != 0:
+ if f in get_all_assigned_pci_devices():
err_msg = 'pci: %s must be co-assigned to' + \
' the same guest with %s'
raise VmError(err_msg % (f, dev.name))
@@ -396,9 +412,8 @@ class PciController(DevController):
dev.devs_check_driver(devs_str)
for s in devs_str:
if not s in pci_str_list:
- 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:
+ if s in get_all_assigned_pci_devices():
err_msg = 'pci: %s must be co-assigned to
the'+\
' same guest with %s'
raise VmError(err_msg % (s, dev.name))
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|