RFC-0128:推出「zx_vcpu_kick」

RFC-0128:導入 `zx_vcpu_kick`
狀態已接受
區域
  • 核心
說明

新的 syscall「zx_vcpu_kick」,可能會導致執行中的 VCPU 離開主機並返回使用者空間。

變更
  • 573781
作者
審查人員
提交日期 (年/月)2021-08-26
審查日期 (年/月)2021-09-25

摘要

建議您新增 zx_vcpu_kick 系統呼叫,這會導致執行中的 vCPU 離開主機並返回使用者空間。此外,我們也建議將 zx_vcpu_resume 重新命名為 zx_vcpu_enter,以便有一致的命名方式。

提振精神

vCPU 執行時,呼叫 zx_vcpu_enter 可能會無限期封鎖。這會導致虛擬機器管理員發生問題,如同充分利用 vCPU,虛擬機器管理員需要透過系統呼叫,將控制權回復到呼叫執行緒,以便安全地釋放所有相關資源。

此外,為了簡化整合測試的目的,有一種方法讓 VCPU 從訪客離開,是非常方便的做法。這樣一來,您就能以更簡潔精確的方式編寫測試。

相關人員

講師:CPU

審查人員:adani、tamid、jamesr

顧問:dgreenaway、brunodalbo

社交化:我們在聊天執行緒中討論了這項設計,也是連線團隊在 Netemul 測試中面臨的問題之一。

設計

本提案包含以下 Zircon syscall 介面的變更:

  1. 新增 zx_vcpu_kick
  2. 正在將 zx_vcpu_resume 重新命名為 zx_vcpu_enter

其中 zx_vcpu_enterzx_vcpu_kick 的定義為:

/// Enter a VCPU, and start or continue execution.
/// Rights: handle must be of type ZX_OBJ_TYPE_VCPU and have ZX_RIGHT_EXECUTE.
// @blocking
zx_status_t zx_vcpu_enter(
    zx_handle_t handle,
    uint32_t options,
    zx_port_packet_t* packet
);

/// Exit from the current or next call to |vcpu_enter|.
/// Rights: handle must be of type ZX_OBJ_TYPE_VCPU and have ZX_RIGHT_EXECUTE.
zx_status_t zx_vcpu_kick(
    zx_handle_t handle
);

在 vCPU 控制代碼上呼叫 zx_vcpu_kick 時,目前正在相同控制代碼上任何執行中對 zx_vcpu_enter 的呼叫都會傳回 ZX_ERR_CANCELED。此外,如果 zx_vcpu_enter 在呼叫 zx_vcpu_kick 時沒有執行,下一個對 zx_vcpu_enter 的呼叫會立即傳回 ZX_ERR_CANCELED。這可讓虛擬機器管理員呼叫 zx_vcpu_kick,並保證 zx_vcpu_enter 會在下一個傳回 ZX_ERR_CANCELED。反之,如果 zx_vcpu_enter 尚未傳回 ZX_ERR_CANCELED,則無論呼叫 zx_vcpu_kick 的次數為何,都只會執行一次。

之所以選擇 ZX_ERR_CANCELED 做為傳回狀態,因此虛擬機器管理員可輕易區分結束事件的原因。這可讓虛擬機器管理員使用該狀態安全地停止 vCPU,而無需在虛擬機器管理員中進行其他狀態管理。當 zx_vcpu_enter 傳回 ZX_ERR_CANCELED 時,可關閉 VCPU 控制代碼並釋放任何其他相關聯的資源。

此外,zx_vcpu_kick 的行為是停止 vCPU,但不會終止。這表示虛擬機器管理員可能會在 zx_vcpu_enter 傳回 ZX_ERR_CANCELED 後再次呼叫 zx_vcpu_enter 繼續執行 vCPU。虛擬機器管理員除了處理傳回值及略過任何封包處理方式外,也不需要採取任何其他行動,而且可以立即呼叫 zx_vcpu_enter 繼續執行作業。

實作

在管理程序中,zx_vcpu_enter 是在 zx_port_wait 之後建立模型。這個版本的 API 幾乎完全相同,只有期限除外。的目標是等待訪客封包送達,然後透過封包返回使用者空間。與 zx_thread_start 不同,這並非建立新執行執行緒的方法,而是轉換目前的執行作業執行緒。

不過,我們認為憑證式方法 (例如 zx_task_suspend 中的金鑰) 不適合中斷 vCPU 的執行作業。以權杖為基礎的方法不符合 vCPU 執行的模型,這種模型需要在使用者空間和核心之間來回轉換。

