NTB 驱动¶
NTB(Non-Transparent Bridge,非透明桥)是一种 PCI-Express 桥接芯片,它将两个或多个计算机的独立内存系统连接到同一个 PCI-Express 结构。现有的 NTB 硬件支持一组通用功能:门铃寄存器和内存转换窗口,以及非通用功能,如暂存器和消息寄存器。暂存器是可读写的寄存器,可以从设备的任何一侧访问,以便对等方可以在固定地址交换少量信息。消息寄存器可以用于相同的目的。此外,它们还提供特殊的状态位,以确保信息不会被另一个对等方重写。门铃寄存器提供了一种对等方发送中断事件的方式。内存窗口允许对等内存进行转换后的读写访问。
NTB 核心驱动 (ntb)¶
NTB 核心驱动定义了一个 API,封装了通用功能集,并允许对 NTB 功能感兴趣的客户端发现硬件驱动程序支持的 NTB 设备。这里的“客户端”一词是指利用 NTB API 的上层组件。“驱动程序”或“硬件驱动程序”一词是指特定供应商和型号的 NTB 硬件的驱动程序。
NTB 客户端驱动¶
NTB 客户端驱动应向 NTB 核心驱动注册。注册后,客户端的探测和删除函数将在插入和删除 ntb 硬件或硬件驱动程序时被适当调用。该注册使用 Linux 设备框架,因此对于编写过 pci 驱动的任何人来说,都应该感到熟悉。
NTB 典型客户端驱动实现¶
NTB 的主要目的是在至少两个系统之间共享一些内存。因此,NTB 设备的功能(如暂存器/消息寄存器)主要用于执行正确的内存窗口初始化。通常,NTB API 支持两种类型的内存窗口接口:本地 ntb 端口上配置的入站转换和对等端口上对等方配置的出站转换。第一种类型如下图所示
Inbound translation:
Memory: Local NTB Port: Peer NTB Port: Peer MMIO:
____________
| dma-mapped |-ntb_mw_set_trans(addr) |
| memory | _v____________ | ______________
| (addr) |<======| MW xlat addr |<====| MW base addr |<== memory-mapped IO
|------------| |--------------| | |--------------|
因此,第一种类型内存窗口初始化的典型场景是:1) 分配一个内存区域,2) 将转换后的地址放入 NTB 配置,3) 以某种方式通知对等设备已执行的初始化,4) 对等设备映射相应的出站内存窗口,以便访问共享内存区域。
第二种类型的接口,意味着共享窗口由对等设备初始化,如下图所示
Outbound translation:
Memory: Local NTB Port: Peer NTB Port: Peer MMIO:
____________ ______________
| dma-mapped | | | MW base addr |<== memory-mapped IO
| memory | | |--------------|
| (addr) |<===================| MW xlat addr |<-ntb_peer_mw_set_trans(addr)
|------------| | |--------------|
第二种类型接口初始化的典型场景是:1) 分配一个内存区域,2) 以某种方式将转换后的地址传递给对等设备,3) 对等方将转换后的地址放入 NTB 配置,4) 对等设备映射出站内存窗口,以便访问共享内存区域。
可以看出,所描述的场景可以组合成一个可移植的算法。
- 本地设备
为共享窗口分配内存
通过分配区域的转换地址初始化内存窗口(如果不支持本地内存窗口初始化,则可能会失败)
将转换后的地址和内存窗口索引发送给对等设备
- 对等设备
使用从另一个设备(由其分配)的内存区域的检索地址初始化内存窗口(如果不支持对等内存窗口初始化,则可能会失败)
映射出站内存窗口
根据此场景,NTB 内存窗口 API 可以如下使用
- 本地设备
ntb_mw_count(pidx) - 检索内存范围的数量,这些内存范围可以分配给本地设备和指定索引的端口的对等设备之间的内存窗口。
ntb_get_align(pidx, midx) - 检索限制共享内存区域对齐和大小的参数。然后可以正确分配内存。
根据 2) 中检索到的限制,分配物理上连续的内存区域。
ntb_mw_set_trans(pidx, midx) - 尝试为定义的对等设备设置具有指定索引的内存窗口的转换地址(如果不支持本地转换地址设置,则可能会失败)
使用暂存器或消息寄存器等,将转换后的基地址(通常与内存窗口号一起)发送到对等设备。
- 对等设备
ntb_peer_mw_set_trans(pidx, midx) - 尝试为指定的内存窗口设置从其他设备(与 pidx 相关)接收到的转换地址。如果检索到的地址超过最大可能地址或未正确对齐,则可能会失败。
ntb_peer_mw_get_addr(widx) - 检索 MMIO 地址以映射内存窗口,以便访问共享内存。
此外,值得注意的是,方法 ntb_mw_count(pidx) 应该返回与具有端口索引 - pidx 的对等方上的 ntb_peer_mw_count() 相同的值。
NTB 传输客户端 (ntb_transport) 和 NTB Netdev (ntb_netdev)¶
NTB 的主要客户端是传输客户端,与 NTB Netdev 结合使用。这些驱动程序协同工作以创建到对等方的逻辑链接,跨越 ntb,以交换网络数据包。传输客户端建立到对等方的逻辑链接,并创建队列对以交换消息和数据。然后,NTB Netdev 使用传输队列对创建一个以太网设备。网络数据在套接字缓冲区和传输队列对缓冲区之间复制。传输客户端可以用于除 Netdev 之外的其他用途,但是尚未编写其他应用程序。
NTB Ping Pong 测试客户端 (ntb_pingpong)¶
Ping Pong 测试客户端用作演示,用于练习 NTB 硬件的门铃和暂存器,并作为一个简单的 NTB 客户端示例。Ping Pong 启用链接后,等待 NTB 链接启动,然后继续读取和写入 NTB 的门铃暂存器。对等方使用门铃位的位掩码相互中断,该位掩码在每一轮中都移动一位,以测试多个门铃位和中断向量的行为。Ping Pong 驱动程序还在写入对等方门铃寄存器之前,读取第一个本地暂存器,并将该值加 1 写入第一个对等方暂存器。
模块参数
- unsafe - 某些硬件在暂存器和门铃方面存在已知问题
寄存器。默认情况下,Ping Pong 不会尝试练习此类硬件。您可以通过设置 unsafe=1 以您自己的风险覆盖此行为。
- delay_ms - 指定接收门铃之间的延迟
中断事件和为下一轮设置对等方门铃寄存器之间的时间。
- init_db - 指定启动新系列轮次的门铃位。一个新的
一旦所有门铃位都已移出范围,该系列就会开始。
- dyndbg - 建议在加载此模块时指定 dyndbg=+p,并且
然后在控制台上观察调试输出。
NTB 工具测试客户端 (ntb_tool)¶
工具测试客户端主要用于调试 ntb 硬件和驱动程序。该工具通过 debugfs 提供访问权限,用于读取、设置和清除 NTB 门铃,以及读取和写入暂存器。
该工具当前没有任何模块参数。
Debugfs 文件
- debugfs/ntb_tool/hw/
将为该工具探测的每个 NTB 设备在 debugfs 中创建一个目录。此目录在下面缩短为 *hw*。
- hw/db
此文件用于读取、设置和清除本地门铃。并非所有操作都可能受所有硬件的支持。要读取门铃,请读取该文件。要设置门铃,请写入 s,后跟要设置的位(例如:echo 's 0x0101' > db)。要清除门铃,请写入 c,后跟要清除的位。
- hw/mask
此文件用于读取、设置和清除本地门铃掩码。有关详细信息,请参见 *db*。
- hw/peer_db
此文件用于读取、设置和清除对等方门铃。有关详细信息,请参见 *db*。
- hw/peer_mask
此文件用于读取、设置和清除对等方门铃掩码。有关详细信息,请参见 *db*。
- hw/spad
此文件用于读取和写入本地暂存器。要读取所有暂存器的值,请读取该文件。要写入值,请写入一系列暂存器号和值的对(例如:echo '4 0x123 7 0xabc' > spad # 将暂存器 4 和 7 分别设置为 0x123 和 0xabc)。
- hw/peer_spad
此文件用于读取和写入对等方暂存器。有关详细信息,请参见 *spad*。
NTB MSI 测试客户端 (ntb_msi_test)¶
MSI 测试客户端用于测试和调试 MSI 库,该库允许通过 NTB 内存窗口传递 MSI 中断。测试客户端通过 debugfs 文件系统进行交互
- debugfs/ntb_msi_test/hw/
将为 msi 测试探测的每个 NTB 设备在 debugfs 中创建一个目录。此目录在下面缩短为 *hw*。
- hw/port
此文件描述了本地端口号
- hw/irq*_occurrences
每个中断都存在一个 occurrences 文件,读取该文件时,会返回中断被触发的次数。
- hw/peer*/port
此文件描述了每个对等方的端口号
- hw/peer*/count
此文件描述了可以在每个对等方上触发的中断数
- hw/peer*/trigger
写入一个中断号(任何小于计数中指定的值的数字)将触发指定对等方上的中断。该对等方的中断的 occurrence 文件应增加。
NTB 硬件驱动¶
NTB 硬件驱动应向 NTB 核心驱动注册设备。注册后,将调用客户端探测和删除函数。
NTB Intel 硬件驱动 (ntb_hw_intel)¶
Intel 硬件驱动支持 Xeon 和 Atom CPU 上的 NTB。
模块参数
- b2b_mw_idx
如果要通过内存窗口访问对等方 ntb,则使用此内存窗口访问对等方 ntb。零或正值从第一个 mw idx 开始,负值从最后一个 mw idx 开始。双方都必须在此处设置相同的值!默认值为 -1。
- b2b_mw_share
如果要通过内存窗口访问对等方 ntb,并且如果内存窗口足够大,仍然允许客户端使用内存窗口的后半部分进行地址转换到对等方。
- xeon_b2b_usd_bar2_addr64
如果在 Xeon 硬件上使用 B2B 拓扑,则在 NTB 设备之间的总线上使用此 64 位地址作为 BAR2 的窗口,位于链接的上游侧。
xeon_b2b_usd_bar4_addr64 - 参见 *xeon_b2b_bar2_addr64*。
xeon_b2b_usd_bar4_addr32 - 参见 *xeon_b2b_bar2_addr64*。
xeon_b2b_usd_bar5_addr32 - 参见 *xeon_b2b_bar2_addr64*。
xeon_b2b_dsd_bar2_addr64 - 参见 *xeon_b2b_bar2_addr64*。
xeon_b2b_dsd_bar4_addr64 - 参见 *xeon_b2b_bar2_addr64*。
xeon_b2b_dsd_bar4_addr32 - 参见 *xeon_b2b_bar2_addr64*。
xeon_b2b_dsd_bar5_addr32 - 参见 *xeon_b2b_bar2_addr64*。