MmAllocatePagesForMdl and MmUnmapLockedPages

Hello ,

I like to reserve several chunks of memory and only map them when I need them. When I use the *Scenario 1* flow on W2k, all seems to
work until I call "MyReadWrite" for the second time. It seems to be that the "MmUnmapLockedPages" call does not revert the state of
the MDL allocated pages as they were after I called MmGetSystemAddressForMdlSafe. Most of the time I get a
"PAGE_FAULT_IN_NONPAGED_AREA" when accessing the "*PMemory" during the second call of "MyReadWrite", sometimes it occurs during the
3rd of later call.

When I tried out *Scenario 2* , everything runs perfect ! Now, I assume that when calling "MmUnmapLockedPages" and
"MmGetSystemAddressForMdlSafe" shortly after each other, the allocated memory remains *intact*. When there is big time gab between
those calls, the OS takes the time to unlock ( or whatever ) the memory after the first call of "MmUnmapLockedPages".

When I try out *Scenario 3* with the new XP-and-higher functions, I get literally the message "The driver is mismanaging system
PTEs" .

All scenario calls run at PASSIVE_LEVEL. Using the equivalents "MmMapLockedPagesSpecifyCache" or "MmMapLockedPages" instead of
"MmGetSystemAddressForMdlSafe" brought no relief.

When I looked around for samples in the DDK that also used MmAllocatePagesForMdl, I did found "intrface.c" at \kernel\agp\agplib.
That sample adds MDL_PAGES_LOCKED into the Mdl flags after the call of MmAllocatePagesForMdl, but that didn't solve the problem.

Is there a way or trick to bring the memory described by the MDL back into a "good and healthy" status ?

Scenario 1 ( Windows 2000 ) :

MyAddDevice ( )
{
....
DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress , HghAddress, SkipSize , ulChunkSize ) ;

....
}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
....

DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;

*(DeviceExtension->pMemory) = .... // access the memory here .....

MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;
}

Scenario 2 ( Windows 2000 ) :

MyAddDevice ( )
{
....
DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;

....
}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
....

MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;

DeviceExtension->pMemory =
MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;

*pMemory = .... // access the memory here .....

//// commented out : MmUnmapLockedPages ( pMemory , DeviceExtension->pMDL ) ;
}

Scenario 3 ( Windows XP ) :

MyAddDevice ( )
{
....
DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
DeviceExtension->pMapping = MmAllocateMappingAddress ( _size , uTag ) ;
....
}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
....

DeviceExtension->pMemory =
MmMapLockedPagesWithReservedMapping ( DeviceExtension->pMapping , uTag ,
DeviceExtension->pMDL , MmNonCached ) ;

*(DeviceExtension->pMemory) = .... // access the memory here .....

MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag , DeviceExtension->pMDL ) ;
....
}

Is there really nobody who feels involved with my problem ?

C.

----- Original Message -----
From: “Christiaan Ghijselinck”
To: “Windows System Software Devs Interest List”
Sent: Thursday, July 15, 2004 11:47 AM
Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

>
>
> Hello ,
>
>
> I like to reserve several chunks of memory and only map them when I need them. When I use the Scenario 1 flow on W2k, all seems
to
> work until I call “MyReadWrite” for the second time. It seems to be that the “MmUnmapLockedPages” call does not revert the state
of
> the MDL allocated pages as they were after I called MmGetSystemAddressForMdlSafe. Most of the time I get a
> “PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory” during the second call of “MyReadWrite”, sometimes it occurs during
the
> 3rd of later call.
>
> When I tried out Scenario 2 , everything runs perfect ! Now, I assume that when calling “MmUnmapLockedPages” and
> “MmGetSystemAddressForMdlSafe” shortly after each other, the allocated memory remains intact. When there is big time gab between
> those calls, the OS takes the time to unlock ( or whatever ) the memory after the first call of “MmUnmapLockedPages”.
>
> When I try out Scenario 3 with the new XP-and-higher functions, I get literally the message “The driver is mismanaging system
> PTEs” .
>
> All scenario calls run at PASSIVE_LEVEL. Using the equivalents “MmMapLockedPagesSpecifyCache” or “MmMapLockedPages” instead of
> “MmGetSystemAddressForMdlSafe” brought no relief.
>
> When I looked around for samples in the DDK that also used MmAllocatePagesForMdl, I did found “intrface.c” at \kernel\agp\agplib.
> That sample adds MDL_PAGES_LOCKED into the Mdl flags after the call of MmAllocatePagesForMdl, but that didn’t solve the problem.
>
> Is there a way or trick to bring the memory described by the MDL back into a “good and healthy” status ?
>
>
> Scenario 1 ( Windows 2000 ) :
> ----------------------------
> MyAddDevice ( )
> {
> …
> DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
>
> …
> }
> MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> {
> …
>
> DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;
>
> *(DeviceExtension->pMemory) = … // access the memory here …
>
> MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;
> }
>
> Scenario 2 ( Windows 2000 ) :
> ----------------------------
> MyAddDevice ( )
> {
> …
> DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
> DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;
>
> …
> }
> MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> {
> …
>
> MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;
>
> DeviceExtension->pMemory =
> MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;
>
> *(DeviceExtension->pMemory) = … // access the memory here …
>
> //// commented out : MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;
> }
>
>
> Scenario 3 ( Windows XP ) :
> ----------------------------
> MyAddDevice ( )
> {
> …
> DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
> DeviceExtension->pMapping = MmAllocateMappingAddress ( _size , uTag ) ;
> …
> }
> MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> {
> …
>
> DeviceExtension->pMemory =
> MmMapLockedPagesWithReservedMapping ( DeviceExtension->pMapping , uTag ,
> DeviceExtension->pMDL , MmNonCached ) ;
>
> *(DeviceExtension->pMemory) = … // access the memory here …
>
> MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag , DeviceExtension->pMDL ) ;
> …
> }
>
>
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compaqnet.be
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

Hello ,

I like to reserve several chunks of memory and only map them when I need them. When I use the *Scenario 1* flow on W2k, all seems
to work until I call "MyReadWrite" for the second time. It seems to be that the "MmUnmapLockedPages" call does not revert the state
of the MDL allocated pages as they were after I called MmGetSystemAddressForMdlSafe. Most of the time I get a
"PAGE_FAULT_IN_NONPAGED_AREA" when accessing the "*PMemory" during the second call of "MyReadWrite", sometimes it occurs during the
3rd of later call.

When I tried out *Scenario 2* , everything runs perfect ! Now, I assume that when calling "MmUnmapLockedPages" and
"MmGetSystemAddressForMdlSafe" shortly after each other, the allocated memory remains *intact*. When there is big time gab between
those calls, the OS takes the time to unlock ( or whatever ) the memory after the first call of "MmUnmapLockedPages".

When I try out *Scenario 3* on Xp using the new "XP-and-higher" functions, I get literally the message "The driver is mismanaging
system PTEs".

All scenario calls run at PASSIVE_LEVEL. Using the equivalents "MmMapLockedPagesSpecifyCache" or "MmMapLockedPages" instead of
"MmGetSystemAddressForMdlSafe" brought no relief.

When I looked around for samples in the DDK that also used MmAllocatePagesForMdl, I did found "intrface.c" at \kernel\agp\agplib.
That sample adds MDL_PAGES_LOCKED into the Mdl flags after the call of MmAllocatePagesForMdl, but that didn't solve the problem. Is
there a way or trick to bring the memory described by the MDL back into a "good and healthy" status ?

The scenarios are pseudo code only. All success/no-success defensive checks are omitted

