Page 1 of 1

BIOS PCI enumeration question

Posted: Wed Nov 11, 2015 4:34 am
by stdcall
Hey.
I'm a bit confused about the enumeration process of the PCI in x86 BIOS.
What I don't understand, is what is finally written to the BAR's by the BIOS.
In few places in the internet, It states that before reading the size mask, the BAR value is read and restored to the BAR afterwards.
And in other places I read that the BIOS write's the actual mapped memory address back to the BAR.

If the first is true,
How does the PCI device knows where it has been mapped ?

Thanks
Ramon

Re: BIOS PCI enumeration question

Posted: Wed Nov 11, 2015 6:58 am
by Brendan
Hi,
mellowcandle wrote:I'm a bit confused about the enumeration process of the PCI in x86 BIOS.
What I don't understand, is what is finally written to the BAR's by the BIOS.
In few places in the internet, It states that before reading the size mask, the BAR value is read and restored to the BAR afterwards.
And in other places I read that the BIOS write's the actual mapped memory address back to the BAR.
The lowest bits of the BAR's address part are hardwired to zero to indicate the size (and minimum alignment) of the area that the device needs. If the BAR's address part contains 0x00000000 you can't know how many bits are hardwired to zero with that information alone. You'd have to write "all ones" and read it back to determine how many bits are hardwired to zero. If you read it back and get (e.g.) 0xFFFF0000 then you know (or can determine - e.g. using "not then increment") that the size required by the device is 0x00010000 bytes. Of course if you don't want to trash whatever was in the BAR beforehand (which is relatively typical for an OS) then you'll need to save the original contents and restore it after.

When a computer is first turned on the PCI devices (and their BARs) aren't configured yet, and the PCI devices are essentially disabled (note: there are a few exceptions to this, but that's the general idea). It's firmware's responsibility to examine the PCI devices, allocate areas of the physical address for them, configure them (their BARs, IRQs, etc), and enable them. For fun I'm going to call this "PCI device resource assignment".

Note that an OS might just rely on "PCI device resource assignment" done by firmware; or it might do "PCI device resource assignment" itself from scratch. It turns out that in some cases (hot-plug PCI) the OS mostly has to be able to do it itself (at least partially).

How "PCI device resource assignment" works is a little complicated; as there's other constraints to worry about. Specifically; where bridges are involved the bride has a "range of addresses to forward from primary bus to secondary bus", which means that all devices on any sub-bus need to be configured to use the same range. The other complication is that PCI devices require "natural alignment" - an "X byte" area has to be aligned on an "X byte" boundary.

You could assign physical address space to devices one at a time in the order they're found; but that can cause a lot of space wasted for aligning areas. For example, if the first device wants 128 MiB, the second device wants 1 MiB and the third device wants 128 MiB, then that middle area is going to cause 127 MiB of the physical address space to be wasted. Much smarter is to examine a sub-bus and arrange the areas in order of smallest to largest (or from largest to smallest) to minimise space wasted for alignment.

This is done recursively, using "depth first" (e.g. resources assigned to child sub-buses before you start worrying about parent sub-buses), while configuring bridges as you go.

The other thing that complicates it is that there may not be enough space in the first 4 GiB of the physical address space (e.g. maybe 3 GiB of it is RAM, and there's normally also things like ROM/firmware, APICs, HPET, etc). If you need more space for PCI devices, then you have to look at which devices (and bridges) support 64-bit addresses. If anything on a sub-bus can't handle 64-bit addresses then everything on that sub-bus must go in the first 4 GiB of the physical address space.

As I'm sure you can imagine, it gets messy. ;)


Cheers,

Brendan

Re: BIOS PCI enumeration question

Posted: Wed Nov 11, 2015 8:04 am
by SpyderTL
mellowcandle wrote: How does the PCI device knows where it has been mapped?
The PCI registers (including the BAR registers) are actually physically located on the PCI device, so when the BIOS changes a devices address, it immediately knows its new address.

Re: BIOS PCI enumeration question

Posted: Thu Nov 12, 2015 8:03 am
by stdcall
Thanks ! now it's clear.