blob: 736b87088081937ccfda759adf8bc312df588e40 [file]
// Copyright 2026 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
use super::port_dispatcher::PortDispatcher;
use crate::vm::vm_address_region::VmAddressRegion;
use fbl::{RefPtr, UniquePtr};
use zx_status::Status;
use zx_types::{zx_status_t, zx_vaddr_t};
unsafe extern "C" {
fn cpp_guest_create(guest_out: *mut *mut Guest) -> zx_status_t;
fn cpp_guest_root_vmar(guest: *const Guest) -> *mut VmAddressRegion;
fn cpp_guest_destroy(guest: *mut Guest);
fn cpp_guest_set_trap(
guest: *mut Guest,
kind: u32,
addr: zx_vaddr_t,
len: usize,
port: *mut PortDispatcher,
key: u64,
) -> zx_status_t;
}
fbl::impl_opaque_unique_facade!(
/// Facade for the C++ `Guest` class.
pub struct Guest,
cpp_guest_destroy,
);
impl Guest {
/// Returns a raw pointer to this `Guest` for FFI calls.
#[inline]
pub fn as_ffi(&self) -> *const Self {
self as *const Self
}
/// Returns a mutable raw pointer to this `Guest` for FFI calls.
#[inline]
pub fn as_ffi_mut(&self) -> *mut Self {
self as *const Self as *mut Self
}
/// Creates a new `Guest` instance.
pub fn create() -> Result<UniquePtr<Self>, Status> {
let mut guest_raw = core::ptr::null_mut();
// SAFETY: `guest_raw` is a valid out-pointer to receive the created `Guest*` on `ZX_OK`.
let status = unsafe { cpp_guest_create(&mut guest_raw) };
Status::ok(status)?;
// SAFETY: `cpp_guest_create` succeeded and returned a non-null owning `Guest*` released
// from `ktl::unique_ptr<Guest>`.
Ok(unsafe { UniquePtr::from_raw(guest_raw) })
}
/// Returns the root `VmAddressRegion` of the guest physical address space.
pub fn root_vmar(&self) -> RefPtr<VmAddressRegion> {
// SAFETY: `self.as_ffi()` is a valid `Guest` pointer, and `cpp_guest_root_vmar` returns
// a non-null `VmAddressRegion*` exported via `fbl::ExportToRawPtr`.
unsafe { RefPtr::from_raw(cpp_guest_root_vmar(self.as_ffi())) }
}
/// Sets a trap on the guest within the specified address range.
pub fn set_trap(
&self,
kind: u32,
addr: zx_vaddr_t,
len: usize,
port: Option<RefPtr<PortDispatcher>>,
key: u64,
) -> Result<(), Status> {
let port_raw = port.map_or(core::ptr::null_mut(), |p| RefPtr::into_raw(p).cast_mut());
// SAFETY: `self.as_ffi_mut()` is a valid `Guest` pointer for the lifetime of `self`, and
// `port_raw` is either null or a valid raw `PortDispatcher` pointer carrying an owned
// reference that `cpp_guest_set_trap` adopts via `fbl::ImportFromRawPtr`.
let status =
unsafe { cpp_guest_set_trap(self.as_ffi_mut(), kind, addr, len, port_raw, key) };
Status::ok(status)
}
}