Scenario 1 ( Windows 2000 ) :

MyAddDevice ( )
{
....
DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
....
}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
....
DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;

*(DeviceExtension->pMemory) = .... // access the memory here .....

MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;
}

Scenario 2 ( Windows 2000 ) :

MyAddDevice ( )
{
....
DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;
....
}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
....
MmUnmapLockedPages ( DeviceExtension->pMemory , DeviceExtension->pMDL ) ;
DeviceExtension->pMemory =
MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL , HighPagePriority ) ;

*pMemory = .... // access the memory here .....

//// commented out : MmUnmapLockedPages ( pMemory , DeviceExtension->pMDL ) ;
}

Scenario 3 ( Windows XP ) :

MyAddDevice ( )
{
....
DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
DeviceExtension->pMapping = MmAllocateMappingAddress ( _size , uTag ) ;
....
}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
....

DeviceExtension->pMemory =
MmMapLockedPagesWithReservedMapping ( DeviceExtension->pMapping , uTag , DeviceExtension->pMDL , mNonCached ) ;

*(DeviceExtension->pMemory) = .... // access the memory here .....

MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag , DeviceExtension->pMDL ) ;
....
}

Christiaan,

MmGetSystemAddressForMdlSafe() is a macro that checks
MDL_MAPPED_TO_SYSTEM_VA flag inside the MDL.
If it is not set then the macro calls MmMapLockedPagesSpecifyCache()
See ddk.h for the definition of this macro.

It seems that Windows 2000 MmUnmapLockedPages() has a bug: it
doesn’t clear MDL_MAPPED_TO_SYSTEM_VA
so you have to do it explicitly by doing

MmUnmapLockedPages(…, mdl);
mdl->MdlFlags ~= MDL_MAPPED_TO_SYSTEM_VA;

XP MmUnmapLockedPages() does it by itself.

In Scenario 3 it is very likely that you reserve virtual address space in the
context
of System process (PnP Manager) but then you try to use this address space in

the arbitrary context (any process that reads/writes from you device if your
driver is
the top driver).

Dmitriy Budko, VMware

-----Original Message-----
From: Christiaan Ghijselinck

Sent: Sunday, July 18, 2004 1:39 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

Hello ,

I like to reserve several chunks of memory and only map them
when I need them. When I use the *Scenario 1* flow on W2k, all seems
to work until I call “MyReadWrite” for the second time. It
seems to be that the “MmUnmapLockedPages” call does not
revert the state
of the MDL allocated pages as they were after I called
MmGetSystemAddressForMdlSafe. Most of the time I get a
“PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory”
during the second call of “MyReadWrite”, sometimes it occurs
during the
3rd of later call.

When I tried out *Scenario 2* , everything runs perfect !
Now, I assume that when calling “MmUnmapLockedPages” and
“MmGetSystemAddressForMdlSafe” shortly after each other, the
allocated memory remains *intact*. When there is big time gab between
those calls, the OS takes the time to unlock ( or whatever )
the memory after the first call of “MmUnmapLockedPages”.

When I try out *Scenario 3* on Xp using the new
“XP-and-higher” functions, I get literally the message “The
driver is mismanaging
system PTEs”.

All scenario calls run at PASSIVE_LEVEL. Using the
equivalents “MmMapLockedPagesSpecifyCache” or
“MmMapLockedPages” instead of
“MmGetSystemAddressForMdlSafe” brought no relief.

When I looked around for samples in the DDK that also used
MmAllocatePagesForMdl, I did found “intrface.c” at \kernel\agp\agplib.
That sample adds MDL_PAGES_LOCKED into the Mdl flags after
the call of MmAllocatePagesForMdl, but that didn’t solve the
problem. Is
there a way or trick to bring the memory described by the MDL
back into a “good and healthy” status ?

The scenarios are pseudo code only. All success/no-success
defensive checks are omitted

Scenario 1 ( Windows 2000 ) :

MyAddDevice ( )
{

DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress
, HghAddress, SkipSize , ulChunkSize ) ;

}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{

DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
DeviceExtension->pMDL , HighPagePriority ) ;

*(DeviceExtension->pMemory) = … // access the memory here …

MmUnmapLockedPages ( DeviceExtension->pMemory ,
DeviceExtension->pMDL ) ;
}

Scenario 2 ( Windows 2000 ) :

MyAddDevice ( )
{

DeviceExtension->pMDL = MmAllocatePagesForMdl (
LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
DeviceExtension->pMDL , HighPagePriority ) ;

}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{

MmUnmapLockedPages ( DeviceExtension->pMemory ,
DeviceExtension->pMDL ) ;
DeviceExtension->pMemory =
MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL ,
HighPagePriority ) ;

*pMemory = … // access the memory here …

//// commented out : MmUnmapLockedPages ( pMemory ,
DeviceExtension->pMDL ) ;
}

Scenario 3 ( Windows XP ) :

MyAddDevice ( )
{

DeviceExtension->pMDL = MmAllocatePagesForMdl (
LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
DeviceExtension->pMapping = MmAllocateMappingAddress (
_size , uTag ) ;

}
MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{

DeviceExtension->pMemory =
MmMapLockedPagesWithReservedMapping (
DeviceExtension->pMapping , uTag , DeviceExtension->pMDL ,
mNonCached ) ;

*(DeviceExtension->pMemory) = … // access the memory here …

MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag
, DeviceExtension->pMDL ) ;

}

Many thanks for your answer.

Personally I did not notice that MmUnmapLockedPages() did let hang the
MDL_MAPPED_TO_SYSTEM_VA flag. It has been cleared every time.
Probably because I build and linked the driver for XP ( DDK 2600 ) or due
of the latest W2000 service packs ( SP4 is installed ).

However, I did found out that MDL_PAGES_LOCKED is set by
MmAllocatePagesForMdl while running on XP and NOT while running W2000.

Nevertheless, the PAGE_FAULT_IN_NONPAGED_AREA occurs also on XP
when using *scenario 1*. Could it have something to do with the different
process contexts of MyAddDevice and MyReadWrite ? It’s hardly to believe
that this is the cause of the problem, otherwise *Scenario 2* would fail too.

Any ideas or suggestions are still very welcome !

*Scenario 3* is thus not an alternative, just because MyReadWrite may be called
from different ( unknown ) processes. Or there should be a way to circumvent that
behavior. It 's regrettable that those functions have such a restricted usage.

Christiaan

----- Original Message -----
From: “Dmitriy Budko”
To: “Windows System Software Devs Interest List”
Cc:
Sent: Tuesday, July 20, 2004 4:33 AM
Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

