Kernel timer BSOD TIMER_OR_DPC_INVALID (c7)

Hi,

In my Ethernet NDIS Miniport driver initialization routine a bugcheck c7 was hit, it looks like the reset complete timer object was found in a block of memory where a timer object is not permitted. This BSOD happens in DTM NDISTest during Miniport Initialize call to NdisInitializeTimer which initializes reset complete timer with DPC timer function. I saw during Miniport Halt handler the NdisCancelTimer call almost always fails and it can’t cancel this timer properly. Does this cause the NdisInitializeTimer in Miniport Init to have this BSOD?
Does anyone know how to find the root cause?

The WinDbg crash analysis is attached. Any feedback is greatly appreciated.

Thanks.

TIMER_OR_DPC_INVALID (c7)
Kernel timer or DPC used incorrectly.
Arguments:
Arg1: 00000000, Timer object found in memory which must not contain such items.
Arg2: 8a5c8ae0, Address of the timer object.
Arg3: 8a5c8ae0, Start of memory range being checked.
Arg4: 8a5c8b08, End of memory range being checked.

Debugging Details:

*** No owner thread found for resource 805591e0
*** No owner thread found for resource 805591e0
*** No owner thread found for resource 805591e0
*** No owner thread found for resource 805591e0

DEFAULT_BUCKET_ID: INTEL_CPU_MICROCODE_ZERO

BUGCHECK_STR: 0xC7

PROCESS_NAME: System

LOCK_ADDRESS: 80559260 – (!locks 80559260)

Resource @ nt!IopDeviceTreeLock (0x80559260) Shared 1 owning threads
Threads: 8a7263c8-01<*>
1 total locks, 1 locks currently held

PNP_TRIAGE:
Lock address : 0x80559260
Thread Count : 1
Thread address: 0x8a7263c8
Thread wait : 0x2c4

LAST_CONTROL_TRANSFER: from 8053277f to 804e35a2

STACK_TEXT:
f78d6250 8053277f 00000003 f78d65ac 00000000 nt!RtlpBreakWithStatusInstruction
f78d629c 80533256 00000003 8055a2b8 8a5c8ae0 nt!KiBugCheckDebugBreak+0x19
f78d667c 80533846 000000c7 00000000 8a5c8ae0 nt!KeBugCheck2+0x574
f78d669c 805338f1 000000c7 00000000 8a5c8ae0 nt!KeBugCheckEx+0x1b
f78d66c4 8066d650 005c8ae0 00000018 f78d66e4 nt!KeCheckForTimer+0x9d
f78d66d4 8066d672 8a5c8ae0 00000000 f78d66f4 nt!VerifierKeInitializeTimerEx+0x18
f78d66e4 ba4f16a8 8a5c8ae0 f78d68f8 f78d671c nt!VerifierKeInitializeTimer+0xf
f78d66f4 ba6c7e95 8a5c8ae0 ba6c5c50 8a5c89c0 NDIS!NdisInitializeTimer+0x10
f78d671c ba4fbdea f78d6758 f78d6760 ba4f7200 net_vio!MPInitialize+0x185 [c:\virtio\virtio.0719\sys\miniport.c @ 329]
f78d68d4 ba4fb9cc 8a6f9870 f78d68f8 f78d69a0 NDIS!ndisMInitializeAdapter+0x3b7
f78d69a8 ba4fb8ba 8a6f9870 00000000 8a5e9dd8 NDIS!ndisInitializeAdapter+0xb9
f78d69dc ba4fcdaf 8a4dd788 8a559040 8b6ccf00 NDIS!ndisPnPStartDevice+0xd6
f78d6a0c 804e3807 8a4dd788 8b6ccf20 806f02e8 NDIS!ndisPnPDispatch+0x306
f78d6a1c 8066c245 8b6ccffc f78d6aac 8b6ccf20 nt!IopfCallDriver+0x31
f78d6a40 8059be6f f78d6aac 8a74b648 00000000 nt!IovCallDriver+0xa0
f78d6a6c 805b5027 8a4dd788 f78d6a88 00000000 nt!IopSynchronousCall+0xb7
f78d6ab0 80509678 8a74b648 8a6420c8 00000001 nt!IopStartDevice+0x4d
f78d6acc 805b4ec3 8a74b648 8a642001 00000000 nt!PipProcessStartPhase1+0x4e
f78d6d24 805abdac 8a74bab8 00000001 00000000 nt!PipProcessDevNodeTree+0x1db
f78d6d4c 8050733a 00000003 805592c0 805622fc nt!PiProcessStartSystemDevices+0x3a
f78d6d74 804e427b 00000000 00000000 8a7263c8 nt!PipDeviceActionWorker+0x166
f78d6dac 8057b0df 00000000 00000000 00000000 nt!ExpWorkerThread+0x100
f78d6ddc 804f88fa 804e41a6 00000001 00000000 nt!PspSystemThreadStartup+0x34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16

