blob: ef9e724194bc229fd408ccfd4546c28ade2f77c0 [file] [log] [blame] [view]
<!--
Copyright 2023 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.
DO NOT EDIT. Generated from FIDL library zx by zither, a Fuchsia platform tool.
See //docs/reference/syscalls/README.md#documentation-generation for
regeneration instructions.
-->
# zx_vmar_map
## 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_base + *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
`ZX_VM_FAULT_BEYOND_STREAM_SIZE` is set, 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.
- `ZX_VM_FAULT_BEYOND_STREAM_SIZE` Memory accesses beyond the stream size rounded up to the page
boundary will fault. Requires `ZX_VM_ALLOW_FAULTS`.
*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 will be internally rounded up to be 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.
`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. Or,
`ZX_VM_FAULT_BEYOND_STREAM_SIZE` is set and *vmo* is physical or contiguous.
`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