RFC-0128:引入“zx_vcpu_kick” | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 新的系统调用“zx_vcpu_kick”,可能会导致正在运行的 vCPU 退出到主机并返回用户空间。 |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021 年 8 月 26 日 |
审核日期(年-月-日) | 2021-09-25 |
摘要
我们提议添加新的系统调用 zx_vcpu_kick
,它可导致运行中的 vCPU
退出到主机并返回用户空间。此外,我们还建议重命名
将 zx_vcpu_resume
重命名为 zx_vcpu_enter
,以便采用一致的命名法。
设计初衷
当一个 vCPU 正在运行时,它可能会在对
zx_vcpu_enter
。这会给虚拟机管理器带来问题,因为
彻底关闭 vCPU,则虚拟机管理器需要系统调用返回
以便能够安全地释放所有相关的
资源。
此外,为了简化集成测试, 有一种方法来强制某个 vCPU 退出客户机,非常方便。如此一来, 可以更简洁、更精确地编写测试。
利益相关方
教员:CPU
审核者:adanis、tamird、jamesr
已咨询:dgreenaway、brunodalbo
社交化:我们在聊天会话中讨论了设计,这是 用于解决连接团队在使用 netemul 时遇到的问题, 测试。
设计
该方案包含对 Zircon 系统调用接口的以下更改:
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_kick
时 zx_vcpu_enter
未运行,则
对 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
后的 vCPU 返回 ZX_ERR_CANCELED
zx_vcpu_enter
。除了处理返回值和绕过
虚拟机管理器不需要执行任何操作
特殊,可以立即调用 zx_vcpu_enter
以继续执行。
实现
在 Hypervisor 中,zx_vcpu_enter
的建模依据是 zx_port_wait
。它具有
API 几乎完全相同,只不过是截止时间。而是需要等待
然后带该数据包返回到用户空间
与 zx_thread_start
不同,它并不是为创建
执行,而不是转换当前的执行线程。
话虽如此,但我们认为基于令牌的方法
在 zx_task_suspend
中找到)对中断 vCPU 的执行很有效。答
基于词元的方法不适合 VCPU 执行模型,
常量来回传递。
我们提议 zx_vcpu_kick
直接导致 zx_vcpu_enter
返回
用户空间,并显示一个表明已中断的错误代码。在
Hypervisor,zx_vcpu_kick
的实现方式与
zx_vcpu_interrupt
。它会:
- 设置状态。对于
zx_vcpu_kick
,此状态是一个原子布尔值,用于 指示 vCPU 在退出客户机时应返回。此变量 可通过使用zx_object_get_info
进行查询,主题为ZX_INFO_VCPU
和相应的zx_info_vcpu_t
类型。 - 检查此 vCPU 当前是否正在运行,如果是,则 IPI 为物理 CPU 当前运行的 vCPU 数量这会强制此 vCPU 退出 来宾客处理中断,从而允许其为事件提供服务 请求返回。
原子布尔值跟踪是否调用了 zx_vcpu_kick
以及 vCPU
如果不再有任何待处理的请求,则应返回 ZX_ERR_CANCELED
返回用户空间的信息这意味着,如果有未完成的
用户空间的来宾数据包,在返回之前会成功返回
在对 zx_vcpu_enter
的后续调用中调用 ZX_ERR_CANCELED
。
此方法使 zx_vcpu_enter
的行为类似于 zx_port_wait
,
发生超时。
将在单个 CL 中进行实现,因为 Hypervisor 包含在 Fuchsia 代码库中。此次变更将包括 对系统调用的文档和语言绑定的更新,以及相关更改 虚拟机管理器角色
性能
除了导致访客退出之外,对性能没有任何已知的影响 执行。它的主要用途是正常终止 应该不会产生实际影响
工效学设计
讨论了 zx_vcpu_enter
和 zx_vcpu_kick
的人体工学注意事项
在设计部分。
向后兼容性
Hypervisor 的所有已知用户都包含在 Fuchsia 代码库中,
因此可以引入 zx_vcpu_kick
并重命名
将zx_vcpu_resume
更改为zx_vcpu_enter
。
安全注意事项
应对使用 zx_vcpu_kick
的虚拟机管理器进行审核,以确保
任何使用 zx_vcpu_enter
的行为都会考虑 ZX_ERR_CANCELED
返回
并且它必须忽略返回的 PortPacket
(如果要
恢复操作。如果未忽略 PortPacket
,则
对已清零的无效数据执行操作 - 如果任何错误都为 true,
zx_vcpu_enter
返回的状态。
隐私注意事项
此方案对隐私权没有任何影响。
测试
实现 CL 上线后,我们就可以为 虚拟机管理器测试,证明我们可以在没有相关虚拟机的情况下 ASAN 故障。
文档
我们需要为 zx_vcpu_kick
系统调用添加其他文档,并且
我们需要将 zx_vcpu_enter
系统调用的文档扩展为
包括新的退货状态和 PortPacket
处理建议。
缺点、替代方案和未知问题
该方案的缺点是引入了额外的系统调用。它
最初提议我们可以重复使用 zx_task_kill
或
zx_handle_close
,但两者都有自己的缺点。
如需专门将 zx_task_kill
与 vCPU 配合使用,我们必须考虑
将 vCPU 设为一项任务,从而让所有与任务相关的系统调用都适用于 vCPU。
如果我们只将 zx_task_kill
用于 vCPU,而不使用任何其他 CPU
与任务相关的系统调用,则可能是不一致的。
我们可以依赖 zx_handle_close
的语义并添加一个
on_zero_handles
处理程序添加到 VcpuDispatcher
。这样,我们便可以
如果句柄计数为零,则终止 VCPU。不过,这有两个
直接缺点:vCPU 停止后便无法再恢复,
并让 vCPU 句柄失效“vCPU 句柄的失效”现为
尤其容易出现问题,因为它本身就是一种竞态操作。其他消息串
可能正在使用 vCPU 句柄进行注入和中断,
句柄无效,因此会导致意外错误。
另一种方法是引入此系统调用的更通用的版本,
示例 zx_thread_cancel
,其中指定线程上的任何阻塞操作
会立即返回 ZX_ERR_CANCELED
。这样,我们就可以扩展系统调用
未来使用与 vCPU 类似的模型的用例。
先验技术和参考资料
Apple 的 Hypervisor Framework 中存在类似的操作: https://developer.apple.com/documentation/hypervisor/1441468-hv_vcpu_interrupt
以及在 Linux 的 KVM(基于内核的虚拟机)中: https://www.kernel.org/doc/html/latest/virt/kvm/vcpu-requests.html#vcpu-kicks