STACK_COMMAND: kb

FOLLOWUP_IP:
net_vio!MPInitialize+185 [c:\virtio\virtio.0719\sys\miniport.c @ 329]
ba6c7e95 8b4df0 mov ecx,dword ptr [ebp-10h]

FAULTING_SOURCE_CODE:
325: //
326: NdisInitializeTimer(
327: &Adapter->ResetTimer,
328: (PNDIS_TIMER_FUNCTION) NICResetCompleteTimerDpc,

329: (PVOID) Adapter);
330:

Can you show us definition of Adapter->ResetTimer? Is it a pointer by
chance?
–pa

wrote in message news:xxxxx@ntdev…
> Hi,
>
> In my Ethernet NDIS Miniport driver initialization routine a bugcheck c7
> was hit, it looks like the reset complete timer object was found in a
> block of memory where a timer object is not permitted. This BSOD happens
> in DTM NDISTest during Miniport Initialize call to NdisInitializeTimer
> which initializes reset complete timer with DPC timer function. I saw
> during Miniport Halt handler the NdisCancelTimer call almost always fails
> and it can’t cancel this timer properly. Does this cause the
> NdisInitializeTimer in Miniport Init to have this BSOD?
> Does anyone know how to find the root cause?
>
> The WinDbg crash analysis is attached. Any feedback is greatly
> appreciated.
>
> Thanks.
>
> TIMER_OR_DPC_INVALID (c7)
> Kernel timer or DPC used incorrectly.
> Arguments:
> Arg1: 00000000, Timer object found in memory which must not contain such
> items.
> Arg2: 8a5c8ae0, Address of the timer object.
> Arg3: 8a5c8ae0, Start of memory range being checked.
> Arg4: 8a5c8b08, End of memory range being checked.
>
> Debugging Details:
> ------------------
>
> No owner thread found for resource 805591e0
>
No owner thread found for resource 805591e0
> No owner thread found for resource 805591e0
>
No owner thread found for resource 805591e0
>
> DEFAULT_BUCKET_ID: INTEL_CPU_MICROCODE_ZERO
>
> BUGCHECK_STR: 0xC7
>
> PROCESS_NAME: System
>
> LOCK_ADDRESS: 80559260 – (!locks 80559260)
>
> Resource @ nt!IopDeviceTreeLock (0x80559260) Shared 1 owning threads
> Threads: 8a7263c8-01<*>
> 1 total locks, 1 locks currently held
>
> PNP_TRIAGE:
> Lock address : 0x80559260
> Thread Count : 1
> Thread address: 0x8a7263c8
> Thread wait : 0x2c4
>
> LAST_CONTROL_TRANSFER: from 8053277f to 804e35a2
>
> STACK_TEXT:
> f78d6250 8053277f 00000003 f78d65ac 00000000
> nt!RtlpBreakWithStatusInstruction
> f78d629c 80533256 00000003 8055a2b8 8a5c8ae0 nt!KiBugCheckDebugBreak+0x19
> f78d667c 80533846 000000c7 00000000 8a5c8ae0 nt!KeBugCheck2+0x574
> f78d669c 805338f1 000000c7 00000000 8a5c8ae0 nt!KeBugCheckEx+0x1b
> f78d66c4 8066d650 005c8ae0 00000018 f78d66e4 nt!KeCheckForTimer+0x9d
> f78d66d4 8066d672 8a5c8ae0 00000000 f78d66f4
> nt!VerifierKeInitializeTimerEx+0x18
> f78d66e4 ba4f16a8 8a5c8ae0 f78d68f8 f78d671c
> nt!VerifierKeInitializeTimer+0xf
> f78d66f4 ba6c7e95 8a5c8ae0 ba6c5c50 8a5c89c0 NDIS!NdisInitializeTimer+0x10
> f78d671c ba4fbdea f78d6758 f78d6760 ba4f7200 net_vio!MPInitialize+0x185
> [c:\virtio\virtio.0719\sys\miniport.c @ 329]
> f78d68d4 ba4fb9cc 8a6f9870 f78d68f8 f78d69a0
> NDIS!ndisMInitializeAdapter+0x3b7
> f78d69a8 ba4fb8ba 8a6f9870 00000000 8a5e9dd8
> NDIS!ndisInitializeAdapter+0xb9
> f78d69dc ba4fcdaf 8a4dd788 8a559040 8b6ccf00 NDIS!ndisPnPStartDevice+0xd6
> f78d6a0c 804e3807 8a4dd788 8b6ccf20 806f02e8 NDIS!ndisPnPDispatch+0x306
> f78d6a1c 8066c245 8b6ccffc f78d6aac 8b6ccf20 nt!IopfCallDriver+0x31
> f78d6a40 8059be6f f78d6aac 8a74b648 00000000 nt!IovCallDriver+0xa0
> f78d6a6c 805b5027 8a4dd788 f78d6a88 00000000 nt!IopSynchronousCall+0xb7
> f78d6ab0 80509678 8a74b648 8a6420c8 00000001 nt!IopStartDevice+0x4d
> f78d6acc 805b4ec3 8a74b648 8a642001 00000000 nt!PipProcessStartPhase1+0x4e
> f78d6d24 805abdac 8a74bab8 00000001 00000000
> nt!PipProcessDevNodeTree+0x1db
> f78d6d4c 8050733a 00000003 805592c0 805622fc
> nt!PiProcessStartSystemDevices+0x3a
> f78d6d74 804e427b 00000000 00000000 8a7263c8
> nt!PipDeviceActionWorker+0x166
> f78d6dac 8057b0df 00000000 00000000 00000000 nt!ExpWorkerThread+0x100
> f78d6ddc 804f88fa 804e41a6 00000001 00000000
> nt!PspSystemThreadStartup+0x34
> 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
>
>
> STACK_COMMAND: kb
>
> FOLLOWUP_IP:
> net_vio!MPInitialize+185 [c:\virtio\virtio.0719\sys\miniport.c @ 329]
> ba6c7e95 8b4df0 mov ecx,dword ptr [ebp-10h]
>
> FAULTING_SOURCE_CODE:
> 325: //
> 326: NdisInitializeTimer(
> 327: &Adapter->ResetTimer,
> 328: (PNDIS_TIMER_FUNCTION) NICResetCompleteTimerDpc,
>> 329: (PVOID) Adapter);
> 330:
>

