nt!MiInitializeSystemCache函数分析之PointerPte->u.List.NextEntry的由来

第一部分:
1: kd> dd 0xc0304200
c0304200  c10c0000 00000000 00000000 00000000
c0304210  00000000 00000000 00000000 00000000
c0304220  00000000 00000000 00000000 00000000
c0304230  00000000 00000000 00000000 00000000
c0304240  00000000 00000000 00000000 00000000
c0304250  00000000 00000000 00000000 00000000
c0304260  00000000 00000000 00000000 00000000
c0304270  00000000 00000000 00000000 00000000
1: kd> dd 0xc0304300
c0304300  c1100000 00000000 00000000 00000000
c0304310  00000000 00000000 00000000 00000000
c0304320  00000000 00000000 00000000 00000000
c0304330  00000000 00000000 00000000 00000000
c0304340  00000000 00000000 00000000 00000000
c0304350  00000000 00000000 00000000 00000000
c0304360  00000000 00000000 00000000 00000000
c0304370  00000000 00000000 00000000 00000000
1: kd> dd 0xc0304400
c0304400  c1140000 00000000 00000000 00000000
c0304410  00000000 00000000 00000000 00000000
c0304420  00000000 00000000 00000000 00000000
c0304430  00000000 00000000 00000000 00000000
c0304440  00000000 00000000 00000000 00000000


第二部分:
VOID
MiInitializeSystemCache (
    IN ULONG MinimumWorkingSet,
    IN ULONG MaximumWorkingSet
    )


    //
    // Build a free list structure in the PTEs for the system cache.
    //

    MmSystemCachePteBase = MI_PTE_BASE_FOR_LOWEST_KERNEL_ADDRESS;

    SizeOfSystemCacheInPages = MI_COMPUTE_PAGES_SPANNED (MmSystemCacheStart,
                                (PCHAR)MmSystemCacheEnd - (PCHAR)MmSystemCacheStart + 1);

    HunksOf256KInCache = SizeOfSystemCacheInPages / (X256K / PAGE_SIZE);

    PointerPte = MiGetPteAddress (MmSystemCacheStart);

    MmFirstFreeSystemCache = PointerPte;

    for (i = 0; i < HunksOf256KInCache; i += 1) {
        PointerPte->u.List.NextEntry = (PointerPte + (X256K / PAGE_SIZE)) - MmSystemCachePteBase;
        PointerPte += X256K / PAGE_SIZE;
    }

PointerPte->u.List.NextEntry = (PointerPte + (X256K / PAGE_SIZE)) - MmSystemCachePteBase;

(PointerPte + (X256K / PAGE_SIZE))表示指针,MmSystemCachePteBase表示指针
减完要除以4,表示个数,右移2位


第三部分:

#define PAGE_SIZE                   0x1000
#define X256K 0x40000

1: kd> ?0x40000/0x1000
Evaluate expression: 64 = 00000040

0100 0000
0100 0000 00
01    00 00    00 00    =    0x100

0xc0304000+0x100=0xc0304100
0xc0304100-0xc0000000=0x304100

304100

0011 00    00     0100     0001     0000 0000
11 00    00     0100     0001     0000 00
11 00    00     01    00     00    01     00    00 00
c1040

 

      +0x000 List             : _MMPTE_LIST
         +0x000 Valid            : Pos 0, 1 Bit
         +0x000 OneEntry         : Pos 1, 1 Bit
         +0x000 filler0          : Pos 2, 8 Bits
         +0x000 Prototype        : Pos 10, 1 Bit
         +0x000 filler1          : Pos 11, 1 Bit
         +0x000 NextEntry        : Pos 12, 20 Bits

1: kd> x nt!MmSystemCachePteBase
80b2358c          nt!MmSystemCachePteBase = 0xc0000000

1: kd> dd 0xc0304000
c0304000  c1040000

第四部分:

0xc0304200

0xc0304300

304300
0011 0000 0100 0011 0000 0000

11 0000 0100 0011 0000 0000 00

11 00    00 01    00 00    11 00    00 00    00 00
c10c0

