From: Bjorn Helgaas <helgaas@kernel.org>
To: Muni Sekhar <munisekharrms@gmail.com>
Cc: linux-pci@vger.kernel.org
Subject: Re: Query Regarding PCI Configuration Space Mapping and BAR Programming
Date: Fri, 21 Mar 2025 12:30:19 -0500 [thread overview]
Message-ID: <20250321173019.GA1133365@bhelgaas> (raw)
In-Reply-To: <CAHhAz+j5TMvoxsSQsgsLcuYqjwjS5Hu_6KXtJigWD-noQTeE9Q@mail.gmail.com>
On Fri, Mar 21, 2025 at 04:38:09PM +0530, Muni Sekhar wrote:
> On Thu, Mar 20, 2025 at 12:45 AM Bjorn Helgaas <helgaas@kernel.org> wrote:
> > On Wed, Mar 19, 2025 at 11:27:07PM +0530, Muni Sekhar wrote:
> > > Dear Linux-PCI Maintainers,
> > >
> > > I have a few questions regarding PCI configuration space and Base
> > > Address Register (BAR) programming:
> > >
> > > PCI Configuration Space Mapping:
> > > PCI devices have standard registers (Device ID, Vendor ID, Status,
> > > Command, etc.) in their configuration space.
> > > These registers are mapped to memory locations.
> >
> > In general, config registers are not mapped to memory locations.
> >
> > Some systems use the ECAM mechanism for config access, which is
> > basically memory-mapped I/O that converts CPU memory accesses to PCI
> > config accesses. This mechanism is hidden inside the Linux config
> > accessors (pci_read_config_word(), etc), and drivers should not use
> > ECAM directly.
>
> Both pci_bus_read_config_word() and pci_user_read_config_word() eventually call:
> res = bus->ops->read(bus, devfn, pos, len, &data);
> ret = dev->bus->ops->read(dev->bus, dev->devfn, pos, sizeof(type), &data);
>
> This suggests that both kernel-space (pci_read_config_*()) and
> user-space (pci_user_read_config_*()) accessors use the same
> underlying function for configuration space access.
> Could you confirm if my understanding is correct?
That's correct.
> I tried locating the implementation of bus->ops->read() but could not
> find its definition in the kernel source.Even using the function_graph
> tracer, I was unable to capture the exact function being executed.
> Could you point me to where this function is defined in the kernel?
Each struct pci_bus has a "struct pci_ops *ops" pointer. The struct
pci_ops supplies config accessors. These are platform-dependent or
host bridge-dependent.
For x86, it's typically pci_root_ops:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/pci/common.c?id=v6.13#n72
> > > How can we determine
> > > the exact memory location where these configuration space registers
> > > are mapped?
> >
> > Drivers use pci_read_config_word() and similar interfaces to access
> > config registers. Userspace can use the setpci utility.
> >
> > > Base Address Registers (BARs) Programming:
> > > How are BAR registers programmed, and what ensures they do not
> > > conflict with other devices mapped memory in the system?
> > > If a BAR mapping clashes with another device’s memory range, how does
> > > the system handle this?
> > >
> > > Does the BIOS/firmware allocate BAR addresses, or does the OS have a
> > > role in reconfiguring them during device initialization?
> >
> > On x86 systems, the BIOS generally assigns BAR addresses. Linux
> > doesn't change these unless they are invalid. Some firmware does not
> > assign BARs, and generally firmware does not assign BARs for hot-added
> > devices. In those cases, Linux assigns them.
>
> Once a hotplug event is detected (either via a PCIe hotplug interrupt
> or an ACPI event), which kernel function is responsible for
> dynamically assigning the Bus, Device, and Function (BDF) number to
> the new device?
The kernel doesn't assign the BDF. The bus number is the bus on which
the new device lives. This is determined by the PCI host bridge and
any bridges in the path to the device. The PCI bus number below a
host bridge is determined by firmware or a native host bridge driver.
The bus numbers below other bridges are configured either by firmware
or by the Linux core setting the bridge secondary bus number. This is
mostly in pci_scan_child_bus_extend().
The device and function numbers are basically a function of the
hardware device.
> Additionally, which function in the kernel assigns Base Address
> Registers (BARs) for the hotplugged device?
Start in pciehp_configure_device(), which calls
pci_assign_unassigned_bridge_resources():
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/hotplug/pciehp_pci.c?id=v6.13#n32
prev parent reply other threads:[~2025-03-21 17:30 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-19 17:57 Query Regarding PCI Configuration Space Mapping and BAR Programming Muni Sekhar
2025-03-19 19:15 ` Bjorn Helgaas
2025-03-20 1:49 ` Hans Zhang
2025-03-21 11:08 ` Muni Sekhar
2025-03-21 17:30 ` Bjorn Helgaas [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250321173019.GA1133365@bhelgaas \
--to=helgaas@kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=munisekharrms@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox