Opened 19 years ago

Last modified 5 weeks ago

#3 in-progress bug

PCI bus_manager does no memory resource assignment

Reported by: marcusoverhagen Owned by: marcusoverhagen
Priority: high Milestone: R1.1
Component: System/Kernel Version: R1/Development
Keywords: Cc: diver
Blocked By: #6213 Blocking: #18558
Platform: All


The PCI bus_manager does no memory resource assignment

Change History (13)

comment:1 by marcusoverhagen, 18 years ago

Status: newassigned

comment:2 by diver, 17 years ago

Cc: diver added

comment:3 by korli, 13 years ago

Blocked By: 6213 added

comment:4 by waddlesplash, 9 years ago

Version: R1/Development

Still an issue?

comment:5 by euan, 8 years ago

A more detailed explanation of why the PCI bus manager needs resource assignment and what it is might help inspire or motivate someone to take up the task.

Last edited 8 years ago by euan (previous) (diff)

comment:6 by anevilyak, 8 years ago

I may be mistaken, but I believe it's mainly for the case of systems where the BIOS only takes care of assigning resources for the bare minimum devices needed to boot, and leaves the rest to the OS (I.e. the "PnP OS" setting one sometimes sees). In such a case, the bus manager needs to take care of resource configuration for the remaining devices in order for them to be usable.

comment:7 by euan, 8 years ago

Sounds familiar. Is it still valid? was this for non acpi compliant systems?

comment:8 by pulkomandy, 3 years ago

Milestone: R1R1.1

comment:9 by X512, 18 months ago

Memory assignment is implemented for riscv64 PCI ECAM: This should be moved or reimplemented in generic PCI bus manager code.

comment:10 by pulkomandy, 18 months ago

Sounds familiar. Is it still valid? was this for non acpi compliant systems?

Yes, it's still valid.

During boot, the BIOS may or may not assign addresses to each device. You can expect that basic devices (graphics, network, etc) will be initialized because the BIOS needs them. Maybe they will assign addresses to everything, but maybe not.

In the case where the BIOS didn't do it, we see that the BAR registers for the affected device will still be 0 (this is visible in syslog when we dump the PCI information). In this case it is up to us to figure out an address for the device. The basic process is:

  • Write FFFFFFFF to the BAR register
  • Read back the register to know how much space the device needs, and if it has constraints (memory or IO space, 32 or 64bit addressing, prefetchable or not).
  • Restore the initial value of the BAR register

We already do these steps in PCI::_GetBarInfo in the PCI bus manager.

After this step we are left with two types of devices:

  • Those which are already mapped by the BIOS, will have an address in their BAR registers already. Now we also know their size.
  • Those which are not already mapped, will have an address of 0. We need to allocate them an address and write it to the BAR register.

Now we need to figure out how to allocate that address. It must be in the memory window of the PCI host controller. In the case of devices that are accessed theough a pci-to-pci bridge, we get that info from the bridge, which specifies which memory space it makes visible. However, in the case of devices attached to the root of the PCI bus, it's not clear how we get the info. Apparently it is platform specific and we know it from how we located the PCI bus in the first place. On x86 we use ACPI for that. I don't see where the info is in the ACPI table we use. If you look at the RISC-V ECAM code you will see that it gets the info from the FDT there.

comment:11 by pulkomandy, 18 months ago

So, after some research, it seems we need to rework our PCI bus detection and initialization quite a bit.

Currently, we find the PCI configuration space by looking at the MCFG ACPI table. This only gives us the address of the configuration space, where we can access the BAR for the PCI devices on the bus.

But the info we need is in the DSDT table, in ACPI nodes with PNP0A03/PNP0A08 cid/hid. Conveniently, ACPICA already detects these and sets the ACPI_PCI_ROOT_BRIDGE flag for us.

We are supposed to find that first, and get the segment and bus numbers from there (_BBN and _SEG methods). From these, we can lookup the corresponding base address in the MCFG. But in addition, we also get the _CRS method, which gives us information about the address range allocated to this PCI bus. Once we know that, we can see which parts of this space are already allocated to devices, and finally use the remaining space to assign addresses to the devices that don't yet have one.

This is how it's done in freeBSD:

Last edited 18 months ago by pulkomandy (previous) (diff)

comment:12 by X512, 18 months ago

If rework is planned, it will be nice to implement dynamic install and uninstall of PCI host controllers instead of assuming that all controllers are discovered at initialization.

comment:13 by pulkomandy, 5 weeks ago

Blocking: 18558 added
Note: See TracTickets for help on using tickets.