1: kd> dd 0xc0304200
c0304200  c10c0000 00000000 00000000 00000000
c0304210  00000000 00000000 00000000 00000000
c0304220  00000000 00000000 00000000 00000000
c0304230  00000000 00000000 00000000 00000000
c0304240  00000000 00000000 00000000 00000000
c0304250  00000000 00000000 00000000 00000000
c0304260  00000000 00000000 00000000 00000000
c0304270  00000000 00000000 00000000 00000000
1: kd> dd 0xc0304300
c0304300  c1100000 00000000 00000000 00000000
c0304310  00000000 00000000 00000000 00000000
c0304320  00000000 00000000 00000000 00000000
c0304330  00000000 00000000 00000000 00000000
c0304340  00000000 00000000 00000000 00000000
c0304350  00000000 00000000 00000000 00000000
c0304360  00000000 00000000 00000000 00000000
c0304370  00000000 00000000 00000000 00000000
1: kd> dd 0xc0304400
c0304400  c1140000 00000000 00000000 00000000
c0304410  00000000 00000000 00000000 00000000
c0304420  00000000 00000000 00000000 00000000
c0304430  00000000 00000000 00000000 00000000
c0304440  00000000 00000000 00000000 00000000

第五部分:F:\srv03rtm\base\ntos/mm/mapcache.c:39:PMMPTE MmSystemCachePteBase;

MmSystemCachePteBase类型是指针,+1相当于+4,向左移两位。


    PointerPte = MmFirstFreeSystemCache;            0xc0304000

    //
    // Update next free entry.
    //

    ASSERT (PointerPte->u.Hard.Valid == 0);

    MmFirstFreeSystemCache = MmSystemCachePteBase + PointerPte->u.List.NextEntry;
    ASSERT (MmFirstFreeSystemCache <= MiGetPteAddress (MmSystemCacheEnd));

0xc1040+0xc0000000=0xc00c1040

1: kd> dd 0xc0304000
c0304000  c1040000


      +0x000 List             : _MMPTE_LIST
         +0x000 Valid            : Pos 0, 1 Bit
         +0x000 OneEntry         : Pos 1, 1 Bit
         +0x000 filler0          : Pos 2, 8 Bits
         +0x000 Prototype        : Pos 10, 1 Bit
         +0x000 filler1          : Pos 11, 1 Bit
         +0x000 NextEntry        : Pos 12, 20 Bits

c1040
1100 0001 0000 0100 0000  
11    00 00    01 00    00 01    00 00    00 00

304100
c0304100

