xref: /linux/drivers/xen/pci.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10) !
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 
xen_add_device(struct device * dev)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 
47 	if (pci_domain_nr(pci_dev->bus) >> 16) {
48 		/*
49 		 * The hypercall interface is limited to 16bit PCI segment
50 		 * values, do not attempt to register devices with Xen in
51 		 * segments greater or equal than 0x10000.
52 		 */
53 		dev_info(dev,
54 			 "not registering with Xen: invalid PCI segment\n");
55 		return 0;
56 	}
57 
58 	if (pci_seg_supported) {
59 		DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1);
60 
61 		add->seg = pci_domain_nr(pci_dev->bus);
62 		add->bus = pci_dev->bus->number;
63 		add->devfn = pci_dev->devfn;
64 
65 #ifdef CONFIG_ACPI
66 		acpi_handle handle;
67 #endif
68 
69 #ifdef CONFIG_PCI_IOV
70 		if (pci_dev->is_virtfn) {
71 			add->flags = XEN_PCI_DEV_VIRTFN;
72 			add->physfn.bus = physfn->bus->number;
73 			add->physfn.devfn = physfn->devfn;
74 		} else
75 #endif
76 		if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
77 			add->flags = XEN_PCI_DEV_EXTFN;
78 
79 #ifdef CONFIG_ACPI
80 		handle = ACPI_HANDLE(&pci_dev->dev);
81 #ifdef CONFIG_PCI_IOV
82 		if (!handle && pci_dev->is_virtfn)
83 			handle = ACPI_HANDLE(physfn->bus->bridge);
84 #endif
85 		if (!handle) {
86 			/*
87 			 * This device was not listed in the ACPI name space at
88 			 * all. Try to get acpi handle of parent pci bus.
89 			 */
90 			struct pci_bus *pbus;
91 			for (pbus = pci_dev->bus; pbus; pbus = pbus->parent) {
92 				handle = acpi_pci_get_bridge_handle(pbus);
93 				if (handle)
94 					break;
95 			}
96 		}
97 		if (handle) {
98 			acpi_status status;
99 
100 			do {
101 				unsigned long long pxm;
102 
103 				status = acpi_evaluate_integer(handle, "_PXM",
104 							       NULL, &pxm);
105 				if (ACPI_SUCCESS(status)) {
106 					add->optarr[0] = pxm;
107 					add->flags |= XEN_PCI_DEV_PXM;
108 					break;
109 				}
110 				status = acpi_get_parent(handle, &handle);
111 			} while (ACPI_SUCCESS(status));
112 		}
113 #endif /* CONFIG_ACPI */
114 
115 		r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add);
116 		if (r != -ENOSYS)
117 			return r;
118 		pci_seg_supported = false;
119 	}
120 
121 	if (pci_domain_nr(pci_dev->bus))
122 		r = -ENOSYS;
123 #ifdef CONFIG_PCI_IOV
124 	else if (pci_dev->is_virtfn) {
125 		struct physdev_manage_pci_ext manage_pci_ext = {
126 			.bus		= pci_dev->bus->number,
127 			.devfn		= pci_dev->devfn,
128 			.is_virtfn 	= 1,
129 			.physfn.bus	= physfn->bus->number,
130 			.physfn.devfn	= physfn->devfn,
131 		};
132 
133 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
134 			&manage_pci_ext);
135 	}
136 #endif
137 	else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
138 		struct physdev_manage_pci_ext manage_pci_ext = {
139 			.bus		= pci_dev->bus->number,
140 			.devfn		= pci_dev->devfn,
141 			.is_extfn	= 1,
142 		};
143 
144 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
145 			&manage_pci_ext);
146 	} else {
147 		struct physdev_manage_pci manage_pci = {
148 			.bus	= pci_dev->bus->number,
149 			.devfn	= pci_dev->devfn,
150 		};
151 
152 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add,
153 			&manage_pci);
154 	}
155 
156 	return r;
157 }
158 
xen_remove_device(struct device * dev)159 static int xen_remove_device(struct device *dev)
160 {
161 	int r;
162 	struct pci_dev *pci_dev = to_pci_dev(dev);
163 
164 	if (pci_domain_nr(pci_dev->bus) >> 16) {
165 		/*
166 		 * The hypercall interface is limited to 16bit PCI segment
167 		 * values.
168 		 */
169 		dev_info(dev,
170 			 "not unregistering with Xen: invalid PCI segment\n");
171 		return 0;
172 	}
173 
174 	if (pci_seg_supported) {
175 		struct physdev_pci_device device = {
176 			.seg = pci_domain_nr(pci_dev->bus),
177 			.bus = pci_dev->bus->number,
178 			.devfn = pci_dev->devfn
179 		};
180 
181 		r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
182 					  &device);
183 	} else if (pci_domain_nr(pci_dev->bus))
184 		r = -ENOSYS;
185 	else {
186 		struct physdev_manage_pci manage_pci = {
187 			.bus = pci_dev->bus->number,
188 			.devfn = pci_dev->devfn
189 		};
190 
191 		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
192 					  &manage_pci);
193 	}
194 
195 	return r;
196 }
197 
xen_reset_device(const struct pci_dev * dev)198 int xen_reset_device(const struct pci_dev *dev)
199 {
200 	struct pci_device_reset device = {
201 		.dev.seg = pci_domain_nr(dev->bus),
202 		.dev.bus = dev->bus->number,
203 		.dev.devfn = dev->devfn,
204 		.flags = PCI_DEVICE_RESET_FLR,
205 	};
206 
207 	if (pci_domain_nr(dev->bus) >> 16) {
208 		/*
209 		 * The hypercall interface is limited to 16bit PCI segment
210 		 * values.
211 		 */
212 		dev_info(&dev->dev,
213 			 "unable to notify Xen of device reset: invalid PCI segment\n");
214 		return 0;
215 	}
216 
217 	return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device);
218 }
219 EXPORT_SYMBOL_GPL(xen_reset_device);
220 
xen_pci_notifier(struct notifier_block * nb,unsigned long action,void * data)221 static int xen_pci_notifier(struct notifier_block *nb,
222 			    unsigned long action, void *data)
223 {
224 	struct device *dev = data;
225 	int r = 0;
226 
227 	switch (action) {
228 	case BUS_NOTIFY_ADD_DEVICE:
229 		r = xen_add_device(dev);
230 		break;
231 	case BUS_NOTIFY_DEL_DEVICE:
232 		r = xen_remove_device(dev);
233 		break;
234 	default:
235 		return NOTIFY_DONE;
236 	}
237 	if (r)
238 		dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n",
239 			action == BUS_NOTIFY_ADD_DEVICE ? "add" :
240 			(action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?"));
241 	return NOTIFY_OK;
242 }
243 
244 static struct notifier_block device_nb = {
245 	.notifier_call = xen_pci_notifier,
246 };
247 
register_xen_pci_notifier(void)248 static int __init register_xen_pci_notifier(void)
249 {
250 	if (!xen_initial_domain())
251 		return 0;
252 
253 	return bus_register_notifier(&pci_bus_type, &device_nb);
254 }
255 
256 arch_initcall(register_xen_pci_notifier);
257 
258 #ifdef CONFIG_PCI_MMCONFIG
xen_mcfg_late(void)259 static int xen_mcfg_late(void)
260 {
261 	struct pci_mmcfg_region *cfg;
262 	int rc;
263 
264 	if (!xen_initial_domain())
265 		return 0;
266 
267 	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
268 		return 0;
269 
270 	if (list_empty(&pci_mmcfg_list))
271 		return 0;
272 
273 	/* Check whether they are in the right area. */
274 	list_for_each_entry(cfg, &pci_mmcfg_list, list) {
275 		struct physdev_pci_mmcfg_reserved r;
276 
277 		r.address = cfg->address;
278 		r.segment = cfg->segment;
279 		r.start_bus = cfg->start_bus;
280 		r.end_bus = cfg->end_bus;
281 		r.flags = XEN_PCI_MMCFG_RESERVED;
282 
283 		rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r);
284 		switch (rc) {
285 		case 0:
286 		case -ENOSYS:
287 			continue;
288 
289 		default:
290 			pr_warn("Failed to report MMCONFIG reservation"
291 				" state for %s to hypervisor"
292 				" (%d)\n",
293 				cfg->name, rc);
294 		}
295 	}
296 	return 0;
297 }
298 #endif
299 
300 #ifdef CONFIG_XEN_DOM0
301 struct xen_device_domain_owner {
302 	domid_t domain;
303 	struct pci_dev *dev;
304 	struct list_head list;
305 };
306 
307 static DEFINE_SPINLOCK(dev_domain_list_spinlock);
308 static LIST_HEAD(dev_domain_list);
309 
find_device(struct pci_dev * dev)310 static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
311 {
312 	struct xen_device_domain_owner *owner;
313 
314 	list_for_each_entry(owner, &dev_domain_list, list) {
315 		if (owner->dev == dev)
316 			return owner;
317 	}
318 	return NULL;
319 }
320 
xen_find_device_domain_owner(struct pci_dev * dev)321 int xen_find_device_domain_owner(struct pci_dev *dev)
322 {
323 	struct xen_device_domain_owner *owner;
324 	int domain = -ENODEV;
325 
326 	spin_lock(&dev_domain_list_spinlock);
327 	owner = find_device(dev);
328 	if (owner)
329 		domain = owner->domain;
330 	spin_unlock(&dev_domain_list_spinlock);
331 	return domain;
332 }
333 EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
334 
xen_register_device_domain_owner(struct pci_dev * dev,uint16_t domain)335 int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
336 {
337 	struct xen_device_domain_owner *owner;
338 
339 	owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
340 	if (!owner)
341 		return -ENODEV;
342 
343 	spin_lock(&dev_domain_list_spinlock);
344 	if (find_device(dev)) {
345 		spin_unlock(&dev_domain_list_spinlock);
346 		kfree(owner);
347 		return -EEXIST;
348 	}
349 	owner->domain = domain;
350 	owner->dev = dev;
351 	list_add_tail(&owner->list, &dev_domain_list);
352 	spin_unlock(&dev_domain_list_spinlock);
353 	return 0;
354 }
355 EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
356 
xen_unregister_device_domain_owner(struct pci_dev * dev)357 int xen_unregister_device_domain_owner(struct pci_dev *dev)
358 {
359 	struct xen_device_domain_owner *owner;
360 
361 	spin_lock(&dev_domain_list_spinlock);
362 	owner = find_device(dev);
363 	if (!owner) {
364 		spin_unlock(&dev_domain_list_spinlock);
365 		return -ENODEV;
366 	}
367 	list_del(&owner->list);
368 	spin_unlock(&dev_domain_list_spinlock);
369 	kfree(owner);
370 	return 0;
371 }
372 EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
373 #endif
374