Create a pager owned VMO.


#include <zircon/syscalls.h>

zx_status_t zx_pager_create_vmo(zx_handle_t pager,
                                uint32_t options,
                                zx_handle_t port,
                                uint64_t key,
                                uint64_t size,
                                zx_handle_t* out);


Creates a VMO owned by a pager object. size will be rounded up to the next page size boundary, and options must be zero or a combination of the following flags:

ZX_VMO_RESIZABLE - if the VMO can be resized.

ZX_VMO_TRAP_DIRTY - if writes to clean pages in the VMO should be trapped by the kernel and forwarded to the pager service for acknowledgement before proceeding with the write.

ZX_VMO_UNBOUNDED to create a VMO that is initialized to the largest possible size. Cannot be used in conjunction with ZX_VMO_RESIZABLE. Size argument sets the stream size only.

On success, the returned VMO has the same rights as a VMO created with zx_vmo_create(), as well as having the same behavior with respect to ZX_VMO_ZERO_CHILDREN. Syscalls that operate on VMOs require an explicit flag to allow blocking IPC to the userspace pager service; beyond this, whether or not a VMO is owned by a pager does not affect the semantics of syscalls.

TODO(stevend): Update differences after updates to cloning and decommit

Page requests will be delivered to port when certain conditions are met. Those packets will have type set to ZX_PKT_TYPE_PAGE_REQUEST and key set to the value provided to zx_pager_create_vmo(). The packet's union is of type zx_packet_page_request_t:

typedef struct zx_packet_page_request {
    uint16_t command;
    uint16_t flags;
    uint32_t reserved0;
    uint64_t offset;
    uint64_t length;
    uint64_t reserved1;
} zx_packet_page_request_t;

offset and length are always page-aligned. The value of any bits in flags for which flags are not defined is unspecified - currently no flags are defined. The trigger and meaning of the packet depends on command, which can take one of the following values:

ZX_PAGER_VMO_READ: Sent when an application accesses a non-resident page in a pager's VMO. The pager service should populate the range [offset, offset + length) in the registered VMO with zx_pager_supply_pages(). Supplying pages is an implicit positive acknowledgement of the request.

ZX_PAGER_VMO_DIRTY: Sent when an application writes to a resident clean page in a pager's VMO created with the ZX_VMO_TRAP_DIRTY flag. The pager service should acknowledge that the range [offset, offset + length) can be dirtied, allowing the write to proceed, with zx_pager_op_range() ZX_PAGER_OP_DIRTY.

ZX_PAGER_VMO_COMPLETE: Sent when no more pager requests will be sent for the corresponding VMO, either because of zx_pager_detach_vmo() or because no references to the VMO remain.

If pager is closed, then no more packets will be delivered to port (including no ZX_PAGER_VMO_COMPLETE message). Furthermore, all future accesses will behave as if zx_pager_detach_vmo() had been called.


pager must be of type ZX_OBJ_TYPE_PAGER and have ZX_RIGHT_ATTACH_VMO.

port must be of type ZX_OBJ_TYPE_PORT and have ZX_RIGHT_WRITE.

Return value

zx_pager_create_vmo() returns ZX_OK on success, or one of the following error codes on failure.


ZX_ERR_INVALID_ARGS out is an invalid pointer or NULL, options contains an unsupported combination of flags.

ZX_ERR_BAD_HANDLE pager or port is not a valid handle.

ZX_ERR_ACCESS_DENIED pager does not have ZX_RIGHT_ATTACH_VMO or port does not have ZX_RIGHT_WRITE.

ZX_ERR_WRONG_TYPE pager is not a pager handle or port is not a port handle.

ZX_ERR_OUT_OF_RANGE The requested size is larger than the maximum VMO size.

ZX_ERR_NO_MEMORY Failure due to lack of memory.

See also