<think>嗯,用户在使用WDK 10.0.26100.2454时遇到了找不到`desc->u.Message.MaximumVector`的问题。首先,我需要确定这个问题的背景。可能是在处理中断相关代码时,用户参考了一些旧的示例或文档,而新版WDK中的结构体发生了变化。 首先,我应该回顾一下Windows驱动开发中的中断描述符结构。在旧版WDK中,`IO_INTERRUPT_MESSAGE_DESCRIPTOR`结构可能有`u.Message.MaximumVector`字段,用于表示最大中断向量数。但在新版本中,微软可能对结构进行了调整,导致这个字段不存在了。 接下来,我需要检查最新的WDK文档,确认`IO_INTERRUPT_MESSAGE_DESCRIPTOR`的定义是否有变化。如果该字段已被移除或重命名,用户需要更新代码以适应新的结构。可能的情况包括字段名称变更、结构重组,或者该信息现在通过其他API获取。 另外,用户提到的WDK版本号是10.0.26100.2454,这可能对应于Windows 11的某个版本。我需要考虑WDK版本与Windows版本的兼容性,以及是否有相关的更新日志提到这一变更。 然后,考虑替代方案。如果`MaximumVector`字段确实被移除了,用户可能需要使用其他方法获取最大向量数,比如调用新的内核API函数,或者访问不同的结构字段。例如,某些信息可能现在通过PCI配置空间或ACPI表来获取。 还需要检查用户代码的上下文,确认是否正确初始化了中断描述符,以及是否使用了正确的结构版本。有时候,结构的不同版本会有不同的联合体(union)成员,用户可能需要调整访问路径。 此外,可能涉及到中断注册流程的变化。新版WDK可能引入了新的函数或参数来替代旧有的方法,用户需要根据最新的文档调整代码逻辑。 最后,总结可能的解决方案:更新代码以使用新字段或API,查阅最新的WDK文档和示例,或者参考微软的官方更新说明和社区讨论,寻找类似问题的解决方法。同时,建议用户检查是否有WDK的更新或补丁,可能修复了相关的问题或提供了更多的兼容性支持。</think>--- ### **问题分析** 您在 WDK 10.0.26100.2454 中无法找到 `desc->u.Message.MaximumVector`,这通常是由于 **中断描述符结构体** 的版本变更或 API 调整导致的。以下是具体原因与解决方案: --- ### **1. 结构体变更背景** 在较新版本的 WDK 中,`IO_INTERRUPT_MESSAGE_DESCRIPTOR` 结构体已更新,关键变化如下: | **旧版字段** | **新版替代方案** | **作用** | |-----------------------------|-------------------------------------|----------------------------------| | `u.Message.MaximumVector` | `MessageInfo.MaximumMessageCount` | 表示设备支持的 **最大消息信号中断(MSI/MSI-X)向量数** | | `u.Message.Unused` | **已移除** | 旧版占位字段,不再需要 | --- ### **2. 修正代码示例** #### **方案一:使用新版字段 `MessageInfo`** ```c // 检查中断描述符类型是否匹配 if (desc->Type == InterruptTypeMessage) { // 获取最大 MSI/MSI-X 向量数 ULONG maxVectors = desc->MessageInfo.MaximumMessageCount; // 实际分配向量数需满足设备能力和系统限制 ULONG allocatedVectors = min(maxVectors, requestedVectors); // 配置中断参数 IO_CONNECT_INTERRUPT_PARAMETERS params = {0}; params.Version = CONNECT_FULLY_SPECIFIED; params.FullySpecified.MessageCount = allocatedVectors; // 设置实际分配的向量数 // ...其他参数初始化 NTSTATUS status = IoConnectInterruptEx(&params); } ``` #### **方案二:通过 PCI 能力查询动态获取** 若直接访问结构体不可靠,可通过 PCI 配置空间直接读取设备能力: ```c // 获取 PCI 设备的 MSI/MSI-X 能力 NTSTATUS GetMsixCapability(IN PDEVICE_OBJECT DeviceObject, OUT PULONG MaxVectors) { PCI_MSIX_CAPABILITY msixCap; ULONG pciAddress = ...; // 通过 IoQueryDeviceDescription 获取 PCI 地址 // 查找 MSI-X Capability UCHAR capPtr = 0; NTSTATUS status = PciFindCapability(pciAddress, PCI_CAPABILITY_ID_MSIX, &capPtr); if (NT_SUCCESS(status)) { // 读取 MSI-X 表大小 msixCap.Control = READ_REGISTER_USHORT((PUSHORT)(pciAddress + capPtr + 2)); *MaxVectors = (msixCap.Control & 0x7FF) + 1; // TableSize = (Control & 0x7FF) + 1 } return status; } ``` --- ### **3. 兼容性处理** | **场景** | **应对措施** | |---------------------------|-----------------------------------------------------------------------------| | 旧版 WDK (19041 之前) | 使用 `desc->u.Message.MaximumVector` | | 新版 WDK (22000+) | 改用 `desc->MessageInfo.MaximumMessageCount` 或 PCI 能力查询 | | 跨版本兼容代码 | 通过条件编译适配不同版本:<br>`#if (NTDDI_VERSION < NTDDI_WIN10_CO) ... #else ... #endif` | --- ### **4. 调试与验证** #### **WinDbg 检查中断描述符** ```bash # 查看中断描述符内存布局 dt nt!_IO_INTERRUPT_MESSAGE_DESCRIPTOR <address> # 确认字段名称和偏移 # 跟踪 IoConnectInterruptEx 调用 bp nt!IoConnectInterruptEx "dv /i /t params; g" ``` #### **日志记录** 在驱动中记录关键参数: ```c DbgPrint("Maximum MSI-X vectors: %lu, Allocated: %lu", maxVectors, allocatedVectors); ``` --- ### **总结** 由于 WDK 结构体更新,`desc->u.Message.MaximumVector` 已被替换为 **`desc->MessageInfo.MaximumMessageCount`**。建议采取以下措施: 1. **更新代码**:直接使用新版字段。 2. **动态查询**:通过 PCI 配置空间获取设备能力。 3. **版本适配**:使用条件编译实现跨版本兼容。 若问题仍未解决,请检查: - 驱动工程的 WDK 版本设置(`Target Version`) - `NTDDI_VERSION` 宏是否与系统版本匹配 - 是否包含最新 `wdm.h` 或 `ntddk.h` 头文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值