使用OHCI-1394 FireWire控制器提供的物理DMA进行调试¶
简介¶
目前使用的几乎所有FireWire控制器都符合OHCI-1394规范。该规范将控制器定义为PCI总线主控器,它使用DMA将数据传输从CPU卸载,并拥有一个“物理响应单元”,该单元在应用OHCI-1394驱动程序定义的过滤器后,通过使用PCI总线主控DMA执行特定请求。
一旦正确配置,远程机器可以发送这些请求,要求OHCI-1394控制器对物理系统内存执行读写请求,对于读请求,将物理内存读取的结果发送回请求者。
通过这种方式,可以通过读取如printk缓冲区或进程表等感兴趣的内存位置来调试问题。
通过FireWire,也可以获取完整的系统内存转储,数据传输速率可达10MB/秒或更高。
对于大多数FireWire控制器,内存访问限于物理地址空间的低4 GB。这在内存主要位于该限制之上的机器上可能是一个问题,但在x86、x86-64和PowerPC等更常见的硬件上,这很少是一个问题。
已知LSI FW643e和FW643e2控制器至少支持访问4 GB以上的物理地址,但此功能目前尚未被Linux启用。
结合OHCI-1394控制器早期用于调试的初始化,此功能在检查printk缓冲区中的长调试日志、调试ACPI等系统无法启动的早期启动问题时非常有用,因为其他调试方式(串行端口)要么不可用(笔记本电脑),要么对于大量调试信息(如ACPI)来说太慢。
驱动程序¶
drivers/firewire 中的 firewire-ohci 驱动程序默认使用过滤的物理DMA,这更安全但不适合远程调试。向驱动程序传递 remote_dma=1 参数以获取未过滤的物理DMA。
由于firewire-ohci驱动程序依赖于PCI枚举完成,因此为x86实现了一个运行非常早的初始化例程。此例程在console_init()可以被调用之前很久就运行了,即在printk缓冲区出现在控制台之前。
要激活它,请启用 CONFIG_PROVIDE_OHCI1394_DMA_INIT(内核开发菜单:通过FireWire在启动早期进行远程调试),并在启动时将参数“ohci1394_dma=early”传递给重新编译的内核。
工具¶
firescope - 最初由Benjamin Herrenschmidt开发,Andi Kleen将其从PowerPC移植到x86和x86_64并增加了功能,firescope现在可以用来查看远程机器的printk缓冲区,甚至可以进行实时更新。
Bernhard Kaindl增强了firescope,使其支持从32位firescope访问64位机器,反之亦然:- http://v3.sk/~lkundrak/firescope/
并且他实现了快速系统转储(alpha版本 - 阅读README.txt):- http://halobates.de/firewire/firedump-0.1.tar.bz2
还有一个FireWire的gdb代理,它允许使用gdb访问vmlinux中gdb找到的符号可以引用的数据:- http://halobates.de/firewire/fireproxy-0.33.tar.bz2
这个gdb代理的最新版本(fireproxy-0.34)可以通过基于内存的通信模块(kgdbom)与kgdb通信(尚未稳定)。
入门¶
OHCI-1394规范规定OHCI-1394控制器在每次总线复位时必须禁用所有物理DMA。
这意味着,如果您想在中断被禁用且OHCI-1394控制器未进行总线复位轮询的系统状态下调试问题,您必须在系统进入该状态__之前__建立所有FireWire电缆连接并完全初始化所有FireWire硬件。
使用早期OHCI初始化使用firescope的分步说明
验证您的硬件是否受支持
加载firewire-ohci模块并检查您的内核日志。您应该看到类似以下内容的行:
firewire_ohci 0000:15:00.1: added OHCI v1.0 device as card 2, 4 IR + 4 IT ... contexts, quirks 0x11
加载驱动程序时。如果您没有受支持的控制器,市面上有许多完全符合OHCI-1394规范的PCI、CardBus甚至某些Express卡可用。如果它不需要Windows操作系统的驱动程序,那么它很可能就是兼容的。只有专门的商店才有不兼容的卡,它们基于TI PCILynx芯片,需要Windows操作系统的驱动程序。
如果控制器实现了可写的物理上限(Physical Upper Bound)寄存器,则上述内核日志消息会包含字符串“physUB”。这是4 GB以上物理DMA所需的(但Linux尚未利用此功能)。
建立一个工作的FireWire电缆连接
任何FireWire电缆都可以,只要它能提供电气和机械上稳定的连接,并且连接器匹配(有小的4针和大的6针FireWire端口)。
如果两台机器上都运行着驱动程序,那么当电缆插入并连接两台机器时,您应该在两台机器的内核日志中看到类似以下内容的行:
firewire_core 0000:15:00.1: created device fw1: GUID 00061b0020105917, S400
当电缆插入并连接两台机器时,两台机器的内核日志中都会出现。
使用firescope测试物理DMA
在调试主机上,确保/dev/fw*可访问,然后启动firescope
$ firescope Port 0 (/dev/fw1) opened, 2 nodes detected FireScope --------- Target : <unspecified> Gen : 1 [Ctrl-T] choose target [Ctrl-H] this menu [Ctrl-Q] quit ------> Press Ctrl-T now, the output should be similar to: 2 nodes available, local node is: 0 0: ffc0, uuid: 00000000 00000000 [LOCAL] 1: ffc1, uuid: 00279000 ba4bb801
除了[LOCAL]节点外,它还必须显示另一个没有错误消息的节点。
准备使用早期OHCI-1394初始化进行调试
4.1) 在调试目标上编译和安装内核
使用启用了CONFIG_PROVIDE_OHCI1394_DMA_INIT(内核开发:提供在启动早期通过FireWire启用DMA的代码)的内核进行编译,并将其安装到被调试机器(调试目标)上。
4.2) 将被调试内核的System.map传输到调试主机
将被调试内核的System.map复制到调试主机(通过FireWire电缆连接到被调试机器的主机)上。
获取printk缓冲区内容
连接好FireWire电缆,在调试主机上加载OHCI-1394驱动程序后,重新启动被调试机器,启动已启用CONFIG_PROVIDE_OHCI1394_DMA_INIT选项的内核,并带有 ohci1394_dma=early 参数。
然后,在调试主机上运行firescope,例如使用-A参数
firescope -A System.map-of-debug-target-kernel
注意:-A会自动附加到第一个非本地节点。它仅在仅有两台机器通过FireWire连接时才能可靠工作。
附加到调试目标后,按Ctrl-D查看完整的printk缓冲区,或按Ctrl-U进入自动更新模式,以获取调试目标上最新内核消息的实时更新视图。
调用“firescope -h”以获取更多关于firescope选项的信息。
备注¶
文档和规范:http://halobates.de/firewire/
FireWire是Apple Inc.的商标 - 更多信息请参阅:https://en.wikipedia.org/wiki/FireWire