天天看點

VirtIO驅動——規範1

    1  前言

    VirtIO驅動定義了一組規範,隻要guest和host按照此規範進行資料操作,就可以使虛拟機IO繞過核心空間而直接再使用者空間的兩個程序間傳輸資料,以此達到提高IO性能的目的。

    VirtIO驅動的實作可以有很多種,最廣泛的就是VirtIO Over PCI Bus,其它實作:VirtIO Over MMIO和VirtIO Over Channel IO不熟悉,不做介紹,這裡隻介紹qemu實作的VirtO驅動。

    2  VirtIO基礎元件

    VirtIO裝置被發現和識别的方法,通常和基于哪種總線實作方式有關。但無論是基于何種方式,一個VirtIO裝置必須具備以下幾個功能元件:

  •     裝置狀态域
  •     特性标志位
  •     裝置配置空間

    2.1 裝置狀态域

    VirtIO裝置的初始化必須按照以下步驟順序進行才被認為被識别:

  •     重新開機裝置。
  •     标記ACKNOWLEDGE狀态标志位,表示客戶機發現了此裝置。
  •     标記DRIVER狀态标志位,表示客戶機知道怎麼驅動這個裝置。
  •     讀取裝置特性标志位并給VirtIO裝置設定特性标志,在此階段,驅動可以讀取特定裝置相關的一些域的資料,驅動依賴檢查自己是否支援這些特性,如果支援,就采納之。
  •     設定FEATURES_OK狀态标志位,此階段之後,驅動就不能再采納新的特性了。
  •     再次讀取裝置狀态,确認FEATURES_OK标志已經被裝置成功:如果沒有被設定成功,表示這個裝置不支援該特性,裝置無法就無法使用。
  •     執行具體裝置的設定操作:包括掃描裝置關聯的virtqueues,總線設定,如果是VirtIO over PCI還需要寫裝置的VirtIO配置空間,還有virtqueues的使能以及運用。
  •     最後标記DRIVER_OK狀态标志位,自此VirtIO裝置就初始化完成,可以使用了。

    以上步驟中涉及的狀态标志位,由裝置狀态域表示。它指出完成初始化時需要drivert做的動作。可以把它想象成訓示燈,同裝置狀态域,外部可以知道這個裝置處于什麼階段。裝置狀态域定義如下:

    ACKNOWLEDGE                1

    表示客戶機發現了此裝置,并識别到它是一個有效地VirtIO裝置。

    DRIVER                                 2

    表示客戶機知道怎麼驅動這個裝置,設定該标志位後可能有一段較長延時。比如在Linux系統中,驅動作為可加載子產品,需要等子產品加載完畢。

    FAILED                                  128

    表示客戶機出錯,該裝置被置棄。出現這種情況的原因可能是内部錯誤,或者driver在裝置操作過程中産生了緻命錯誤等。

    FEATURES_OK                   8

    表示客戶機已經識别并接受裝置的所有特性,并完成了特性協商。

    DRIVER_OK                          4

    表示驅動設定完畢,可以對裝置進行正常的操作。

    DEVICE_NEEDS_RESET  64

    表示裝置出錯,并且無法恢複,隻能重新開機裝置。

     驅動對裝置狀态域的支援:

    驅動需要更新裝置狀态域,實時标記裝置狀态域以此訓示驅動初始化處于哪一個階段,驅動禁止清楚裝置狀态位。如果驅動将裝置狀态置為FAILED,那麼必須在執行裝置複位操作後才能重新初始化。

    驅動不能根據DEVICE_NEEDS_RESET位是否置位來判斷操作是否完成。比如,如果DEVICE_NEEDS_RESET被置位,驅動不能根據這個資訊認為目前的請求已經完成或者未完成。好的驅動實作,是重新開機裝置并恢複裝置。

     裝置對裝置狀态域的支援:

    裝置被複位後,需要将裝置狀态域置0,這個動作由裝置負責。

    在DRIVER_OK狀态前,裝置禁止使用buffer,禁止向驅動發送通知消息。

    裝置遇到錯誤時,負責将狀态域裝置為DEVICE_NEEDS_RESET,通知驅動該裝置需要複位。DEVICE_NEEDS_RESET狀态後如果DRIVER_OK 被置位,裝置需要将其配置更改通知到驅動。

    2.2  特性标志位

     每個VirtIO裝置都需要支援各種特性。在裝置初始化階段,驅動讀取這個特性标志,然後通知VirtIO裝置驅動可以接受的特性子集。特性一定确定,隻有複位VirtIO裝置,才能重新協商。特性标志前後端必須一緻,必須向後相容,如果驅動支援的特性裝置不支援,以裝置的特性為準;如果裝置支援的特性驅動不支援,以驅動特性為準。

    特性标志位各個字段含義:

    0~23:特性标志

    24~32:預留的特性标志位,用于queue和特性協商機制的擴充

    33及以上:保留,用于将來的擴充

    比如,特性标志為0,對網絡裝置來說,表示支援包checksum。如果裝置中增加了新的配置空間,也會通過新增特性标志bit來表示。

    驅動對特性标志的支援:

    驅動禁止接受裝置沒有提供的特性,也不能接受依賴其它未提供特性的特性。同時,驅動必須向後相容:如果裝置提供的特性驅動無法了解,則必須以驅動的為準。

    裝置對特性标志的支援:

    裝置提供的特性,不能依賴其它無法支援的特性。驅動接受的任何特性子集,裝置都應該支援,否則,在将裝置狀态域設定為FEATURES_OK時會失敗。

    2.3 裝置配置空間

    裝置配置空間,通常用于配置不常變動的參數,或者初始化階段設定的參數。特性标志位包含表示配置空間是否存在的bit位,後面的版本會通過在特性标志位的末尾新添新的bit位來擴充配置空間。

    Virtio裝置的每一次資料傳遞,都附帶一個配置空間的統計計數,該計數可變。是以對同一配置空間進行通路,兩個通路者可能擷取到不同的配置空間版本。

    驅動對裝置配置空間的支援:

    驅動對配置空間的讀取大于32-bit位寬,就不能保證讀操作時原子的。驅動應該按照以下方式通路配置空間條目:

u32 before, after; 

do { 

        before = get_config_generation(device); 

        // read config entry/entries. 

        after = get_config_generation(device); 

} while (after != before);

    對可選的配置空間域,驅動在通路時需要通過特性标志位預先檢查其是否被支援。

    驅動不能限制裝置配置空間的長度。相反,驅動隻能檢查裝置配置空間是否足夠長,是否能滿足必要的裝置操作。舉例:比如Virtio規範申明裝置配置空間包含8-bit長度的空間,對驅動來說,除了這已經申明的8-bit空間外,配置空間可能還包括末尾擴充的任意長度的空間,驅動必須要處理長度大于8-bit的配置資訊。

    裝置對裝置配置空間的支援:

    在FEATURES_OK狀态被設定前,裝置需要支援驅動對所有配置空間的通路,這些空間包含特性标志中指明提供的特性對應的配置空間域。