MmMapLockedPagesSpecifyCache fails with 2003 server

Hi,

I have code that has run fine on Windows2000, XP, and EmbeddedXP.
When I run it on Windows Server 2003, it fails.

I have a hardware device with a dynamic PCI aperture that can be
programmed to map physical memory. The device can then directly
read/write into the main systems memory.

The driver code uses AllocateCommonBuffer to allocate a contiguous block
of non-cached memory. It programs the PCI device with the LogicalAddress.

I then give a UserMode program a pointer to this memory, so he can
read/write directly into this memory that the device is accessing.
I do this by calling IoAllocateMdl, MmBuildMdlForNonPagedPool, and
finally MmMapLockedPagesSpecifyCache to obtain a UserVirtualAddress to
the buffer.

This code has run fine for years on 2000, XP, and EmbeddedXP. However,
with Windows 2003 server (both std & enterprise), I get an exception
when calling MmMapLockedPagesSpecifyCache. The exception returned is
0xC0000141, STATUS_INVALID_ADDRESS

Here’s code snippet:

ulLength = 0x20000;

pKernelVA = pDevExt->pMyAdapter->DmaOperations->AllocateCommonBuffer
(pDevExt->pMyAdapter,
ulLength,
&pLogicalAddress,
FALSE);

pMdl = IoAllocateMdl(pKernelVA, ulLength, FALSE, FALSE, NULL);
if (pMdl == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}

//*------------------------------------------------------------------------
//* Update the MDL that specifies our virtual memory buffer in nonpaged
//* pool to describe the underlying physical pages.
//*------------------------------------------------------------------------
try
{
MmBuildMdlForNonPagedPool (pMdl);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl (pMdl);
return STATUS_INSUFFICIENT_RESOURCES;
}

//*------------------------------------------------------------------------
//* Map physical pages described by MDL and return UserVA.
//*------------------------------------------------------------------------
try
{
pUserVA = MmMapLockedPagesSpecifyCache (pMdl, UserMode,
MmNonCached, NULL, FALSE, NormalPagePriority);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
CallDdk IoFreeMdl (zpvMdl);
return status;
}

Any hints would be appreciated,
John

Just a guess: AllocateCommonBuffer actually always allocates “cached”
memory, it entirely ignores the CacheEnabled parameter (this actually just
came up in one of the MS newsgroups over the weekend). So, it’s possible
that MmMapLockedPagesSpecifyCache is failing because of a conflict in the
caching types. For fun you might try passing MmCached instead of MmNonCached
and see if the exception goes away.

If that guess doesn’t work out your next best bet would be stepping through
the function and finding the exact point of failure.

Regards,

-scott


Scott Noone
Software Engineer
OSR Open Systems Resources, Inc.
http://www.osronline.com

