Is PCIe device tree information cached by the OS?

I have an interesting case that has popped up … one of my drivers scans the PCI bus gathering ECAM information using IoEnumerateDeviceObjectList, similar to as discussed here [ https://community.osr.com/discussion/104211/ioenumeratedeviceobjectlist-help ] and I’m aware that Doron wants a bus filter driver written rather than “brute forcing through the device tree” but a bus filter driver is several orders of magnitude more complex than what I’m trying to do and introduces a whole new raft of complexity … it’s the equivalent of using a neutron bomb to get rid of a gopher, it will work but is a bit of an overkill …

Using IoEnumerateDeviceObjectList has worked very nicely up until recently, when I started using a ThunderBolt3 external PCIe chassis for various reasons. What I’ve found is that if I have a PCIe card in the external chassis, recognized by the OS and with driver loaded, when the TB3 cable is removed the PCIe card is still “found” by IoEnumerateDeviceObjectList (which makes no sense unless the OS is simply returning a cached value and not doing a true Enumeration of the Device Object List). Refreshing Device Manager (which coincidentally also uses IoEnumerateDeviceObjectList, don’t know why Device Manager doesn’t just install it’s own bus filter driver to get that information rather than use that API) also “shows” the physically removed device …

More disturbingly, this “phantom” device appears to survive a warm boot (cold boot clears it, thankfully and rationally) so again the evidence seems to point that the OS is building a list on boot and simply returning that cached result in IoEnumerateDeviceObjectList (maybe it should be renamed to IoReturnDeviceObjectListFoundOnInitialBoot) …

Does anyone have any additional information, or seen something like this? I can do a workaround by treating IoEnumerateDeviceObjectList as IoReturnDeviceObjectListFoundOnInitialBoot and individually interrogating each PCIe device in the list to see if it’s really there or not, but that doesn’t fix the problem of a PCIe device attached via a TB3 connection during a running session … that’s a question for another topic …

Thx!

Ignoring the snark:

  1. I don’t see calls to IoEnumerateDeviceObjectList in the pnp code, but I could have easily missed it.
  2. Ignoring 1, even if the pnp code is using the API call, it also has access to the internal pnp state lock and data structures hanging off the device objects so it can synchronize walking the list with pnp device tree changes.

Hey Doron! Thanks for the quick response, sorry for the snark (too much angst trying to work through this new TB3 “discovery”, probably) …

The question remains though, when IoEnumerateDeviceObjectList is called is the OS going to make an actual walk through the PCI devices to build a list of attached devices that are attached (physical and TB3 bridged) and return that, or is the OS going to return a cached list of devices that were attached (physical and TB3 bridged) at the time of boot that it stored away in the registry somewhere?

Thx!

IoEnumerateDeviceObjectList walks the list of device objects created by the driver (via the driver object, no registry involved). It does not trigger a pnp tree re-query. If/when PCI detects the external device on the other end of the wire is removed, it will invalidate its device relations, report the device as missing and the list of devices returned by IoEnumerateDeviceObjectList will reflect this change. If you want to force re query the tree (or a subset of it), you need to call CM_Reenumerate_DevNode in user mode.

Hmm … OK, so IoEnumerateXX is returning a cached value from the last pnp bus enumeration, so if the TB3 disconnect event is not being properly reported to the OS then it makes sense that pnp will still see no changes …

Aside from being usermode and my driver being, well, kernel mode using CM_Reenumerate_DevNode is going to be tricky due to needing privileges that a usermode program won’t have [ https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_reenumerate_devnode?redirectedfrom=MSDN ] and [ https://stackoverflow.com/questions/14937261/equivalent-of-scan-for-hardware-changes-in-device-manager-doesnt-work-after-f ] so that’s not really an option either …

This is the second time I’ve need to figure out a way to trigger a pnp re-query programattically … I sense a trend … :confused:

It is the pci bus driver that is in charge of pci device enumeration state,
not ‘pnp’. Dynamic bus reconfiguration for pci devices was originally not
supported at all and quite painful to get working on hardware that
supported it. Then there was limited support for pci dynamic reconfig,
introduced maybe with Server 2003? I have no idea what has changed since
then, but I’m guessing, ‘not much’, but the docs do claim that if the
platform supports pcie hotplug, the os supports it too.

Mark Roddy

Agreed.

The changes (some would say hacks) required to support Thurderbolt, where a PCI Root Complex can “just appear” were also considerable. PCI has been through some pretty interesting changes since Windows 8.

By the way, you can now cause PCI to re-enumerate its bus… This surprised me, because it had been something Windows didn’t do for so long. But, indeed, there’s a function for that. So, there is SOME dynamic review available.

Peter