[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1 of 2] pci passtrough: add xm pci-assignable-add/remove commands



Add two commands to xm, make xend toolstack parallel to xl toolstack. Functions
can be used in managed pci devices handling.

Signed-off-by: Chunyan Liu <cyliu@xxxxxxxx>

diff -r 64b36dde26bc -r f0b2ddf43585 tools/python/xen/util/pci.py
--- a/tools/python/xen/util/pci.py      Fri Jan 04 15:58:37 2013 +0000
+++ b/tools/python/xen/util/pci.py      Tue Jan 08 15:03:17 2013 +0800
@@ -20,6 +20,7 @@ from xen.xend import sxp
 from xen.xend.XendConstants import AUTO_PHP_SLOT
 from xen.xend.XendSXPDev import dev_dict_to_sxp
 from xen.xend.XendLogging import log
+from xen.xend.xenstore.xstransact import xstransact
 
 # for 2.3 compatibility
 try:
@@ -27,9 +28,11 @@ try:
 except NameError:
     from sets import Set as set
 
+XS_PCIBACK_PATH = '/xm/pciback'
 PROC_PCI_PATH = '/proc/bus/pci/devices'
 PROC_PCI_NUM_RESOURCES = 7
 
+SYSFS_PCI_DRVS_PATH = 'bus/pci/drivers'
 SYSFS_PCI_DEVS_PATH = '/bus/pci/devices'
 SYSFS_PCI_DEV_RESOURCE_PATH = '/resource'
 SYSFS_PCI_DEV_CONFIG_PATH = '/config'
@@ -427,6 +430,9 @@ def __pci_dict_to_fmt_str(fmt, dev):
 def pci_dict_to_bdf_str(dev):
     return __pci_dict_to_fmt_str('%04x:%02x:%02x.%01x', dev)
 
+def pci_dict_to_xs_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)
 
@@ -560,6 +566,111 @@ def find_all_assignable_devices():
         dev_list = dev_list + [dev]
     return dev_list
 
+def pci_assignable_add(dev, rebind):
+    '''detach pci device from driver that we need to unbind from and rebind
+       to pciback driver, then it can be assigned to guest.
+    '''
+    sysfs_mnt = find_sysfs_mnt()
+    pcidev_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH
+    pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
+
+    # See if the device exists
+    pci_bdf = pci_dict_to_bdf_str(dev)
+    path = pcidev_path + '/' + pci_bdf
+    if not os.path.exists(path):
+        log.debug("Pci device %s doesn't exist" % pci_bdf)
+        return -1
+
+    # Check to see if it's already assigned to pciback
+    path = pciback_path + '/' + pci_bdf
+    if os.path.exists(path):
+        log.debug("Pci device %s is already assigned to pciback" % pci_bdf)
+        return 0
+
+    # Check to see if there's already a driver that we need to unbind from
+    path = pcidev_path + '/' + pci_bdf + '/driver'
+    drv_path = None
+    if os.path.exists(path):
+        drv_path = os.path.realpath(path)
+        cmd = 'echo %s > %s/unbind' % (pci_bdf, drv_path)
+        if os.system(cmd):
+            log.debug("Couldn't unbind device")
+            return -1;
+
+    # Store Store driver_path for rebinding to dom0
+    if rebind:
+        if drv_path is not None: 
+            xs_pci_bdf = pci_dict_to_xs_bdf_str(dev)
+            path = XS_PCIBACK_PATH + '/' + xs_pci_bdf
+            xstransact.Mkdir(path)
+            xstransact.Write(path, 'driver_path', drv_path)
+        else:
+            log.debug("Not bound to a driver, will not be rebound")
+
+    # Bind to pciback
+    # Scan through /sys/.../pciback/slots looking for pcidev's BDF
+    slots = os.popen('cat %s/slots' % pciback_path).read()
+    if re.search(pci_bdf, slots) is None:
+        # write bdf to new_slot
+        cmd = 'echo %s > %s/new_slot' % (pci_bdf, pciback_path)
+        if os.system(cmd):
+            log.debug("Couldn't add device to pciback new_slot")
+            return -1
+
+    # Bind to pciback
+    cmd = 'echo %s > %s/bind' % (pci_bdf, pciback_path)
+    if os.system(cmd):
+        log.debug("Couldn't bind device to pciback")
+        return -1
+
+    return 0
+
+def pci_assignable_remove(dev, rebind):
+    '''unbind pci device from pciback, and rebind to host pci driver where it
+       was detached from in pci-assignable-add.
+    '''
+    sysfs_mnt = find_sysfs_mnt()
+    pcidrv_path = sysfs_mnt + SYSFS_PCI_DRVS_PATH
+    pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH
+    pci_bdf = pci_dict_to_bdf_str(dev)
+
+    # Unbind from pciback
+    path = pciback_path + '/' + pci_bdf
+    if os.path.exists(path):
+        # unbind
+        cmd = 'echo %s > %s/unbind' % (pci_bdf, pciback_path)
+        if os.system(cmd):
+            log.debug("Couldn't unbind device to pciback")
+            return -1
+
+        # remove slots if necessary
+        slots = os.popen('cat %s/slots' % pciback_path).read()
+        if re.search(pci_bdf, slots):
+            # write bdf to remove_slot
+            cmd = 'echo %s > %s/remove_slot' % (pci_bdf, pciback_path)
+            if os.system(cmd):
+                log.debug("Couldn't remove pciback slot")
+                return -1
+    else:
+        log.debug("Not bound to pciback")
+
+    # Rebind if necessary
+    xs_pci_bdf = pci_dict_to_xs_bdf_str(dev)
+    path = XS_PCIBACK_PATH + '/' + xs_pci_bdf
+    drv_path = xstransact.Read(path, 'driver_path')
+    if drv_path:
+        if rebind:
+            cmd = 'echo %s > %s/bind' % (pci_bdf, drv_path)
+            if os.system(cmd):
+                log.debug("Couldn't rebind to driver %s" % drv_path)
+                return -1
+        xstransact.Remove(path)
+    else:
+        if rebind:
+            log.debug("Counldn't find path for original driver.Not rebinding")
+
+    return 0
+
 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.
