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, HandleBased, HandleRef, NullableHandle, Resource, Status, ok, sys};
8
9/// An object representing a Zircon iommu
10///
11/// As essentially a subtype of `NullableHandle`, it can be freely interconverted.
12#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
13#[repr(transparent)]
14pub struct Iommu(NullableHandle);
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(NullableHandle::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 = Iommu::create_stub(
70            &Resource::from(NullableHandle::invalid()),
71            IommuDescStub::default(),
72        );
73        assert_eq!(status, Err(Status::BAD_HANDLE));
74    }
75
76    #[test]
77    fn iommu_create_valid() {
78        use zx::{Channel, HandleBased, MonotonicInstant};
79        let (client_end, server_end) = Channel::create();
80        connect_channel_to_protocol::<fkernel::IommuResourceMarker>(server_end).unwrap();
81        let service = fkernel::IommuResourceSynchronousProxy::new(client_end);
82        let resource =
83            service.get(MonotonicInstant::INFINITE).expect("couldn't get iommu resource");
84        // This test and fuchsia-zircon are different crates, so we need
85        // to use from_raw to convert between the zx handle and this test handle.
86        // See https://fxbug.dev/42173139 for details.
87        let resource = unsafe { Resource::from(NullableHandle::from_raw(resource.into_raw())) };
88        let iommu = Iommu::create_stub(&resource, IommuDescStub::default()).unwrap();
89        assert!(!iommu.as_handle_ref().is_invalid());
90
91        let info = iommu.as_handle_ref().basic_info().unwrap();
92        assert_eq!(info.object_type, ObjectType::IOMMU);
93    }
94}