0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/pci.h>
0009 #include <linux/acpi.h>
0010 #include <linux/pci-acpi.h>
0011 #include <xen/pci.h>
0012 #include <xen/xen.h>
0013 #include <xen/interface/physdev.h>
0014 #include <xen/interface/xen.h>
0015
0016 #include <asm/xen/hypervisor.h>
0017 #include <asm/xen/hypercall.h>
0018 #include "../pci/pci.h"
0019 #ifdef CONFIG_PCI_MMCONFIG
0020 #include <asm/pci_x86.h>
0021
0022 static int xen_mcfg_late(void);
0023 #endif
0024
0025 static bool __read_mostly pci_seg_supported = true;
0026
0027 static int xen_add_device(struct device *dev)
0028 {
0029 int r;
0030 struct pci_dev *pci_dev = to_pci_dev(dev);
0031 #ifdef CONFIG_PCI_IOV
0032 struct pci_dev *physfn = pci_dev->physfn;
0033 #endif
0034 #ifdef CONFIG_PCI_MMCONFIG
0035 static bool pci_mcfg_reserved = false;
0036
0037
0038
0039
0040
0041 if (!pci_mcfg_reserved) {
0042 xen_mcfg_late();
0043 pci_mcfg_reserved = true;
0044 }
0045 #endif
0046 if (pci_seg_supported) {
0047 struct {
0048 struct physdev_pci_device_add add;
0049 uint32_t pxm;
0050 } add_ext = {
0051 .add.seg = pci_domain_nr(pci_dev->bus),
0052 .add.bus = pci_dev->bus->number,
0053 .add.devfn = pci_dev->devfn
0054 };
0055 struct physdev_pci_device_add *add = &add_ext.add;
0056
0057 #ifdef CONFIG_ACPI
0058 acpi_handle handle;
0059 #endif
0060
0061 #ifdef CONFIG_PCI_IOV
0062 if (pci_dev->is_virtfn) {
0063 add->flags = XEN_PCI_DEV_VIRTFN;
0064 add->physfn.bus = physfn->bus->number;
0065 add->physfn.devfn = physfn->devfn;
0066 } else
0067 #endif
0068 if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
0069 add->flags = XEN_PCI_DEV_EXTFN;
0070
0071 #ifdef CONFIG_ACPI
0072 handle = ACPI_HANDLE(&pci_dev->dev);
0073 #ifdef CONFIG_PCI_IOV
0074 if (!handle && pci_dev->is_virtfn)
0075 handle = ACPI_HANDLE(physfn->bus->bridge);
0076 #endif
0077 if (!handle) {
0078
0079
0080
0081
0082 struct pci_bus *pbus;
0083 for (pbus = pci_dev->bus; pbus; pbus = pbus->parent) {
0084 handle = acpi_pci_get_bridge_handle(pbus);
0085 if (handle)
0086 break;
0087 }
0088 }
0089 if (handle) {
0090 acpi_status status;
0091
0092 do {
0093 unsigned long long pxm;
0094
0095 status = acpi_evaluate_integer(handle, "_PXM",
0096 NULL, &pxm);
0097 if (ACPI_SUCCESS(status)) {
0098 add->optarr[0] = pxm;
0099 add->flags |= XEN_PCI_DEV_PXM;
0100 break;
0101 }
0102 status = acpi_get_parent(handle, &handle);
0103 } while (ACPI_SUCCESS(status));
0104 }
0105 #endif
0106
0107 r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add);
0108 if (r != -ENOSYS)
0109 return r;
0110 pci_seg_supported = false;
0111 }
0112
0113 if (pci_domain_nr(pci_dev->bus))
0114 r = -ENOSYS;
0115 #ifdef CONFIG_PCI_IOV
0116 else if (pci_dev->is_virtfn) {
0117 struct physdev_manage_pci_ext manage_pci_ext = {
0118 .bus = pci_dev->bus->number,
0119 .devfn = pci_dev->devfn,
0120 .is_virtfn = 1,
0121 .physfn.bus = physfn->bus->number,
0122 .physfn.devfn = physfn->devfn,
0123 };
0124
0125 r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
0126 &manage_pci_ext);
0127 }
0128 #endif
0129 else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
0130 struct physdev_manage_pci_ext manage_pci_ext = {
0131 .bus = pci_dev->bus->number,
0132 .devfn = pci_dev->devfn,
0133 .is_extfn = 1,
0134 };
0135
0136 r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
0137 &manage_pci_ext);
0138 } else {
0139 struct physdev_manage_pci manage_pci = {
0140 .bus = pci_dev->bus->number,
0141 .devfn = pci_dev->devfn,
0142 };
0143
0144 r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add,
0145 &manage_pci);
0146 }
0147
0148 return r;
0149 }
0150
0151 static int xen_remove_device(struct device *dev)
0152 {
0153 int r;
0154 struct pci_dev *pci_dev = to_pci_dev(dev);
0155
0156 if (pci_seg_supported) {
0157 struct physdev_pci_device device = {
0158 .seg = pci_domain_nr(pci_dev->bus),
0159 .bus = pci_dev->bus->number,
0160 .devfn = pci_dev->devfn
0161 };
0162
0163 r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
0164 &device);
0165 } else if (pci_domain_nr(pci_dev->bus))
0166 r = -ENOSYS;
0167 else {
0168 struct physdev_manage_pci manage_pci = {
0169 .bus = pci_dev->bus->number,
0170 .devfn = pci_dev->devfn
0171 };
0172
0173 r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
0174 &manage_pci);
0175 }
0176
0177 return r;
0178 }
0179
0180 static int xen_pci_notifier(struct notifier_block *nb,
0181 unsigned long action, void *data)
0182 {
0183 struct device *dev = data;
0184 int r = 0;
0185
0186 switch (action) {
0187 case BUS_NOTIFY_ADD_DEVICE:
0188 r = xen_add_device(dev);
0189 break;
0190 case BUS_NOTIFY_DEL_DEVICE:
0191 r = xen_remove_device(dev);
0192 break;
0193 default:
0194 return NOTIFY_DONE;
0195 }
0196 if (r)
0197 dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n",
0198 action == BUS_NOTIFY_ADD_DEVICE ? "add" :
0199 (action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?"));
0200 return NOTIFY_OK;
0201 }
0202
0203 static struct notifier_block device_nb = {
0204 .notifier_call = xen_pci_notifier,
0205 };
0206
0207 static int __init register_xen_pci_notifier(void)
0208 {
0209 if (!xen_initial_domain())
0210 return 0;
0211
0212 return bus_register_notifier(&pci_bus_type, &device_nb);
0213 }
0214
0215 arch_initcall(register_xen_pci_notifier);
0216
0217 #ifdef CONFIG_PCI_MMCONFIG
0218 static int xen_mcfg_late(void)
0219 {
0220 struct pci_mmcfg_region *cfg;
0221 int rc;
0222
0223 if (!xen_initial_domain())
0224 return 0;
0225
0226 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
0227 return 0;
0228
0229 if (list_empty(&pci_mmcfg_list))
0230 return 0;
0231
0232
0233 list_for_each_entry(cfg, &pci_mmcfg_list, list) {
0234 struct physdev_pci_mmcfg_reserved r;
0235
0236 r.address = cfg->address;
0237 r.segment = cfg->segment;
0238 r.start_bus = cfg->start_bus;
0239 r.end_bus = cfg->end_bus;
0240 r.flags = XEN_PCI_MMCFG_RESERVED;
0241
0242 rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r);
0243 switch (rc) {
0244 case 0:
0245 case -ENOSYS:
0246 continue;
0247
0248 default:
0249 pr_warn("Failed to report MMCONFIG reservation"
0250 " state for %s to hypervisor"
0251 " (%d)\n",
0252 cfg->name, rc);
0253 }
0254 }
0255 return 0;
0256 }
0257 #endif
0258
0259 #ifdef CONFIG_XEN_DOM0
0260 struct xen_device_domain_owner {
0261 domid_t domain;
0262 struct pci_dev *dev;
0263 struct list_head list;
0264 };
0265
0266 static DEFINE_SPINLOCK(dev_domain_list_spinlock);
0267 static LIST_HEAD(dev_domain_list);
0268
0269 static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
0270 {
0271 struct xen_device_domain_owner *owner;
0272
0273 list_for_each_entry(owner, &dev_domain_list, list) {
0274 if (owner->dev == dev)
0275 return owner;
0276 }
0277 return NULL;
0278 }
0279
0280 int xen_find_device_domain_owner(struct pci_dev *dev)
0281 {
0282 struct xen_device_domain_owner *owner;
0283 int domain = -ENODEV;
0284
0285 spin_lock(&dev_domain_list_spinlock);
0286 owner = find_device(dev);
0287 if (owner)
0288 domain = owner->domain;
0289 spin_unlock(&dev_domain_list_spinlock);
0290 return domain;
0291 }
0292 EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
0293
0294 int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
0295 {
0296 struct xen_device_domain_owner *owner;
0297
0298 owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
0299 if (!owner)
0300 return -ENODEV;
0301
0302 spin_lock(&dev_domain_list_spinlock);
0303 if (find_device(dev)) {
0304 spin_unlock(&dev_domain_list_spinlock);
0305 kfree(owner);
0306 return -EEXIST;
0307 }
0308 owner->domain = domain;
0309 owner->dev = dev;
0310 list_add_tail(&owner->list, &dev_domain_list);
0311 spin_unlock(&dev_domain_list_spinlock);
0312 return 0;
0313 }
0314 EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
0315
0316 int xen_unregister_device_domain_owner(struct pci_dev *dev)
0317 {
0318 struct xen_device_domain_owner *owner;
0319
0320 spin_lock(&dev_domain_list_spinlock);
0321 owner = find_device(dev);
0322 if (!owner) {
0323 spin_unlock(&dev_domain_list_spinlock);
0324 return -ENODEV;
0325 }
0326 list_del(&owner->list);
0327 spin_unlock(&dev_domain_list_spinlock);
0328 kfree(owner);
0329 return 0;
0330 }
0331 EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
0332 #endif