“John B” wrote in message news:xxxxx@ntdev…
> Hi,
>
> I have code that has run fine on Windows2000, XP, and EmbeddedXP.
> When I run it on Windows Server 2003, it fails.
>
> I have a hardware device with a dynamic PCI aperture that can be
> programmed to map physical memory. The device can then directly
> read/write into the main systems memory.
>
> The driver code uses AllocateCommonBuffer to allocate a contiguous block
> of non-cached memory. It programs the PCI device with the LogicalAddress.
>
> I then give a UserMode program a pointer to this memory, so he can
> read/write directly into this memory that the device is accessing.
> I do this by calling IoAllocateMdl, MmBuildMdlForNonPagedPool, and
> finally MmMapLockedPagesSpecifyCache to obtain a UserVirtualAddress to
> the buffer.
>
> This code has run fine for years on 2000, XP, and EmbeddedXP. However,
> with Windows 2003 server (both std & enterprise), I get an exception
> when calling MmMapLockedPagesSpecifyCache. The exception returned is
> 0xC0000141, STATUS_INVALID_ADDRESS
>
> Here’s code snippet:
>
> ulLength = 0x20000;
>
> pKernelVA = pDevExt->pMyAdapter->DmaOperations->AllocateCommonBuffer
> (pDevExt->pMyAdapter,
> ulLength,
> &pLogicalAddress,
> FALSE);
>
> pMdl = IoAllocateMdl(pKernelVA, ulLength, FALSE, FALSE, NULL);
> if (pMdl == NULL)
> {
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> //------------------------------------------------------------------------
> //
Update the MDL that specifies our virtual memory buffer in nonpaged
> //* pool to describe the underlying physical pages.
> //------------------------------------------------------------------------
> try
> {
> MmBuildMdlForNonPagedPool (pMdl);
> }
> except (EXCEPTION_EXECUTE_HANDLER)
> {
> IoFreeMdl (pMdl);
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> //
------------------------------------------------------------------------
> //* Map physical pages described by MDL and return UserVA.
> //*------------------------------------------------------------------------
> try
> {
> pUserVA = MmMapLockedPagesSpecifyCache (pMdl, UserMode,
> MmNonCached, NULL, FALSE, NormalPagePriority);
> }
> except (EXCEPTION_EXECUTE_HANDLER)
> {
> status = GetExceptionCode();
> CallDdk IoFreeMdl (zpvMdl);
> return status;
> }
>
>
> Any hints would be appreciated,
> John
>

Hi Scott,

I gave that a shot and it worked. Thanks for the quick suggestion.
I guess it’s time to delve into possible caching issues.

Thanks,
John

Scott Noone wrote:

Just a guess: AllocateCommonBuffer actually always allocates “cached”
memory, it entirely ignores the CacheEnabled parameter (this actually just
came up in one of the MS newsgroups over the weekend). So, it’s possible
that MmMapLockedPagesSpecifyCache is failing because of a conflict in the
caching types. For fun you might try passing MmCached instead of MmNonCached
and see if the exception goes away.

If that guess doesn’t work out your next best bet would be stepping through
the function and finding the exact point of failure.

Regards,

-scott

Calling MmAllocateContiguousMemorySpecifyCache directly might also be an
option if you really need non-cached memory (this is the DDI that
AllocateCommonBuffer uses internally).

Regards,

-scott


Scott Noone
Software Engineer
OSR Open Systems Resources, Inc.
http://www.osronline.com

“JMB” wrote in message news:xxxxx@ntdev…
> Hi Scott,
>
> I gave that a shot and it worked. Thanks for the quick suggestion.
> I guess it’s time to delve into possible caching issues.
>
> Thanks,
> John
>
> Scott Noone wrote:
>> Just a guess: AllocateCommonBuffer actually always allocates “cached”
>> memory, it entirely ignores the CacheEnabled parameter (this actually
>> just came up in one of the MS newsgroups over the weekend). So, it’s
>> possible that MmMapLockedPagesSpecifyCache is failing because of a
>> conflict in the caching types. For fun you might try passing MmCached
>> instead of MmNonCached and see if the exception goes away.
>>
>> If that guess doesn’t work out your next best bet would be stepping
>> through the function and finding the exact point of failure.
>>
>> Regards,
>>
>> -scott
>>
>

Scott,

I definitely needed to stay with NON-cache for my buffer. Calling
MmAllocateContiguousMemorySpecificCache and MmGetPhysicalAddress did the
trick.

Thanks for the quick help,
John

Scott Noone wrote:

Calling MmAllocateContiguousMemorySpecifyCache directly might also be an
option if you really need non-cached memory (this is the DDI that
AllocateCommonBuffer uses internally).

Regards,

-scott

> Scott,

I definitely needed to stay with NON-cache for my buffer. Calling
MmAllocateContiguousMemorySpecificCache and MmGetPhysicalAddress did the
trick.

Thanks for the quick help,
John

John,

Why do you need to have non-cached memory for the buffer? x86/x64 CPUs and
chipsets provide HW-based memory-cache coherency for DMA devices.

Dmitriy Budko
VMware