> Christiaan,
>
> MmGetSystemAddressForMdlSafe() is a macro that checks
> MDL_MAPPED_TO_SYSTEM_VA flag inside the MDL.
> If it is not set then the macro calls MmMapLockedPagesSpecifyCache()
> See ddk.h for the definition of this macro.
>
> It seems that Windows 2000 MmUnmapLockedPages() has a bug: it
> doesn’t clear MDL_MAPPED_TO_SYSTEM_VA
> so you have to do it explicitly by doing
>
> MmUnmapLockedPages(…, mdl);
> mdl->MdlFlags ~= MDL_MAPPED_TO_SYSTEM_VA;
>
> XP MmUnmapLockedPages() does it by itself.
>
>
> In Scenario 3 it is very likely that you reserve virtual address space in the
> context
> of System process (PnP Manager) but then you try to use this address space in
>
> the arbitrary context (any process that reads/writes from you device if your
> driver is
> the top driver).
>
>
> Dmitriy Budko, VMware
>
>
>
> > -----Original Message-----
> > From: Christiaan Ghijselinck
> >
> > Sent: Sunday, July 18, 2004 1:39 PM
> > To: Windows System Software Devs Interest List
> > Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> >
> >
> >
> >
> > Hello ,
> >
> >
> > I like to reserve several chunks of memory and only map them
> > when I need them. When I use the Scenario 1 flow on W2k, all seems
> > to work until I call “MyReadWrite” for the second time. It
> > seems to be that the “MmUnmapLockedPages” call does not
> > revert the state
> > of the MDL allocated pages as they were after I called
> > MmGetSystemAddressForMdlSafe. Most of the time I get a
> > “PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory”
> > during the second call of “MyReadWrite”, sometimes it occurs
> > during the
> > 3rd of later call.
> >
> > When I tried out Scenario 2 , everything runs perfect !
> > Now, I assume that when calling “MmUnmapLockedPages” and
> > “MmGetSystemAddressForMdlSafe” shortly after each other, the
> > allocated memory remains intact. When there is big time gab between
> > those calls, the OS takes the time to unlock ( or whatever )
> > the memory after the first call of “MmUnmapLockedPages”.
> >
> > When I try out Scenario 3 on Xp using the new
> > “XP-and-higher” functions, I get literally the message “The
> > driver is mismanaging
> > system PTEs”.
> >
> > All scenario calls run at PASSIVE_LEVEL. Using the
> > equivalents “MmMapLockedPagesSpecifyCache” or
> > “MmMapLockedPages” instead of
> > “MmGetSystemAddressForMdlSafe” brought no relief.
> >
> > When I looked around for samples in the DDK that also used
> > MmAllocatePagesForMdl, I did found “intrface.c” at \kernel\agp\agplib.
> > That sample adds MDL_PAGES_LOCKED into the Mdl flags after
> > the call of MmAllocatePagesForMdl, but that didn’t solve the
> > problem. Is
> > there a way or trick to bring the memory described by the MDL
> > back into a “good and healthy” status ?
> >
> > The scenarios are pseudo code only. All success/no-success
> > defensive checks are omitted
> >
> > Scenario 1 ( Windows 2000 ) :
> > ----------------------------
> > MyAddDevice ( )
> > {
> > …
> > DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress
> > , HghAddress, SkipSize , ulChunkSize ) ;
> > …
> > }
> > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > {
> > …
> > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > DeviceExtension->pMDL , HighPagePriority ) ;
> >
> > *(DeviceExtension->pMemory) = … // access the memory here …
> >
> > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > DeviceExtension->pMDL ) ;
> > }
> >
> > Scenario 2 ( Windows 2000 ) :
> > ----------------------------
> > MyAddDevice ( )
> > {
> > …
> > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
> > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > DeviceExtension->pMDL , HighPagePriority ) ;
> > …
> > }
> > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > {
> > …
> > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > DeviceExtension->pMDL ) ;
> > DeviceExtension->pMemory =
> > MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL ,
> > HighPagePriority ) ;
> >
> > *pMemory = … // access the memory here …
> >
> > //// commented out : MmUnmapLockedPages ( pMemory ,
> > DeviceExtension->pMDL ) ;
> > }
> >
> > Scenario 3 ( Windows XP ) :
> > ----------------------------
> > MyAddDevice ( )
> > {
> > …
> > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
> > DeviceExtension->pMapping = MmAllocateMappingAddress (
> > _size , uTag ) ;
> > …
> > }
> > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > {
> > …
> >
> > DeviceExtension->pMemory =
> > MmMapLockedPagesWithReservedMapping (
> > DeviceExtension->pMapping , uTag , DeviceExtension->pMDL ,
> > mNonCached ) ;
> >
> > *(DeviceExtension->pMemory) = … // access the memory here …
> >
> > MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag
> > , DeviceExtension->pMDL ) ;
> > …
> > }
>
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compaqnet.be
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>

I believe reserve addresses are always in the kernel address space and
thus are available in any process context.

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Christiaan
Ghijselinck
Sent: Tuesday, July 20, 2004 10:29 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

Many thanks for your answer.

Personally I did not notice that MmUnmapLockedPages() did let hang the
MDL_MAPPED_TO_SYSTEM_VA flag. It has been cleared every time.
Probably because I build and linked the driver for XP ( DDK 2600 ) or
due of the latest W2000 service packs ( SP4 is installed ).

However, I did found out that MDL_PAGES_LOCKED is set by
MmAllocatePagesForMdl while running on XP and NOT while running W2000.

Nevertheless, the PAGE_FAULT_IN_NONPAGED_AREA occurs also on XP when
using *scenario 1*. Could it have something to do with the different
process contexts of MyAddDevice and MyReadWrite ? It’s hardly to
believe that this is the cause of the problem, otherwise *Scenario 2*
would fail too.

Any ideas or suggestions are still very welcome !

*Scenario 3* is thus not an alternative, just because MyReadWrite may be
called from different ( unknown ) processes. Or there should be a way to
circumvent that behavior. It 's regrettable that those functions have
such a restricted usage.

Christiaan

----- Original Message -----
From: “Dmitriy Budko”
To: “Windows System Software Devs Interest List”
Cc:
Sent: Tuesday, July 20, 2004 4:33 AM
Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

> Christiaan,
>
> MmGetSystemAddressForMdlSafe() is a macro that checks
> MDL_MAPPED_TO_SYSTEM_VA flag inside the MDL.
> If it is not set then the macro calls MmMapLockedPagesSpecifyCache()
> See ddk.h for the definition of this macro.
>
> It seems that Windows 2000 MmUnmapLockedPages() has a bug: it
> doesn’t clear MDL_MAPPED_TO_SYSTEM_VA
> so you have to do it explicitly by doing
>
> MmUnmapLockedPages(…, mdl);
> mdl->MdlFlags ~= MDL_MAPPED_TO_SYSTEM_VA;
>
> XP MmUnmapLockedPages() does it by itself.
>
>
> In Scenario 3 it is very likely that you reserve virtual address space
in the
> context
> of System process (PnP Manager) but then you try to use this address
space in
>
> the arbitrary context (any process that reads/writes from you device
if your
> driver is
> the top driver).
>
>
> Dmitriy Budko, VMware
>
>
>
> > -----Original Message-----
> > From: Christiaan Ghijselinck
> >
> > Sent: Sunday, July 18, 2004 1:39 PM
> > To: Windows System Software Devs Interest List
> > Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> >
> >
> >
> >
> > Hello ,
> >
> >
> > I like to reserve several chunks of memory and only map them
> > when I need them. When I use the Scenario 1 flow on W2k, all seems
> > to work until I call “MyReadWrite” for the second time. It
> > seems to be that the “MmUnmapLockedPages” call does not
> > revert the state
> > of the MDL allocated pages as they were after I called
> > MmGetSystemAddressForMdlSafe. Most of the time I get a
> > “PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory”
> > during the second call of “MyReadWrite”, sometimes it occurs
> > during the
> > 3rd of later call.
> >
> > When I tried out Scenario 2 , everything runs perfect !
> > Now, I assume that when calling “MmUnmapLockedPages” and
> > “MmGetSystemAddressForMdlSafe” shortly after each other, the
> > allocated memory remains intact. When there is big time gab
between
> > those calls, the OS takes the time to unlock ( or whatever )
> > the memory after the first call of “MmUnmapLockedPages”.
> >
> > When I try out Scenario 3 on Xp using the new
> > “XP-and-higher” functions, I get literally the message “The
> > driver is mismanaging
> > system PTEs”.
> >
> > All scenario calls run at PASSIVE_LEVEL. Using the
> > equivalents “MmMapLockedPagesSpecifyCache” or
> > “MmMapLockedPages” instead of
> > “MmGetSystemAddressForMdlSafe” brought no relief.
> >
> > When I looked around for samples in the DDK that also used
> > MmAllocatePagesForMdl, I did found “intrface.c” at
\kernel\agp\agplib.
> > That sample adds MDL_PAGES_LOCKED into the Mdl flags after
> > the call of MmAllocatePagesForMdl, but that didn’t solve the
> > problem. Is
> > there a way or trick to bring the memory described by the MDL
> > back into a “good and healthy” status ?
> >
> > The scenarios are pseudo code only. All success/no-success
> > defensive checks are omitted
> >
> > Scenario 1 ( Windows 2000 ) :
> > ----------------------------
> > MyAddDevice ( )
> > {
> > …
> > DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress
> > , HghAddress, SkipSize , ulChunkSize ) ;
> > …
> > }
> > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > {
> > …
> > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > DeviceExtension->pMDL , HighPagePriority ) ;
> >
> > *(DeviceExtension->pMemory) = … // access the memory here

