xref: /linux/drivers/xen/pci.c (revision 55d0969c451159cff86949b38c39171cab962069)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2009, Intel Corporation.
4  *
5  * Author: Weidong Han <weidong.han@intel.com>
6  */
7 
8 #include <linux/pci.h>
9 #include <linux/acpi.h>
10 #include <linux/pci-acpi.h>
11 #include <xen/pci.h>
12 #include <xen/xen.h>
13 #include <xen/interface/physdev.h>
14 #include <xen/interface/xen.h>
15 
16 #include <asm/xen/hypervisor.h>
17 #include <asm/xen/hypercall.h>
18 #include "../pci/pci.h"
19 #ifdef CONFIG_PCI_MMCONFIG
20 #include <asm/pci_x86.h>
21 
22 static int xen_mcfg_late(void);
23 #endif
24 
25 static bool __read_mostly pci_seg_supported = true;
26 
27 static int xen_add_device(struct device *dev)
28 {
29 	int r;
30 	struct pci_dev *pci_dev = to_pci_dev(dev);
31 #ifdef CONFIG_PCI_IOV
32 	struct pci_dev *physfn = pci_dev->physfn;
33 #endif
34 #ifdef CONFIG_PCI_MMCONFIG
35 	static bool pci_mcfg_reserved = false;
36 	/*
37 	 * Reserve MCFG areas in Xen on first invocation due to this being
38 	 * potentially called from inside of acpi_init immediately after
39 	 * MCFG table has been finally parsed.
40 	 */
41 	if (!pci_mcfg_reserved) {
42 		xen_mcfg_late();
43 		pci_mcfg_reserved = true;
44 	}
45 #endif
46 	if (pci_seg_supported) {
47 		DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1);
48 
49 		add->seg = pci_domain_nr(pci_dev->bus);
50 		add->bus = pci_dev->bus->number;
51 		add->devfn = pci_dev->devfn;
52 
53 #ifdef CONFIG_ACPI
54 		acpi_handle handle;
55 #endif
56 
57 #ifdef CONFIG_PCI_IOV
58 		if (pci_dev->is_virtfn) {
59 			add->flags = XEN_PCI_DEV_VIRTFN;
60 			add->physfn.bus = physfn->bus->number;
61 			add->physfn.devfn = physfn->devfn;
62 		} else
63 #endif
64 		if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
65 			add->flags = XEN_PCI_DEV_EXTFN;
66 
67 #ifdef CONFIG_ACPI
68 		handle = ACPI_HANDLE(&pci_dev->dev);
69 #ifdef CONFIG_PCI_IOV
70 		if (!handle && pci_dev->is_virtfn)
71 			handle = ACPI_HANDLE(physfn->bus->bridge);
72 #endif
73 		if (!handle) {
74 			/*
75 			 * This device was not listed in the ACPI name space at
76 			 * all. Try to get acpi handle of parent pci bus.
77 			 */
78 			struct pci_bus *pbus;
79 			for (pbus = pci_dev->bus; pbus; pbus = pbus->parent) {
80 				handle = acpi_pci_get_bridge_handle(pbus);
81 				if (handle)
82 					break;
83 			}
84 		}
85 		if (handle) {
86 			acpi_status status;
87 
88 			do {
89 				unsigned long long pxm;
90 
91 				status = acpi_evaluate_integer(handle, "_PXM",
92 							       NULL, &pxm);
93 				if (ACPI_SUCCESS(status)) {
94 					add->optarr[0] = pxm;
95 					add->flags |= XEN_PCI_DEV_PXM;
96 					break;
97 				}
98 				status = acpi_get_parent(handle, &handle);
99 			} while (ACPI_SUCCESS(status));
100 		}
101 #endif /* CONFIG_ACPI */
102 
103 		r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add);
104 		if (r != -ENOSYS)
105 			return r;
106 		pci_seg_supported = false;
107 	}
108 
109 	if (pci_domain_nr(pci_dev->bus))
110 		r = -ENOSYS;
111 #ifdef CONFIG_PCI_IOV
112 	else if (pci_dev->is_virtfn) {
113 		struct physdev_manage_pci_ext manage_pci_ext = {
114 			.bus		= pci_dev->bus->number,
115 			.devfn		= pci_dev->devfn,
116 			.is_virtfn 	= 1,
117 			.physfn.bus	= physfn->bus->number,
118 			.physfn.devfn	= physfn->devfn,
119 		};
120 
121 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
122 			&manage_pci_ext);
123 	}
124 #endif
125 	else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
126 		struct physdev_manage_pci_ext manage_pci_ext = {
127 			.bus		= pci_dev->bus->number,
128 			.devfn		= pci_dev->devfn,
129 			.is_extfn	= 1,
130 		};
131 
132 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
133 			&manage_pci_ext);
134 	} else {
135 		struct physdev_manage_pci manage_pci = {
136 			.bus	= pci_dev->bus->number,
137 			.devfn	= pci_dev->devfn,
138 		};
139 
140 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add,
141 			&manage_pci);
142 	}
143 
144 	return r;
145 }
146 
147 static int xen_remove_device(struct device *dev)
148 {
149 	int r;
150 	struct pci_dev *pci_dev = to_pci_dev(dev);
151 
152 	if (pci_seg_supported) {
153 		struct physdev_pci_device device = {
154 			.seg = pci_domain_nr(pci_dev->bus),
155 			.bus = pci_dev->bus->number,
156 			.devfn = pci_dev->devfn
157 		};
158 
159 		r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
160 					  &device);
161 	} else if (pci_domain_nr(pci_dev->bus))
162 		r = -ENOSYS;
163 	else {
164 		struct physdev_manage_pci manage_pci = {
165 			.bus = pci_dev->bus->number,
166 			.devfn = pci_dev->devfn
167 		};
168 
169 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
170 					  &manage_pci);
171 	}
172 
173 	return r;
174 }
175 
176 int xen_reset_device(const struct pci_dev *dev)
177 {
178 	struct pci_device_reset device = {
179 		.dev.seg = pci_domain_nr(dev->bus),
180 		.dev.bus = dev->bus->number,
181 		.dev.devfn = dev->devfn,
182 		.flags = PCI_DEVICE_RESET_FLR,
183 	};
184 
185 	return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device);
186 }
187 EXPORT_SYMBOL_GPL(xen_reset_device);
188 
189 static int xen_pci_notifier(struct notifier_block *nb,
190 			    unsigned long action, void *data)
191 {
192 	struct device *dev = data;
193 	int r = 0;
194 
195 	switch (action) {
196 	case BUS_NOTIFY_ADD_DEVICE:
197 		r = xen_add_device(dev);
198 		break;
199 	case BUS_NOTIFY_DEL_DEVICE:
200 		r = xen_remove_device(dev);
201 		break;
202 	default:
203 		return NOTIFY_DONE;
204 	}
205 	if (r)
206 		dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n",
207 			action == BUS_NOTIFY_ADD_DEVICE ? "add" :
208 			(action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?"));
209 	return NOTIFY_OK;
210 }
211 
212 static struct notifier_block device_nb = {
213 	.notifier_call = xen_pci_notifier,
214 };
215 
216 static int __init register_xen_pci_notifier(void)
217 {
218 	if (!xen_initial_domain())
219 		return 0;
220 
221 	return bus_register_notifier(&pci_bus_type, &device_nb);
222 }
223 
224 arch_initcall(register_xen_pci_notifier);
225 
226 #ifdef CONFIG_PCI_MMCONFIG
227 static int xen_mcfg_late(void)
228 {
229 	struct pci_mmcfg_region *cfg;
230 	int rc;
231 
232 	if (!xen_initial_domain())
233 		return 0;
234 
235 	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
236 		return 0;
237 
238 	if (list_empty(&pci_mmcfg_list))
239 		return 0;
240 
241 	/* Check whether they are in the right area. */
242 	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
243 		struct physdev_pci_mmcfg_reserved r;
244 
245 		r.address = cfg->address;
246 		r.segment = cfg->segment;
247 		r.start_bus = cfg->start_bus;
248 		r.end_bus = cfg->end_bus;
249 		r.flags = XEN_PCI_MMCFG_RESERVED;
250 
251 		rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r);
252 		switch (rc) {
253 		case 0:
254 		case -ENOSYS:
255 			continue;
256 
257 		default:
258 			pr_warn("Failed to report MMCONFIG reservation"
259 				" state for %s to hypervisor"
260 				" (%d)\n",
261 				cfg->name, rc);
262 		}
263 	}
264 	return 0;
265 }
266 #endif
267 
268 #ifdef CONFIG_XEN_DOM0
269 struct xen_device_domain_owner {
270 	domid_t domain;
271 	struct pci_dev *dev;
272 	struct list_head list;
273 };
274 
275 static DEFINE_SPINLOCK(dev_domain_list_spinlock);
276 static LIST_HEAD(dev_domain_list);
277 
278 static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
279 {
280 	struct xen_device_domain_owner *owner;
281 
282 	list_for_each_entry(owner, &dev_domain_list, list) {
283 		if (owner->dev == dev)
284 			return owner;
285 	}
286 	return NULL;
287 }
288 
289 int xen_find_device_domain_owner(struct pci_dev *dev)
290 {
291 	struct xen_device_domain_owner *owner;
292 	int domain = -ENODEV;
293 
294 	spin_lock(&dev_domain_list_spinlock);
295 	owner = find_device(dev);
296 	if (owner)
297 		domain = owner->domain;
298 	spin_unlock(&dev_domain_list_spinlock);
299 	return domain;
300 }
301 EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
302 
303 int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
304 {
305 	struct xen_device_domain_owner *owner;
306 
307 	owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
308 	if (!owner)
309 		return -ENODEV;
310 
311 	spin_lock(&dev_domain_list_spinlock);
312 	if (find_device(dev)) {
313 		spin_unlock(&dev_domain_list_spinlock);
314 		kfree(owner);
315 		return -EEXIST;
316 	}
317 	owner->domain = domain;
318 	owner->dev = dev;
319 	list_add_tail(&owner->list, &dev_domain_list);
320 	spin_unlock(&dev_domain_list_spinlock);
321 	return 0;
322 }
323 EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
324 
325 int xen_unregister_device_domain_owner(struct pci_dev *dev)
326 {
327 	struct xen_device_domain_owner *owner;
328 
329 	spin_lock(&dev_domain_list_spinlock);
330 	owner = find_device(dev);
331 	if (!owner) {
332 		spin_unlock(&dev_domain_list_spinlock);
333 		return -ENODEV;
334 	}
335 	list_del(&owner->list);
336 	spin_unlock(&dev_domain_list_spinlock);
337 	kfree(owner);
338 	return 0;
339 }
340 EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
341 #endif
342