1 /* 2 * PCI Backend - Provides restricted access to the real PCI bus topology 3 * to the frontend 4 * 5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 6 */ 7 8 #include <linux/list.h> 9 #include <linux/pci.h> 10 #include <linux/mutex.h> 11 #include "pciback.h" 12 13 struct passthrough_dev_data { 14 /* Access to dev_list must be protected by lock */ 15 struct list_head dev_list; 16 struct mutex lock; 17 }; 18 19 static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev, 20 unsigned int domain, 21 unsigned int bus, 22 unsigned int devfn) 23 { 24 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 25 struct pci_dev_entry *dev_entry; 26 struct pci_dev *dev = NULL; 27 28 mutex_lock(&dev_data->lock); 29 30 list_for_each_entry(dev_entry, &dev_data->dev_list, list) { 31 if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus) 32 && bus == (unsigned int)dev_entry->dev->bus->number 33 && devfn == dev_entry->dev->devfn) { 34 dev = dev_entry->dev; 35 break; 36 } 37 } 38 39 mutex_unlock(&dev_data->lock); 40 41 return dev; 42 } 43 44 static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, 45 struct pci_dev *dev, 46 int devid, publish_pci_dev_cb publish_cb) 47 { 48 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 49 struct pci_dev_entry *dev_entry; 50 unsigned int domain, bus, devfn; 51 int err; 52 53 dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL); 54 if (!dev_entry) 55 return -ENOMEM; 56 dev_entry->dev = dev; 57 58 mutex_lock(&dev_data->lock); 59 list_add_tail(&dev_entry->list, &dev_data->dev_list); 60 mutex_unlock(&dev_data->lock); 61 62 /* Publish this device. */ 63 domain = (unsigned int)pci_domain_nr(dev->bus); 64 bus = (unsigned int)dev->bus->number; 65 devfn = dev->devfn; 66 err = publish_cb(pdev, domain, bus, devfn, devid); 67 68 return err; 69 } 70 71 static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 72 struct pci_dev *dev) 73 { 74 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 75 struct pci_dev_entry *dev_entry, *t; 76 struct pci_dev *found_dev = NULL; 77 78 mutex_lock(&dev_data->lock); 79 80 list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) { 81 if (dev_entry->dev == dev) { 82 list_del(&dev_entry->list); 83 found_dev = dev_entry->dev; 84 kfree(dev_entry); 85 } 86 } 87 88 mutex_unlock(&dev_data->lock); 89 90 if (found_dev) 91 pcistub_put_pci_dev(found_dev); 92 } 93 94 static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 95 { 96 struct passthrough_dev_data *dev_data; 97 98 dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL); 99 if (!dev_data) 100 return -ENOMEM; 101 102 mutex_init(&dev_data->lock); 103 104 INIT_LIST_HEAD(&dev_data->dev_list); 105 106 pdev->pci_dev_data = dev_data; 107 108 return 0; 109 } 110 111 static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev, 112 publish_pci_root_cb publish_root_cb) 113 { 114 int err = 0; 115 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 116 struct pci_dev_entry *dev_entry, *e; 117 struct pci_dev *dev; 118 int found; 119 unsigned int domain, bus; 120 121 mutex_lock(&dev_data->lock); 122 123 list_for_each_entry(dev_entry, &dev_data->dev_list, list) { 124 /* Only publish this device as a root if none of its 125 * parent bridges are exported 126 */ 127 found = 0; 128 dev = dev_entry->dev->bus->self; 129 for (; !found && dev != NULL; dev = dev->bus->self) { 130 list_for_each_entry(e, &dev_data->dev_list, list) { 131 if (dev == e->dev) { 132 found = 1; 133 break; 134 } 135 } 136 } 137 138 domain = (unsigned int)pci_domain_nr(dev_entry->dev->bus); 139 bus = (unsigned int)dev_entry->dev->bus->number; 140 141 if (!found) { 142 err = publish_root_cb(pdev, domain, bus); 143 if (err) 144 break; 145 } 146 } 147 148 mutex_unlock(&dev_data->lock); 149 150 return err; 151 } 152 153 static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev) 154 { 155 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 156 struct pci_dev_entry *dev_entry, *t; 157 158 list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) { 159 list_del(&dev_entry->list); 160 pcistub_put_pci_dev(dev_entry->dev); 161 kfree(dev_entry); 162 } 163 164 kfree(dev_data); 165 pdev->pci_dev_data = NULL; 166 } 167 168 static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev, 169 struct xen_pcibk_device *pdev, 170 unsigned int *domain, unsigned int *bus, 171 unsigned int *devfn) 172 { 173 *domain = pci_domain_nr(pcidev->bus); 174 *bus = pcidev->bus->number; 175 *devfn = pcidev->devfn; 176 return 1; 177 } 178 179 const struct xen_pcibk_backend xen_pcibk_passthrough_backend = { 180 .name = "passthrough", 181 .init = __xen_pcibk_init_devices, 182 .free = __xen_pcibk_release_devices, 183 .find = __xen_pcibk_get_pcifront_dev, 184 .publish = __xen_pcibk_publish_pci_roots, 185 .release = __xen_pcibk_release_pci_dev, 186 .add = __xen_pcibk_add_pci_dev, 187 .get = __xen_pcibk_get_pci_dev, 188 }; 189