zx/
iommu.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Type-safe bindings for Zircon iommu objects.
6
7use crate::{AsHandleRef, Handle, HandleBased, HandleRef, Resource, Status, ok, sys};
8
9/// An object representing a Zircon iommu
10///
11/// As essentially a subtype of `Handle`, it can be freely interconverted.
12#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
13#[repr(transparent)]
14pub struct Iommu(Handle);
15impl_handle_based!(Iommu);
16
17// ABI-compatible with zx_iommu_desc_stub_t.
18#[repr(C)]
19#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
20pub struct IommuDescStub {
21    padding1: u8,
22}
23
24// TODO(b/459887557): Remove this alias when this name is ready to be completely retired.
25pub type IommuDescDummy = IommuDescStub;
26
27impl Iommu {
28    // Create an iommu object.
29    //
30    // Wraps the
31    // [`zx_iommu_create`](https://fuchsia.dev/fuchsia-src/reference/syscalls/iommu_create) system call to create an iommu with type `ZX_IOMMU_TYPE_STUB`
32    pub fn create_stub(resource: &Resource, desc: IommuDescStub) -> Result<Iommu, Status> {
33        let mut iommu_handle = sys::zx_handle_t::default();
34        let status = unsafe {
35            // SAFETY:
36            //  * desc parameter is a valid pointer (desc).
37            //  * desc_size parameter is the size of desc.
38            sys::zx_iommu_create(
39                resource.raw_handle(),
40                sys::ZX_IOMMU_TYPE_STUB,
41                std::ptr::from_ref(&desc).cast::<u8>(),
42                std::mem::size_of_val(&desc),
43                &mut iommu_handle,
44            )
45        };
46        ok(status)?;
47        unsafe {
48            // SAFETY: The syscall docs claim that upon success, iommu_handle will be a valid
49            // handle to an iommu object.
50            Ok(Iommu::from(Handle::from_raw(iommu_handle)))
51        }
52    }
53
54    // TODO(b/459887557): Remove this alias when this name is ready to be completely retired.
55    pub fn create_dummy(resource: &Resource, desc: IommuDescStub) -> Result<Iommu, Status> {
56        Self::create_stub(resource, desc)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use crate::ObjectType;
64    use fidl_fuchsia_kernel as fkernel;
65    use fuchsia_component::client::connect_channel_to_protocol;
66
67    #[test]
68    fn iommu_create_invalid_resource() {
69        let status =
70            Iommu::create_stub(&Resource::from(Handle::invalid()), IommuDescStub::default());
71        assert_eq!(status, Err(Status::BAD_HANDLE));
72    }
73
74    #[test]
75    fn iommu_create_valid() {
76        use zx::{Channel, HandleBased, MonotonicInstant};
77        let (client_end, server_end) = Channel::create();
78        connect_channel_to_protocol::<fkernel::IommuResourceMarker>(server_end).unwrap();
79        let service = fkernel::IommuResourceSynchronousProxy::new(client_end);
80        let resource =
81            service.get(MonotonicInstant::INFINITE).expect("couldn't get iommu resource");
82        // This test and fuchsia-zircon are different crates, so we need
83        // to use from_raw to convert between the zx handle and this test handle.
84        // See https://fxbug.dev/42173139 for details.
85        let resource = unsafe { Resource::from(Handle::from_raw(resource.into_raw())) };
86        let iommu = Iommu::create_stub(&resource, IommuDescStub::default()).unwrap();
87        assert!(!iommu.as_handle_ref().is_invalid());
88
89        let info = iommu.as_handle_ref().basic_info().unwrap();
90        assert_eq!(info.object_type, ObjectType::IOMMU);
91    }
92}