> >
> > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > DeviceExtension->pMDL ) ;
> > }
> >
> > Scenario 2 ( Windows 2000 ) :
> > ----------------------------
> > MyAddDevice ( )
> > {
> > …
> > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
> > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > DeviceExtension->pMDL , HighPagePriority ) ;
> > …
> > }
> > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > {
> > …
> > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > DeviceExtension->pMDL ) ;
> > DeviceExtension->pMemory =
> > MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL ,
> > HighPagePriority ) ;
> >
> > *pMemory = … // access the memory here …
> >
> > //// commented out : MmUnmapLockedPages ( pMemory ,
> > DeviceExtension->pMDL ) ;
> > }
> >
> > Scenario 3 ( Windows XP ) :
> > ----------------------------
> > MyAddDevice ( )
> > {
> > …
> > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
> > DeviceExtension->pMapping = MmAllocateMappingAddress (
> > _size , uTag ) ;
> > …
> > }
> > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > {
> > …
> >
> > DeviceExtension->pMemory =
> > MmMapLockedPagesWithReservedMapping (
> > DeviceExtension->pMapping , uTag , DeviceExtension->pMDL ,
> > mNonCached ) ;
> >
> > *(DeviceExtension->pMemory) = … // access the memory here

> >
> > MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag
> > , DeviceExtension->pMDL ) ;
> > …
> > }
>
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as:
xxxxx@compaqnet.be
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> From: Peter Wieland [mailto:xxxxx@windows.microsoft.com]

I believe reserve addresses are always in the kernel address space and
thus are available in any process context.

-p

Peter,

yes, you are right, I was wrong here.
MmAllocateMappingAddress() reserves system adress space.

Christiaan,

something is wrong in your implementation. Here is the relevant code from
my test driver that works perfectly under high memory pressure on XP SP1.
It implements your Scenarios 1 and 3:

#define MAPPED_TAG ‘tpaM’

MDL *mdl1, *mdl3;
void* mapping;

MDL*
AllocatePages(size_t numPages)
{
MDL* mdl;
PHYSICAL_ADDRESS zero;
PHYSICAL_ADDRESS topMemory;

zero.QuadPart = 0;
topMemory.QuadPart = -1;

/* allocate MDL, allocate pages, fill in the MDL */
mdl = MmAllocatePagesForMdl(zero, topMemory, zero, numPages * PAGE_SIZE);
if (mdl == NULL) {
DbgPrint((“Can’t MmAllocatePagesForMdl() to allocate %u pages\n”,
numPages));
return NULL;
}

if (MmGetMdlByteCount(mdl) != numPages * PAGE_SIZE) {
DbgPrint((“MmAllocatePagesForMdl() allocated only %u from %u requested
pages\n”,
MmGetMdlByteCount(mdl)/ PAGE_SIZE, numPages));

MmFreePagesFromMdl(mdl);
ExFreePool(mdl);

return NULL;
}
return mdl;
}

void
FreePages(MDL* mdl)
{
if (mdl) {
MmFreePagesFromMdl(mdl);
ExFreePool(mdl);
}
}

void*
ReserveSystemAdressSpace(size_t numPages)
{
return MmAllocateMappingAddress(numPages * PAGE_SIZE, MAPPED_TAG);
}

void
UnreserveSystemAdressSpace(void* ptr)
{
if (ptr) {
MmFreeMappingAddress(ptr, MAPPED_TAG);
}
}

void
MapWriteUmmapMem1(MDL* mdl)
{
static char c;
void* ptr;

ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
if (!ptr) {
KdBreakPoint();
return;
}
RtlFillMemory(ptr, MmGetMdlByteCount(mdl), c++);
MmUnmapLockedPages(ptr, mdl);
}

void
MapWriteUmmapMem3(MDL* mdl, void* reservedAddr)
{
static char c;
void* ptr;

ptr = MmMapLockedPagesWithReservedMapping (reservedAddr, MAPPED_TAG, mdl,
MmCached);
if (!ptr) {
KdBreakPoint();
return;
}
RtlFillMemory(ptr, MmGetMdlByteCount(mdl), c++);
MmUnmapReservedMapping(ptr, MAPPED_TAG, mdl);
}

LockMemDrvDeviceControl()
{

switch ( ioControlCode ) {

case IOCTL_LOCKMEM_MAP1: {
MapWriteUmmapMem1(mdl1);
break;
}

case IOCTL_LOCKMEM_MAP3: {
MapWriteUmmapMem3(mdl3, mapping);
break;
}
}

}

DriverEntry()
{

mdl1 = AllocatePages(16*1024*1024/PAGE_SIZE);
mdl3 = AllocatePages(16*1024*1024/PAGE_SIZE);
mapping = ReserveSystemAdressSpace(16*1024*1024/PAGE_SIZE);

}

LockMemDrvUnload()
{

FreePages(mdl1);
FreePages(mdl3);
UnreserveSystemAdressSpace(mapping);

}

Dmitriy Budko, VMware

-----Original Message-----
From: Christiaan Ghijselinck
[mailto:xxxxx@CompaqNet.be]
Sent: Tuesday, July 20, 2004 10:29 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

Many thanks for your answer.

Personally I did not notice that MmUnmapLockedPages() did
let hang the
MDL_MAPPED_TO_SYSTEM_VA flag. It has been cleared every time.
Probably because I build and linked the driver for XP ( DDK
2600 ) or due
of the latest W2000 service packs ( SP4 is installed ).

However, I did found out that MDL_PAGES_LOCKED is set by
MmAllocatePagesForMdl while running on XP and NOT while
running W2000.

Nevertheless, the PAGE_FAULT_IN_NONPAGED_AREA occurs also on XP
when using *scenario 1*. Could it have something to do with
the different
process contexts of MyAddDevice and MyReadWrite ? It’s
hardly to believe
that this is the cause of the problem, otherwise *Scenario 2*
would fail too.

Any ideas or suggestions are still very welcome !

*Scenario 3* is thus not an alternative, just because
MyReadWrite may be called
from different ( unknown ) processes. Or there should be a
way to circumvent that
behavior. It 's regrettable that those functions have such a
restricted usage.

Christiaan