ResetTimer is defined as:
NDIS_TIMER ResetTimer;
in a typical miniport Adapter structure.

Thanks.

wrote in message news:xxxxx@ntdev…
> ResetTimer is defined as:
> NDIS_TIMER ResetTimer;
> in a typical miniport Adapter structure.
>

Bad news then, it may be a massive memory corruption.
Is this virtio a ndis 5 IM driver on NT6 OS?

–pa

Run !timers from windbg

Does this happen after your fail to cancel a prior timer on adapter halt? If
so it is likely that the bugcheck is a corrupt timer list.

Mark Roddy

On Fri, Oct 1, 2010 at 9:16 PM, Pavel A. wrote:

> wrote in message news:xxxxx@ntdev…
>
> ResetTimer is defined as:
>> NDIS_TIMER ResetTimer;
>> in a typical miniport Adapter structure.
>>
>>
> Bad news then, it may be a massive memory corruption.
> Is this virtio a ndis 5 IM driver on NT6 OS?
>
> --pa
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

This is a NDIS 5 driver on Windows XP. I believe it does happen after the NdisCancelTimer call fails to cancel the timer on adapter halt. But why does NdisCancelTimer fail? Is there a way to gracefully clean up the timers upon cancellation failure? How do I track down the timer corruption?

Thanks.

Side note: Never user typecase for function pointers. Gratuituous casting is also pointless and sometimes harmful. Typecasts often hide legitimate programming errors.

NdisInitializeTimer(
&Adapter->ResetTimer,
NICResetCompleteTimerDpc,
Adapter);

Is your timer callback setting the timer again?

Mark Roddy

