| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library zx; |
| |
| alias VmOption = uint32; |
| |
| // TODO(scottmg): bits for ZX_VM_xyz flags, and const for ZX_VM_ALIGN_xyz. |
| @transport("Syscall") |
| closed protocol Vmar { |
| /// ## Summary |
| /// |
| /// Allocate a new subregion. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vmar_allocate(zx_handle_t parent_vmar, |
| /// zx_vm_option_t options, |
| /// size_t offset, |
| /// size_t size, |
| /// zx_handle_t* child_vmar, |
| /// zx_vaddr_t* child_addr); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// Creates a new VMAR within the one specified by *parent_vmar*. |
| /// |
| /// *options* is a bit vector that contains one more of the following: |
| /// |
| /// - `ZX_VM_COMPACT` A hint to the kernel that allocations and mappings |
| /// within the newly created subregion should be kept close together. See the |
| /// NOTES section below for discussion. |
| /// - `ZX_VM_SPECIFIC` Use the *offset* to place the mapping, invalid if |
| /// *parent_vmar* does not have the `ZX_VM_CAN_MAP_SPECIFIC` permission. *offset* |
| /// is an offset relative to the base address of the parent region. It is an error |
| /// to specify an address range that overlaps with another VMAR or mapping. |
| /// - `ZX_VM_OFFSET_IS_UPPER_LIMIT` Interpret the *offset* as an upper limit |
| /// to constrain the selection of the offset by the kernel, invalid if *parent_vmar* |
| /// does not have the `ZX_VM_CAN_MAP_SPECIFIC` permission. The resulting mapping |
| /// will have an offset + *size* that is <= *offset*. This option cannot be |
| /// specified if `ZX_VM_SPECIFIC` is used. |
| /// - `ZX_VM_CAN_MAP_SPECIFIC` The new VMAR can have subregions/mappings |
| /// created with `ZX_VM_SPECIFIC`. It is NOT an error if the parent does |
| /// not have `ZX_VM_CAN_MAP_SPECIFIC` permissions. |
| /// - `ZX_VM_CAN_MAP_READ` The new VMAR can contain readable mappings. |
| /// It is an error if the parent does not have `ZX_VM_CAN_MAP_READ` permissions. |
| /// - `ZX_VM_CAN_MAP_WRITE` The new VMAR can contain writable mappings. |
| /// It is an error if the parent does not have `ZX_VM_CAN_MAP_WRITE` permissions. |
| /// - `ZX_VM_CAN_MAP_EXECUTE` The new VMAR can contain executable mappings. |
| /// It is an error if the parent does not have `ZX_VM_CAN_MAP_EXECUTE` permissions. |
| /// |
| /// *offset* must be 0 if *options* does not have `ZX_VM_SPECIFIC` or |
| /// `ZX_VM_OFFSET_IS_UPPER_LIMIT` set. |
| /// |
| /// In addition, the following power-of-two alignment flags can added: |
| /// |
| /// - `ZX_VM_ALIGN_1KB` aligns *child_addr* to a power-of-2 at least 1K bytes. |
| /// - `ZX_VM_ALIGN_2KB` aligns *child_addr* to a power-of-2 at least 2K bytes. |
| /// - `ZX_VM_ALIGN_4KB` aligns *child_addr* to a power-of-2 at least 4K bytes. |
| /// - `ZX_VM_ALIGN_8KB` aligns *child_addr* to a power-of-2 at least 8K bytes. |
| /// |
| /// and continues up to |
| /// |
| /// - `ZX_VM_ALIGN_4GB` aligns *child_addr* to a power-of-2 at least 4G bytes. |
| /// |
| /// Using `ZX_VM_ALIGN` flags with `ZX_VM_SPECIFIC` will fail if the |
| /// *parent_vmar* base address + *offset* are not aligned to the requested |
| /// value. |
| /// |
| /// ## Rights |
| /// |
| /// If *options* & `ZX_VM_CAN_MAP_READ`, *parent_vmar* must be of type `ZX_OBJ_TYPE_VMAR` and have `ZX_RIGHT_READ`. |
| /// |
| /// If *options* & `ZX_VM_CAN_MAP_WRITE`, *parent_vmar* must be of type `ZX_OBJ_TYPE_VMAR` and have `ZX_RIGHT_WRITE`. |
| /// |
| /// If *options* & `ZX_VM_CAN_MAP_EXECUTE`, *parent_vmar* must be of type `ZX_OBJ_TYPE_VMAR` and have `ZX_RIGHT_EXECUTE`. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_allocate()` returns `ZX_OK`, the absolute base address of the |
| /// subregion (via *child_addr*), and a handle to the new subregion (via |
| /// *child_vmar*) on success. The base address will be page-aligned and non-zero. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *parent_vmar* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *parent_vmar* is not a VMAR handle. |
| /// |
| /// `ZX_ERR_BAD_STATE` *parent_vmar* refers to a destroyed VMAR. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` for any of the following: |
| /// - *child_vmar* or *child_addr* are not valid, |
| /// - *offset* is non-zero when `ZX_VM_SPECIFIC` or `ZX_VM_OFFSET_IS_UPPER_LIMIT` is not given. |
| /// - `ZX_VM_OFFSET_IS_UPPER_LIMIT` is specified together with `ZX_VM_SPECIFIC`. |
| /// - *offset* and *size* describe an unsatisfiable allocation due to exceeding the region bounds |
| /// - *offset* or *size* is not page-aligned, or *size* is 0. |
| /// |
| /// `ZX_ERR_NO_MEMORY` This may be due to the following: |
| /// |
| /// * A free address range of the requested size is not available within |
| /// *parent_vmar*. |
| /// * The system is out of memory resources. |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` Insufficient privileges to make the requested allocation. |
| /// |
| /// ## Notes |
| /// |
| /// ### Deallocation |
| /// |
| /// The address space occupied by a VMAR will remain allocated (within its |
| /// parent VMAR) until the VMAR is destroyed by calling [`zx_vmar_destroy()`]. |
| /// |
| /// Note that just closing the VMAR's handle does not deallocate the address |
| /// space occupied by the VMAR. |
| /// |
| /// ### The COMPACT flag |
| /// |
| /// The kernel interprets this flag as a request to reduce sprawl in allocations. |
| /// While this does not necessitate reducing the absolute entropy of the allocated |
| /// addresses, there will potentially be a very high correlation between allocations. |
| /// This is a trade-off that the developer can make to increase locality of |
| /// allocations and reduce the number of page tables necessary, if they are willing |
| /// to have certain addresses be more correlated. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_destroy()`] |
| /// - [`zx_vmar_map()`] |
| /// - [`zx_vmar_protect()`] |
| /// - [`zx_vmar_unmap()`] |
| /// |
| /// [`zx_vmar_destroy()`]: vmar_destroy.md |
| /// [`zx_vmar_map()`]: vmar_map.md |
| /// [`zx_vmar_protect()`]: vmar_protect.md |
| /// [`zx_vmar_unmap()`]: vmar_unmap.md |
| strict Allocate(resource struct { |
| parent_vmar Handle:VMAR; |
| options VmOption; |
| offset usize64; |
| size usize64; |
| }) -> (resource struct { |
| child_vmar Handle:VMAR; |
| child_addr Vaddr; |
| }) error Status; |
| |
| // TODO(https://fxbug.dev/42107929): handle No rights required? |
| /// ## Summary |
| /// |
| /// Destroy a virtual memory address region. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vmar_destroy(zx_handle_t handle); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vmar_destroy()` unmaps all mappings within the given region, and destroys |
| /// all sub-regions of the region. Note that this operation is logically recursive. |
| /// |
| /// This operation does not close *handle*. Any outstanding handles to this |
| /// VMAR will remain valid handles, but all VMAR operations on them will fail. |
| /// |
| /// The root VMAR, as obtained by `zx_process_create()`, cannot be destroyed. |
| /// |
| /// ## Rights |
| /// |
| /// TODO(https://fxbug.dev/42107318) |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_destroy()` returns `ZX_OK` on success. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` *handle* does not have `ZX_RIGHT_OP_CHILDREN`. |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* is not a VMAR handle. |
| /// |
| /// `ZX_ERR_BAD_STATE` This region is already destroyed. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` *handle* is a root VMAR. |
| /// |
| /// ## Notes |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_allocate()`] |
| /// - [`zx_vmar_map()`] |
| /// - [`zx_vmar_protect()`] |
| /// - [`zx_vmar_unmap()`] |
| /// |
| /// [`zx_vmar_allocate()`]: vmar_allocate.md |
| /// [`zx_vmar_map()`]: vmar_map.md |
| /// [`zx_vmar_protect()`]: vmar_protect.md |
| /// [`zx_vmar_unmap()`]: vmar_unmap.md |
| strict Destroy(resource struct { |
| handle Handle:VMAR; |
| }) -> () error Status; |
| |
| // TODO(https://fxbug.dev/42107318): TODO handle and vmo and options must all match, and options can't specify them. |
| /// ## Summary |
| /// |
| /// Add a memory mapping. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #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); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// Maps the given VMO into the given virtual memory address region. The mapping |
| /// retains a reference to the underlying virtual memory object, which means |
| /// closing the VMO handle does not remove the mapping added by this function. |
| /// |
| /// *options* is a bit vector of the following: |
| /// |
| /// - `ZX_VM_SPECIFIC` Use the *vmar_offset* to place the mapping, invalid if |
| /// *handle* does not have the `ZX_VM_CAN_MAP_SPECIFIC` permission. |
| /// *vmar_offset* is an offset relative to the base address of the given VMAR. |
| /// It is an error to specify a range that overlaps with another VMAR or mapping. |
| /// - `ZX_VM_SPECIFIC_OVERWRITE` Same as `ZX_VM_SPECIFIC`, but can |
| /// overlap another mapping. It is still an error to partially-overlap another VMAR. |
| /// If the range meets these requirements, it will atomically (with respect to all |
| /// other map/unmap/protect operations) replace existing mappings in the range |
| /// specified by *vmar_offset* and *len*. If that range partially overlaps any |
| /// mappings, then the portions of those mappings outside the range will remain mapped. |
| /// - `ZX_VM_OFFSET_IS_UPPER_LIMIT` Interpret the *vmar_offset* as an upper limit |
| /// to constrain the selection of the offset by the kernel, invalid if *handle* |
| /// does not have the `ZX_VM_CAN_MAP_SPECIFIC` permission. The resulting mapping |
| /// will have an offset + *len* that is <= *vmar_offset*. This option cannot be |
| /// specified if `ZX_VM_SPECIFIC` or `ZX_VM_SPECIFIC_OVERWRITE` is used. |
| /// - `ZX_VM_PERM_READ` Map *vmo* as readable. It is an error if *handle* |
| /// does not have `ZX_VM_CAN_MAP_READ` permissions, the *handle* does |
| /// not have the `ZX_RIGHT_READ` right, or the *vmo* handle does not have the |
| /// `ZX_RIGHT_READ` right. |
| /// - `ZX_VM_PERM_WRITE` Map *vmo* as writable. It is an error if *handle* |
| /// does not have `ZX_VM_CAN_MAP_WRITE` permissions, the *handle* does |
| /// not have the `ZX_RIGHT_WRITE` right, the *vmo* handle does not have the |
| /// `ZX_RIGHT_WRITE` right, or *options* does not specify `ZX_VM_PERM_READ`. |
| /// - `ZX_VM_PERM_EXECUTE` Map *vmo* as executable. It is an error if *handle* |
| /// does not have `ZX_VM_CAN_MAP_EXECUTE` permissions, the *handle* handle does |
| /// not have the `ZX_RIGHT_EXECUTE` right, the *vmo* handle does not have the |
| /// `ZX_RIGHT_EXECUTE` right, or *options* does not specify `ZX_VM_PERM_READ`. |
| /// - `ZX_VM_MAP_RANGE` Immediately page into the new mapping all backed |
| /// regions of the VMO. This cannot be specified if |
| /// `ZX_VM_SPECIFIC_OVERWRITE` is used. |
| /// - `ZX_VM_ALLOW_FAULTS` Required if it would be possible for the created |
| /// mapping to generate faults. In particular, it is required if *vmo* is resizable, |
| /// if *vmo* is non-resizable but the mapping extends past the end of *vmo*, if |
| /// *vmo* is discardable, or if *vmo* was created from [`zx_pager_create_vmo()`]. |
| /// - `ZX_VM_PERM_READ_IF_XOM_UNSUPPORTED` Map *vmo* as readable if the system does |
| /// not support mapping execute-only pages. If the system can map execute-only |
| /// this flag is ignored. |
| /// - `ZX_VM_REQUIRE_NON_RESIZABLE` Fail if *vmo* is resizable. |
| /// |
| /// *vmar_offset* must be 0 if *options* does not have `ZX_VM_SPECIFIC`, |
| /// `ZX_VM_SPECIFIC_OVERWRITE` or `ZX_VM_OFFSET_IS_UPPER_LIMIT` set. |
| /// `ZX_VM_OFFSET_IS_UPPER_LIMIT` serves to constrain the selection range, and |
| /// otherwise behaves similarly to the case where neither `ZX_VM_SPECIFIC` nor |
| /// `ZX_VM_SPECIFIC_OVERWRITE` are set, with the mapping being assigned an offset |
| /// at random by the kernel (with an allocator determined by policy set on the |
| /// target VMAR). |
| /// |
| /// *len* must be non-zero and page-aligned. |
| /// |
| /// In addition one of the following power-of-two alignment flags can added: |
| /// |
| /// - `ZX_VM_ALIGN_1KB` aligns *child_addr* to a power-of-2 at least 1K bytes. |
| /// - `ZX_VM_ALIGN_2KB` aligns *child_addr* to a power-of-2 at least 2K bytes. |
| /// - `ZX_VM_ALIGN_4KB` aligns *child_addr* to a power-of-2 at least 4K bytes. |
| /// - `ZX_VM_ALIGN_8KB` aligns *child_addr* to a power-of-2 at least 8K bytes. |
| /// and continues up to |
| /// - `ZX_VM_ALIGN_4GB` aligns *child_addr* to a power-of-2 at least 4G bytes. |
| /// |
| /// Using `ZX_VM_ALIGN` flags with `ZX_VM_SPECIFIC` will fail if the vmar |
| /// base address + *vmo_offset* are not aligned to the requested value. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type `ZX_OBJ_TYPE_VMAR`. |
| /// |
| /// *vmo* must be of type `ZX_OBJ_TYPE_VMO`. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_map()` returns `ZX_OK` and the absolute base address of the |
| /// mapping (via *mapped_addr*) on success. The base address will be page-aligned |
| /// and non-zero. In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* or *vmo* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* or *vmo* is not a VMAR or VMO handle, respectively. |
| /// |
| /// `ZX_ERR_BAD_STATE` *handle* refers to a destroyed VMAR. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` for any of the following: |
| /// - *mapped_addr* or *options* is not valid. |
| /// - *vmar_offset* is non-zero when none of `ZX_VM_SPECIFIC`, `ZX_VM_SPECIFIC_OVERWRITE` or |
| /// `ZX_VM_OFFSET_IS_UPPER_LIMIT` is specified. |
| /// - `ZX_VM_SPECIFIC_OVERWRITE` and `ZX_VM_MAP_RANGE` are both specified. |
| /// - `ZX_VM_OFFSET_IS_UPPER_LIMIT` is specified together with either `ZX_VM_SPECIFIC` |
| /// or `ZX_VM_SPECIFIC_OVERWRITE`. |
| /// - *vmar_offset* and *len* describe an unsatisfiable allocation due to exceeding the region bounds. |
| /// - *vmar_offset* or *vmo_offset* is not page-aligned. |
| /// - *len* is 0 or not page-aligned. |
| /// |
| /// `ZX_ERR_ALREADY_EXISTS` `ZX_VM_SPECIFIC` has been specified without |
| /// `ZX_VM_SPECIFIC_OVERWRITE`, and the requested range overlaps with another mapping. |
| /// |
| /// `ZX_ERR_NO_RESOURCES` If a spot could not be found in the VMAR to create the mapping. |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` Insufficient privileges to make the requested mapping. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` If the vmo is resizable, discardable, or backed by a pager but |
| /// `ZX_VM_ALLOW_FAULTS` is not set. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` If the vmo is resizable and `ZX_VM_REQUIRE_NON_RESIZABLE` is set. |
| /// |
| /// `ZX_ERR_BUFFER_TOO_SMALL` The VMO is not resizable and the mapping extends past the end |
| /// of the VMO but `ZX_VM_ALLOW_FAULTS` is not set. |
| /// |
| /// `ZX_ERR_NO_MEMORY` Failure due to lack of memory. |
| /// There is no good way for userspace to handle this (unlikely) error. |
| /// In a future build this error will no longer occur. |
| /// |
| /// `ZX_ERR_OUT_OF_RANGE` `vmo_offset + ROUNDUP(len, PAGE_SIZE)` overflows. |
| /// |
| /// ## Notes |
| /// |
| /// The VMO that backs a memory mapping can be resized to a smaller size. This can cause the |
| /// thread is reading or writing to the VMAR region to fault. To avoid this hazard, services |
| /// that receive VMOs from clients should use `ZX_VM_REQUIRE_NON_RESIZABLE` when mapping |
| /// the VMO. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_allocate()`] |
| /// - [`zx_vmar_destroy()`] |
| /// - [`zx_vmar_protect()`] |
| /// - [`zx_vmar_unmap()`] |
| /// |
| /// [`zx_pager_create_vmo()`]: pager_create_vmo.md |
| /// [`zx_vmar_allocate()`]: vmar_allocate.md |
| /// [`zx_vmar_destroy()`]: vmar_destroy.md |
| /// [`zx_vmar_protect()`]: vmar_protect.md |
| /// [`zx_vmar_unmap()`]: vmar_unmap.md |
| strict Map(resource struct { |
| handle Handle:VMAR; |
| options VmOption; |
| vmar_offset usize64; |
| vmo Handle:VMO; |
| vmo_offset uint64; |
| len usize64; |
| }) -> (struct { |
| mapped_addr Vaddr; |
| }) error Status; |
| |
| // TODO(https://fxbug.dev/42107929): handle No rights required? |
| /// ## Summary |
| /// |
| /// Unmap virtual memory pages. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vmar_unmap(zx_handle_t handle, zx_vaddr_t addr, size_t len); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vmar_unmap()` unmaps all VMO mappings and destroys (as if [`zx_vmar_destroy()`] |
| /// were called) all sub-regions within the absolute range including *addr* and ending |
| /// before exclusively at `addr + len`. Any sub-region that is in the range must |
| /// be fully in the range (i.e. partial overlaps are an error). If a mapping is |
| /// only partially in the range, the mapping is split and the requested portion is |
| /// unmapped. |
| /// |
| /// *len* must be page-aligned. |
| /// |
| /// ## Rights |
| /// |
| /// TODO(https://fxbug.dev/42107318) |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_unmap()` returns `ZX_OK` on success. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* is not a VMAR handle. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` *addr* is not page-aligned, *len* is 0 or not page-aligned, |
| /// or the requested range partially overlaps a sub-region, or the requested range overlapped |
| /// a sub-region and *handle* did not have `ZX_RIGHT_OP_CHILDREN`. |
| /// |
| /// `ZX_ERR_BAD_STATE` *handle* refers to a destroyed handle. |
| /// |
| /// `ZX_ERR_NOT_FOUND` Could not find the requested mapping. |
| /// |
| /// ## Notes |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_allocate()`] |
| /// - [`zx_vmar_destroy()`] |
| /// - [`zx_vmar_map()`] |
| /// - [`zx_vmar_protect()`] |
| /// |
| /// [`zx_vmar_allocate()`]: vmar_allocate.md |
| /// [`zx_vmar_destroy()`]: vmar_destroy.md |
| /// [`zx_vmar_map()`]: vmar_map.md |
| /// [`zx_vmar_protect()`]: vmar_protect.md |
| strict Unmap(resource struct { |
| handle Handle:VMAR; |
| addr Vaddr; |
| len usize64; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Set protection of virtual memory pages. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vmar_protect(zx_handle_t handle, |
| /// zx_vm_option_t options, |
| /// zx_vaddr_t addr, |
| /// size_t len); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vmar_protect()` alters the access protections for the memory mappings |
| /// in the range of *len* bytes starting from *addr*. The *options* argument should |
| /// be a bitwise-or of one or more of the following: |
| /// |
| /// - `ZX_VM_PERM_READ` Map as readable. It is an error if *handle* |
| /// does not have `ZX_VM_CAN_MAP_READ` permissions or *handle* does |
| /// not have the `ZX_RIGHT_READ` right. It is also an error if the VMO handle |
| /// used to create the mapping did not have the `ZX_RIGHT_READ` right. |
| /// - `ZX_VM_PERM_WRITE` Map as writable. It is an error if *handle* |
| /// does not have `ZX_VM_CAN_MAP_WRITE` permissions or *handle* does |
| /// not have the `ZX_RIGHT_WRITE` right. It is also an error if the VMO handle |
| /// used to create the mapping did not have the `ZX_RIGHT_WRITE` right. |
| /// - `ZX_VM_PERM_EXECUTE` Map as executable. It is an error if *handle* |
| /// does not have `ZX_VM_CAN_MAP_EXECUTE` permissions or *handle* does |
| /// not have the `ZX_RIGHT_EXECUTE` right. It is also an error if the VMO handle |
| /// used to create the mapping did not have the `ZX_RIGHT_EXECUTE` right. |
| /// - `ZX_VM_PERM_READ_IF_XOM_UNSUPPORTED` Map as readable if the system does |
| /// not support mapping execute-only pages. If the system can map execute-only |
| /// this flag is ignored. |
| /// |
| /// For any mappings in sub-regions in the requested range, their access permissions must either |
| /// be reduced, or left unchanged, by the requested change. |
| /// |
| /// *len* must be page-aligned. |
| /// |
| /// ## Rights |
| /// |
| /// If *options* & `ZX_VM_PERM_READ`, *handle* must be of type `ZX_OBJ_TYPE_VMAR` and have `ZX_RIGHT_READ`. |
| /// |
| /// If *options* & `ZX_VM_PERM_WRITE`, *handle* must be of type `ZX_OBJ_TYPE_VMAR` and have `ZX_RIGHT_WRITE`. |
| /// |
| /// If *options* & `ZX_VM_PERM_EXECUTE`, *handle* must be of type `ZX_OBJ_TYPE_VMAR` and have `ZX_RIGHT_EXECUTE`. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_protect()` returns `ZX_OK` on success. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* is not a VMAR handle. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` *prot_flags* is an unsupported combination of flags |
| /// (e.g., `ZX_VM_PERM_WRITE` but not `ZX_VM_PERM_READ`), *addr* is |
| /// not page-aligned, *len* is 0, or some subrange of the requested range is |
| /// occupied by a subregion and *handle* did not have `ZX_RIGHT_OP_CHILDREN`. |
| /// |
| /// `ZX_ERR_NOT_FOUND` Some subrange of the requested range is not mapped. |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` *handle* does not have the proper rights for the |
| /// requested change, the original VMO handle used to create the mapping did not |
| /// have the rights for the requested change, or the VMAR itself does not allow |
| /// the requested change, or there is a mapping in a sub-region that would have |
| /// its mapping permissions increased. |
| /// |
| /// `ZX_ERR_NO_MEMORY` Failure due to lack of memory. |
| /// There is no good way for userspace to handle this (unlikely) error. |
| /// In a future build this error will no longer occur. |
| /// |
| /// ## Notes |
| /// |
| /// For failures other than `ZX_ERR_NO_MEMORY`, all access permissions in the range |
| /// will have been left unchanged. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_allocate()`] |
| /// - [`zx_vmar_destroy()`] |
| /// - [`zx_vmar_map()`] |
| /// - [`zx_vmar_unmap()`] |
| /// |
| /// [`zx_vmar_allocate()`]: vmar_allocate.md |
| /// [`zx_vmar_destroy()`]: vmar_destroy.md |
| /// [`zx_vmar_map()`]: vmar_map.md |
| /// [`zx_vmar_unmap()`]: vmar_unmap.md |
| strict Protect(resource struct { |
| handle Handle:VMAR; |
| options VmOption; |
| addr Vaddr; |
| len usize64; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Perform an operation on VMOs mapped into this VMAR. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vmar_op_range(zx_handle_t handle, |
| /// uint32_t op, |
| /// zx_vaddr_t address, |
| /// size_t size, |
| /// void* buffer, |
| /// size_t buffer_size); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vmar_op_range()` performs operation *op* on VMOs mapped in the range *address* to |
| /// *address*+*size*. |
| /// |
| /// *address* and *size* must fall entirely within this VMAR, and must meet the alignment requirements |
| /// specified for the corresponding VMO *op* (if there is one) by [`zx_vmo_op_range()`]. |
| /// |
| /// *buffer* and *buffer_size* are currently unused, and must be empty. |
| /// |
| /// The supported operations are: |
| /// |
| /// `ZX_VMAR_OP_COMMIT` - Requires that *handle*, and the VMO handles used to create any affected |
| /// mappings, have the `ZX_RIGHT_WRITE` right and that the address range must not have any child VMARs. |
| /// The operation's semantics are otherwise as described by |
| /// [`zx_vmo_op_range()`](/reference/syscalls/vmo_op_range.md) `ZX_VMO_OP_COMMIT`. |
| /// |
| /// `ZX_VMO_OP_DECOMMIT` - Deprecated. Use `ZX_VMAR_OP_DECOMMIT` instead. |
| /// |
| /// `ZX_VMAR_OP_PREFETCH` - Requires that *handle*, and the VMO handles used to create any affected |
| /// mappings, have the `ZX_RIGHT_READ`. The operation's semantics are otherwise as described by |
| /// [`zx_vmo_op_range()`](/reference/syscalls/vmo_op_range.md) `ZX_VMO_OP_PREFETCH`. |
| /// |
| /// `ZX_VMAR_OP_DECOMMIT` - Requires that *handle*, and the VMO handles used to create any affected |
| /// mappings, have the `ZX_RIGHT_WRITE` right and that the address range must not have any child VMARs. |
| /// The operation's semantics are otherwise as described by |
| /// [`zx_vmo_op_range()`](/reference/syscalls/vmo_op_range.md) `ZX_VMO_OP_DECOMMIT`. |
| /// |
| /// `ZX_VMAR_OP_MAP_RANGE` - Populates entries in the CPU page tables (or architectural equivalent) |
| /// for committed pages in the given range. Entries for uncommitted pages in the range are not |
| /// populated. Skips entries that already exist for any page in the range. |
| /// |
| /// `ZX_VMAR_OP_DONT_NEED` - Hints that pages in the specified range are not needed anymore and should |
| /// be considered for memory reclamation. Intended to be used on mappings for VMOs created with |
| /// [`zx_pager_create_vmo()`](/reference/syscalls/pager_create_vmo.md); trivially succeeds for |
| /// mappings for other VMO types. |
| /// |
| /// Please refer to [`zx_vmo_op_range()`](/reference/syscalls/vmo_op_range.md) |
| /// `ZX_VMO_OP_DONT_NEED` for more details. |
| /// |
| /// `ZX_VMAR_OP_ALWAYS_NEED` - Hints that pages in the specified range are important and should be |
| /// protected from memory reclamation. Intended to be used on mappings for VMOs created with |
| /// [`zx_pager_create_vmo()`](/reference/syscalls/pager_create_vmo.md); trivially succeeds for |
| /// mappings for other VMO types. |
| /// |
| /// Please refer to [`zx_vmo_op_range()`](/reference/syscalls/vmo_op_range.md) |
| /// `ZX_VMO_OP_ALWAYS_NEED` for more details. |
| /// |
| /// ## Rights |
| /// |
| /// If *op* is `ZX_VMAR_OP_DECOMMIT`, *handle* must have `ZX_RIGHT_WRITE`. |
| /// |
| /// If *op* is `ZX_VMAR_OP_COMMIT`, *handle* must have `ZX_RIGHT_WRITE`. |
| /// |
| /// If *op* is `ZX_VMAR_OP_PREFETCH`, *handle* must have `ZX_RIGHT_READ`. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_op_range()` returns `ZX_OK` on success. In the event of failure, a negative error value |
| /// is returned. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` *handle* does not have the proper rights for the requested change, or the |
| /// original VMO handle used to created one of the affected mappings did not have the rights for the |
| /// requested change, or the VMAR itself did not allow the requested change. |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* is not a valid handle. |
| /// |
| /// `ZX_ERR_BAD_STATE` *handle* is not a live VMAR, or the range specified by *address* and *size* |
| /// spans unmapped regions. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` Returned for any of the following reasons: |
| /// |
| /// - *buffer* is non-null. |
| /// - *buffer_size* is non-zero. |
| /// - *size* is zero. |
| /// - *address* was not page-aligned. |
| /// - *op* is not a valid operation. |
| /// - *op* was one of `ZX_VMAR_OP_COMMIT` or `ZX_VMAR_OP_DECOMMIT` and the requested range |
| /// had subregions. |
| /// - the requested range overlapped a sub-region and *handle* did not have |
| /// `ZX_RIGHT_OP_CHILDREN`. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` *op* was not `ZX_VMO_OP_DECOMMIT`, or one or more mapped VMOs do not |
| /// support the requested *op*. |
| /// |
| /// `ZX_ERR_OUT_OF_RANGE` The range specified by *address* and *size* is not wholly within the VM |
| /// address range specified by *handle*, or any VMOs mapped in this range are resized down such |
| /// that access in the specified range should generate a fault. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* is not a VMAR handle. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_map()`] |
| /// - [`zx_vmar_unmap()`] |
| /// - [`zx_vmo_op_range()`] |
| /// |
| /// [`zx_pager_create_vmo()`]: pager_create_vmo.md |
| /// [`zx_vmar_map()`]: vmar_map.md |
| /// [`zx_vmar_unmap()`]: vmar_unmap.md |
| /// [`zx_vmo_op_range()`]: vmo_op_range.md |
| strict OpRange(resource struct { |
| handle Handle:VMAR; |
| op uint32; |
| address Vaddr; |
| size usize64; |
| @inout |
| @voidptr |
| buffer vector<byte>:MAX; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Map the memory regions attached to an IOBuffer. This call has |
| /// similar semantics to `zx_vmar_map`, however, mapping subsets of regions |
| /// is not supported. |
| /// |
| /// ## Declaration |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vmar_map_iob(zx_handle_t handle, |
| /// zx_vm_option_t options, |
| /// size_t vmar_offset, |
| /// zx_handle_t iob_ep, |
| /// uint32_t region_index, |
| /// size_t region_len, |
| /// zx_vaddr_t* addr_out); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// Maps the given IOBuffer region into the given virtual memory |
| /// address region. Mapping a region retains a reference to the mapped |
| /// region, which means closing the endpoint that mapped the region does not |
| /// remove the mapping added by this function. |
| /// |
| /// *options* is equivalent to the *options* parameter of `zx_vmar_map` |
| /// |
| /// *vmar_offset* is equivalent to the *vmar_offset* parameter of `zx_vmar_map`. |
| /// |
| /// *ep* is the endpoint containing the region to map as created in |
| /// `zx_iob_create`. |
| /// |
| /// *region_index* is the index of the memory region to map. |
| /// |
| /// *region_offset* is equivalent to the *vmo_offset* parameter of `zx_vmar_map`. |
| /// |
| /// *region_len* is equivalent to the *len* parameter of `zx_vmar_map`. It |
| /// must by non-zero and page-aligned |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vmar_map_iob()` returns `ZX_OK` and the absolute base address of the |
| /// mapping (via *addr_out*) on success. The base address will be page-aligned |
| /// and non-zero. In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// `ZX_ERR_BAD_HANDLE` *handle* or *iob_ep* is not a valid handle. |
| /// |
| /// `ZX_ERR_WRONG_TYPE` *handle* or *iob_ep* is not a VMAR or IOB handle, respectively. |
| /// |
| /// `ZX_ERR_BAD_STATE` *handle* refers to a destroyed VMAR. |
| /// |
| /// `ZX_ERR_INVALID_ARGS` for any of the following: |
| /// - *mapped_addr* or *options* is not valid. |
| /// - *vmar_offset* is non-zero when none of `ZX_VM_SPECIFIC`, `ZX_VM_SPECIFIC_OVERWRITE` or |
| /// `ZX_VM_OFFSET_IS_UPPER_LIMIT` is specified. |
| /// - `ZX_VM_SPECIFIC_OVERWRITE` and `ZX_VM_MAP_RANGE` are both specified. |
| /// - `ZX_VM_OFFSET_IS_UPPER_LIMIT` is specified together with either `ZX_VM_SPECIFIC` |
| /// or `ZX_VM_SPECIFIC_OVERWRITE`. |
| /// - *vmar_offset* and *len* describe an unsatisfiable allocation due to exceeding the region bounds. |
| /// - *vmar_offset* or *region_offset* is not page-aligned. |
| /// - *region_len* is 0 or not page-aligned. |
| /// |
| /// `ZX_ERR_ALREADY_EXISTS` `ZX_VM_SPECIFIC` has been specified without |
| /// `ZX_VM_SPECIFIC_OVERWRITE`, and the requested range overlaps with another mapping. |
| /// |
| /// `ZX_ERR_NO_RESOURCES` If a spot could not be found in the VMAR to create the mapping. |
| /// |
| /// `ZX_ERR_ACCESS_DENIED` Insufficient privileges to make the requested mapping. |
| /// |
| /// `ZX_ERR_NOT_SUPPORTED` If the region is resizable, discardable, or backed by a pager but |
| /// `ZX_VM_ALLOW_FAULTS` is not set. |
| /// |
| /// `ZX_ERR_BUFFER_TOO_SMALL` The region is not resizable and the mapping extends past the end |
| /// of the region but `ZX_VM_ALLOW_FAULTS` is not set. |
| /// |
| /// `ZX_ERR_NO_MEMORY` Failure due to lack of memory. |
| /// There is no good way for userspace to handle this (unlikely) error. |
| /// In a future build this error will no longer occur. |
| /// |
| /// `ZX_ERR_OUT_OF_RANGE` for any of the following: |
| /// - `region_offset + ROUNDUP(len, PAGE_SIZE)` overflows. |
| /// - *region_index* is not valid for the provided IOB |
| /// |
| /// |
| /// ## Notes |
| /// |
| /// ### VMAR Operations |
| /// |
| /// Mapped regions generally support VMAR operations, such as `zx_vmar_protect`, |
| /// `zx_vmar_op_range`, `zx_vmar_destroy`. A region's access discipline may modify |
| /// or restrict these operations as described in the discipline spec. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_vmar_map()`] |
| /// - [`zx_iob_create()`] |
| /// |
| /// [`zx_iob_create()`]: iob_create.md |
| /// [`zx_vmar_map()`]: vmar_map.md |
| strict MapIob(resource struct { |
| handle Handle:VMAR; |
| options VmOption; |
| vmar_offset usize64; |
| ep Handle; |
| region_index uint32; |
| region_offset uint64; |
| region_length usize64; |
| }) -> (resource struct { |
| mapped_addr Vaddr; |
| }) error Status; |
| }; |