使用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的分步說明

  1. 驗證您的硬體是否受支援

    載入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尚未利用此功能)。

  2. 建立一個工作的FireWire電纜連線

    任何FireWire電纜都可以,只要它能提供電氣和機械上穩定的連線,並且聯結器匹配(有小的4針和大的6針FireWire埠)。

    如果兩臺機器上都執行著驅動程式,那麼當電纜插入並連線兩臺機器時,您應該在兩臺機器的核心日誌中看到類似以下內容的行:

    firewire_core 0000:15:00.1: created device fw1: GUID 00061b0020105917, S400
    

    當電纜插入並連線兩臺機器時,兩臺機器的核心日誌中都會出現。

  3. 使用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]節點外,它還必須顯示另一個沒有錯誤訊息的節點。

  4. 準備使用早期OHCI-1394初始化進行除錯

    4.1) 在除錯目標上編譯和安裝核心

    使用啟用了CONFIG_PROVIDE_OHCI1394_DMA_INIT(核心開發:提供在啟動早期透過FireWire啟用DMA的程式碼)的核心進行編譯,並將其安裝到被除錯機器(除錯目標)上。

    4.2) 將被除錯核心的System.map傳輸到除錯主機

    將被除錯核心的System.map複製到除錯主機(透過FireWire電纜連線到被除錯機器的主機)上。

  5. 獲取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