Type something to search...

0x50 AcpBt EBox Plug In

Issue Description

Repro step:

  1. Boot system without EBOX connected normally
  2. connect EBOX with RTX3060
  3. Wait 5s
  4. System BSOD

Issue CND if EBOX is connected when system boot.

Once EBOX is connected from boot, further hotplug will CND.

Analysis

4: kd> k
 # Child-SP          RetAddr               Call Site
00 ffff998f`fe34eb38 fffff805`920d6ce5     nt!KeBugCheckEx [minkernel\ntos\ke\amd64\procstat.asm @ 140]
01 ffff998f`fe34eb40 fffff805`9203425f     nt!MiSystemFault+0x735 [minkernel\ntos\mm\mmfault.c @ 4893]
02 ffff998f`fe34ec30 fffff805`92480ccb     nt!MmAccessFault+0x2ff [minkernel\ntos\mm\mmfault.c @ 8472]
03 ffff998f`fe34eda0 fffff805`2a550336     nt!KiPageFault+0x38b [minkernel\ntos\ke\amd64\trap.asm @ 1552]
04 ffff998f`fe34ef38 fffff805`2a5501ab     amdacpbtacx!CAfdBtI2SInterface::REG_READ+0x2a [c:\constructicon\builds\gfx\five\24.10\drivers\acp\acx\amdacpbtacx\src\acpbtacx_i2sinterface.cpp @ 447]
05 ffff998f`fe34ef40 fffff805`2a59a111     amdacpbtacx!CAfdBtI2SInterface::EnableI2SControllerInstance+0x217 [c:\constructicon\builds\gfx\five\24.10\drivers\acp\acx\amdacpbtacx\src\acpbtacx_i2sinterface.cpp @ 329]
06 ffff998f`fe34efa0 fffff805`23d1a7b7     amdacpbtacx!AfdBt_EvtDevicePrepareHardware+0x199 [c:\constructicon\builds\gfx\five\24.10\drivers\acp\acx\amdacpbtacx\src\acpbtacx_device.cpp @ 475]
07 ffff998f`fe34f050 fffff805`23ccb191     Wdf01000!FxPnpDevicePrepareHardware::InvokeClient+0x27 [minkernel\wdf\framework\shared\irphandlers\pnp\pnpcallbacks.cpp @ 447]
08 ffff998f`fe34f0a0 fffff805`23cf44a4     Wdf01000!FxPrePostCallback::InvokeStateful+0xa5 [minkernel\wdf\framework\shared\irphandlers\pnp\cxpnppowercallbacks.cpp @ 291]
09 (Inline Function) --------`--------     Wdf01000!FxPnpDevicePrepareHardware::Invoke+0x51 [minkernel\wdf\framework\shared\irphandlers\pnp\pnpcallbacks.cpp @ 421]
0a ffff998f`fe34f0e0 fffff805`23d41b2c     Wdf01000!FxPkgPnp::PnpPrepareHardware+0xf8 [minkernel\wdf\framework\shared\irphandlers\pnp\pnpstatemachine.cpp @ 3596]
0b ffff998f`fe34f130 fffff805`23d08bc1     Wdf01000!FxPkgPnp::PnpEventStartingFromStopped+0x1c [minkernel\wdf\framework\shared\irphandlers\pnp\pnpstatemachine.cpp @ 2491]
0c ffff998f`fe34f160 fffff805`23d088d1     Wdf01000!FxPkgPnp::PnpEnterNewState+0x125 [minkernel\wdf\framework\shared\irphandlers\pnp\pnpstatemachine.cpp @ 1240]
0d ffff998f`fe34f200 fffff805`23d085a2     Wdf01000!FxPkgPnp::PnpProcessEventInner+0xd1 [minkernel\wdf\framework\shared\irphandlers\pnp\pnpstatemachine.cpp @ 1154]
0e ffff998f`fe34f280 fffff805`23cfca02     Wdf01000!FxPkgPnp::_PnpProcessEventInner+0x32 [minkernel\wdf\framework\shared\irphandlers\pnp\pnpstatemachine.cpp @ 983]
0f ffff998f`fe34f2b0 fffff805`23cfc8e5     Wdf01000!FxEventQueue::EventQueueWorker+0x9a [minkernel\wdf\framework\shared\irphandlers\pnp\eventqueue.cpp @ 279]
10 ffff998f`fe34f300 fffff805`9203b56a     Wdf01000!FxWorkItemEventQueue::_WorkItemCallback+0x25 [minkernel\wdf\framework\shared\irphandlers\pnp\km\eventqueuekm.cpp @ 114]
11 ffff998f`fe34f330 fffff805`92143370     nt!IopProcessWorkItem+0x45a [minkernel\ntos\io\iomgr\misc.c @ 1616]
12 ffff998f`fe34f3c0 fffff805`9225a5fa     nt!ExpWorkerThread+0x2a0 [minkernel\ntos\ex\worker.c @ 4303]
13 ffff998f`fe34f570 fffff805`92472c94     nt!PspSystemThreadStartup+0x5a [minkernel\ntos\ps\psexec.c @ 11878]
14 ffff998f`fe34f5c0 00000000`00000000     nt!KiStartSystemThread+0x34 [minkernel\ntos\ke\amd64\threadbg.asm @ 87]

The REG_READ is simple, it uses a private field m_pRegAddrStart , plus an offset from parameter _Offset . This is the address we fault on.

Looking into it you see the m_pRegAddrStart itself is invalid page.

4: kd> dx -id 0,0,ffffdf0e70548040 -r1 ((amdacpbtacx!CAfdBtI2SInterface *)0xffffdf0e7a17d440)
((amdacpbtacx!CAfdBtI2SInterface *)0xffffdf0e7a17d440)                 : 0xffffdf0e7a17d440 [Type: CAfdBtI2SInterface *]
    [=0xfffff8052a568b18] m_Instance       : 0xffffdf0e7a17d440 [Type: CAfdBtI2SInterface *]
    [+0x000] m_pRegAddrStart  : 0xffff958f6836f000 : Unable to read memory at Address 0xffff958f6836f000 [Type: unsigned char *]
    [+0x008] m_ControllerInstance : 0x3 [Type: unsigned long]
    [+0x00c] m_ClockMode      : 0x2 [Type: unsigned long]
    [+0x010] m_AcpRevisionID  : 0x70 [Type: unsigned char]
4: kd> !pte 0xffff958f6836f000
                                           VA ffff958f6836f000
PXE at FFFFF97CBE5F2958    PPE at FFFFF97CBE52B1E8    PDE at FFFFF97CA563DA08    PTE at FFFFF94AC7B41B78
contains 0A00000647026863  contains 0A00000647027863  contains 0A0000012FB7C863  contains 0000000000000000
pfn 647026    ---DA--KWEV  pfn 647027    ---DA--KWEV  pfn 12fb7c    ---DA--KWEV  not valid

If we trace back in code you see this field is defined and assigned by:

So it is assigned to the constructor parameter. Dive further back the constructor is called only in AfdBt_EvtBusDeviceAdd .

PAGED_CODE_SEG
NTSTATUS
AfdBt_EvtBusDeviceAdd(
    _In_    WDFDRIVER _Driver,
    _Inout_ PWDFDEVICE_INIT _DeviceInit
)
{
    PAGED_CODE();

    NTSTATUS Status = STATUS_SUCCESS;

    DBG_TRACE_STATUS();

    /* Initialize the pnpPowerCallbacks structure. */
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = AfdBt_EvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = AfdBt_EvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry = AfdBt_EvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = AfdBt_EvtDeviceD0EntryPostInterruptsEnabled;
    pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = AfdBt_EvtDeviceD0ExitPreInterruptsDisabled;
    pnpPowerCallbacks.EvtDeviceD0Exit = AfdBt_EvtDeviceD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks(_DeviceInit, &pnpPowerCallbacks);

...

    /* Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    * that you don't get the popup in usermode (on Win2K) when you surprise
    * remove the device.
    */
    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
    pnpCaps.SurpriseRemovalOK = WdfTrue;
    WdfDeviceSetPnpCapabilities(AfdBtDevice, &pnpCaps);

    /* Get the AcpBus Interface */
    CAfdBtAcpBusPciInterface::setInstance(new CAfdBtAcpBusPciInterface(pDevCtx, AcpClientTypeBt)); /*Child PDO is BT*/
    Status = CAfdBtAcpBusPciInterface::getInstance()->Initialize();
    ACP_STATUS_CHECK(Status, "CAfdBtAcpBusPciInterface::Initialize()", Exit);

    /* Initialize I2S class interface*/
    CAfdBtI2SInterface::setInstance(new CAfdBtI2SInterface(CAfdBtAcpBusPciInterface::getInstance()->m_pRegMap));

This is in EvtBusDeviceAdd , but when eBox hot plug, OS called only EvtDevicePrepareHardware .

Sequence of events

When 1st boot without eBox. OS calls the sequence:

  1. DriverEntry
    1. Calls WDF_DRIVER_CONFIG_INIT(&wdfCfg, AfdBt_EvtBusDeviceAdd) , provide EvtBusDeviceAdd callback to OS.
  2. WDF calls EvtBusDeviceAdd
    1. Creates PNPPOWERCALLBACK , provide WDF with a series of callbacks (Key point is EvtDevicePrepareHardware),and calls WdfDeviceInitSetPnpPowerEventCallbacks .

          WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
          WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
          pnpPowerCallbacks.EvtDevicePrepareHardware = AfdBt_EvtDevicePrepareHardware;
          pnpPowerCallbacks.EvtDeviceReleaseHardware = AfdBt_EvtDeviceReleaseHardware;
          pnpPowerCallbacks.EvtDeviceD0Entry = AfdBt_EvtDeviceD0Entry;
          pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = AfdBt_EvtDeviceD0EntryPostInterruptsEnabled;
          pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = AfdBt_EvtDeviceD0ExitPreInterruptsDisabled;
          pnpPowerCallbacks.EvtDeviceD0Exit = AfdBt_EvtDeviceD0Exit;
          WdfDeviceInitSetPnpPowerEventCallbacks(_DeviceInit, &pnpPowerCallbacks);
    2. Create a new CAfdBtI2SInterface , feed it with the register map address, and set it as static instance.

  3. WDF calls EvtPrepareHardware
    1. We write some register based on the address in CAfdBtI2SInterface.m_pRegAddrStart .

So far, so good. Problems start occuring when we plug in eBox.

Since eBox is a PCIE hardware device, I’m guessing PnP has some rebalance to do. In fact, if we look at the device tree in dump, you see ACP has just went through this process.

DevNode 0xffffdf0e705a7b30 for PDO 0xffffdf0e743ed060
  InstancePath is "PCI\VEN_1022&DEV_15E2&SUBSYS_15E21022&REV_70\4&35fe04f8&0&0541"
  ServiceName is "amdacpbus"
  State = DeviceNodeStarted (0x30a)
  Previous State = DeviceNodeRestartCompletion (0x30d)
  DevNode 0xffffdf0e844609a0 for PDO 0xffffdf0e820a5410
    InstancePath is "ACP\DEVTYPE_0001&DEVREV_0000&VEN_1022&DEV_15E2&SUBSYS_102215E2&REV_70\5&105e5341&1&01"
    State = DeviceNodeRestartCompletion (0x30d)
    Previous State = DeviceNodeStartPending (0x307)
  DevNode 0xffffdf0e8445b9a0 for PDO 0xffffdf0e820bb8f0
    InstancePath is "ACP\DEVTYPE_0004&DEVREV_0001&VEN_1022&DEV_15E2&SUBSYS_102215E2&REV_70\5&105e5341&1&05"
    ServiceName is "AMDAcpBtAudioService"
    TargetDeviceNotify List - f 0xffff9d0a2f6eb190  b 0xffff9d0a2f6eb190
    State = DeviceNodeStartPending (0x307)
    Previous State = DeviceNodeStopped (0x30c)

When we plug in the eBox, WDF only calls EvtPrepareHardware . Where it expects us to reinitialize the device. But we previously stored CAfdBtI2SInterface.m_pRegAddrStart as a static instance. We are never released or unloaded, so we used a wrong value and bugchecked.

According to MSFT, we should “Map physical memory addresses to VA” in EvtPrepareHardware instead of in EvtBusDeviceAdd .

See also:

https://learn.microsoft.com/en-us/windows-hardware/drivers/wdf/a-user-plugs-in-a-device

https://learn.microsoft.com/en-us/windows-hardware/drivers/wdf/the-pnp-manager-redistributes-system-resources

Related Posts

0x19C.50 Stx S3S4Restart

6: kd> .bugcheck Bugcheck code 0000019C Arguments 00000000`00000050 ffff800b`a18fa380 00000000`00000000 00000000`000000006: kd> .thread

read more

0x9F.3 Strix Stress ACP

6: kd> .bugcheck Bugcheck code 0000009F Arguments 00000000`00000003 ffff948f`e9be4060 ffffe381`3d0ef040 ffff948f`ee90eba06: kd> !addrMap

read more

0x19C.50 Stx S4 Resume Video Playing

5: kd> .bugcheck Bugcheck code 0000019C Arguments 00000000`00000050 ffff808e`23621380 00000000`00000000 00000000`000000005: kd> !thread

read more

0x133.1 3xW6400 PBR

0: kd> .bugcheck Bugcheck code 00000133 Arguments 00000000`00000001 00000000`00001e00 fffff807`0a91c340 00000000`000000000: kd> !corelis

read more

0x9F.3 Strix S4

5: kd> .bugcheck Bugcheck code 0000009F Arguments 00000000`00000003 ffff800f`943e4360 ffffc906`fbaa7178 ffff800f`a4a6c7505: kd> !irp ffff

read more

0x0 Live AcpWdfWorkItem Leak

Customer observed higher memory usage after using Edge to play music overnight. Captured live dump after playing music for a while. 0: kd> !p

read more

0x0 Live Lid Close Open Screen Dim

Symptom The display dims automatically 5s after lid close → open. Issue occurs only on SKUs with ToF sensor (HPD). Display Connect a live syste

read more

0x19C.50 Lid

2: kd> .bugcheck Bugcheck code 0000019C Arguments 00000000`00000050 ffffbf87`de64a3c0 00000000`00000000 00000000`000000002: kd> !thread

read more

0x9F.3 Gfx Stuck Cause Acp PoIrp Timeout

5: kd> .bugcheck Bugcheck code 0000009F Arguments 00000000`00000003 ffffcf07`04d3caf0 ffffcd04`6bb4f010 ffffcf07`0dec88a0 9: kd> k # Child-SP

read more

0x19C.50 WuReject PostT7Delay

In dce110_edp_backlight_control, we request a wait of "post_T7_delay". This wait was n

read more

0x133.0 NPU Line Interrupt

The BSOD sequence of event looks like this:OS is starting up NPU device.Something w

read more

Session Space

When debugging Windows kernels, sometimes you see addresses that “looks” like kernel space memory. It begins with 0xffff, resides within module presen

read more

!pte "Levels not implemented for this platform"

!pte command comes from extension kdexts.dll, which is bundled with debuggers for Windows package. The command performs machine type check with t

read more

Recursively Debug User-Mode Child Process

When you enable “debug child process” in WinDbg, it only attempts to debug the children. 0:000> sxe -c ".childdbg 1;bu wlanapi!WlanQueryInterfac

read more

Rundown Protection

Acquire with nt!ExAcquireRundownProtection. 0: kd> uf fffff802`148c8d80 nt!ExAcquireRundownProtection [minkernel\ntos\ex\rundown.c @ 333]: 3

read more

DISPATCHER_HEADER

See DISPATCHER_HEADER (geoffchappell.com)

read more

Power IRP Source

All Windows drivers / component / internally dispatch Power IRP with the routine. 0: kd> dt nt!PoRequestPowerIrp PoRequestPowerIrp long ( _D

read more

WDF

WDF is object based, the objects have to be created and manipulated by function calls to WDF itself. WDF objects are used by handles! Not their ptr t

read more

WinDbg System Uptime

Trace print code of “System Uptime” unicode string. 0:007> !for_each_module s-u @#Base @#End "System Uptime" 00007ffe`d8ec8e30 0053 0079 0073

read more

NT Wait Times

NT Wait Time OS store shared data as nt!_KUSER_SHARED_DATA . It is always mapped to 0xfffff78000000000 in all process. It is done through page t

read more

Self-Signed WHQL Certificate for Testing

Root Certificate $params = @{ Type = 'Custom' SerialNumber = '28cc3a25bfba44ac449a9b586b4339aa' KeyAlgorithm = 'RSA' HashAlgo

read more

When entering S3/S4, GFX receives D0 request

What is the D0? Set BP on our handler, and filter by cond BP for set power state 12: kd> bl 0 e Disable Clear fffff802`7b359020 000

read more