Skip to content

Commit b51f572

Browse files
roygerjfvogel
authored andcommitted
xen/pci: Do not register devices with segments >= 0x10000
[ Upstream commit 5ccf1b8ae76ddf348e02a0d1564ff9baf8b6c415 ] The current hypercall interface for doing PCI device operations always uses a segment field that has a 16 bit width. However on Linux there are buses like VMD that hook up devices into the PCI hierarchy at segment >= 0x10000, after the maximum possible segment enumerated in ACPI. Attempting to register or manage those devices with Xen would result in errors at best, or overlaps with existing devices living on the truncated equivalent segment values. Note also that the VMD segment numbers are arbitrarily assigned by the OS, and hence there would need to be some negotiation between Xen and the OS to agree on how to enumerate VMD segments and devices behind them. Skip notifying Xen about those devices. Given how VMD bridges can multiplex interrupts on behalf of devices behind them there's no need for Xen to be aware of such devices for them to be usable by Linux. Signed-off-by: Roger Pau Monné <[email protected]> Acked-by: Juergen Gross <[email protected]> Message-ID: <[email protected]> Signed-off-by: Juergen Gross <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 3e10592b477ec6e8ea49d8a6c0d52dcb57fa79d0) Signed-off-by: Jack Vogel <[email protected]>
1 parent f65be26 commit b51f572

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

drivers/xen/pci.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ static int xen_add_device(struct device *dev)
4343
pci_mcfg_reserved = true;
4444
}
4545
#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+
4658
if (pci_seg_supported) {
4759
DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1);
4860

@@ -149,6 +161,16 @@ static int xen_remove_device(struct device *dev)
149161
int r;
150162
struct pci_dev *pci_dev = to_pci_dev(dev);
151163

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+
152174
if (pci_seg_supported) {
153175
struct physdev_pci_device device = {
154176
.seg = pci_domain_nr(pci_dev->bus),
@@ -182,6 +204,16 @@ int xen_reset_device(const struct pci_dev *dev)
182204
.flags = PCI_DEVICE_RESET_FLR,
183205
};
184206

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+
185217
return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device);
186218
}
187219
EXPORT_SYMBOL_GPL(xen_reset_device);

0 commit comments

Comments
 (0)