Hello all,
Another question, again around allocating physical pages inside a driver and gaining access to those physical pages from user mode through the use of a virtual address mapping.
If I use MmAllocatePagesForMdl() to allocate physical pages, then I have the possibility to obtain a user virtual address with the following calls:
- PMDL pMdl_master = MmAllocatePagesForMdl(0x00000000, 0xFFFFFFFF, 4096, 10*4096); // 10 pages allocated
- PMDL pMdl_slave = IoAllocateMdl(NULL, 8192, FALSE, FALSE, NULL); // place for 2 pages
- IoBuildPartialMdl(pMdl_master, pMdl_slave, 4096, 8192); // extract pages 1 and 2
- PVOID pUser = MmMapLockedPagesSpecifyCache(pMdl_slave, UserMode, MmCached, NULL, FALSE, NormalPagePriority); // mapping
All this works fine and I obtain a valid user virtual address that points to pages 1 and 2.
The problem is that I cannot find a way to map into a single user virtual address several sections of my physical pages…
How can I do if I want to obtain a user virtual address that maps to page 1, page 2 and page 8 for example?
Thanks a lot in advance.
Vincent
> The problem is that I cannot find a way to map into a single user virtual
address several sections of my physical pages…
How can I do if I want to obtain a user virtual address that maps to page
1, page 2 and page 8 for example?
Do you want to map the 1st, 2nd and 8th pages to a consecutive virtual
adress range that spans 3 virtual pages?
If yes then use MmMapLockedPagesSpecifyCache two times - for the 1st-2nd
pages and for the 8th page provide the virtual address - add to the virtual
address returned from the first call the size of two pages. Maybe you are
lucky and the address will be free, if you want to be sure - find a free
virtual address range which spans at least 3 pages( find the address range
alligned on a 64 KB boundary ) and use it for calling
MmMapLockedPagesSpecifyCache.
–
Slava Imameyev, xxxxx@hotmail.com
wrote in message news:xxxxx@ntdev…
> Hello all,
>
> Another question, again around allocating physical pages inside a driver
> and gaining access to those physical pages from user mode through the use
> of a virtual address mapping.
>
> If I use MmAllocatePagesForMdl() to allocate physical pages, then I have
> the possibility to obtain a user virtual address with the following calls:
> 1. PMDL pMdl_master = MmAllocatePagesForMdl(0x00000000, 0xFFFFFFFF, 4096,
> 10*4096); // 10 pages allocated
> 2. PMDL pMdl_slave = IoAllocateMdl(NULL, 8192, FALSE, FALSE, NULL); //
> place for 2 pages
> 3. IoBuildPartialMdl(pMdl_master, pMdl_slave, 4096, 8192); // extract
> pages 1 and 2
> 4. PVOID pUser = MmMapLockedPagesSpecifyCache(pMdl_slave, UserMode,
> MmCached, NULL, FALSE, NormalPagePriority); // mapping
>
> All this works fine and I obtain a valid user virtual address that points
> to pages 1 and 2.
>
> The problem is that I cannot find a way to map into a single user virtual
> address several sections of my physical pages…
> How can I do if I want to obtain a user virtual address that maps to page
> 1, page 2 and page 8 for example?
>
> Thanks a lot in advance.
>
> Vincent
>
Thank you very much for this answer.
“Do you want to map the 1st, 2nd and 8th pages to a consecutive virtual adress range that spans 3 virtual pages?”
That’s an example of what I want to do, yes!
But, as you say, I want to be sure that I will succeed, so you talk about a way to find a free virtual address range; how can you do that?
Vincent
> But, as you say, I want to be sure that I will succeed, so you talk about a
way to
find a free virtual address range; how can you do that?
MmMapLockedPagesSpecifyCache should do it automatically.
–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com
Thank you Maxim and Slava.
I think I understand what does the MmMapLockedPagesSpecifyCache() function and how I can use it (at a very high level).
But let me explain my concern more in details:
- I know how to extract pages 1 and 2 from pMdl_master into pMdl_1 for example:
PMDL pMdl_1 = IoAllocateMdl(NULL, 2*4096, FALSE, FALSE, NULL);
IoBuildPartialMdl(pMdl_master, pMdl_1, 1*4096, 2*4096);
- I know how to extract page 8 from pMdl_master into pMdl_2 for example:
PMDL pMdl_2 = IoAllocateMdl(NULL, 1*4096, FALSE, FALSE, NULL);
IoBuildPartialMdl(pMdl_master, pMdl_2, 8*4096, 1*4096);
- But I don’t know how to MERGE or APPEND those two MDLs (pMdl_1 and pMdl_2) so that I can obtain one single MDL that will describes pages 1, 2 and 8.
After that, I will be able to use MmMapLockedPagesSpecifyCache() to map those 3 pages.
Is it clear to you, or is it a completely strange idea?
Best regards.
Vincent
He’s asking how to take a set of pages he’s allocated as (for example) a,b,c,d,e,f and how to map pages a,b,e into contiguous virtual addresses.
It is an unusual thing to want to do, Vincent, and Windows doesn’t really have an “ordinary” way of doing this. Why not just map the whole range (a-f) into user virtual address space, and provide virtual address pointers of the valid data back to the user??
If you *really* want to do this, I guess you could build build a new MDL manually, specifying the 3 PFNs that you want to include in the buffer. This’ll get you a single, contiguous, virtual address space allocated when you map those pages into user space. But, you better build the MDL correctly 
Peter
OSR
Thank you Peter.
The reason why I am doing this is precisely because I want to avoid mapping everything into virtual user address space. I want to manage a big buffer (2 GB) and I cannot afford mapping everything for obvious virtual address space limitations.
Vincent
That’s cool. But you want the discrete pieces of the buffer you’ve allocated to mapped into a single contiguous virtual address space? I don’t pretend to know your implementation or requirement, but what’s more typical in Windows is either (a) you allocate a buffer and map it all back into a contiguous virtual address space, or (b) you allocate a big buffer, and you return chunks of the buffer, each CHUNK mapped into its own contiguous virtual address space. So, (in option b) if you wanted to return pages a,b and e you’d map a and b into one virtual address range, and e into another, then return the TWO separate UVA pointers.
I assume you’re gonna have to tell the user that a,b and e are “separate things” in some way through the interface provided by your driver? If so, you might wanna consider returning two separate UVAs or whatever.
In ANY case, now you know how to do it either way… though I don’t recommend people hand-build their MDLs (as the MDL is SUPPOSED to be an opaque structure). But, oh well…
P
Yes, I already implemented solution (b), and it works fine.
Being able to map discrete pieces of my buffer into one contiguous virtual address space would make things easier for me and for my clients…
I think that what I’m asking would be completely feasible as a kernel developer, but using only Mm/Io APIs, it seems to be impossible 
This is strange that someone never had this need too; it’s seems pretty useful to me.
For your information, I found something: TdiCopyMdlChainToMdlChain()
But I’m not sure it’s a good idea…
Vincent
TdiCopyMdlChainToMdlChain() is definitely not for me, it copies data pointed to my MDLs…
> 3. But I don’t know how to MERGE or APPEND those two MDLs (pMdl_1 and
pMdl_2) so that I can obtain one single MDL that will describes pages 1, 2 and
There is no API to do this.
Nevertheless, the AGP440 sample in the old DDKs have demonstrated the tecnhique
of doing exactly this by dealing with the MDL tails directly.
–
Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com
Thanks for this information Maxim.
I found the file: WINDDK\3790.1830\src\kernel\agp\agplib\intrface.c
And the function: AgpCombineMdlList()
According to you, what are the risks associated with using such a function?
Dude… We’ve answered your question a few times now: Build another MDL and fill in the PFN array with the pages you want. As I already explained, the risks are that (a) you’re doing something that Windows doesn’t provide an API for or anticipate you doing, (b) The MDL is *supposed* to be an opaque structure and you’ll be violating that opacity.
If you don’t understand how to build another MDL and fill in the PFN array as required I most humbly suggest you shouldn’t be doing something that’s non-standard like this. Knowledge first – Hacking second.
Peter
OSR