Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen/pci: Do not register devices with segments >= 0x10000

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é <roger.pau@citrix.com>
Acked-by: Juergen Gross <jgross@suse.com>
Message-ID: <20250219092059.90850-2-roger.pau@citrix.com>
Signed-off-by: Juergen Gross <jgross@suse.com>

authored by

Roger Pau Monne and committed by
Juergen Gross
5ccf1b8a 421d62f4

+32
+32
drivers/xen/pci.c
··· 43 43 pci_mcfg_reserved = true; 44 44 } 45 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 + 46 58 if (pci_seg_supported) { 47 59 DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1); 48 60 ··· 161 149 int r; 162 150 struct pci_dev *pci_dev = to_pci_dev(dev); 163 151 152 + if (pci_domain_nr(pci_dev->bus) >> 16) { 153 + /* 154 + * The hypercall interface is limited to 16bit PCI segment 155 + * values. 156 + */ 157 + dev_info(dev, 158 + "not unregistering with Xen: invalid PCI segment\n"); 159 + return 0; 160 + } 161 + 164 162 if (pci_seg_supported) { 165 163 struct physdev_pci_device device = { 166 164 .seg = pci_domain_nr(pci_dev->bus), ··· 203 181 .dev.devfn = dev->devfn, 204 182 .flags = PCI_DEVICE_RESET_FLR, 205 183 }; 184 + 185 + if (pci_domain_nr(dev->bus) >> 16) { 186 + /* 187 + * The hypercall interface is limited to 16bit PCI segment 188 + * values. 189 + */ 190 + dev_info(&dev->dev, 191 + "unable to notify Xen of device reset: invalid PCI segment\n"); 192 + return 0; 193 + } 206 194 207 195 return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device); 208 196 }