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@intel.com>
This commit is contained in:
Keir Fraser committed 2009-07-28 16:42:12 +01:00
1 parent 0a8f3082f6
commit fb4a420c9b
4 files changed
+50 -41

No files matched your search

-3
View File
@@ -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':
+25 -27
View File
@@ -42,7 +42,7 @@ from xen.util import xsconstants
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,10 +2455,18 @@ 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
XendDomain.instance().add_domain(self)
+4 -5
View File
@@ -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:
+21 -6
View File
@@ -58,6 +58,25 @@ def parse_hex(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):
def __init__(self, vm):
@@ -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))
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.