----- Original Message -----
From: “Dmitriy Budko”
> To: “Windows System Software Devs Interest List”
> Cc:
> Sent: Tuesday, July 20, 2004 4:33 AM
> Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
>
>
> > Christiaan,
> >
> > MmGetSystemAddressForMdlSafe() is a macro that checks
> > MDL_MAPPED_TO_SYSTEM_VA flag inside the MDL.
> > If it is not set then the macro calls MmMapLockedPagesSpecifyCache()
> > See ddk.h for the definition of this macro.
> >
> > It seems that Windows 2000 MmUnmapLockedPages() has a bug: it
> > doesn’t clear MDL_MAPPED_TO_SYSTEM_VA
> > so you have to do it explicitly by doing
> >
> > MmUnmapLockedPages(…, mdl);
> > mdl->MdlFlags ~= MDL_MAPPED_TO_SYSTEM_VA;
> >
> > XP MmUnmapLockedPages() does it by itself.
> >
> >
> > In Scenario 3 it is very likely that you reserve virtual
> address space in the
> > context
> > of System process (PnP Manager) but then you try to use
> this address space in
> >
> > the arbitrary context (any process that reads/writes from
> you device if your
> > driver is
> > the top driver).
> >
> >
> > Dmitriy Budko, VMware
> >
> >
> >
> > > -----Original Message-----
> > > From: Christiaan Ghijselinck
> > >
> > > Sent: Sunday, July 18, 2004 1:39 PM
> > > To: Windows System Software Devs Interest List
> > > Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> > >
> > >
> > >
> > >
> > > Hello ,
> > >
> > >
> > > I like to reserve several chunks of memory and only map them
> > > when I need them. When I use the Scenario 1 flow on
> W2k, all seems
> > > to work until I call “MyReadWrite” for the second time. It
> > > seems to be that the “MmUnmapLockedPages” call does not
> > > revert the state
> > > of the MDL allocated pages as they were after I called
> > > MmGetSystemAddressForMdlSafe. Most of the time I get a
> > > “PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory”
> > > during the second call of “MyReadWrite”, sometimes it occurs
> > > during the
> > > 3rd of later call.
> > >
> > > When I tried out Scenario 2 , everything runs perfect !
> > > Now, I assume that when calling “MmUnmapLockedPages” and
> > > “MmGetSystemAddressForMdlSafe” shortly after each other, the
> > > allocated memory remains intact. When there is big time
> gab between
> > > those calls, the OS takes the time to unlock ( or whatever )
> > > the memory after the first call of “MmUnmapLockedPages”.
> > >
> > > When I try out Scenario 3 on Xp using the new
> > > “XP-and-higher” functions, I get literally the message “The
> > > driver is mismanaging
> > > system PTEs”.
> > >
> > > All scenario calls run at PASSIVE_LEVEL. Using the
> > > equivalents “MmMapLockedPagesSpecifyCache” or
> > > “MmMapLockedPages” instead of
> > > “MmGetSystemAddressForMdlSafe” brought no relief.
> > >
> > > When I looked around for samples in the DDK that also used
> > > MmAllocatePagesForMdl, I did found “intrface.c” at
> \kernel\agp\agplib.
> > > That sample adds MDL_PAGES_LOCKED into the Mdl flags after
> > > the call of MmAllocatePagesForMdl, but that didn’t solve the
> > > problem. Is
> > > there a way or trick to bring the memory described by the MDL
> > > back into a “good and healthy” status ?
> > >
> > > The scenarios are pseudo code only. All success/no-success
> > > defensive checks are omitted
> > >
> > > Scenario 1 ( Windows 2000 ) :
> > > ----------------------------
> > > MyAddDevice ( )
> > > {
> > > …
> > > DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress
> > > , HghAddress, SkipSize , ulChunkSize ) ;
> > > …
> > > }
> > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > {
> > > …
> > > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > > DeviceExtension->pMDL , HighPagePriority ) ;
> > >
> > > *(DeviceExtension->pMemory) = … // access the
> memory here …
> > >
> > > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > > DeviceExtension->pMDL ) ;
> > > }
> > >
> > > Scenario 2 ( Windows 2000 ) :
> > > ----------------------------
> > > MyAddDevice ( )
> > > {
> > > …
> > > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > > LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
> > > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > > DeviceExtension->pMDL , HighPagePriority ) ;
> > > …
> > > }
> > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > {
> > > …
> > > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > > DeviceExtension->pMDL ) ;
> > > DeviceExtension->pMemory =
> > > MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL ,
> > > HighPagePriority ) ;
> > >
> > > *pMemory = … // access the memory here …
> > >
> > > //// commented out : MmUnmapLockedPages ( pMemory ,
> > > DeviceExtension->pMDL ) ;
> > > }
> > >
> > > Scenario 3 ( Windows XP ) :
> > > ----------------------------
> > > MyAddDevice ( )
> > > {
> > > …
> > > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > > LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
> > > DeviceExtension->pMapping = MmAllocateMappingAddress (
> > > _size , uTag ) ;
> > > …
> > > }
> > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > {
> > > …
> > >
> > > DeviceExtension->pMemory =
> > > MmMapLockedPagesWithReservedMapping (
> > > DeviceExtension->pMapping , uTag , DeviceExtension->pMDL ,
> > > mNonCached ) ;
> > >
> > > *(DeviceExtension->pMemory) = … // access the
> memory here …
> > >
> > > MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag
> > > , DeviceExtension->pMDL ) ;
> > > …
> > > }

Thank you Dmitriy for having taken the time to program a sample. I am almost sure that the cause of my
problem are concurrent “MyReadWrite” calls, that, as I have noticed do indeed occur . This may mess up the
data stored at the MDL storage at PMDL.

I had to think about this before , just because I posted on this OSR list some time ago a question about simultaneous
reads and writes tasks to drivers. Sorry for having spoiled your time on this problem.

Christiaan

----- Original Message -----
From: “Dmitriy Budko”
To: “Windows System Software Devs Interest List”
Cc: “Christiaan Ghijselinck”
Sent: Wednesday, July 21, 2004 4:20 AM
Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

> > From: Peter Wieland [mailto:xxxxx@windows.microsoft.com]
> >
> > I believe reserve addresses are always in the kernel address space and
> > thus are available in any process context.
> >
> > -p
>
> Peter,
>
> yes, you are right, I was wrong here.
> MmAllocateMappingAddress() reserves system adress space.
>
>
> Christiaan,
>
> something is wrong in your implementation. Here is the relevant code from
> my test driver that works perfectly under high memory pressure on XP SP1.
> It implements your Scenarios 1 and 3:
>
>
> #define MAPPED_TAG ‘tpaM’
>
> MDL mdl1, mdl3;
> void
mapping;
>
>
> MDL

