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 权限,则无效。生成的映射 将具有 <= vmar_base + vmar_offset 的偏移量 + len。如果使用 ZX_VM_SPECIFICZX_VM_SPECIFIC_OVERWRITE,则无法指定此选项 。
  • ZX_VM_PERM_READvmo 映射为可读。 如果 handle 没有 ZX_VM_CAN_MAP_READ 权限,或者 handle 没有 ZX_RIGHT_READ 权限,或者 vmo 句柄没有 ZX_RIGHT_READ 权限,则会出错。
  • ZX_VM_PERM_WRITEvmo 映射为可写。 如果 handle 没有 ZX_VM_CAN_MAP_WRITE 权限,或者 handle 没有 ZX_RIGHT_WRITE 权限,或者 vmo 句柄没有 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 可调整大小,或者设置了 ZX_VM_FAULT_BEYOND_STREAM_SIZE,或者 vmo 不可调整大小但映射超出了 vmo 的末尾,或者 vmo 可舍弃,或者 vmo 是通过 zx_pager_create_vmo() 创建的,则需要此项。
  • ZX_VM_PERM_READ_IF_XOM_UNSUPPORTED 如果系统不支持映射仅执行页面,则将 vmo 映射为可读。如果系统可以映射仅执行,则会忽略此标志。
  • ZX_VM_REQUIRE_NON_RESIZABLE 如果 vmo 可调整大小,则失败。
  • ZX_VM_FAULT_BEYOND_STREAM_SIZE 超出流大小(向上舍入到页面边界)的内存访问将导致故障。需要 ZX_VM_ALLOW_FAULTS

如果 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 必须为非零值,并且会在内部向上舍入以与页面对齐。

此外,还可以添加以下 2 的幂对齐标志之一:

  • ZX_VM_ALIGN_1KBchild_addr 与至少 1K 字节的 2 的幂对齐。
  • ZX_VM_ALIGN_2KBchild_addr 与至少 2K 字节的 2 的幂对齐。
  • ZX_VM_ALIGN_4KBchild_addr 与至少 4K 字节的 2 的幂对齐。
  • ZX_VM_ALIGN_8KBchild_addr 与至少 8K 字节的 2 的幂对齐。

并继续到

  • ZX_VM_ALIGN_4GBchild_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 不是有效的句柄。

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

ZX_ERR_BAD_STATE handle 引用已销毁的 VMAR。

对于以下任一情况,ZX_ERR_INVALID_ARGS

  • mapped_addroptions 无效。
  • vmar_offset 当未指定 ZX_VM_SPECIFICZX_VM_SPECIFIC_OVERWRITEZX_VM_OFFSET_IS_UPPER_LIMIT 中的任何一个时,为非零值。
  • 同时指定了 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_VM_FAULT_BEYOND_STREAM_SIZEvmo 是物理的或连续的。

ZX_ERR_BUFFER_TOO_SMALL VMO 不可调整大小,并且映射超出了 VMO 的末尾,但未设置 ZX_VM_ALLOW_FAULTS

ZX_ERR_NO_MEMORY 因内存不足而失败。 用户空间没有很好的方法来处理此(不太可能发生的)错误。 在未来的版本中,此错误将不再发生。

ZX_ERR_OUT_OF_RANGE vmo_offset + ROUNDUP(len, PAGE_SIZE) 溢出。

备注

支持内存映射的 VMO 可以调整为较小的大小。这可能会导致线程读取或写入 VMAR 区域时发生故障。为避免此风险,从客户端接收 VMO 的服务在映射 VMO 时应使用 ZX_VM_REQUIRE_NON_RESIZABLE

另请参阅