| // 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") |
| protocol Vcpu { |
| /// ## Summary |
| /// |
| /// Create a VCPU. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vcpu_create(zx_handle_t guest, |
| /// uint32_t options, |
| /// zx_vaddr_t entry, |
| /// zx_handle_t* out); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vcpu_create()` creates a VCPU within a guest, which allows for execution |
| /// within the virtual machine. One or more VCPUs may be created per guest, where |
| /// the number of VCPUs does not need to match the number of physical CPUs on the |
| /// machine. |
| /// |
| /// *entry* is the instruction pointer used to indicate where in guest physical |
| /// memory execution of the VCPU should start. |
| /// |
| /// *out* is bound to the thread that created it, and all syscalls that operate on |
| /// it must be called from the same thread, with the exception of |
| /// [`zx_vcpu_interrupt()`]. |
| /// |
| /// Only one VCPU may exist on a thread at a time. A thread can create another VCPU |
| /// after it has closed the existing one. |
| /// |
| /// N.B. VCPU is an abbreviation of virtual CPU. |
| /// |
| /// The following rights will be set on the handle *out* by default: |
| /// |
| /// **ZX_RIGHT_DUPLICATE** — *out* may be duplicated. |
| /// |
| /// **ZX_RIGHT_TRANSFER** — *out* may be transferred over a channel. |
| /// |
| /// **ZX_RIGHT_EXECUTE** — *out* may have its execution resumed (or begun) |
| /// |
| /// **ZX_RIGHT_SIGNAL** — *out* may be interrupted |
| /// |
| /// **ZX_RIGHT_READ** — *out* may have its state read |
| /// |
| /// **ZX_RIGHT_WRITE** — may have its state written |
| /// |
| /// ## Rights |
| /// |
| /// *guest* must be of type **ZX_OBJ_TYPE_GUEST** and have **ZX_RIGHT_MANAGE_THREAD**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vcpu_create()` returns **ZX_OK** on success. On failure, an error value is |
| /// returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *guest* does not have the **ZX_RIGHT_MANAGE_THREAD** |
| /// right. |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *guest* is an invalid handle. |
| /// |
| /// **ZX_ERR_BAD_STATE** The thread currently has a VCPU. Only one VCPU can be |
| /// active on a thread at a time. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *args* contains an invalid argument, or *out* is an |
| /// invalid pointer, or *options* is nonzero. |
| /// |
| /// **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_WRONG_TYPE** *guest* is not a handle to a guest. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_guest_create()`] |
| /// - [`zx_guest_set_trap()`] |
| /// - [`zx_vcpu_enter()`] |
| /// - [`zx_vcpu_interrupt()`] |
| /// - [`zx_vcpu_kick()`] |
| /// - [`zx_vcpu_read_state()`] |
| /// - [`zx_vcpu_write_state()`] |
| /// |
| /// [`zx_guest_create()`]: guest_create.md |
| /// [`zx_guest_set_trap()`]: guest_set_trap.md |
| /// [`zx_vcpu_enter()`]: vcpu_enter.md |
| /// [`zx_vcpu_interrupt()`]: vcpu_interrupt.md |
| /// [`zx_vcpu_kick()`]: vcpu_kick.md |
| /// [`zx_vcpu_read_state()`]: vcpu_read_state.md |
| /// [`zx_vcpu_write_state()`]: vcpu_write_state.md |
| Create(resource struct { |
| guest Handle:GUEST; |
| options uint32; |
| entry Vaddr; |
| }) -> (resource struct { |
| out Handle:VCPU; |
| }) error Status; |
| |
| // See port.fidl for definition of PortPacket. |
| /// ## Summary |
| /// |
| /// Enter a VCPU, causing it to resume execution. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// #include <zircon/syscalls/port.h> |
| /// |
| /// zx_status_t zx_vcpu_enter(zx_handle_t handle, zx_port_packet_t* packet); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vcpu_enter()` begins or resumes execution of *handle*, and blocks until it |
| /// has paused execution. On pause of execution, *packet* is populated with reason |
| /// for the pause. After handling the reason, execution may be resumed by calling |
| /// `zx_vcpu_enter()` again. |
| /// |
| /// If `zx_vcpu_enter()` returns **ZX_ERR_CANCELED** due to `zx_vcpu_kick()` being |
| /// called on *handle*, execution may be resumed by calling `zx_vcpu_enter()` again. |
| /// |
| /// `zx_vcpu_enter()` must be called on the same thread *handle* was created on. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_VCPU** and have **ZX_RIGHT_EXECUTE**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vcpu_enter()` returns **ZX_OK** on success. On failure, an error value is |
| /// returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* does not have the **ZX_RIGHT_EXECUTE** right. |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is an invalid handle. |
| /// |
| /// **ZX_ERR_BAD_STATE** *handle* is in a bad state, and can not be executed. |
| /// |
| /// **ZX_ERR_CANCELED** execution of *handle* was canceled, due to `zx_vcpu_kick()` |
| /// being called on *handle*. |
| /// |
| /// **ZX_ERR_INTERNAL** There was an error executing *handle*. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *packet* is an invalid pointer. |
| /// |
| /// **ZX_ERR_NOT_SUPPORTED** An unsupported operation was encountered while |
| /// executing *handle*. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not a handle to a VCPU. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_guest_create()`] |
| /// - [`zx_guest_set_trap()`] |
| /// - [`zx_vcpu_create()`] |
| /// - [`zx_vcpu_interrupt()`] |
| /// - [`zx_vcpu_kick()`] |
| /// - [`zx_vcpu_read_state()`] |
| /// - [`zx_vcpu_write_state()`] |
| /// |
| /// [`zx_guest_create()`]: guest_create.md |
| /// [`zx_guest_set_trap()`]: guest_set_trap.md |
| /// [`zx_vcpu_create()`]: vcpu_create.md |
| /// [`zx_vcpu_interrupt()`]: vcpu_interrupt.md |
| /// [`zx_vcpu_kick()`]: vcpu_kick.md |
| /// [`zx_vcpu_read_state()`]: vcpu_read_state.md |
| /// [`zx_vcpu_write_state()`]: vcpu_write_state.md |
| @blocking |
| Enter(resource struct { |
| handle Handle:VCPU; |
| }) -> (struct { |
| packet PortPacket; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Kick a VCPU, causing it to stop execution. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vcpu_kick(zx_handle_t handle); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vcpu_kick()` forces the current or next execution of `zx_vcpu_enter()` on |
| /// *handle* to return immediately with **ZX_ERR_CANCELED**. |
| /// |
| /// `zx_vcpu_kick()` may be called multiple times on *handle*, but will only affect |
| /// the current or next execution of `zx_vcpu_enter()`. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_VCPU** and have **ZX_RIGHT_EXECUTE**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vcpu_kick()` returns **ZX_OK** on success. On failure, an error value is |
| /// returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* does not have the **ZX_RIGHT_EXECUTE** right. |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is an invalid handle. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not a handle to a VCPU. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_guest_create()`] |
| /// - [`zx_guest_set_trap()`] |
| /// - [`zx_vcpu_create()`] |
| /// - [`zx_vcpu_enter()`] |
| /// - [`zx_vcpu_interrupt()`] |
| /// - [`zx_vcpu_read_state()`] |
| /// - [`zx_vcpu_write_state()`] |
| /// |
| /// [`zx_guest_create()`]: guest_create.md |
| /// [`zx_guest_set_trap()`]: guest_set_trap.md |
| /// [`zx_vcpu_create()`]: vcpu_create.md |
| /// [`zx_vcpu_enter()`]: vcpu_enter.md |
| /// [`zx_vcpu_interrupt()`]: vcpu_interrupt.md |
| /// [`zx_vcpu_read_state()`]: vcpu_read_state.md |
| /// [`zx_vcpu_write_state()`]: vcpu_write_state.md |
| Kick(resource struct { |
| handle Handle:VCPU; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Raise an interrupt on a VCPU. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vcpu_interrupt(zx_handle_t handle, uint32_t vector); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vcpu_interrupt()` raises an interrupt of *vector* on *handle*, and may be |
| /// called from any thread. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_VCPU** and have **ZX_RIGHT_SIGNAL**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vcpu_interrupt()` returns **ZX_OK** on success. On failure, an error value is |
| /// returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* does not have the **ZX_RIGHT_SIGNAL** right. |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is an invalid handle. |
| /// |
| /// **ZX_ERR_OUT_OF_RANGE** *vector* is outside of the range interrupts supported by |
| /// the current architecture. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not a handle to a VCPU. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_guest_create()`] |
| /// - [`zx_guest_set_trap()`] |
| /// - [`zx_vcpu_create()`] |
| /// - [`zx_vcpu_enter()`] |
| /// - [`zx_vcpu_kick()`] |
| /// - [`zx_vcpu_read_state()`] |
| /// - [`zx_vcpu_write_state()`] |
| /// |
| /// [`zx_guest_create()`]: guest_create.md |
| /// [`zx_guest_set_trap()`]: guest_set_trap.md |
| /// [`zx_vcpu_create()`]: vcpu_create.md |
| /// [`zx_vcpu_enter()`]: vcpu_enter.md |
| /// [`zx_vcpu_kick()`]: vcpu_kick.md |
| /// [`zx_vcpu_read_state()`]: vcpu_read_state.md |
| /// [`zx_vcpu_write_state()`]: vcpu_write_state.md |
| Interrupt(resource struct { |
| handle Handle:VCPU; |
| vector uint32; |
| }) -> () error Status; |
| |
| /// ## Summary |
| /// |
| /// Read the state of a VCPU. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vcpu_read_state(zx_handle_t handle, |
| /// uint32_t kind, |
| /// void* buffer, |
| /// size_t buffer_size); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vcpu_read_state()` reads the state of *handle* as specified by *kind* into |
| /// *buffer*. It is only valid to read the state of *handle* when execution has been |
| /// paused. |
| /// |
| /// *kind* must be **ZX_VCPU_STATE**. |
| /// |
| /// `zx_vcpu_read_state()` must be called on the same thread *handle* was created |
| /// on. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_VCPU** and have **ZX_RIGHT_READ**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vcpu_read_state()` returns **ZX_OK** on success. On failure, an error value |
| /// is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* does not have the **ZX_RIGHT_READ** right. |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is an invalid handle. |
| /// |
| /// **ZX_ERR_BAD_STATE** *handle* is in a bad state, and state can not be read. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *kind* does not name a known VCPU state, *buffer* is an |
| /// invalid pointer, or *buffer_size* does not match the expected size of *kind*. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not a handle to a VCPU. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_guest_create()`] |
| /// - [`zx_guest_set_trap()`] |
| /// - [`zx_vcpu_create()`] |
| /// - [`zx_vcpu_enter()`] |
| /// - [`zx_vcpu_interrupt()`] |
| /// - [`zx_vcpu_kick()`] |
| /// - [`zx_vcpu_write_state()`] |
| /// |
| /// [`zx_guest_create()`]: guest_create.md |
| /// [`zx_guest_set_trap()`]: guest_set_trap.md |
| /// [`zx_vcpu_create()`]: vcpu_create.md |
| /// [`zx_vcpu_enter()`]: vcpu_enter.md |
| /// [`zx_vcpu_interrupt()`]: vcpu_interrupt.md |
| /// [`zx_vcpu_kick()`]: vcpu_kick.md |
| /// [`zx_vcpu_write_state()`]: vcpu_write_state.md |
| ReadState(resource struct { |
| handle Handle:VCPU; |
| kind uint32; |
| }) -> (struct { |
| @voidptr |
| buffer vector<byte>:MAX; |
| }) error Status; |
| |
| /// ## Summary |
| /// |
| /// Write the state of a VCPU. |
| /// |
| /// ## Declaration |
| /// |
| /// ```c |
| /// #include <zircon/syscalls.h> |
| /// |
| /// zx_status_t zx_vcpu_write_state(zx_handle_t handle, |
| /// uint32_t kind, |
| /// const void* buffer, |
| /// size_t buffer_size); |
| /// ``` |
| /// |
| /// ## Description |
| /// |
| /// `zx_vcpu_write_state()` writes the state of *handle* as specified by *kind* from |
| /// *buffer*. It is only valid to write the state of *handle* when execution has |
| /// been paused. |
| /// |
| /// *kind* may be **ZX_VCPU_STATE** or **ZX_VCPU_IO**. |
| /// |
| /// `zx_vcpu_write_state()` must be called on the same thread *handle* was created |
| /// on. |
| /// |
| /// ## Rights |
| /// |
| /// *handle* must be of type **ZX_OBJ_TYPE_VCPU** and have **ZX_RIGHT_WRITE**. |
| /// |
| /// ## Return value |
| /// |
| /// `zx_vcpu_write_state()` returns **ZX_OK** on success. On failure, an error value |
| /// is returned. |
| /// |
| /// ## Errors |
| /// |
| /// **ZX_ERR_ACCESS_DENIED** *handle* does not have the **ZX_RIGHT_WRITE** right. |
| /// |
| /// **ZX_ERR_BAD_HANDLE** *handle* is an invalid handle. |
| /// |
| /// **ZX_ERR_BAD_STATE** *handle* is in a bad state, and state can not be written. |
| /// |
| /// **ZX_ERR_INVALID_ARGS** *kind* does not name a known VCPU state, *buffer* is an |
| /// invalid pointer, or *buffer_size* does not match the expected size of *kind*. |
| /// |
| /// **ZX_ERR_WRONG_TYPE** *handle* is not a handle to a VCPU. |
| /// |
| /// ## See also |
| /// |
| /// - [`zx_guest_create()`] |
| /// - [`zx_guest_set_trap()`] |
| /// - [`zx_vcpu_create()`] |
| /// - [`zx_vcpu_enter()`] |
| /// - [`zx_vcpu_interrupt()`] |
| /// - [`zx_vcpu_kick()`] |
| /// - [`zx_vcpu_read_state()`] |
| /// |
| /// [`zx_guest_create()`]: guest_create.md |
| /// [`zx_guest_set_trap()`]: guest_set_trap.md |
| /// [`zx_vcpu_create()`]: vcpu_create.md |
| /// [`zx_vcpu_enter()`]: vcpu_enter.md |
| /// [`zx_vcpu_interrupt()`]: vcpu_interrupt.md |
| /// [`zx_vcpu_kick()`]: vcpu_kick.md |
| /// [`zx_vcpu_read_state()`]: vcpu_read_state.md |
| WriteState(resource struct { |
| handle Handle:VCPU; |
| kind uint32; |
| @voidptr |
| buffer vector<byte>:MAX; |
| }) -> () error Status; |
| }; |