| // 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; |
| |
| @transport("Syscall") |
| closed protocol Bti { |
| // TODO(fxbug.dev/32803): This is an unusual rights spec. |
| /// ## Summary |
| /// |
| /// Create a new bus transaction initiator. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_bti_create(zx_handle_t iommu, |
| /// uint32_t options, |
| /// uint64_t bti_id, |
| /// zx_handle_t* out); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_bti_create()` creates a new [bus transaction initiator](/docs/reference/kernel_objects/bus_transaction_initiator.md) |
| /// given a handle to an IOMMU and a hardware transaction identifier for a device |
| /// downstream of that IOMMU. |
| /// |
| /// *options* must be 0 (reserved for future definition of creation flags). |
| /// |
| /// Upon success a handle for the new BTI is returned. This handle will have rights |
| /// **ZX_RIGHT_READ**, **ZX_RIGHT_WRITE**, **ZX_RIGHT_MAP**, **ZX_RIGHT_INSPECT**, |
| /// **ZX_RIGHT_DUPLICATE**, and **ZX_RIGHT_TRANSFER**. |
| /// |
| /// ## Rights |
| /// |
| /// *iommu* must be of type **ZX_OBJ_TYPE_IOMMU** and have **ZX_RIGHT_NONE**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_bti_create()` returns **ZX_OK** and a handle to the new BTI |
| /// (via *out*) on success. In the event of failure, a negative error value |
| /// is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *iommu* is not a valid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *iommu* is not an iommu handle. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *iommu* handle does not have sufficient privileges. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *bti_id* is invalid on the given IOMMU, |
| /// *out* is an invalid pointer, or *options* is non-zero. |
| /// |
| /// **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. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_bti_pin()`] |
| /// - [`zx_bti_release_quarantine()`] |
| /// - [`zx_pmt_unpin()`] |
| /// |
| /// [`zx_bti_pin()`]: bti_pin.md |
| /// [`zx_bti_release_quarantine()`]: bti_release_quarantine.md |
| /// [`zx_pmt_unpin()`]: pmt_unpin.md |
| strict Create(resource struct { |
| iommu Handle:IOMMU; |
| options uint32; |
| bti_id uint64; |
| }) -> (resource struct { |
| out Handle:BTI; |
| }) error Status; |
| |
| // READ is intentional in the EXECUTE condition. |
| /// ## Summary |
| /// |
| /// Pin pages and grant devices access to them. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_bti_pin(zx_handle_t handle, |
| /// uint32_t options, |
| /// zx_handle_t vmo, |
| /// uint64_t offset, |
| /// uint64_t size, |
| /// zx_paddr_t* addrs, |
| /// size_t num_addrs, |
| /// zx_handle_t* pmt); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_bti_pin()` pins pages of a VMO (i.e. prevents them from being decommitted |
| /// with [`zx_vmo_op_range()`]) and grants the hardware |
| /// transaction ID represented by the BTI the ability to access these pages, |
| /// with the permissions specified in *options*. |
| /// |
| /// *offset* must be aligned to page boundaries. |
| /// |
| /// *options* is a bitfield that may contain one or more of **ZX_BTI_PERM_READ**, |
| /// **ZX_BTI_PERM_WRITE**, **ZX_BTI_PERM_EXECUTE**, **ZX_BTI_COMPRESS**, and |
| /// **ZX_BTI_CONTIGUOUS**. In order for the call to succeed, *vmo* must have the |
| /// READ/WRITE rights corresponding to the permissions flags set in *options*. |
| /// (Note: **ZX_BTI_PERM_EXECUTE** requires **ZX_RIGHT_READ**, not **ZX_RIGHT_EXECUTE**.) |
| /// **ZX_BTI_CONTIGUOUS** is only allowed if *vmo* was allocated via |
| /// [`zx_vmo_create_contiguous()`] or [`zx_vmo_create_physical()`]. |
| /// **ZX_BTI_COMPRESS** and **ZX_BTI_CONTIGUOUS** are mutually exclusive. |
| /// |
| /// If the range in *vmo* specified by *offset* and *size* contains non-committed |
| /// pages, a successful invocation of this function will result in those pages |
| /// having been committed. On failure, it is undefined whether they have been |
| /// committed. |
| /// |
| /// *addrs* will be populated with the device-physical addresses of the requested |
| /// VMO pages. These addresses may be given to devices that issue memory |
| /// transactions with the hardware transaction ID associated with the BTI. The |
| /// number of addresses returned depends on whether the **ZX_BTI_COMPRESS** or |
| /// **ZX_BTI_CONTIGUOUS** options were given. The number of addresses will be one |
| /// of three possibilities: |
| /// |
| /// 1. If neither is set, one per page (`size / PAGE_SIZE`). |
| /// 2. If **ZX_BTI_COMPRESS** is set, `size / minimum-contiguity`, rounded up |
| /// (each address representing a run of *minimum-contiguity* run of bytes, |
| /// with the last one being potentially short if *size* is not a multiple of |
| /// *minimum-contiguity*). It is guaranteed that all returned addresses will be |
| /// *minimum-contiguity*-aligned. Note that *minimum-contiguity* is discoverable |
| /// via [`zx_object_get_info()`]. |
| /// 3. If **ZX_BTI_CONTIGUOUS** is set, the single address of the start of the memory. |
| /// |
| /// *num_addrs* is the number of entries in the *addrs* array. It is an error for |
| /// *num_addrs* to not match the value calculated above. |
| /// |
| /// The PMT retains a reference to the associated VMO, so the underlying VMO won't be |
| /// destroyed until the PMT is unpinned. |
| /// |
| /// Resizable VMOs can be pinned. If a call to [`zx_vmo_set_size()`] would discard |
| /// pinned pages, that call will fail. |
| /// |
| /// ## Options |
| /// |
| /// - **ZX_BTI_PERM_READ**, **ZX_BTI_PERM_WRITE**, and **ZX_BTI_PERM_EXECUTE** define |
| /// the access types that the hardware bus transaction initiator will be allowed |
| /// to use. |
| /// - **ZX_BTI_COMPRESS** causes the returned address list to contain one entry per |
| /// block of *minimum-contiguity* bytes, rather than one per *PAGE_SIZE*. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_BTI** and have **ZX_RIGHT_MAP**. |
| /// |
| /// *vmo* must be of type **ZX_OBJ_TYPE_VMO** and have **ZX_RIGHT_MAP**. |
| /// |
| /// If *options* & **ZX_BTI_PERM_READ**, *vmo* must be of type **ZX_OBJ_TYPE_VMO** and have **ZX_RIGHT_READ**. |
| /// |
| /// If *options* & **ZX_BTI_PERM_WRITE**, *vmo* must be of type **ZX_OBJ_TYPE_VMO** and have **ZX_RIGHT_WRITE**. |
| /// |
| /// If *options* & **ZX_BTI_PERM_EXECUTE**, *vmo* must be of type **ZX_OBJ_TYPE_VMO** and have **ZX_RIGHT_READ**. |
| /// |
| /// ## Return value |
| /// |
| /// On success, `zx_bti_pin()` returns **ZX_OK**. The device-physical addresses of the |
| /// requested VMO pages will be written in *addrs*. A handle to the created Pinned |
| /// Memory Token is returned via *pmt*. When the PMT is no longer needed, |
| /// [`zx_pmt_unpin()`] should be invoked. |
| /// |
| /// 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* is not a BTI handle or *vmo* is not a VMO |
| /// handle. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* or *vmo* does not have the **ZX_RIGHT_MAP**, |
| /// or *options* contained a permissions flag corresponding to a right that *vmo* |
| /// does not have. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *options* is 0 or contains an undefined flag, either |
| /// *addrs* or *pmt* is not a valid pointer, *num_addrs* is not the same as the |
| /// number of entries that would be returned, or *offset* or *size* is not |
| /// page-aligned. |
| /// |
| /// **ZX_ERR_OUT_OF_RANGE** `offset + size` is out of the bounds of *vmo*. |
| /// |
| /// **ZX_ERR_UNAVAILABLE** (Temporary) At least one page in the requested range |
| /// could not be pinned at this time. |
| /// |
| /// **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. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_bti_create()`] |
| /// - [`zx_object_get_info()`] |
| /// - [`zx_pmt_unpin()`] |
| /// |
| /// [`zx_bti_create()`]: bti_create.md |
| /// [`zx_object_get_info()`]: object_get_info.md |
| /// [`zx_pmt_unpin()`]: pmt_unpin.md |
| /// [`zx_vmo_create_contiguous()`]: vmo_create_contiguous.md |
| /// [`zx_vmo_create_physical()`]: vmo_create_physical.md |
| /// [`zx_vmo_op_range()`]: vmo_op_range.md |
| /// [`zx_vmo_set_size()`]: vmo_set_size.md |
| strict Pin(resource struct { |
| handle Handle:BTI; |
| options uint32; |
| vmo Handle:VMO; |
| offset uint64; |
| size uint64; |
| }) -> (resource struct { |
| @embedded_alias("zx/Paddr") |
| addrs vector<Paddr>:MAX; |
| pmt Handle:PMT; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Releases all quarantined PMTs. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_bti_release_quarantine(zx_handle_t handle); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_bti_release_quarantine()` releases all quarantined PMTs for the given BTI. |
| /// This will release the PMTs' underlying references to VMOs and physical page |
| /// pins. The underlying physical pages may be eligible to be reallocated |
| /// afterwards. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_BTI** and have **ZX_RIGHT_WRITE**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_bti_release_quarantine()` returns **ZX_OK** on success. |
| /// In the event of failure, a negative error value is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is not a valid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not a BTI handle. |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* does not have the **ZX_RIGHT_WRITE** right. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_bti_pin()`] |
| /// - [`zx_pmt_unpin()`] |
| /// |
| /// [`zx_bti_pin()`]: bti_pin.md |
| /// [`zx_pmt_unpin()`]: pmt_unpin.md |
| strict ReleaseQuarantine(resource struct { |
| handle Handle:BTI; |
| }) -> () error Status; |
| }; |