zxvmar_map

摘要

添加内存映射。

声明

#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_OVERWRITEZX_VM_SPECIFIC 相同,但可以与其他映射重叠。与其他 VMAR 部分重叠仍会导致错误。如果范围符合这些要求,则会以原子方式(相对于所有其他映射/取消映射/保护操作)替换 vmar_offsetlen 指定的范围内的现有映射。如果该范围与任何映射部分重叠,则这些映射在该范围之外的部分仍会保持映射状态。
  • ZX_VM_OFFSET_IS_UPPER_LIMITvmar_offset 解释为上限,以限制内核选择偏移量;如果 handle 没有 ZX_VM_CAN_MAP_SPECIFIC 权限,则无效。生成的映射将具有 offset + len,且该值小于等于 vmar_base + vmar_offset。如果使用 ZX_VM_SPECIFICZX_VM_SPECIFIC_OVERWRITE,则无法指定此选项。
  • ZX_VM_PERM_READvmo 映射为可读。如果 handle 没有 ZX_VM_CAN_MAP_READ 权限、handle 没有 ZX_RIGHT_READ 权限,或者 vmo handle 没有 ZX_RIGHT_READ 权限,则会出错。
  • ZX_VM_PERM_WRITEvmo 映射为可写入。如果 handle 没有 ZX_VM_CAN_MAP_WRITE 权限、handle 没有 ZX_RIGHT_WRITE 权限、vmo handle 没有 ZX_RIGHT_WRITE 权限,或者 options 未指定 ZX_VM_PERM_READ,则会出错。
  • ZX_VM_PERM_EXECUTEvmo 映射为可执行文件。如果 handle 没有 ZX_VM_CAN_MAP_EXECUTE 权限、handle 句柄没有 ZX_RIGHT_EXECUTE 权限、vmo 句柄没有 ZX_RIGHT_EXECUTE 权限,或者 options 未指定 ZX_VM_PERM_READ,则会出错。
  • ZX_VM_MAP_RANGE 将 VMO 的所有后备区域立即分页到新映射中。如果使用 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 映射为可读。如果系统可以映射只执行映像,则会忽略此标志。
  • ZX_VM_REQUIRE_NON_RESIZABLE 如果 vmo 可调整大小,则失败。

如果 options 未设置 ZX_VM_SPECIFICZX_VM_SPECIFIC_OVERWRITEZX_VM_OFFSET_IS_UPPER_LIMIT,则 vmar_offset 必须为 0。ZX_VM_OFFSET_IS_UPPER_LIMIT 用于约束选择范围,否则其行为与未设置 ZX_VM_SPECIFICZX_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 handlevmo 不是有效的 handle。

ZX_ERR_WRONG_TYPE handlevmo 分别不是 VMAR 或 VMO 句柄。

ZX_ERR_BAD_STATE handle 是指已销毁的 VMAR。

ZX_ERR_INVALID_ARGS 适用于以下任一情况: - mapped_addroptions 无效。 - 如果未指定 ZX_VM_SPECIFICZX_VM_SPECIFIC_OVERWRITEZX_VM_OFFSET_IS_UPPER_LIMIT,则 vmar_offset 不为零。 - 同时指定了 ZX_VM_SPECIFIC_OVERWRITEZX_VM_MAP_RANGE。 - ZX_VM_OFFSET_IS_UPPER_LIMITZX_VM_SPECIFICZX_VM_SPECIFIC_OVERWRITE 一起指定。 - vmar_offsetlen 描述了因超出区域边界而无法满足的分配。 - vmar_offsetvmo_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 如果 vmo 可调整大小、可丢弃或由页面器支持,但未设置 ZX_VM_ALLOW_FAULTS

ZX_ERR_NOT_SUPPORTED 如果 vmo 可调整大小且已设置 ZX_VM_REQUIRE_NON_RESIZABLE

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 区域时发生故障。为避免此类风险,从客户端接收 VMO 的服务应在映射 VMO 时使用 ZX_VM_REQUIRE_NON_RESIZABLE

另请参阅