全部產品
Search
文件中心

Elastic Compute Service:高版本核心熱拔virtio裝置Oops異常

更新時間:Jun 08, 2024

本文介紹如何處理在部分高版本核心的ECS執行個體中熱拔virtio裝置時出現Oops異常的問題。

問題現象

在部分高版本核心的ECS執行個體中熱拔virtio裝置(例如磁碟、網卡)時,作業系統會發生如下Oops異常:

  • 在配置了kernel.panic_on_oops = 1的執行個體中,會發生核心Panic異常。

  • 在配置了kernel.panic_on_oops = 0的執行個體中,會出現hung錯誤。

說明

在Linux核心中,kernel.panic_on_oops是一個核心參數,用於控制當核心遇到Oops(一種核心錯誤,通常包括訪問無效記憶體位址時發生的情況)時的行為。

  • 如果核心出現Panic異常,系統會立即停止運行當前的所有任務,儲存一些調試資訊,然後重啟或者關機,有助於快速響應問題並減少潛在的損害。

  • 如果核心出現hung錯誤,核心可能會嘗試繼續運行,在生產環境中不推薦該配置,因為可能會進一步導致資料損毀或其他嚴重損害。

問題原因

Linux上遊社區在核心社區中添加了對virtio裝置Admin Virtqueue的支援:commit詳情

在該commit中:

  • 對virtio_pci_device的定義中添加了一個is_avq的函數指標,用於判斷是否存在Admin Virtqueue。

  • 在modern virtio裝置的初始化函數virtio_pci_modern_probe中添加了對is_avq函數指標的賦值。image.png

  • 在熱拔virtio裝置時,代碼會檢查當前隊列是否為Admin Virtqueue。

    image.png

但是上遊社區忽略了一個問題:如果該virtio裝置不是一個modern virtio裝置,而是一個legacy virtio裝置時,並沒有對is_avq函數指標進行賦值,導致legacy virtio裝置中的virtio_pci_device結構體中的函數指標is_avq是一個null 指標(NULL Pointer)。此時如果熱拔virtio裝置,調用到if (vp_dev->is_avq(vdev, vq->index)) 代碼時,CPU的RIP寄存器執行了一個null 指標地址,從而觸發了null 指標異常,也就是嘗試執行一個無效的記憶體位址,這是作業系統不允許的,會導致程式崩潰或系統錯誤。

影響範圍

  • Linux上遊社區

    上遊社區已經針對該問題進行了修複:commit詳情。在該commit中,對is_avq函數指標是否為空白的情況進行了判斷,修複了該問題。

  • 作業系統

  • virtio裝置

    執行個體使用了legacy virtio裝置,並在進行熱拔操作。

解決方案

  • 方案一:更換modern virtio裝置的執行個體規格類型系列。具體操作,請參見修改執行個體規格

    建議使用以下執行個體規格類型系列,以下規格類型系列是modern virtio裝置,不受該問題影響。

    ecs.c8i、ecs.g8i、ecs.r8i、ecs.c8ae、ecs.g8ae、ecs.r8ae、ecs.c8a、ecs.g8a、ecs.r8a。更多資訊,請參見執行個體規格類型系列

  • 方案二

    1. 升級最新核心軟體包,並確認最新軟體包是否已合入is_avq函數指標判斷的補丁包:virtio-pci: Check if is_avq is NULL

    2. (條件必選)如果最新的核心中沒有合入is_avq函數指標判斷的補丁包,請自行合入。

附錄:名詞解釋

關於文檔中涉及的virtio裝置、Admin Virtqueue、virtio_pci_device等名詞解釋說明如下:

名詞

說明

virtio裝置

virtio是一種標準化的虛擬化裝置通訊架構,允許虛擬機器高效地與宿主機上的虛擬硬體裝置互動。virtio裝置是在虛擬化環境中類比出來的硬體裝置(如磁碟、網卡),分為傳統legacy virtio和現代modern virtio兩類,主要區別在於使用的配置介面不同。

Admin Virtqueue

是一個特殊的virtio隊列,用於執行裝置的管理操作,比如擷取裝置狀態、配置裝置等。並非所有virtio裝置都支援Admin Virtqueue。

virtio_pci_device

是在核心中表示一個virtio PCI裝置的資料結構,包含了指向各種功能函數的指標,其中之一就是新添加的is_avq函數指標,用於判斷給定的隊列是否為Admin Virtqueue。

is_avq

該函數用於判斷給定的virtio隊列是否為Admin Virtqueue。

virtio_pci_modern_probe

該函數負責virtio PCI裝置的探測和初始化過程。在裝置被系統發現後,此函數會被調用來完成裝置的設定,包括配置空間的讀取、裝置特性的檢測以及必要的資源分派等。

RIP寄存器

RIP(Instruction Pointer Register)寄存器是x86架構CPU中的一個寄存器,儲存了當前執行指令的下一條指令的地址。當程式發生異常,如嘗試執行一個null 指標所指向的地址時,RIP寄存器會指向引發異常的那條指令的地址。