How to slove DRIVER_IRQL_NOT_LESS_OR_EQUAL in my Dispatch routine??

Discussion in 'Windows Vista Drivers' started by paullee, Jun 2, 2004.

  1. paullee

    paullee Guest

    Hi all

    I got a bugcode 0xD1 when I run my test AP and then open "file
    manager"

    The WinDbg tell me ,it carsh in my Dispatch routine like this

    Case IOCTL_DATA_COPY:
    KeAcquireSpinLock( &pLDI->irpQueueSpinLock, &oldIrql );

    pMPG = (PMPG_PARAM) pIrp->AssociatedIrp.SystemBuffer;

    RtlCopyMemory( pMPG->Message, (PULONG
    )pLDI->DMABuffers[pMPG->DmaChannel].Virtual,pMPG->DataLen*sizeof(ULONG));

    RtlZeroMemory( pLDI->DMABuffers[pMPG->DmaChannel].Virtual,pMPG->DataLen*sizeof(ULONG));
    --------> BOSD here!!!

    KeReleaseSpinLock( &pLDI ->irpQueueSpinLock, oldIrql );

    break;

    How to slove this problem??

    Should I need to use MmLockPagableCodeSection to lock??

    Thanks a lot
     
    paullee, Jun 2, 2004
    #1
    1. Advertisements

  2. paullee

    Mark Roddy Guest

    I gather from your code segment that you are using an IOCTL to transfer a
    pointer to your data rather than the data itself to your driver. This
    practice is discouraged as performing such indirect data transfer operations
    is complicated and thus difficult to get right. Instead you should redesign
    your IOCTL interface so that you directly transfer the data to your driver.


    --

    =====================
    Mark Roddy
    Windows 2003/XP/2000 Consulting
    Hollis Technology Solutions 603-321-1032
    www.hollistech.com
     
    Mark Roddy, Jun 2, 2004
    #2
    1. Advertisements

  3. paullee

    Maurice zmau Guest

    Case IOCTL_DATA_COPY:
    I do not have all code, so I am not sure if my advice is correct.
    Anyway, One more option :
    Can you ommit the "KeAcquireSpinLock" ? I do not see in your code why do
    you acquire this spin lock (The acquire action raises the IRQL).
    Maybe you can postpone, the acquire action to the phase where you really
    need to ? I gather from your code & names that you need to acuire the
    spinlock inorder to insert the IRP to some queue.

    One more question, is this code from your DeviceControl function ?


    good luck
    Maurice
     
    Maurice zmau, Jun 2, 2004
    #3
  4. paullee

    paullee Guest

    Thanks Maurice and Mark

    Mark, May I ask you how to design a IOCTL interface

    that can copy data form driver to AP??

    It seem like cann't assign a kernal space pointer
    that I can use it in AP。


    for Maurice , This was already all program code,
    I just follow the code that in DDK SERIAL smaple like this

    case IOCTL_SERIAL_GET_BAUD_RATE: {

    PSERIAL_BAUD_RATE Br =
    (PSERIAL_BAUD_RATE)Irp->AssociatedIrp.SystemBuffer;
    if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
    sizeof(SERIAL_BAUD_RATE)) {

    Status = STATUS_BUFFER_TOO_SMALL;
    break;

    }

    KeAcquireSpinLock(
    &Extension->ControlLock,
    &OldIrql
    );

    Br->BaudRate = Extension->CurrentBaud;

    KeReleaseSpinLock(
    &Extension->ControlLock,
    OldIrql
    );

    Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);

    break;

    }


    So I do the same thing ,Is it not necessary to call KeAcquireSpinLock
    like above??
     
    paullee, Jun 3, 2004
    #4
  5. you need to acquire the spinlock only if there is another thread that can
    touch the fields you are updating during the processing of the ioctl. if you
    look at serial, it only touches CurrentBaud while hold the lock in all
    instances. hypothetically, if the only instance was in the ioctl handler,
    there would be no need for a lock.

    d
     
    Doron Holan [MS], Jun 3, 2004
    #5
  6. paullee

    Mark Roddy Guest

    What I meant was that you need to redesign your ioctl interface. I think you
    have a data structure such as:

    struct foo {
    ULONG dataLen;
    PVOID buffer;
    };

    You initialize foo.buffer to point to your data, and then you send the foo
    structure to your driver, expecting that your driver can use the value of
    the buffer pointer directly. Not a good idea unless you really know what you
    are doing. Instead you need to redefine your interface. For example:

    struct foo {
    ULONG dataLen;
    UCHAR buffer[1];
    }

    ULONG buffer_length = 2000;
    ULONG fooLen = sizeof(foo) + buffer_length -1;
    ULONG outLen = 0;
    foo aFoo= malloc(fooLen);
    foo->dataLen = buffer_length;
    // do something here to copy some data into foo->buffer
    // now send it to your driver:
    BOOL result = DeviceIoControl(handle, IOCTL_FOO, foo, fooLen, NULL,
    &outLen, NULL);

    But, you say, now I need to copy the buffer in user mode. Good point. So
    instead just send the raw buffer via the IOCTL rather than a 'structure
    containing a buffer'. The length information is available from the OS in
    your driver, you providing it in a control structure is redundant:

    PUCHAR buffer; // a pointer to a data buffer
    ULONG dataLen; // how much data to send
    // init buffer pointer
    // init dataLen
    result = DeviceIoControl(handle, IOCTL_FOO_V2, buffer, dataLen, NULL,
    &outLen, NULL);


    --

    =====================
    Mark Roddy
    Windows 2003/XP/2000 Consulting
    Hollis Technology Solutions 603-321-1032
    www.hollistech.com
     
    Mark Roddy, Jun 3, 2004
    #6
  7. paullee

    Maurice zmau Guest

    for Maurice , This was already all program code,
    You are the one that should bring the answer.
    You acquire a spinlock in order to protect others from accessing same
    data at the same time (i.e. ISR may want to read the same buffers,
    while DeviceControl is writing).

    Good luck
    Maurice
     
    Maurice zmau, Jun 3, 2004
    #7
  8. paullee

    paullee Guest

    Thanks Doron

    Yes,There will be 20 threads run in my AP,So I acquire the spinlock
    sorry , I forgot to say this。
    Can you teach me how to design IOCTL like Mark say??
    I don't know how to copy data form driver to AP like Mark say^"""

    Think a lot
     
    paullee, Jun 3, 2004
    #8
  9. This is something that is too complicated to cover in newsgroup, sorry.

    d

    --
    Please do not send e-mail directly to this alias. this alias is for
    newsgroup purposes only.
    This posting is provided "AS IS" with no warranties, and confers no rights.


     
    Doron Holan [MS], Jun 3, 2004
    #9
  10. paullee

    paullee Guest

    Hi Mark
    Can you explain what is the different between these three method
    or where I can find the book ,paper ,data to see ??

    It seem look like your second method cann't be compile??
    So I modify it like this ,Is is right??

    ULONG buffer_length = 2000;
    ULONG fooLen = sizeof(foo) + buffer_length -1;
    ULONG outLen = 0;
    foo *aFoo= (foo * )malloc(fooLen);
    aFoo->dataLen = buffer_length;


    There will be 20 threads run in my AP,Let me show you the code,Please
    teach me^^

    Here is my data structure just like you say,

    typedef struct _MPG_PARAM {
    ULONG Channel;
    ULONG DataLen;
    ULONG* Message;
    } MPG_PARAM ,*PMPG_PARAM;


    typedef struct _ReadThreadInfo
    {
    HANDLE hHandle;
    HANDLE IntEvent;
    ULONG nIndex;
    MPG_PARAM MpgParam;
    }ReadThreadInfo;

    ReadThreadInfo g_ThreadPatam[MAX_THREAD];

    In my Thread function:

    for(i=0;i<MAX_THREAD;i++)
    {
    g_ThreadPatam.hHandle = hdevice;
    g_hreadPatam.nIndex = i;
    g_ThreadPatam.IntEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
    g_ThreadPatam.MpgParam.Message = (PULONG)
    malloc(DATALEN*sizeof(ULONG));
    g_ThreadPatam.MpgParam.Channel =i;
    g_ThreadPatam.MpgParam.DataLen=DATALEN;
    }
    When I got a IntEvent ,I will issue DeviceIoControl call to get data
    back form driver。

    bResult = DeviceIoControl(hdevice, IOCTL_GET_DATA, &pInfo->MpgParam,
    sizeof(MpgParam),&pInfo->MpgParam, sizeof(MpgParam), &dwRet, NULL);

    The Driver Code :
    case IOCTL_GET_DATA:
    KeAcquireSpinLock( &pLDI->irpQueueSpinLock, &oldIrql );
    pMPG = (PMPG_PARAM) pIrp->AssociatedIrp.SystemBuffer;
    RtlCopyMemory( pMPG->Message, (PULONG
    )pLDI->DMABuffers[pMPG->Channel].Virtual,pMPG->DataLen*sizeof(ULONG));
    KeClearEvent((PKEVENT)pLDI->IntEvHand[pMPG->Channel]);
    RtlZeroMemory( pLDI->DMABuffers[pMPG->Channel].Virtual,pMPG->DataLen*sizeof(ULONG));
    ----------->BSOD Here
    KeReleaseSpinLock( &pLDI ->irpQueueSpinLock, oldIrql );
    break;

    I need to check which one buffer is valid,So I need to pass a index
    So I use the first data structure like you say。


    sorry my poor english,I hope your can understand


    Ps:Thanks Maurice and Doron again^_^
     
    paullee, Jun 4, 2004
    #10
  11. paullee

    paullee Guest

    Hi all

    Can anyone explain what is the different between these three method
    that say by mark??

    someone say I need to lock afoo.buffer ,how to do it ??

    How can I got data safely form driver to AP by issue DeviceIoControl??

    Thanks
     
    paullee, Jun 9, 2004
    #11
  12. paullee

    Ashish Guest

    Hi Paul,

    I dont know if I am getting you correctly, but if I am, then I know
    whats going wrong => (Please see my comments after your message
    fragment)



    1. Here what I can make out is that your pMPG is pointing to the
    system copy of your MPG_PARAM structure. This structure has a pointer
    "Message" for which you have allocated memory in the user address
    space. This memory might have been already paged out before you are
    trying to access it in the driver and would cause a pagefault if you
    are at dispatch level (KeAcquireSpinLock is going to raise the IRQL to
    dispatch level). BUT, in this case the BSOD should have occured after
    your "RtlCopyMemory" statement. This is what is confusing.

    2. I am wondering whether same thing is happening with the memory
    pointed to by "pLDI->DMABuffers[pMPG->Channel].Virtual" for your
    RtlZeroMemory call. (OR that memory is not of size >=
    pMPG->DataLen*sizeof(ULONG).)

    In case thats the reason you would need to use the
    ProbeForRead/ProbeForWrite, but in which case you cannot raise the
    IRQL to DISPATCH_LEVEL as ProbeForXxx has to run at IRQL <= APC_LEVEL.

    I dont know if my thoughts are of any help to you. But anyways,
    wishing you the best results of your efforts !!!

    Thanks,
    Ashish
    --
     
    Ashish, Jun 25, 2004
    #12
  13. Event handle cannot be used directly in KeWaitForSingleObject, KeClearEvent,
    etc. See ObReferenceObjectByHandle function.

     
    Alexander Grigoriev, Jun 25, 2004
    #13
  14. Hi,

    One of the reason can be the use of KeAcquireSpinLock at dispatch level
    using paged memory, because this function rise the IRQL level and if in
    between occurred a paged memory they stop the execution with this error
    code. May be you can try to use the following functions
    KeAcquireSpinLockAtDpcLevel and KeReleaseSpinLockFromDpcLevel instead

    See:
    http://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/Locks.doc

    Regards
    Juan Schiavoni


     
    Juan Schiavoni, Jun 30, 2004
    #14
  15. You cannot tough anything pageable - nor data nor code - while holding a
    spinlock.

    --
    Maxim Shatskih, Windows DDK MVP
    StorageCraft Corporation

    http://www.storagecraft.com


     
    Maxim S. Shatskih, Jun 30, 2004
    #15
  16. Maxim,
    Right, data or code.
    Juan Schiavoni

     
    Juan Schiavoni, Jun 30, 2004
    #16
  17. you can only call KeAcquireSpinLockAtDpcLevel and
    KeReleaseSpinLockFromDpcLevel while you are at DPC_LEVEL. If you call
    these functions while at PASSIVE_LEVEL, you will deadlock the machine if you
    attempt to acquire the same spinlock at DPC level.

    d

    --
    Please do not send e-mail directly to this alias. this alias is for
    newsgroup purposes only.
    This posting is provided "AS IS" with no warranties, and confers no rights.


     
    Doron Holan [MS], Jun 30, 2004
    #17
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.