Better way of scanning PCE?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Better way of scanning PCE?

Post by Ethin »

So, I've just managed to get PCE working. (Hooray!) I'mable to enumerate all possible PCI devices on the system. The problem is, of course... that its, well... really, reaaaaally slow. Right now I scan for all 16,777,216 possible devices like this:

Code: Select all

pub fn probe() {
    printkln!("Init: PCI scan started");
    if let Ok(table) = acpi::init() {
        if let Some(regions) = table.pci_config_regions {
            for sg in 0..MAX_SG {
                for bus in 0..MAX_BUS {
                    for device in 0..MAX_DEVICE {
                        for function in 0..MAX_FUNCTION {
                            if let Some(addr) = regions.physical_address(
                                sg as u16,
                                bus as u8,
                                device as u8,
                                function as u8,
                            ) {
                                // Do this check anyway
                                use crate::memory::{allocate_phys_range, free_range};
                                allocate_phys_range(addr.clone(), addr.clone() + 4096);
                                if (read_dword(addr as usize, VENDOR_ID) & 0xFFFF) == 0xFFFF {
                                    free_range(addr.clone(), addr.clone() + 4096);
                                    continue;
                                }
                                // Add the device...
                            } else {
                                continue;
                            }
                        }
                    }
                }
            }
            let devs = PCI_DEVICES.read();
            printkln!("init: PCI scan complete; {} devices found", devs.len());
        } else {
            printkln!("init: error: no PCI regions");
        }
    } else {
        printkln!("init: error: ACPI unsupported");
    }
}
As you can imagine, this is absolutely insane. Is there a better way of doing this that doesn't require me to scan segment groups that don't exist?
Edit: Also, if I scan a segment group and ask for all devices on BDF 0:0:0, can I safely assume that no devices exist if I ask for <sg here>:0:0:0 but I don't get anything on that sg:bus:dev:func? Like, if I ask the system for segment group 32, and BDF 0:0:0, can I safely assume that there are no devices in SG 32 if I get nothing back?
Octocontrabass
Member
Member
Posts: 5572
Joined: Mon Mar 25, 2013 7:01 pm

Re: Better way of scanning PCE?

Post by Octocontrabass »

You meant PCIe instead of PCE, right?

The ACPI MCFG table describes all valid sg:bus combinations and their MMIO addresses. You can't scan segment groups or buses that don't exist, since they have no MMIO address, so your scan will be quite fast even if you do scan all existing segment groups and buses.

The MCFG table doesn't describe hot-pluggable devices, in case you have some of those and want to know why your scan doesn't find them.
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Better way of scanning PCE?

Post by Ethin »

Octocontrabass wrote:You meant PCIe instead of PCE, right?

The ACPI MCFG table describes all valid sg:bus combinations and their MMIO addresses. You can't scan segment groups or buses that don't exist, since they have no MMIO address, so your scan will be quite fast even if you do scan all existing segment groups and buses.

The MCFG table doesn't describe hot-pluggable devices, in case you have some of those and want to know why your scan doesn't find them.
That's odd because if I loop through everything in a nested loop the PCI code appears to take forever to scan through all possible segments. That just might be TCG though. And yes, I did mean PCIe. And thanks for that little tidbit about hot-pluggable devices.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Better way of scanning PCE?

Post by nullplan »

You can reduce the amount of stuff to scan quite significantly:
  1. You only need to scan function 0. If the header for function 0 has the multi-function bit set, then you also need to scan the other functions, but if that bit is not set, or the device doesn't exist, then you don't.
  2. You only need to scan the busses that actually exist. On PCI, this means you only scan the root busses. If you find a PCI bridge, you raise the bus limit up to the bridge's subordinate bus number. All existing busses have consecutive numbers.
I don't know what segment groups are about. I only ever found machines with a single segment group.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5572
Joined: Mon Mar 25, 2013 7:01 pm

Re: Better way of scanning PCE?

Post by Octocontrabass »

Ethin wrote:That's odd because if I loop through everything in a nested loop the PCI code appears to take forever to scan through all possible segments.
That's because you're looping through impossible segment groups as well. Use the MCFG table to limit your search space.
Post Reply