ia64/xen-unstable

changeset 18050:39c2cab9e765

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>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jul 14 10:12:07 2008 +0100 (2008-07-14)
parents e61978c24d84
children 79517ed2a108
files tools/python/xen/util/pci.py tools/python/xen/xm/main.py
line diff
     1.1 --- a/tools/python/xen/util/pci.py	Mon Jul 14 10:11:39 2008 +0100
     1.2 +++ b/tools/python/xen/util/pci.py	Mon Jul 14 10:12:07 2008 +0100
     1.3 @@ -27,6 +27,7 @@ SYSFS_PCI_DEV_DEVICE_PATH = '/device'
     1.4  SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor'
     1.5  SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device'
     1.6  SYSFS_PCI_DEV_CLASS_PATH = '/class'
     1.7 +SYSFS_PCIBACK_PATH = '/bus/pci/drivers/pciback/'
     1.8  
     1.9  LSPCI_CMD = 'lspci'
    1.10  
    1.11 @@ -210,6 +211,109 @@ def restore_pci_conf_space(pci_cfg_list)
    1.12              os.write(fd, dw)
    1.13          os.close(fd) 
    1.14  
    1.15 +def find_all_devices_owned_by_pciback():
    1.16 +    sysfs_mnt = find_sysfs_mnt()
    1.17 +    pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
    1.18 +    pci_names = os.popen('ls ' + pciback_path).read()
    1.19 +    pci_list = re.findall(PCI_DEV_REG_EXPRESS_STR, pci_names)
    1.20 +    dev_list = []
    1.21 +    for pci in pci_list:
    1.22 +        (dom, b, d, f) = parse_pci_name(pci)
    1.23 +        dev = PciDevice(dom, b, d, f)
    1.24 +        dev_list = dev_list + [dev]
    1.25 +    return dev_list
    1.26 +
    1.27 +def transform_list(target, src):
    1.28 +    ''' src: its element is pci string (Format: xxxx:xx:xx:x).
    1.29 +        target: its element is pci string, or a list of pci string.
    1.30 +
    1.31 +        If all the elements in src are in target, we remove them from target
    1.32 +        and add src into target; otherwise, we remove from target all the
    1.33 +        elements that also appear in src.
    1.34 +    '''
    1.35 +    result = []
    1.36 +    target_contains_src = True
    1.37 +    for e in src:
    1.38 +        if not e in target:
    1.39 +            target_contains_src = False
    1.40 +            break
    1.41 +
    1.42 +    if target_contains_src:
    1.43 +        result = result + [src]
    1.44 +    for e in target:
    1.45 +        if not e in src:
    1.46 +             result = result + [e]
    1.47 +    return  result
    1.48 +
    1.49 +def check_FLR_capability(dev_list):
    1.50 +    i = len(dev_list)
    1.51 +    if i == 0:
    1.52 +        return []
    1.53 +    i = i - 1;
    1.54 +    while i >= 0:
    1.55 +        dev = dev_list[i]
    1.56 +        if dev.bus == 0:
    1.57 +            if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr:
    1.58 +                del dev_list[i]
    1.59 +            elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr:
    1.60 +                del dev_list[i]
    1.61 +        i = i - 1
    1.62 +
    1.63 +    pci_list = []
    1.64 +    pci_dev_dict = {}
    1.65 +    for dev in dev_list:
    1.66 +        pci_list = pci_list + [dev.name]
    1.67 +        pci_dev_dict[dev.name] = dev
    1.68 +
    1.69 +    while True:
    1.70 +        need_transform = False
    1.71 +        for pci in pci_list:
    1.72 +            if isinstance(pci, types.StringTypes):
    1.73 +                dev = pci_dev_dict[pci]
    1.74 +                if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr:
    1.75 +                    coassigned_pci_list = dev.find_all_the_multi_functions()
    1.76 +                    need_transform = True
    1.77 +                elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr:
    1.78 +                    coassigned_pci_list = dev.find_coassigned_devices(True)
    1.79 +                    del coassigned_pci_list[0]
    1.80 +                    need_transform = True
    1.81 +
    1.82 +                if need_transform:
    1.83 +                    pci_list = transform_list(pci_list, coassigned_pci_list)
    1.84 +        if not need_transform:
    1.85 +            break
    1.86 +
    1.87 +    if len(pci_list) == 0:
    1.88 +        return []
    1.89 +
    1.90 +    for i in range(0, len(pci_list)):
    1.91 +        if isinstance(pci_list[i], types.StringTypes):
    1.92 +            pci_list[i] = [pci_list[i]]
    1.93 +    
    1.94 +    # Now every element in pci_list is a list of pci string.
    1.95 +
    1.96 +    result = []
    1.97 +    for pci_names in pci_list:
    1.98 +        devs = []
    1.99 +        for pci in pci_names:
   1.100 +            devs = devs + [pci_dev_dict[pci]]
   1.101 +        result = result + [devs]
   1.102 +    return result
   1.103 +
   1.104 +def check_mmio_bar(devs_list):
   1.105 +    result = []
   1.106 +
   1.107 +    for dev_list in devs_list:
   1.108 +        non_aligned_bar_found = False
   1.109 +        for dev in dev_list:
   1.110 +            if dev.has_non_page_aligned_bar:
   1.111 +                non_aligned_bar_found = True
   1.112 +                break
   1.113 +        if not non_aligned_bar_found:
   1.114 +            result = result + [dev_list]
   1.115 +
   1.116 +    return result
   1.117 +
   1.118  class PciDeviceNotFoundError(Exception):
   1.119      def __init__(self,domain,bus,slot,func):
   1.120          self.domain = domain
     2.1 --- a/tools/python/xen/xm/main.py	Mon Jul 14 10:11:39 2008 +0100
     2.2 +++ b/tools/python/xen/xm/main.py	Mon Jul 14 10:12:07 2008 +0100
     2.3 @@ -38,6 +38,7 @@ from select import select
     2.4  import xml.dom.minidom
     2.5  from xen.util.blkif import blkdev_name_to_number
     2.6  from xen.util import vscsi_util
     2.7 +from xen.util.pci import *
     2.8  
     2.9  import warnings
    2.10  warnings.filterwarnings('ignore', category=FutureWarning)
    2.11 @@ -56,6 +57,9 @@ from xen.util.acmpolicy import ACM_LABEL
    2.12  
    2.13  import XenAPI
    2.14  
    2.15 +import xen.lowlevel.xc
    2.16 +xc = xen.lowlevel.xc.xc()
    2.17 +
    2.18  import inspect
    2.19  from xen.xend import XendOptions
    2.20  xoptions = XendOptions.instance()
    2.21 @@ -183,6 +187,7 @@ SUBCOMMAND_HELP = {
    2.22                          'Remove a domain\'s pass-through pci device.'),
    2.23      'pci-list'      :  ('<Domain>',
    2.24                          'List pass-through pci devices for a domain.'),
    2.25 +    'pci-list-assignable-devices' : ('', 'List all the assignable pci devices'),
    2.26      'scsi-attach'  :  ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
    2.27                          'Attach a new SCSI device.'),
    2.28      'scsi-detach'  :  ('<Domain> <VirtDevice>',
    2.29 @@ -355,6 +360,7 @@ device_commands = [
    2.30      "pci-attach",
    2.31      "pci-detach",
    2.32      "pci-list",
    2.33 +    "pci-list-assignable-devices",
    2.34      "scsi-attach",
    2.35      "scsi-detach",
    2.36      "scsi-list",
    2.37 @@ -2116,6 +2122,35 @@ def xm_pci_list(args):
    2.38              hdr = 1
    2.39          print ( fmt_str % x )
    2.40  
    2.41 +def xm_pci_list_assignable_devices(args):
    2.42 +    # Each element of dev_list is a PciDevice
    2.43 +    dev_list = find_all_devices_owned_by_pciback()
    2.44 +
    2.45 +    # Each element of devs_list is a list of PciDevice
    2.46 +    devs_list = check_FLR_capability(dev_list)
    2.47 +
    2.48 +    devs_list = check_mmio_bar(devs_list)
    2.49 +
    2.50 +    # Check if the devices have been assigned to guests.
    2.51 +    final_devs_list = []
    2.52 +    for dev_list in devs_list:
    2.53 +        available = True
    2.54 +        for d in dev_list:
    2.55 +            pci_str = '0x%x,0x%x,0x%x,0x%x' %(d.domain, d.bus, d.slot, d.func)
    2.56 +            # Xen doesn't care what the domid is, so we pass 0 here...
    2.57 +            domid = 0
    2.58 +            bdf = xc.test_assign_device(domid, pci_str)
    2.59 +            if bdf != 0:
    2.60 +                available = False
    2.61 +                break
    2.62 +        if available:
    2.63 +            final_devs_list = final_devs_list + [dev_list]
    2.64 +
    2.65 +    for dev_list in final_devs_list:
    2.66 +        for d in dev_list:
    2.67 +            print d.name,
    2.68 +        print
    2.69 +
    2.70  def vscsi_convert_sxp_to_dict(dev_sxp):
    2.71      dev_dict = {}
    2.72      for opt_val in dev_sxp[1:]:
    2.73 @@ -2645,6 +2680,7 @@ commands = {
    2.74      "pci-attach": xm_pci_attach,
    2.75      "pci-detach": xm_pci_detach,
    2.76      "pci-list": xm_pci_list,
    2.77 +    "pci-list-assignable-devices": xm_pci_list_assignable_devices,
    2.78      # vscsi
    2.79      "scsi-attach": xm_scsi_attach,
    2.80      "scsi-detach": xm_scsi_detach,