mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
xm: vt-d: Add a command "xm pci-list-assignable-devices" to list all
the assignable devices. Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
This commit is contained in:
1 parent
22527b8dcd
commit
73d5acf50f
2 files changed
+140
No files matched your search
@@ -27,6 +27,7 @@ SYSFS_PCI_DEV_DEVICE_PATH = '/device'
|
||||
SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor'
|
||||
SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device'
|
||||
SYSFS_PCI_DEV_CLASS_PATH = '/class'
|
||||
SYSFS_PCIBACK_PATH = '/bus/pci/drivers/pciback/'
|
||||
|
||||
LSPCI_CMD = 'lspci'
|
||||
|
||||
@@ -210,6 +211,109 @@ def restore_pci_conf_space(pci_cfg_list):
|
||||
os.write(fd, dw)
|
||||
os.close(fd)
|
||||
|
||||
def find_all_devices_owned_by_pciback():
|
||||
sysfs_mnt = find_sysfs_mnt()
|
||||
pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
|
||||
pci_names = os.popen('ls ' + pciback_path).read()
|
||||
pci_list = re.findall(PCI_DEV_REG_EXPRESS_STR, pci_names)
|
||||
dev_list = []
|
||||
for pci in pci_list:
|
||||
(dom, b, d, f) = parse_pci_name(pci)
|
||||
dev = PciDevice(dom, b, d, f)
|
||||
dev_list = dev_list + [dev]
|
||||
return dev_list
|
||||
|
||||
def transform_list(target, src):
|
||||
''' src: its element is pci string (Format: xxxx:xx:xx:x).
|
||||
target: its element is pci string, or a list of pci string.
|
||||
|
||||
If all the elements in src are in target, we remove them from target
|
||||
and add src into target; otherwise, we remove from target all the
|
||||
elements that also appear in src.
|
||||
'''
|
||||
result = []
|
||||
target_contains_src = True
|
||||
for e in src:
|
||||
if not e in target:
|
||||
target_contains_src = False
|
||||
break
|
||||
|
||||
if target_contains_src:
|
||||
result = result + [src]
|
||||
for e in target:
|
||||
if not e in src:
|
||||
result = result + [e]
|
||||
return result
|
||||
|
||||
def check_FLR_capability(dev_list):
|
||||
i = len(dev_list)
|
||||
if i == 0:
|
||||
return []
|
||||
i = i - 1;
|
||||
while i >= 0:
|
||||
dev = dev_list[i]
|
||||
if dev.bus == 0:
|
||||
if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr:
|
||||
del dev_list[i]
|
||||
elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr:
|
||||
del dev_list[i]
|
||||
i = i - 1
|
||||
|
||||
pci_list = []
|
||||
pci_dev_dict = {}
|
||||
for dev in dev_list:
|
||||
pci_list = pci_list + [dev.name]
|
||||
pci_dev_dict[dev.name] = dev
|
||||
|
||||
while True:
|
||||
need_transform = False
|
||||
for pci in pci_list:
|
||||
if isinstance(pci, types.StringTypes):
|
||||
dev = pci_dev_dict[pci]
|
||||
if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr:
|
||||
coassigned_pci_list = dev.find_all_the_multi_functions()
|
||||
need_transform = True
|
||||
elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr:
|
||||
coassigned_pci_list = dev.find_coassigned_devices(True)
|
||||
del coassigned_pci_list[0]
|
||||
need_transform = True
|
||||
|
||||
if need_transform:
|
||||
pci_list = transform_list(pci_list, coassigned_pci_list)
|
||||
if not need_transform:
|
||||
break
|
||||
|
||||
if len(pci_list) == 0:
|
||||
return []
|
||||
|
||||
for i in range(0, len(pci_list)):
|
||||
if isinstance(pci_list[i], types.StringTypes):
|
||||
pci_list[i] = [pci_list[i]]
|
||||
|
||||
# Now every element in pci_list is a list of pci string.
|
||||
|
||||
result = []
|
||||
for pci_names in pci_list:
|
||||
devs = []
|
||||
for pci in pci_names:
|
||||
devs = devs + [pci_dev_dict[pci]]
|
||||
result = result + [devs]
|
||||
return result
|
||||
|
||||
def check_mmio_bar(devs_list):
|
||||
result = []
|
||||
|
||||
for dev_list in devs_list:
|
||||
non_aligned_bar_found = False
|
||||
for dev in dev_list:
|
||||
if dev.has_non_page_aligned_bar:
|
||||
non_aligned_bar_found = True
|
||||
break
|
||||
if not non_aligned_bar_found:
|
||||
result = result + [dev_list]
|
||||
|
||||
return result
|
||||
|
||||
class PciDeviceNotFoundError(Exception):
|
||||
def __init__(self,domain,bus,slot,func):
|
||||
self.domain = domain
|
||||
|
||||
@@ -38,6 +38,7 @@ from select import select
|
||||
import xml.dom.minidom
|
||||
from xen.util.blkif import blkdev_name_to_number
|
||||
from xen.util import vscsi_util
|
||||
from xen.util.pci import *
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings('ignore', category=FutureWarning)
|
||||
@@ -56,6 +57,9 @@ from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
|
||||
|
||||
import XenAPI
|
||||
|
||||
import xen.lowlevel.xc
|
||||
xc = xen.lowlevel.xc.xc()
|
||||
|
||||
import inspect
|
||||
from xen.xend import XendOptions
|
||||
xoptions = XendOptions.instance()
|
||||
@@ -183,6 +187,7 @@ SUBCOMMAND_HELP = {
|
||||
'Remove a domain\'s pass-through pci device.'),
|
||||
'pci-list' : ('<Domain>',
|
||||
'List pass-through pci devices for a domain.'),
|
||||
'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
|
||||
'scsi-attach' : ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
|
||||
'Attach a new SCSI device.'),
|
||||
'scsi-detach' : ('<Domain> <VirtDevice>',
|
||||
@@ -355,6 +360,7 @@ device_commands = [
|
||||
"pci-attach",
|
||||
"pci-detach",
|
||||
"pci-list",
|
||||
"pci-list-assignable-devices",
|
||||
"scsi-attach",
|
||||
"scsi-detach",
|
||||
"scsi-list",
|
||||
@@ -2116,6 +2122,35 @@ def xm_pci_list(args):
|
||||
hdr = 1
|
||||
print ( fmt_str % x )
|
||||
|
||||
def xm_pci_list_assignable_devices(args):
|
||||
# Each element of dev_list is a PciDevice
|
||||
dev_list = find_all_devices_owned_by_pciback()
|
||||
|
||||
# Each element of devs_list is a list of PciDevice
|
||||
devs_list = check_FLR_capability(dev_list)
|
||||
|
||||
devs_list = check_mmio_bar(devs_list)
|
||||
|
||||
# Check if the devices have been assigned to guests.
|
||||
final_devs_list = []
|
||||
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 = xc.test_assign_device(domid, pci_str)
|
||||
if bdf != 0:
|
||||
available = False
|
||||
break
|
||||
if available:
|
||||
final_devs_list = final_devs_list + [dev_list]
|
||||
|
||||
for dev_list in final_devs_list:
|
||||
for d in dev_list:
|
||||
print d.name,
|
||||
print
|
||||
|
||||
def vscsi_convert_sxp_to_dict(dev_sxp):
|
||||
dev_dict = {}
|
||||
for opt_val in dev_sxp[1:]:
|
||||
@@ -2645,6 +2680,7 @@ commands = {
|
||||
"pci-attach": xm_pci_attach,
|
||||
"pci-detach": xm_pci_detach,
|
||||
"pci-list": xm_pci_list,
|
||||
"pci-list-assignable-devices": xm_pci_list_assignable_devices,
|
||||
# vscsi
|
||||
"scsi-attach": xm_scsi_attach,
|
||||
"scsi-detach": xm_scsi_detach,
|
||||
|
||||