> AllocatePages(size_t numPages)
> {
> MDL* mdl;
> PHYSICAL_ADDRESS zero;
> PHYSICAL_ADDRESS topMemory;
>
> zero.QuadPart = 0;
> topMemory.QuadPart = -1;
>
>
> /* allocate MDL, allocate pages, fill in the MDL /
> mdl = MmAllocatePagesForMdl(zero, topMemory, zero, numPages * PAGE_SIZE);
> if (mdl == NULL) {
> DbgPrint((“Can’t MmAllocatePagesForMdl() to allocate %u pages\n”,
> numPages));
> return NULL;
> }
>
> if (MmGetMdlByteCount(mdl) != numPages * PAGE_SIZE) {
> DbgPrint((“MmAllocatePagesForMdl() allocated only %u from %u requested
> pages\n”,
> MmGetMdlByteCount(mdl)/ PAGE_SIZE, numPages));
>
> MmFreePagesFromMdl(mdl);
> ExFreePool(mdl);
>
> return NULL;
> }
> return mdl;
> }
>
>
> void
> FreePages(MDL
mdl)
> {
> if (mdl) {
> MmFreePagesFromMdl(mdl);
> ExFreePool(mdl);
> }
> }
>
>
> void*
> ReserveSystemAdressSpace(size_t numPages)
> {
> return MmAllocateMappingAddress(numPages * PAGE_SIZE, MAPPED_TAG);
> }
>
> void
> UnreserveSystemAdressSpace(void* ptr)
> {
> if (ptr) {
> MmFreeMappingAddress(ptr, MAPPED_TAG);
> }
> }
>
>
>
> void
> MapWriteUmmapMem1(MDL* mdl)
> {
> static char c;
> void* ptr;
>
> ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
> if (!ptr) {
> KdBreakPoint();
> return;
> }
> RtlFillMemory(ptr, MmGetMdlByteCount(mdl), c++);
> MmUnmapLockedPages(ptr, mdl);
> }
>
> void
> MapWriteUmmapMem3(MDL* mdl, void* reservedAddr)
> {
> static char c;
> void* ptr;
>
> ptr = MmMapLockedPagesWithReservedMapping (reservedAddr, MAPPED_TAG, mdl,
> MmCached);
> if (!ptr) {
> KdBreakPoint();
> return;
> }
> RtlFillMemory(ptr, MmGetMdlByteCount(mdl), c++);
> MmUnmapReservedMapping(ptr, MAPPED_TAG, mdl);
> }
>
>
> LockMemDrvDeviceControl()
> {
> …
> switch ( ioControlCode ) {
> …
> case IOCTL_LOCKMEM_MAP1: {
> MapWriteUmmapMem1(mdl1);
> break;
> }
>
> case IOCTL_LOCKMEM_MAP3: {
> MapWriteUmmapMem3(mdl3, mapping);
> break;
> }
> }
> …
> }
>
>
> DriverEntry()
> {
> …
> mdl1 = AllocatePages(1610241024/PAGE_SIZE);
> mdl3 = AllocatePages(1610241024/PAGE_SIZE);
> mapping = ReserveSystemAdressSpace(1610241024/PAGE_SIZE);
> …
> }
>
>
> LockMemDrvUnload()
> {
> …
> FreePages(mdl1);
> FreePages(mdl3);
> UnreserveSystemAdressSpace(mapping);
> …
> }
>
>
> Dmitriy Budko, VMware
>
>
> > -----Original Message-----
> > From: Christiaan Ghijselinck
> > [mailto:xxxxx@CompaqNet.be]
> > Sent: Tuesday, July 20, 2004 10:29 AM
> > To: Windows System Software Devs Interest List
> > Subject: Re: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> >
> >
> >
> > Many thanks for your answer.
> >
> > Personally I did not notice that MmUnmapLockedPages() did
> > let hang the
> > MDL_MAPPED_TO_SYSTEM_VA flag. It has been cleared every time.
> > Probably because I build and linked the driver for XP ( DDK
> > 2600 ) or due
> > of the latest W2000 service packs ( SP4 is installed ).
> >
> > However, I did found out that MDL_PAGES_LOCKED is set by
> > MmAllocatePagesForMdl while running on XP and NOT while
> > running W2000.
> >
> > Nevertheless, the PAGE_FAULT_IN_NONPAGED_AREA occurs also on XP
> > when using scenario 1. Could it have something to do with
> > the different
> > process contexts of MyAddDevice and MyReadWrite ? It’s
> > hardly to believe
> > that this is the cause of the problem, otherwise Scenario 2
> > would fail too.
> >
> > Any ideas or suggestions are still very welcome !
> >
> >
> > Scenario 3 is thus not an alternative, just because
> > MyReadWrite may be called
> > from different ( unknown ) processes. Or there should be a
> > way to circumvent that
> > behavior. It 's regrettable that those functions have such a
> > restricted usage.
> >
> >
> > Christiaan
> >
> >
> > ----- Original Message -----
> > From: “Dmitriy Budko”
> > To: “Windows System Software Devs Interest List”
> > Cc:
> > Sent: Tuesday, July 20, 2004 4:33 AM
> > Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> >
> >
> > > Christiaan,
> > >
> > > MmGetSystemAddressForMdlSafe() is a macro that checks
> > > MDL_MAPPED_TO_SYSTEM_VA flag inside the MDL.
> > > If it is not set then the macro calls MmMapLockedPagesSpecifyCache()
> > > See ddk.h for the definition of this macro.
> > >
> > > It seems that Windows 2000 MmUnmapLockedPages() has a bug: it
> > > doesn’t clear MDL_MAPPED_TO_SYSTEM_VA
> > > so you have to do it explicitly by doing
> > >
> > > MmUnmapLockedPages(…, mdl);
> > > mdl->MdlFlags ~= MDL_MAPPED_TO_SYSTEM_VA;
> > >
> > > XP MmUnmapLockedPages() does it by itself.
> > >
> > >
> > > In Scenario 3 it is very likely that you reserve virtual
> > address space in the
> > > context
> > > of System process (PnP Manager) but then you try to use
> > this address space in
> > >
> > > the arbitrary context (any process that reads/writes from
> > you device if your
> > > driver is
> > > the top driver).
> > >
> > >
> > > Dmitriy Budko, VMware
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Christiaan Ghijselinck
> > > >
> > > > Sent: Sunday, July 18, 2004 1:39 PM
> > > > To: Windows System Software Devs Interest List
> > > > Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> > > >
> > > >
> > > >
> > > >
> > > > Hello ,
> > > >
> > > >
> > > > I like to reserve several chunks of memory and only map them
> > > > when I need them. When I use the Scenario 1 flow on
> > W2k, all seems
> > > > to work until I call “MyReadWrite” for the second time. It
> > > > seems to be that the “MmUnmapLockedPages” call does not
> > > > revert the state
> > > > of the MDL allocated pages as they were after I called
> > > > MmGetSystemAddressForMdlSafe. Most of the time I get a
> > > > “PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory”
> > > > during the second call of “MyReadWrite”, sometimes it occurs
> > > > during the
> > > > 3rd of later call.
> > > >
> > > > When I tried out Scenario 2 , everything runs perfect !
> > > > Now, I assume that when calling “MmUnmapLockedPages” and
> > > > “MmGetSystemAddressForMdlSafe” shortly after each other, the
> > > > allocated memory remains intact. When there is big time
> > gab between
> > > > those calls, the OS takes the time to unlock ( or whatever )
> > > > the memory after the first call of “MmUnmapLockedPages”.
> > > >
> > > > When I try out Scenario 3 on Xp using the new
> > > > “XP-and-higher” functions, I get literally the message “The
> > > > driver is mismanaging
> > > > system PTEs”.
> > > >
> > > > All scenario calls run at PASSIVE_LEVEL. Using the
> > > > equivalents “MmMapLockedPagesSpecifyCache” or
> > > > “MmMapLockedPages” instead of
> > > > “MmGetSystemAddressForMdlSafe” brought no relief.
> > > >
> > > > When I looked around for samples in the DDK that also used
> > > > MmAllocatePagesForMdl, I did found “intrface.c” at
> > \kernel\agp\agplib.
> > > > That sample adds MDL_PAGES_LOCKED into the Mdl flags after
> > > > the call of MmAllocatePagesForMdl, but that didn’t solve the
> > > > problem. Is
> > > > there a way or trick to bring the memory described by the MDL
> > > > back into a “good and healthy” status ?
> > > >
> > > > The scenarios are pseudo code only. All success/no-success
> > > > defensive checks are omitted
> > > >
> > > > Scenario 1 ( Windows 2000 ) :
> > > > ----------------------------
> > > > MyAddDevice ( )
> > > > {
> > > > …
> > > > DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress
> > > > , HghAddress, SkipSize , ulChunkSize ) ;
> > > > …
> > > > }
> > > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > > {
> > > > …
> > > > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > > > DeviceExtension->pMDL , HighPagePriority ) ;
> > > >
> > > > *(DeviceExtension->pMemory) = … // access the
> > memory here …
> > > >
> > > > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > > > DeviceExtension->pMDL ) ;
> > > > }
> > > >
> > > > Scenario 2 ( Windows 2000 ) :
> > > > ----------------------------
> > > > MyAddDevice ( )
> > > > {
> > > > …
> > > > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > > > LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
> > > > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > > > DeviceExtension->pMDL , HighPagePriority ) ;
> > > > …
> > > > }
> > > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > > {
> > > > …
> > > > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > > > DeviceExtension->pMDL ) ;
> > > > DeviceExtension->pMemory =
> > > > MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL ,
> > > > HighPagePriority ) ;
> > > >
> > > > *pMemory = … // access the memory here …
> > > >
> > > > //// commented out : MmUnmapLockedPages ( pMemory ,
> > > > DeviceExtension->pMDL ) ;
> > > > }
> > > >
> > > > Scenario 3 ( Windows XP ) :
> > > > ----------------------------
> > > > MyAddDevice ( )
> > > > {
> > > > …
> > > > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > > > LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
> > > > DeviceExtension->pMapping = MmAllocateMappingAddress (
> > > > _size , uTag ) ;
> > > > …
> > > > }
> > > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > > {
> > > > …
> > > >
> > > > DeviceExtension->pMemory =
> > > > MmMapLockedPagesWithReservedMapping (
> > > > DeviceExtension->pMapping , uTag , DeviceExtension->pMDL ,
> > > > mNonCached ) ;
> > > >
> > > > *(DeviceExtension->pMemory) = … // access the
> > memory here …
> > > >
> > > > MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag
> > > > , DeviceExtension->pMDL ) ;
> > > > …
> > > > }
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@compaqnet.be
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>

I guess we could say that you have locked in on that bug :slight_smile:

=====================
Mark Roddy

-----Original Message-----
From: Christiaan Ghijselinck [mailto:xxxxx@CompaqNet.be]
Sent: Wednesday, July 21, 2004 1:39 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

Thank you Dmitriy for having taken the time to program a sample. I am
almost sure that the cause of my problem are concurrent “MyReadWrite” calls,
that, as I have noticed do indeed occur . This may mess up the data stored
at the MDL storage at PMDL.

I had to think about this before , just because I posted on this OSR list
some time ago a question about simultaneous reads and writes tasks to
drivers. Sorry for having spoiled your time on this problem.

Christiaan

----- Original Message -----
From: “Dmitriy Budko”
To: “Windows System Software Devs Interest List”
Cc: “Christiaan Ghijselinck”
Sent: Wednesday, July 21, 2004 4:20 AM
Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages

> > From: Peter Wieland [mailto:xxxxx@windows.microsoft.com]
> >
> > I believe reserve addresses are always in the kernel address space and
> > thus are available in any process context.
> >
> > -p
>
> Peter,
>
> yes, you are right, I was wrong here.
> MmAllocateMappingAddress() reserves system adress space.
>
>
> Christiaan,
>
> something is wrong in your implementation. Here is the relevant code from
> my test driver that works perfectly under high memory pressure on XP SP1.
> It implements your Scenarios 1 and 3:
>
>
> #define MAPPED_TAG ‘tpaM’
>
> MDL mdl1, mdl3;
> void
mapping;
>
>
> MDL

> AllocatePages(size_t numPages)
> {
> MDL* mdl;
> PHYSICAL_ADDRESS zero;
> PHYSICAL_ADDRESS topMemory;
>
> zero.QuadPart = 0;
> topMemory.QuadPart = -1;
>
>
> /* allocate MDL, allocate pages, fill in the MDL /
> mdl = MmAllocatePagesForMdl(zero, topMemory, zero, numPages
PAGE_SIZE);
> if (mdl == NULL) {
> DbgPrint((“Can’t MmAllocatePagesForMdl() to allocate %u pages\n”,
> numPages));
> return NULL;
> }
>
> if (MmGetMdlByteCount(mdl) != numPages * PAGE_SIZE) {
> DbgPrint((“MmAllocatePagesForMdl() allocated only %u from %u
requested
> pages\n”,
> MmGetMdlByteCount(mdl)/ PAGE_SIZE, numPages));
>
> MmFreePagesFromMdl(mdl);
> ExFreePool(mdl);
>
> return NULL;
> }
> return mdl;
> }
>
>
> void
> FreePages(MDL
mdl)
> {
> if (mdl) {
> MmFreePagesFromMdl(mdl);
> ExFreePool(mdl);
> }
> }
>
>
> void

> ReserveSystemAdressSpace(size_t numPages)
> {
> return MmAllocateMappingAddress(numPages * PAGE_SIZE, MAPPED_TAG);
> }
>
> void
> UnreserveSystemAdressSpace(void* ptr)
> {
> if (ptr) {
> MmFreeMappingAddress(ptr, MAPPED_TAG);
> }
> }
>
>
>
> void
> MapWriteUmmapMem1(MDL* mdl)
> {
> static char c;
> void* ptr;
>
> ptr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
> if (!ptr) {
> KdBreakPoint();
> return;
> }
> RtlFillMemory(ptr, MmGetMdlByteCount(mdl), c++);
> MmUnmapLockedPages(ptr, mdl);
> }
>
> void
> MapWriteUmmapMem3(MDL* mdl, void* reservedAddr)
> {
> static char c;
> void* ptr;
>
> ptr = MmMapLockedPagesWithReservedMapping (reservedAddr, MAPPED_TAG,
mdl,
> MmCached);
> if (!ptr) {
> KdBreakPoint();
> return;
> }
> RtlFillMemory(ptr, MmGetMdlByteCount(mdl), c++);
> MmUnmapReservedMapping(ptr, MAPPED_TAG, mdl);
> }
>
>
> LockMemDrvDeviceControl()
> {
> …
> switch ( ioControlCode ) {
> …
> case IOCTL_LOCKMEM_MAP1: {
> MapWriteUmmapMem1(mdl1);
> break;
> }
>
> case IOCTL_LOCKMEM_MAP3: {
> MapWriteUmmapMem3(mdl3, mapping);
> break;
> }
> }
> …
> }
>
>
> DriverEntry()
> {
> …
> mdl1 = AllocatePages(1610241024/PAGE_SIZE);
> mdl3 = AllocatePages(1610241024/PAGE_SIZE);
> mapping = ReserveSystemAdressSpace(1610241024/PAGE_SIZE);
> …
> }
>
>
> LockMemDrvUnload()
> {
> …
> FreePages(mdl1);
> FreePages(mdl3);
> UnreserveSystemAdressSpace(mapping);
> …
> }
>
>
> Dmitriy Budko, VMware
>
>
> > -----Original Message-----
> > From: Christiaan Ghijselinck
> > [mailto:xxxxx@CompaqNet.be]
> > Sent: Tuesday, July 20, 2004 10:29 AM
> > To: Windows System Software Devs Interest List
> > Subject: Re: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> >
> >
> >
> > Many thanks for your answer.
> >
> > Personally I did not notice that MmUnmapLockedPages() did
> > let hang the
> > MDL_MAPPED_TO_SYSTEM_VA flag. It has been cleared every time.
> > Probably because I build and linked the driver for XP ( DDK
> > 2600 ) or due
> > of the latest W2000 service packs ( SP4 is installed ).
> >
> > However, I did found out that MDL_PAGES_LOCKED is set by
> > MmAllocatePagesForMdl while running on XP and NOT while
> > running W2000.
> >
> > Nevertheless, the PAGE_FAULT_IN_NONPAGED_AREA occurs also on XP
> > when using scenario 1. Could it have something to do with
> > the different
> > process contexts of MyAddDevice and MyReadWrite ? It’s
> > hardly to believe
> > that this is the cause of the problem, otherwise Scenario 2
> > would fail too.
> >
> > Any ideas or suggestions are still very welcome !
> >
> >
> > Scenario 3 is thus not an alternative, just because
> > MyReadWrite may be called
> > from different ( unknown ) processes. Or there should be a
> > way to circumvent that
> > behavior. It 's regrettable that those functions have such a
> > restricted usage.
> >
> >
> > Christiaan
> >
> >
> > ----- Original Message -----
> > From: “Dmitriy Budko”
> > To: “Windows System Software Devs Interest List”
> > Cc:
> > Sent: Tuesday, July 20, 2004 4:33 AM
> > Subject: RE: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> >
> >
> > > Christiaan,
> > >
> > > MmGetSystemAddressForMdlSafe() is a macro that checks
> > > MDL_MAPPED_TO_SYSTEM_VA flag inside the MDL.
> > > If it is not set then the macro calls MmMapLockedPagesSpecifyCache()
> > > See ddk.h for the definition of this macro.
> > >
> > > It seems that Windows 2000 MmUnmapLockedPages() has a bug: it
> > > doesn’t clear MDL_MAPPED_TO_SYSTEM_VA
> > > so you have to do it explicitly by doing
> > >
> > > MmUnmapLockedPages(…, mdl);
> > > mdl->MdlFlags ~= MDL_MAPPED_TO_SYSTEM_VA;
> > >
> > > XP MmUnmapLockedPages() does it by itself.
> > >
> > >
> > > In Scenario 3 it is very likely that you reserve virtual
> > address space in the
> > > context
> > > of System process (PnP Manager) but then you try to use
> > this address space in
> > >
> > > the arbitrary context (any process that reads/writes from
> > you device if your
> > > driver is
> > > the top driver).
> > >
> > >
> > > Dmitriy Budko, VMware
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Christiaan Ghijselinck
> > > >
> > > > Sent: Sunday, July 18, 2004 1:39 PM
> > > > To: Windows System Software Devs Interest List
> > > > Subject: [ntdev] MmAllocatePagesForMdl and MmUnmapLockedPages
> > > >
> > > >
> > > >
> > > >
> > > > Hello ,
> > > >
> > > >
> > > > I like to reserve several chunks of memory and only map them
> > > > when I need them. When I use the Scenario 1 flow on
> > W2k, all seems
> > > > to work until I call “MyReadWrite” for the second time. It
> > > > seems to be that the “MmUnmapLockedPages” call does not
> > > > revert the state
> > > > of the MDL allocated pages as they were after I called
> > > > MmGetSystemAddressForMdlSafe. Most of the time I get a
> > > > “PAGE_FAULT_IN_NONPAGED_AREA” when accessing the “*PMemory”
> > > > during the second call of “MyReadWrite”, sometimes it occurs
> > > > during the
> > > > 3rd of later call.
> > > >
> > > > When I tried out Scenario 2 , everything runs perfect !
> > > > Now, I assume that when calling “MmUnmapLockedPages” and
> > > > “MmGetSystemAddressForMdlSafe” shortly after each other, the
> > > > allocated memory remains intact. When there is big time
> > gab between
> > > > those calls, the OS takes the time to unlock ( or whatever )
> > > > the memory after the first call of “MmUnmapLockedPages”.
> > > >
> > > > When I try out Scenario 3 on Xp using the new
> > > > “XP-and-higher” functions, I get literally the message “The
> > > > driver is mismanaging
> > > > system PTEs”.
> > > >
> > > > All scenario calls run at PASSIVE_LEVEL. Using the
> > > > equivalents “MmMapLockedPagesSpecifyCache” or
> > > > “MmMapLockedPages” instead of
> > > > “MmGetSystemAddressForMdlSafe” brought no relief.
> > > >
> > > > When I looked around for samples in the DDK that also used
> > > > MmAllocatePagesForMdl, I did found “intrface.c” at
> > \kernel\agp\agplib.
> > > > That sample adds MDL_PAGES_LOCKED into the Mdl flags after
> > > > the call of MmAllocatePagesForMdl, but that didn’t solve the
> > > > problem. Is
> > > > there a way or trick to bring the memory described by the MDL
> > > > back into a “good and healthy” status ?
> > > >
> > > > The scenarios are pseudo code only. All success/no-success
> > > > defensive checks are omitted
> > > >
> > > > Scenario 1 ( Windows 2000 ) :
> > > > ----------------------------
> > > > MyAddDevice ( )
> > > > {
> > > > …
> > > > DeviceExtension->pMDL = MmAllocatePagesForMdl ( LowAddress
> > > > , HghAddress, SkipSize , ulChunkSize ) ;
> > > > …
> > > > }
> > > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > > {
> > > > …
> > > > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > > > DeviceExtension->pMDL , HighPagePriority ) ;
> > > >
> > > > *(DeviceExtension->pMemory) = … // access the
> > memory here …
> > > >
> > > > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > > > DeviceExtension->pMDL ) ;
> > > > }
> > > >
> > > > Scenario 2 ( Windows 2000 ) :
> > > > ----------------------------
> > > > MyAddDevice ( )
> > > > {
> > > > …
> > > > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > > > LowAddress , HghAddress, SkipSize , ulChunkSize ) ;
> > > > DeviceExtension->pMemory = MmGetSystemAddressForMdlSafe (
> > > > DeviceExtension->pMDL , HighPagePriority ) ;
> > > > …
> > > > }
> > > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > > {
> > > > …
> > > > MmUnmapLockedPages ( DeviceExtension->pMemory ,
> > > > DeviceExtension->pMDL ) ;
> > > > DeviceExtension->pMemory =
> > > > MmGetSystemAddressForMdlSafe ( DeviceExtension->pMDL ,
> > > > HighPagePriority ) ;
> > > >
> > > > *pMemory = … // access the memory here …
> > > >
> > > > //// commented out : MmUnmapLockedPages ( pMemory ,
> > > > DeviceExtension->pMDL ) ;
> > > > }
> > > >
> > > > Scenario 3 ( Windows XP ) :
> > > > ----------------------------
> > > > MyAddDevice ( )
> > > > {
> > > > …
> > > > DeviceExtension->pMDL = MmAllocatePagesForMdl (
> > > > LowAddress,HghAddress,SkipSize,ulChunkSize ) ;
> > > > DeviceExtension->pMapping = MmAllocateMappingAddress (
> > > > _size , uTag ) ;
> > > > …
> > > > }
> > > > MyReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
> > > > {
> > > > …
> > > >
> > > > DeviceExtension->pMemory =
> > > > MmMapLockedPagesWithReservedMapping (
> > > > DeviceExtension->pMapping , uTag , DeviceExtension->pMDL ,
> > > > mNonCached ) ;
> > > >
> > > > *(DeviceExtension->pMemory) = … // access the
> > memory here …
> > > >
> > > > MmUnmapReservedMapping ( DeviceExtension->pMemory , uTag
> > > > , DeviceExtension->pMDL ) ;
> > > > …
> > > > }
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as:
xxxxx@compaqnet.be
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@stratus.com
To unsubscribe send a blank email to xxxxx@lists.osr.com