diff -r 64b36dde26bc -r f0b2ddf43585 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Fri Jan 04 15:58:37 2013 +0000
+++ b/tools/python/xen/xm/main.py       Tue Jan 08 15:03:17 2013 +0800
@@ -211,6 +211,10 @@ SUBCOMMAND_HELP = {
     'pci-list'      :  ('<Domain>',
                         'List pass-through pci devices for a domain.'),
     'pci-list-assignable-devices' : ('', 'List all the assignable pci 
devices'),
+    'pci-assignable-add' : ('<domain:bus:slot.func>',
+                            'Add a pci device to assignable list.'),
+    'pci-assignable-remove' : ('<domain:bus:slot.func>',
+                               'Remove pci device from assignable list.'),
     'scsi-attach'  :  ('<Domain> <PhysDevice> <VirtDevice> [BackDomain]',
                         'Attach a new SCSI device.'),
     'scsi-detach'  :  ('<Domain> <VirtDevice>',
@@ -472,6 +476,8 @@ device_commands = [
     "pci-detach",
     "pci-list",
     "pci-list-assignable-devices",
+    "pci-assignable-add",
+    "pci-assignable-remove",
     "scsi-attach",
     "scsi-detach",
     "scsi-list",
@@ -2488,6 +2494,21 @@ def xm_pci_list_assignable_devices(args)
         pci = parse_pci_info(x)
         print fmt_str % pci
 
+def xm_pci_assignable_add(args):
+    xenapi_unsupported()
+    arg_check(args, "pci-assignable-add", 1)
+
+    pci_dev_str = args[0]
+    pci_dev = parse_pci_name(pci_dev_str)
+    pci_assignable_add(pci_dev, 1)
+
+def xm_pci_assignable_remove(args):
+    xenapi_unsupported()
+    arg_check(args, "pci-assignable-remove", 1)
+    
+    pci_dev_str = args[0]
+    pci_dev = parse_pci_name(pci_dev_str)
+    pci_assignable_remove(pci_dev, 1)
 
 def vscsi_sort(devs):
     def sort_hctl(ds, l):
@@ -3824,6 +3845,8 @@ commands = {
     "pci-detach": xm_pci_detach,
     "pci-list": xm_pci_list,
     "pci-list-assignable-devices": xm_pci_list_assignable_devices,
+    "pci-assignable-add": xm_pci_assignable_add,
+    "pci-assignable-remove": xm_pci_assignable_remove,
     # vscsi
     "scsi-attach": xm_scsi_attach,
     "scsi-detach": xm_scsi_detach,

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.