NDIS小端口驱动(六)

消息信号中断 (MSI) 提供了网络设备及其微型端口驱动程序可以使用的传统基于线路的中断的替代方法。 从 Windows Vista 开始,操作系统支持两种类型的 MSI:PCI V2.2 MSI 和 PCI V3.0 MSI-X。

支持 MSI-X 的微型端口驱动程序可以指定 中断相关性,这是运行驱动程序的消息中断服务例程) CPU (中央处理单元的子集。 可以为每个 MSI-X 消息指定中断相关性,例如,可以指定具有非统一内存访问 (NUMA) 体系结构的计算机上的中断相关性,其设备与特定 CPU 的“接近度”。

MSI-X 支持可以提供显著的性能优势,尤其是对于支持接收端缩放 (RSS) 的网络接口卡 (NIC) 。

MSI-X 初始化

为了支持 MSI-X,MSI 初始化需要一个预注册阶段,在该阶段中,微型端口驱动程序会建立过滤资源要求的函数。 如果驱动程序将在 MiniportInitializeEx 函数中注册基于行的中断,则此函数可以更改每个 MSI-X 消息的中断相关性或删除消息中断资源。

预注册阶段发生在 NDIS 调用 MiniportInitializeEx 函数之前。 与基于行的中断一样,微型端口驱动程序还会在 MiniportInitializeEx 中初始化微型端口适配器时注册 MSI 中断。

MSI-X 预先注册

若要支持更改 MSI-X 的中断相关性或删除消息中断资源,微型端口驱动程序必须建立资源要求过滤函数。 此预注册步骤在 NDIS 调用 MiniportInitializeEx 函数之前发生。

若要建立资源要求过滤函数,微型端口驱动程序必须提供 MiniportSetOptions 函数。 当微型端口驱动程序从 DriverEntry 例程调用 NdisMRegisterMiniportDriver 函数时,驱动程序会传递 NDIS_MINIPORT_DRIVER_CHARACTERISTICS 结构中 MiniportSetOptions 的入口点。 NDIS 在 NdisMRegisterMiniportDriver 的上下文中调用 MiniportSetOptions 函数。

在 MiniportSetOptions 中,微型端口驱动程序调用 NdisSetOptionalHandlers 函数并指定 NDIS_MINIPORT_PNP_CHARACTERISTICS 结构。 此结构定义 MiniportAddDevice、 MiniportRemoveDevice、 MiniportStartDevice 和 MiniportFilterResourceRequirements 函数的 入口点。

当 NDIS 收到来自 即插即用 (PnP) 管理器的添加设备请求时,NDIS 会调用微型端口驱动程序的 MiniportAddDevice 函数。 NDIS 在 MiniportAdapterHandle 参数中传递给 MiniportAddDevice 的句柄是 NDIS 稍后传递给 MiniportInitializeEx 函数的句柄。

在 MiniportAddDevice 中,驱动程序初始化 NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES 结构,并将此结构传递给 NdisMSetMiniportAttributes 函数。 NDIS_MINIPORT_ADD_DEVICE_REGISTRATION_ATTRIBUTES 结构包含 MiniportAddDeviceContext 成员,该成员是设备微型端口驱动程序分配的上下文区域的句柄。 NDIS 稍后为 MiniportRemoveDevice、 MiniportFilterResourceRequirements、 MiniportStartDevice 和 MiniportInitializeEx 函数提供此上下文句柄。 对于 MiniportInitializeEx,上下文句柄在 MiniportInitParameters 参数指向的 NDIS_MINIPORT_INIT_PARAMETERS 结构的 MiniportAddDeviceContext 成员中传递。

在 NDIS 调用 MiniportAddDevice 且 MiniportAddDevice 返回NDIS_STATUS_SUCCESS后,NDIS 在每次收到 IRP_MN_FILTER_RESOURCE_REQUIREMENTS I/O 请求数据包 (IRP) 时,都会调用 MiniportFilterResourceRequirements 函数。 如果驱动程序将在 MiniportInitializeEx 函数中注册基于行的中断,MiniportFilterResourceRequirements 可以更改每个 MSI-X 消息的中断相关性、添加消息中断资源或删除消息中断资源。 

当 NDIS 收到来自 PnP 管理器的 remove-device 请求时,NDIS 将调用微型端口驱动程序的 MiniportRemoveDevice 函数。 MiniportRemoveDevice 函数应撤消 MiniportAddDevice 函数执行的操作。

MSI-X 资源过滤

如果微型端口驱动程序支持 MSI-X,并且将更改每个 MSI-X 消息的中断相关性,或者将删除消息中断资源,则必须注册资源要求过滤函数。

NDIS 在 NDIS 收到网络接口卡 (NIC) 的IRP_MN_FILTER_RESOURCE_REQUIREMENTS I/O 请求数据包后,NDIS 调用 MiniportFilterResourceRequirements 函数。 NDIS 在设备堆栈中的基础函数驱动程序完成 IRP 后调用 MiniportFilterResourceRequirements 。

在 MiniportAddDevice 函数返回NDIS_STATUS_SUCCESS后,NDIS 将调用 MiniportFilterResourceRequirements。 在调用 MiniportRemoveDevice 之前,NDIS 可以随时再次调用 MiniportFilterResourceRequirements。 当微型端口运行时,NDIS 可能会调用 MiniportFilterResourceRequirements 。 虽然微型端口可能会按如下所述修改资源列表,但微型端口不应立即尝试使用新资源。 NDIS 最终将停止并使用新资源重新初始化微型端口;只有这样,微型端口才应尝试使用新资源。

IRP_MN_FILTER_RESOURCE_REQUIREMENTS在 Irp>-IoStatus.Information 中以IO_RESOURCE_REQUIREMENTS_LIST结构的形式提供资源列表。 列表中的资源由 IO_RESOURCE_DESCRIPTOR 结构描述。

微型端口驱动程序可以修改描述 MSI-X 消息的每个 CmResourceTypeInterrupt 类型的资源的中断关联策略。 如果关联策略请求以特定处理器集为目标,微型端口驱动程序还会在IO_RESOURCE_DESCRIPTOR结构中的 Interrupt.TargetedProcessors 处设置 KAFFINITY 掩码。

微型端口驱动程序可以删除作为消息中断资源的所有 CmResourceTypeInterrupt 类型的资源。 然后,驱动程序可以在 MiniportInitializeEx 函数中注册基于行的中断。 如果微型端口驱动程序不删除这些消息中断资源,如果驱动程序尝试在 MiniportInitializeEx 中注册基于行的中断,操作系统将失败。

NDIS 6.1 或更高版本的微型端口驱动程序可以将消息中断资源添加到资源列表。 例如,在具有八个 CPU 的计算机上,如果 NIC 可以生成四条 MSI-X 消息,并且操作系统启用了四个消息中断,则操作系统会在设备的 MSI-X 配置空间中初始化四个消息表条目,并将四个消息中断资源放入资源列表中。 在这种情况下,由于微型端口驱动程序需要更多的消息中断资源,因此它可以向资源列表再分配四个消息中断资源,并将每个 MSI-X 消息的相关性设置为 CPU。 如果操作系统可以提供更多消息中断资源,则微型端口适配器在启动时会收到 8 个消息中断资源。 在本例中,消息的数字介于 0 到 7。

列表中的每个消息中断资源稍后都会分配一个消息编号,该消息号与它在列表中显示的顺序相对应。 例如,列表中的第一个消息中断资源分配给消息 0,第二个消息被分配给消息 1,依此而行。

若要在运行时将 MSI-X 表项分配给 CPU,微型端口驱动程序可以调用 NdisMConfigMSIXTableEntry 函数,该函数将表项映射到已将关联设置为 CPU 的 MSI-X 消息。

若要为新的资源要求列表分配内存,请使用 NdisAllocateMemoryWithTagPriority 函数。 可以使用 NdisFreeMemory 函数释放旧资源要求列表的内存。

微型端口驱动程序不应修改其他资源,例如 CmResourceTypeMemory 和 CmResourceTypePort 资源。 微型端口驱动程序应避免将新资源添加到资源列表。 但是,NDIS 6.1 及更高版本的微型端口驱动程序可以添加更多消息中断资源。 如果微型端口驱动程序添加了更多消息中断资源,则不得将其从 MiniportStartDevice 函数中删除。

注册和取消注册 MSI 中断

为了注册 MSI 支持,微型端口驱动程序调用 NdisMRegisterInterruptEx 函数来注册 MSI 中断。 驱动程序分配并初始化 NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS 结构,以指定中断特征和函数入口点。 驱动程序必须将 NDIS_MINIPORT_INTERRUPT_CHARACTERISTICS 结构的 MsiSupported 成员设置为 TRUE。 然后,驱动程序将结构传递给 NdisMRegisterInterruptEx。

必须定义以下函数才能支持 MSI 中断:

  • MiniportMessageInterrupt
  • MiniportMessageInterruptDpc
  • MiniportDisableMessageInterrupt
  • MiniportEnableMessageInterrupt

微型端口驱动程序应为基于行的中断函数 (提供入口点,这些入口点如以下列表) 所示,即使驱动程序支持 MSI 入口点。 如果 NDIS 未授予 MSI 中断,它可以将正常中断授予作为回退条件。

行中断函数包括以下内容:

  • MiniportInterrupt
  • MiniportInterruptDPC
  • MiniportDisableInterruptEx
  • MiniportEnableInterruptEx

驱动程序应调用 NdisMDeregisterInterruptEx 函数来释放以前使用 NdisMRegisterInterruptEx 分配的资源。

处理 MSI 中断

当网络接口卡 (NIC) 生成中断时,NDIS 调用 MiniportMessageInterrupt 函数。 此函数中的 MessageId 参数标识 MSI-X 消息。

MiniportMessageInterrupt 在处理中断后应始终返回 TRUE ,因为消息中断不共享。

微型端口驱动程序应在其 MiniportMessageInterrupt 函数中尽可能少地执行工作。 驱动程序应将 I/O 操作延迟到 MiniportMessageInterruptDpc 函数,NDIS 调用该函数来完成中断的延迟处理。

若要在 MiniportMessageInterrupt 返回后将其他延迟的过程调用 (DPC) 排队,微型端口驱动程序设置 MiniportMessageInterrupt 函数的 TargetProcessors 参数的位。 若要从 MiniportMessageInterrupt 或 MiniportMessageInterruptDPC 请求其他 DPC,微型端口驱动程序可以调用 NdisMQueueDpc 函数。

微型端口驱动程序可以调用 NdisMQueueDpc 来请求其他处理器的其他 DPC。

NDIS 6.1 及更高版本保证为同一 CPU 计划的不同消息的 DPC 单独排队。 例如,如果微型端口驱动程序在 CPU 1 上同时计划两个 DPC, (一个 DPC 用于消息 0,另一个 DPC 用于消息 1) ,则两个 DPC 将排队等待 CPU 1 (一个消息为 0 的 DPC,另一个 DPC 与消息 1) 。

NDIS 还保证针对不同 CPU 上计划的同一消息的 DPC 单独排队。 例如,如果微型端口驱动程序计划两个 DPC (CPU 0 上的一个 DPC 用于消息 0,一个 DPC 在 CPU 1 上计划消息 0) ,则两个单独的 DPC 在 CPU 0 和 CPU 1 上排队,这两个 DPC 都用于消息 0。

与 MSI 中断同步

如果微型端口驱动程序的 MiniportMessageInterrupt 函数将资源(如网络接口卡 (NIC) 寄存器或状态变量)与以较低 IRQL 运行的另一个 MiniportXxx 函数共享,则另一个 MiniportXxx 函数必须调用 NdisMSynchronizeWithInterruptEx 函数。 此调用可确保微型端口驱动程序的 MiniportSynchronizeMessageInterrupt 函数以同步且多处理器安全的方式访问共享资源。

更改 MSI-X 表项的 CPU 关联

支持 MSI-X 的 NDIS 6.1 及更高版本的微型端口驱动程序可以调用 NdisMConfigMSIXTableEntry 函数,以屏蔽、取消屏蔽 MSI-X 表条目或将 MSI-X 表条目映射到设备分配的 MSI-X 消息。 支持 RSS 的微型端口驱动程序使用 NdisMConfigMSIXTableEntry 在运行时更改 MSI-X 表条目的 CPU 相关性。

NdisMConfigMSIXTableEntry 是 GUID_MSIX_TABLE_CONFIG_INTERFACE 查询的包装器。 微型端口驱动程序可以在 NDIS 调用 MiniportInitializeEx 函数之后以及驱动程序从 MiniportHaltEx 函数返回之前调用 NdisMConfigMSIXTableEntry。

为每个 RSS 队列分配 MSI-X 表条目且队列数少于 RSS 处理器数量的微型端口驱动程序可以在 MiniportFilterResourceRequirements 函数中添加其他 MSI-X 消息资源。 

微型端口驱动程序可以设置 MSI-X 中断资源的 CPU 相关性,以便设备为每个 RSS 处理器提供至少一条 MSI-X 消息。 请注意,PCI 总线驱动程序最初映射 n MSI-X 表条目 (其中 n 是 NIC 硬件向总线报告的 MSI-X 表条目数) 修改资源中的前 n 个 MSI-X 消息。 在 NDIS 调用 MiniportInitializeEx 后,当微型端口驱动程序更改特定 MSI-X 表条目的目标处理器时,驱动程序将调用 NdisMConfigMSIXTableEntry ,以将表条目映射到已将相关性设置为所需处理器的 MSI-X 消息。

相关推荐

  1. NDIS端口驱动()

    2024-05-26 03:56:30       28 阅读
  2. DDD领域驱动设计()

    2024-05-26 03:56:30       65 阅读
  3. 第二十篇-Ollama-监听本地IP与端口

    2024-05-26 03:56:30       38 阅读
  4. windows驱动开发-内核编程技术汇总()

    2024-05-26 03:56:30       27 阅读
  5. 接口框架项目实战-pytest()csv数据驱动

    2024-05-26 03:56:30       28 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-26 03:56:30       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-26 03:56:30       106 阅读
  3. 在Django里面运行非项目文件

    2024-05-26 03:56:30       87 阅读
  4. Python语言-面向对象

    2024-05-26 03:56:30       96 阅读

热门阅读

  1. unity 常用工具和代码

    2024-05-26 03:56:30       32 阅读
  2. docker image prune -f 命令什么用途

    2024-05-26 03:56:30       32 阅读
  3. dirsearch指令大全

    2024-05-26 03:56:30       41 阅读
  4. golang问题

    2024-05-26 03:56:30       28 阅读
  5. v-if 和 v-for 为什么不建议一起使用 ?

    2024-05-26 03:56:30       33 阅读
  6. HCIA-ARP

    HCIA-ARP

    2024-05-26 03:56:30      36 阅读
  7. 分区4K对齐那些事,你想知道的都在这里

    2024-05-26 03:56:30       36 阅读