首页
社区
课程
招聘
[求助]Windows内核映射内存到任意内核地址是否可行?
发表于: 2020-11-2 19:36 5956

[求助]Windows内核映射内存到任意内核地址是否可行?

2020-11-2 19:36
5956

我想要实现这样的逻辑,有一块2MB(0x200000)内存,我想把他映射到两个连续的虚拟地址。
例如我想把他映射到F1000000和F1200000,当然基地址是随便的,只要是连续的2个2MB地址空间就行。这样的话将这个缓冲作为FIFO复制就简单了。。

 

参考了老外的这个讨论

 

https://community.osr.com/discussion/215596/mapping-a-dma-buffer-twice-in-vitual-memory-contiguously

 

Pavel_Lebedinsky 给出了一个办法,他提出利用 MmMapLockedPagesSpecifyCache 映射到任意地址,不过这个有一个局限就是只能映射到 UserMode,查询MSDN这个函数

 

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-mmmaplockedpagesspecifycache

 

RequestedAddress

 

[in, optional]

 

If AccessMode = UserMode, this parameter specifies the starting user virtual address to map the MDL to, or set to NULL to allow the system to choose the starting address. The system might round down the requested address to fit address boundary requirements, so callers must check the return value.

 

也就是 RequestedAddress 参数只对 AccessMode = UserMode 有效。

 

另外 MmAllocateMappingAddress 这个路子也走不通,他内部会保留2个Page,所以不能通过连续的调用 MmAllocateMappingAddress 拿到连续的虚拟地址。
保留的地址也只能被 MmMapLockedPagesWithReservedMapping 使用一次,而不能将保留的地址分成两半分别被 MmMapLockedPagesWithReservedMapping 锁定。

 

那么我的驱动如何在 KernelMode 条件下,达成这个目标呢?


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-11-2 19:45 被MengXP编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 304
活跃值: (507)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2

我可能想多了。UserMode就UserMode吧,在DriverEntry里好像也能用。。。


PMDL MmMapLockedPagesTwiceContiguously(PMDL BufMdl)
{
    ULONG BufSize = MmGetMdlByteCount(BufMdl);
    PCHAR map1 = NULL, map2 = NULL;
    ULONG MaxTry = 64;
    BOOLEAN found = FALSE;
    PMDL NewBufMdl = NULL;

    while(MaxTry--)
    {
        map1 = MmMapLockedPagesSpecifyCache(BufMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
        map2 = MmMapLockedPagesSpecifyCache(BufMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);

        if(map1 && map2 && map1 + BufSize == map2)
        {
            found = TRUE;
            break;
        }

        if(map1)
            MmUnmapLockedPages(map1, BufMdl);

        if(map2)
            MmUnmapLockedPages(map2, BufMdl);
    }

    if(!found)
        return NULL;

    NewBufMdl = IoAllocateMdl(map1, BufSize * 2, FALSE, FALSE, NULL);
    if(NewBufMdl)
    {
        MmProbeAndLockPages(NewBufMdl, UserMode, IoReadAccess);
    }

    if(map1)
        MmUnmapLockedPages(map1, BufMdl);

    if(map2)
        MmUnmapLockedPages(map2, BufMdl);

    return NewBufMdl;
}


最后于 2020-11-2 21:01 被MengXP编辑 ,原因:
2020-11-2 21:01
0
雪    币: 3275
活跃值: (3863)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
直接改这线性地址的pte它不香吗
2020-11-3 22:12
0
雪    币: 12304
活跃值: (5829)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
用官方api有点看运气,成功率最高的方案我想到的有两种,一如楼上所说直接动页表,二是直接动protopte
2020-11-4 00:27
0
雪    币: 304
活跃值: (507)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
hhkqqs 用官方api有点看运气,成功率最高的方案我想到的有两种,一如楼上所说直接动页表,二是直接动protopte
是的,这种成不成功主要看脸,动页表肯定是最稳定的方案了,先用MmAllocateMappingAddress占坑,然后改页表就行了。
2020-11-4 09:54
0
雪    币: 12304
活跃值: (5829)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
MengXP 是的,这种成不成功主要看脸,动页表肯定是最稳定的方案了,先用MmAllocateMappingAddress占坑,然后改页表就行了。
不推荐直接改MmXXX内存对应的页表项,因为你要映射的2M内存在页表的布局不一定和MmXXX的一致。最好用MmXXX只申请两页的内存用于保存页表信息,把要映射的2M内存强行拆分出512个物理页填进去,再把这两页的物理页帧号填进两个连续空闲的PDE即可
2020-11-4 11:13
0
雪    币: 0
活跃值: (126)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
大佬以前是不是西邮Linux兴趣小组的
2023-5-3 22:16
0
游客
登录 | 注册 方可回帖
返回
//