相反地,我們建議 zx_vcpu_kick 只讓 zx_vcpu_enter 返回使用者空間,並顯示錯誤代碼,表示它中斷。在管理程序中,zx_vcpu_kick 的實作方式將與 zx_vcpu_interrupt 非常類似。本功能將執行以下作業:

  1. 設定狀態。如為 zx_vcpu_kick,這個狀態是不可部分完成的布林值,用於表示 vCPU 在訪客退出訪客時應傳回。您可以使用含有 ZX_INFO_VCPU 主題和對應 zx_info_vcpu_t 類型的 zx_object_get_info 查詢這個變數。
  2. 檢查 vCPU 是否正在運作。如果有的話,表示 vCPU 目前在執行 vCPU 的實體 CPU。這會強制 vCPU 離開訪客體驗中斷,讓訪客能處理要求傳回要求。

原子佈林值會追蹤是否已呼叫 zx_vcpu_kick,以及當 vCPU 不再有任何可傳回使用者空間的其他資訊時,就會傳回 ZX_ERR_CANCELED。換句話說,如果使用者空間還有尚未處理的訪客封包,那麼我們會在後續對 zx_vcpu_enter 的呼叫中傳回 ZX_ERR_CANCELED 之前,成功傳回這個封包。

這種方法可讓 zx_vcpu_enter 的行為類似於發生逾時的 zx_port_wait

實作將在單一 CL 中執行,因為 Fuchsia 存放區中,所有已知管理程序的已知使用者都會納入其中。這項變更包括系統呼叫的說明文件和語言繫結更新,以及管理程序和虛擬機器管理員的變更。

效能

對效能沒有任何已知的影響,除了導致訪客停止執行外。由於主要使用案例是安全終止 VCPU 的執行,這種情況應該不會造成實質影響。

人體工學

設計」一節已探討 zx_vcpu_enterzx_vcpu_kick 的人體工學注意事項。

回溯相容性

所有已知的管理程序使用者都包含在 Fuchsia 存放區中,因此可以導入 zx_vcpu_kick,並將 zx_vcpu_resume 重新命名為 zx_vcpu_enter

安全性考量

請對使用 zx_vcpu_kick 的虛擬機器管理員進行稽核,確保使用 zx_vcpu_enter 的任何行為都會考慮 ZX_ERR_CANCELED 傳回狀態,而且如果系統打算繼續處理 vCPU 的作業,就必須忽略傳回的 PortPacket。如果不忽略 PortPacket,該函式會針對空值已經零的無效資料運作。這對 zx_vcpu_enter 傳回的任何錯誤狀態來說都是如此。

隱私權注意事項

本提案不會影響隱私權。

測試

實作 CL 上線後,我們就可以啟用 ASAN 機器人進行虛擬機器管理員測試,並證明我們可以在沒有 ASAN 故障的情況下正常關閉。

說明文件

我們必須新增 zx_vcpu_kick 系統呼叫的其他文件,而需要展開 zx_vcpu_enter 系統呼叫的說明文件,以納入新的傳回狀態和 PortPacket 處理建議。

缺點、替代方案和未知

本提案的缺點是引入額外的系統呼叫。我們最初建議我們重複使用 zx_task_killzx_handle_close,但兩者都有各自的缺點。

為了讓 zx_task_kill 與 vCPU 搭配運作,我們必須將 vCPU 視為工作,因此讓所有與工作相關的系統呼叫都能與 vCPU 搭配使用。如果我們只讓 zx_task_kill 與 vCPU 搭配使用,而其他工作相關系統呼叫都沒有運作,那麼就會造成乾擾。

我們可以使用 zx_handle_close 的語意,並將 on_zero_handles 處理常式新增至 VcpuDispatcher。這樣一來,如果控制代碼計數降到零,我們就能終止 vCPU。不過,這麼做有兩項立即的缺點:vCPU 停止後就無法再繼續執行,而且 VCPU 控制代碼會失效。VCPU 控制代碼遭撤銷特別問題,因為這本身造成競爭性作業。另一個執行緒可能在處理常式無效時,使用 VCPU 控制代碼插入和中斷程序,進而導致意外錯誤發生。

另一種做法是導入這個系統呼叫的通用版本,例如 zx_thread_cancel,其中特定執行緒的任何封鎖作業會立即傳回 ZX_ERR_CANCELED。透過這項功能,我們可將系統呼叫延伸至日後使用與 vCPU 類似的模型。

先前的圖片和參考資料

Apple 的管理程序架構中也有類似的作業:https://developer.apple.com/documentation/hypervisor/1441468-hv_vcpu_中斷

以及 Linux 的 KVM (核心式虛擬機器):https://www.kernel.org/doc/html/latest/virt/kvm/vcpu-requests.html#vcpu-kicks