QnA
QnA

Reputation: 1103

How does Linux kernel set PCI BARs so that there is no address conflict?

As far as I understand, (which could very well be wrong,) each PCI device knows how much(size) iomem/ioport address space it wants to claim, but it does not know where(offset). Only the BIOS or OS can tell the device where that place should be, because somebody has to talk to all PCI devices and coordinate their iomem/ioport address alloc requests so that the allocated addresses don't overlap, and this coordination happens at boot time, or a hotplug event, or during a pci rescan. However, in Linux kernel code, I only find a function (pci_read_bases) that reads out the BAR information, and sets pci_dev & iomem_resource/ioport_resource accordingly, not changing the BARs. So the questions are:

  1. Can OS(Linux kernel) change BAR? Or only BIOS can do that before loading OS?
  2. If kernel can change BAR, where does the logic for coordinating address allocation live? (I did see functions like pbus_assign_resources_sorted, but it seems to me that that function only maps the existing BARs to kernel objects like iomem_resource, not changing BARs)

Upvotes: 3

Views: 1820

Answers (1)

stark
stark

Reputation: 13189

For normal static allocation the BIOS writes BARs and the kernel reads them at boot. What gets interesting is dynamically-assigned devices like hot-plug of NVMe cards. In this case the BIOS has to reserve a range in case a device is plugged which wasn't there at boot time or is larger than the one removed. The kernel gets an interrupt and has to read the new BAR values and add them to the address space. See for example nvme_remap_bar https://elixir.bootlin.com/linux/v5.4/source/drivers/nvme/host/pci.c#L1649

Upvotes: 1

Related Questions