总结
在访客中设置一个陷阱。
声明
#include <zircon/syscalls.h>
zx_status_t zx_guest_set_trap(zx_handle_t handle,
uint32_t kind,
zx_vaddr_t addr,
size_t size,
zx_handle_t port_handle,
uint64_t key);
说明
zx_guest_set_trap()
在客户机内设置了一个陷阱,该陷阱会在由 kind 定义的地址空间内由 addr 和 size 定义的地址范围内的某个 vCPU 访问时生成数据包。
种类可以是 ZX_GUEST_TRAP_BELL
、ZX_GUEST_TRAP_MEM
或 ZX_GUEST_TRAP_IO
。如果指定了 ZX_GUEST_TRAP_BELL
或 ZX_GUEST_TRAP_MEM
,则 addr 和 size 都必须与页面对齐。ZX_GUEST_TRAP_BELL
是一个异步 trap,而 ZX_GUEST_TRAP_MEM
和 ZX_GUEST_TRAP_IO
都是同步 trap。
同步陷阱的数据包将通过 zx_vcpu_enter()
传送,异步陷阱的数据包将通过 port_handle 传送。
对于同步陷阱,port_handle 必须为 ZX_HANDLE_INVALID
。对于异步 Trap,port_handle 必须有效,每次触发 trap 时,系统都会通过 port_handle 传送 trap 的数据包。每个陷阱预先分配固定数量的数据包。如果所有数据包已耗尽,系统将暂停执行导致 trap 的 VCPU。当至少有一个数据包离开队列时,VCPU 将继续执行。如需从 port_handle 将数据包移出队列,请使用 zx_port_wait()
。多个线程可以使用 zx_port_wait()
将数据包移出队列,从而能够使用线程池来处理陷阱。
key 用于设置 zx_port_packet_t
中的密钥字段,并可用于区分不同陷阱的数据包。
ZX_GUEST_TRAP_BELL
是一种用于定义门铃的陷阱。如果 trap 指定的内存区域访问,则会生成一个数据包,该数据包不会提取与访问关联的指令。然后,数据包将通过 port_handle 异步传送。
如需确定是哪种 trap 生成了数据包,请使用 ZX_PKT_TYPE_GUEST_MEM
、ZX_PKT_TYPE_GUEST_IO
、ZX_PKT_TYPE_GUEST_BELL
和 ZX_PKT_TYPE_GUEST_VCPU
。ZX_PKT_TYPE_GUEST_VCPU
是一个不是由陷阱引起的特殊数据包,表示客户机请求启动额外的 vCPU。
权限
handle 必须为 ZX_OBJ_TYPE_GUEST
类型,且具有 ZX_RIGHT_WRITE
。
port_handle 的类型必须为 ZX_OBJ_TYPE_PORT
,且具有 ZX_RIGHT_WRITE
。
返回值
zx_guest_set_trap()
会在成功时返回 ZX_OK
。如果失败,则返回错误值。
错误
ZX_ERR_ACCESS_DENIED
handle 或 port_handle 没有 ZX_RIGHT_WRITE
权限。
ZX_ERR_ALREADY_EXISTS
已存在与 addr 和 size 相交的 Kind 的 trap。
ZX_ERR_BAD_HANDLE
handle 或 port_handle 是无效的句柄。
ZX_ERR_INVALID_ARGS
种类不是有效的地址空间,或者使用 port_handle 指定了 ZX_GUEST_TRAP_MEM
。
ZX_ERR_NO_MEMORY
由于内存不足而失败。
用户空间没有什么方法来处理此(不太可能)错误。在以后的 build 中,此错误不会再发生。
ZX_ERR_OUT_OF_RANGE
addr 和 size 指定的区域超出地址空间 Kind 的有效边界。
ZX_ERR_WRONG_TYPE
handle 不是客户机的句柄,或者 port_handle 不是端口的句柄。
备注
ZX_GUEST_TRAP_BELL
与 ZX_GUEST_TRAP_MEM
具有相同的地址空间。
在 x86-64 上,如果 kind 为 ZX_GUEST_TRAP_BELL
或 ZX_GUEST_TRAP_MEM
,且 addr 是本地 APIC 的地址,则 size 必须等于页面的大小。这是因为当本地 APIC 的地址发出 trap 请求时,系统会映射一个特殊页面。这样一来,我们就可以在硬件加速的情况下加以利用。
另请参阅
zx_guest_create()
zx_port_create()
zx_port_wait()
zx_vcpu_create()
zx_vcpu_enter()
zx_vcpu_interrupt()
zx_vcpu_kick()
zx_vcpu_read_state()
zx_vcpu_write_state()