总结
添加内存映射。
声明
#include <zircon/syscalls.h>
zx_status_t zx_vmar_map(zx_handle_t handle,
zx_vm_option_t options,
size_t vmar_offset,
zx_handle_t vmo,
uint64_t vmo_offset,
size_t len,
zx_vaddr_t* mapped_addr);
说明
将指定的 VMO 映射到指定的虚拟内存地址区域。该映射会保留对底层虚拟内存对象的引用,这意味着关闭 VMO 句柄不会移除此函数添加的映射。
options 是以下值的位矢量:
ZX_VM_SPECIFIC
使用 vmar_offset 放置映射;如果 handle 没有ZX_VM_CAN_MAP_SPECIFIC
权限,则无效。vmar_offset 是相对于给定 VMAR 基地址的偏移量。指定与其他 VMAR 或映射重叠的范围是错误的。ZX_VM_SPECIFIC_OVERWRITE
与ZX_VM_SPECIFIC
相同,但可以与其他映射重叠。与另一个 VMAR 部分重叠仍然会引发错误。如果该范围满足这些要求,它将以原子方式(相对于所有其他映射/取消映射/保护操作)替换 vmar_offset 和 len 指定的范围内的现有映射。如果该范围与任何映射部分重叠,那么这些映射中超出该范围的部分将保持映射状态。ZX_VM_OFFSET_IS_UPPER_LIMIT
将 vmar_offset 解读为上限,以限制内核对偏移量的选择;如果 handle 没有ZX_VM_CAN_MAP_SPECIFIC
权限,则无效。生成的映射的 offset + len 将为 <= vmar_offset。如果使用ZX_VM_SPECIFIC
或ZX_VM_SPECIFIC_OVERWRITE
,则无法指定此选项。ZX_VM_PERM_READ
将 vmo 映射为可读。如果 handle 没有ZX_VM_CAN_MAP_READ
权限,handle 没有ZX_RIGHT_READ
权限,或者 vmo 句柄没有ZX_RIGHT_READ
权限,则会出错。ZX_VM_PERM_WRITE
将 vmo 映射为可写。如果 handle 没有ZX_VM_CAN_MAP_WRITE
权限,handle 没有ZX_RIGHT_WRITE
权限,vmo 句柄没有ZX_RIGHT_WRITE
权限,或者 options 未指定ZX_VM_PERM_READ
,则会出错。ZX_VM_PERM_EXECUTE
将 vmo 映射为可执行文件。如果 handle 没有ZX_VM_CAN_MAP_EXECUTE
权限,handle 句柄没有ZX_RIGHT_EXECUTE
权限,vmo 句柄没有ZX_RIGHT_EXECUTE
权限,或者 options 未指定ZX_VM_PERM_READ
,则会出错。ZX_VM_MAP_RANGE
立即分页进入虚拟机的所有受支持区域的新映射。如果使用ZX_VM_SPECIFIC_OVERWRITE
,则无法指定此字段。ZX_VM_ALLOW_FAULTS
:如果创建的映射可能会生成故障,则为必需。具体而言,vmo 可调整大小、vmo 不可调整大小但映射超出 vmo 的末尾部分、vmo 可舍弃,或者 vmo 是从zx_pager_create_vmo()
创建的,则必须提供此属性。ZX_VM_PERM_READ_IF_XOM_UNSUPPORTED
如果系统不支持映射只执行页面,则将 vmo 映射为可读页面。如果系统可以映射只执行,系统会忽略此标志。
如果 options 未设置 ZX_VM_SPECIFIC
、ZX_VM_SPECIFIC_OVERWRITE
或 ZX_VM_OFFSET_IS_UPPER_LIMIT
,则 vmar_offset 必须为 0。ZX_VM_OFFSET_IS_UPPER_LIMIT
用于限制选择范围,除此之外的行为类似于未设置 ZX_VM_SPECIFIC
和 ZX_VM_SPECIFIC_OVERWRITE
的情况,因为内核会随机为映射分配偏移量(分配器由目标 VMAR 上设置的政策确定)。
len 必须是非零值且页面对齐。
此外,可以添加以下二次幂对齐标志之一:
ZX_VM_ALIGN_1KB
用于将 child_addr 对齐为至少 1K 字节的 2 的幂。ZX_VM_ALIGN_2KB
用于将 child_addr 对齐为至少 2K 字节的 2 的幂。ZX_VM_ALIGN_4KB
用于将 child_addr 对齐为至少 4K 字节的 2 的幂。ZX_VM_ALIGN_8KB
用于将 child_addr 对齐为至少 8K 字节的 2 次方。ZX_VM_ALIGN_4GB
用于将 child_addr 对齐为至少 4G 字节的 2 的幂。
如果 vmar 基础地址 + vmo_offset 与请求的值不一致,将 ZX_VM_ALIGN
标志与 ZX_VM_SPECIFIC
搭配使用会失败。
权限
handle 的类型必须为 ZX_OBJ_TYPE_VMAR
。
vmo 的类型必须为 ZX_OBJ_TYPE_VMO
。
返回值
zx_vmar_map()
会在成功时返回 ZX_OK
和映射的绝对基址(通过 mapped_addr)。基地址将与页面对齐,且为非零值。如果失败,则返回负数错误值。
错误
ZX_ERR_BAD_HANDLE
handle 或 vmo 不是有效的句柄。
ZX_ERR_WRONG_TYPE
handle 或 vmo 分别不是 VMAR 或 VMO 句柄。
ZX_ERR_BAD_STATE
句柄是指已销毁的 VMAR。
以下任意一项的 ZX_ERR_INVALID_ARGS
:
- mapped_addr 或 options 都无效。
- 如果未指定 ZX_VM_SPECIFIC
、ZX_VM_SPECIFIC_OVERWRITE
或 ZX_VM_OFFSET_IS_UPPER_LIMIT
,vmar_offset 为非零值。
- 同时指定了 ZX_VM_SPECIFIC_OVERWRITE
和 ZX_VM_MAP_RANGE
。
- ZX_VM_OFFSET_IS_UPPER_LIMIT
与 ZX_VM_SPECIFIC
或 ZX_VM_SPECIFIC_OVERWRITE
一起指定。
- vmar_offset 和 len 描述了由于超出区域边界而导致不满足的分配。
- vmar_offset 或 vmo_offset 未进行页面对齐。
- len 为 0 或未页面对齐。
ZX_ERR_ALREADY_EXISTS
ZX_VM_SPECIFIC
已在未指定 ZX_VM_SPECIFIC_OVERWRITE
的情况下指定,并且请求的范围与另一个映射重叠。
ZX_ERR_NO_RESOURCES
:如果在 VMAR 中找不到时间点以创建映射。
ZX_ERR_ACCESS_DENIED
权限不足,无法创建所请求的映射。
ZX_ERR_NOT_SUPPORTED
:如果视频可调整大小、可舍弃或由分页器提供支持,但未设置 ZX_VM_ALLOW_FAULTS
。
ZX_ERR_BUFFER_TOO_SMALL
:VMO 不可调整大小,且映射超出 VMO 的末尾,但 ZX_VM_ALLOW_FAULTS
未设置。
ZX_ERR_NO_MEMORY
由于内存不足而失败。
用户空间没有什么方法来处理此(不太可能)错误。在以后的 build 中,此错误不会再发生。
ZX_ERR_OUT_OF_RANGE
vmo_offset + ROUNDUP(len, PAGE_SIZE)
溢出。
备注
支持内存映射的 VMO 可调整为更小的大小。这可能会导致线程在读取 VMAR 区域或向 VMAR 区域写入数据时发生故障。为了避免此风险,从客户端接收 VMO 的服务应在映射 VMO 时使用 ZX_VM_REQUIRE_NON_RESIZABLE
。