【原創】Linux虛擬化KVM-Qemu分析(十)之virtio驅動

背景

  • Read the fucking source code! --By 魯迅
  • A picture is worth a thousand words. --By 高爾基

說明:

  1. KVM版本:5.9.1
  2. QEMU版本:5.0.0
  3. 工具:Source Insight 3.5, Visio
  4. 文章同步在博客園:https://www.cnblogs.com/LoyenWang/

1. 概述

  • 前篇文章講完了Qemu中如何來創建Virtio Device,本文將圍繞Guest OS中的Virtio Driver來展開;

看一下Guest OS(Linux)中的Virtio框架高層架構圖:

  • 核心模塊爲virtio和virtqueue,其他高層的驅動都是基於核心模塊之上構建的;
  • 顯然,本文會延續這個系列,繼續分析virtio-net驅動,重心在整體流程和框架上,細節不表;
  • virtio-net,又是一個virtio設備,又是一個PCI設備,那麼驅動會怎麼組織呢?帶着問題上路吧。

2. 數據結構

說到驅動怎麼能不提linux設備驅動模型呢,感興趣的朋友可以去看看PCI系列分析文章,簡單來說就是內核創建總線用於掛載設備,總線負責設備與驅動的匹配。Linux內核創建了一個virtio bus:

  • virtio設備和virtio驅動,通過virtio_device_id來匹配,而這個都是在virtio規範中定義好的;
  • virtio_device結構中有一個struct virtio_config_ops,函數集由驅動來進行指定,用於操作具體的設備;

本文描述的virtio-net驅動,既是一個virtio設備,也是一個pci設備,在內核中通過結構體struct virtio_pci_device來組織:

  • 該結構體中維護了幾個IO區域:Common, ISR, Device, Notify,用於獲取virtio設備的各種信息,這個也是由virtio規範決定的;
  • 通常來說一個virtio設備,由以下幾個部分組成:
    1. Device status field
    2. Feature bits
    3. Notifications
    4. Device Configuration space
    5. One or more virtqueues
  • 從結構體看,它用於充當pci設備和virtio設備的紐帶,後續也會在probe函數中針對不同的部分進行對應的初始化;

以總線的匹配視角來看就是這樣子的:

3. 流程分析

3.1 virtio總線創建

先看一下virtio總線的創建,virtio bus當然也算是基建了:

  • bus_register註冊virtio總線,總線負責匹配,在匹配成功後調用通用的virtio_dev_probe函數;
  • 千里姻緣一線牽,當Virtio的ID號能對上時,就會觸發驅動探測,所以什麼時候進行設備註冊呢?

3.2 virtio驅動調用流程

詳細的細節,建議閱讀之前PCI驅動系列的分析文章,下邊羅列關鍵部分:

  • virtio-net設備通過掛在pci總線上,系統在PCI子系統初始化時會去枚舉所有的設備,並將枚舉的設備註冊進系統;
  • 系統在匹配上之後,調用設備的驅動;

  • PCI設備根據Vendor ID來匹配驅動;
  • virtio規範中規定基於PCI的virtio設備,Vendor ID號爲:0x1AF4,因此最終調用的驅動入口爲virtio_pci_probe

  • 在probe函數中分配struct virtio_pci_device結構,前文中也提到過它負責將virtio設備和pci設備綁定到一起,最終會在兩個設備驅動的probe函數中完成整體結構的初始化,也就是virtio_pci_probe完成一部分,實際的virtio設備驅動中完成一部分;
  • virtio_pci_modern_probe:該函數的內容就與virtio規範緊密相關了,簡單來說,virtio設備都會按照規範填充common、device、isr、notification等功能部分,而virtio_pci_modern_probe函數通過virtio_pci_find_capability去獲取對應的能力,並且通過map_capability完成IO空間的映射;
  • virtio_pci_probe中還設置了virtio_pci_config_ops操作函數集,並傳遞給virtio驅動,在驅動中調用這些回調函數來操作virtio設備;
  • register_virtio_device:向系統註冊virtio設備,從而也就觸發了virtio總線的匹配操作,最終調用virtio_dev_probe函數;
  • virtio_dev_probe函數中按照virtio規範分階段設置不同的狀態、獲取virtio設備的feature等,並最終調用實際設備的驅動程序了;

At last,終於摸到本文要說的virtio-net的驅動的入口了,當然,文章也要戛然而止了。

整體執行流程及框架應該清楚了,細節就留給大家了,待續。。。

參考

https://developer.ibm.com/technologies/linux/articles/l-virtio/
Virtual I/O Device (VIRTIO) Version 1.1

歡迎關注個人公衆號,不定期更新技術文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章