RFC-0128:導入 `zx_vcpu_kick` | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 新的 syscall「zx_vcpu_kick」,可能會導致執行中的 VCPU 離開主機並返回使用者空間。 |
變更 | |
作者 | |
審查人員 | |
提交日期 (年/月) | 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 介面的變更:
- 新增
zx_vcpu_kick
- 正在將
zx_vcpu_resume
重新命名為zx_vcpu_enter
其中 zx_vcpu_enter
和 zx_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
非常類似。本功能將執行以下作業:
- 設定狀態。如為
zx_vcpu_kick
,這個狀態是不可部分完成的布林值,用於表示 vCPU 在訪客退出訪客時應傳回。您可以使用含有ZX_INFO_VCPU
主題和對應zx_info_vcpu_t
類型的zx_object_get_info
查詢這個變數。 - 檢查 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_enter
和 zx_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_kill
或 zx_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