On Fri, Oct 1, 2010 at 9:52 PM, wrote:

> This is a NDIS 5 driver on Windows XP. I believe it does happen after the
> NdisCancelTimer call fails to cancel the timer on adapter halt. But why does
> NdisCancelTimer fail? Is there a way to gracefully clean up the timers upon
> cancellation failure? How do I track down the timer corruption?
>
> Thanks.
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

ALso, you should be using NdisMInitializeTimer for a miniport.

wrote in message news:xxxxx@ntdev…
> This is a NDIS 5 driver on Windows XP. I believe it does happen after the
> NdisCancelTimer call fails to cancel the timer on adapter halt. But why
> does NdisCancelTimer fail? Is there a way to gracefully clean up the
> timers upon cancellation failure? How do I track down the timer
> corruption?
>

See the WDK documentation why NdisCancelTimer can return FALSE.
Again, is it IM or MAC driver?
Because, as xxxxx@broadcom wrote, if this is MAC, you use wrong functions.
Good functions are NdisMInitializeTimer and NdisMCancelTimer.

–pa

“Pavel A.” wrote in message news:xxxxx@ntdev…
> wrote in message news:xxxxx@ntdev…
>> This is a NDIS 5 driver on Windows XP. I believe it does happen after the
>> NdisCancelTimer call fails to cancel the timer on adapter halt. But why
>> does NdisCancelTimer fail? Is there a way to gracefully clean up the
>> timers upon cancellation failure? How do I track down the timer
>> corruption?
>>
>
> See the WDK documentation why NdisCancelTimer can return FALSE.
> Again, is it IM or MAC driver?
> Because, as xxxxx@broadcom wrote, if this is MAC, you use wrong
> functions.
> Good functions are NdisMInitializeTimer and NdisMCancelTimer.
>
> --pa

and yes, re-initializing a timer if NdisCancel[M]Timer() on it failed,
is a Very Bad Thing.

Unfortunately WDK documentation does not instruct exactly how to handle
this, beyond of vague sayings:





OTOH the WDK documentation is just that - it’s not a tutorial or recipe
book.
–pa

There are samples that illustrate how to deal with a timer that fails to cancel.

They all require a handshake between the cancel thread and the timer
callback that 1) stops the callback from scheduling new timer
callbacks and 2) informs the cancel thread that the timer has done
this.

For example:

//
// Cancel the perioid timer and if necessary, wait for it to complete
//
NdisInterlockedDecrement(&pNic->ManagementInfo.HwPeriodTimerSync);
// Stop queuing new timers
NdisMCancelTimer(&pNic->ManagementInfo.Timer_HwPeriod, &Cancelled);
if (Cancelled == FALSE)
{
// If the timer is already running, wait for it to finish
while (pNic->ManagementInfo.HwPeriodTimerSync > 0)
{
NdisMSleep(100);
}
}

src\network\ndis\rtlnwifi\hw\hw_main.c
Vista sp1 wdk.

Mark Roddy

On Fri, Oct 1, 2010 at 11:26 PM, Pavel A. wrote:
> “Pavel A.” wrote in message news:xxxxx@ntdev…
>>
>> wrote in message news:xxxxx@ntdev…
>>>
>>> This is a NDIS 5 driver on Windows XP. I believe it does happen after the
>>> NdisCancelTimer call fails to cancel the timer on adapter halt. But why does
>>> NdisCancelTimer fail? Is there a way to gracefully clean up the timers upon
>>> cancellation failure? How do I track down the timer corruption?
>>>
>>
>> See the WDK documentation why ?NdisCancelTimer can return FALSE.
>> Again, is it IM or MAC driver?
>> Because, as xxxxx@broadcom wrote, if this is MAC, you use wrong
>> functions.
>> Good functions are NdisMInitializeTimer and NdisMCancelTimer.
>>
>> --pa
>
> and yes, re-initializing a timer if NdisCancel[M]Timer() on it failed,
> is a Very Bad Thing.
>
> Unfortunately WDK documentation does not instruct exactly how to handle
> this, beyond of vague sayings:
>
>


>
>


>
> OTOH the WDK documentation is just that - it’s not a tutorial or recipe
> book.
> --pa
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Thanks everyone for helping out. It is a MAC driver and I will consider changing the timer APIs to use the miniport ‘M’ versions, and add handshaking to fix the timer cancellation issues.