xref: /openbmc/qemu/rust/common/src/opaque.rs (revision ccafa85a97e38698b798115bba6c18c849846e25)
1 // SPDX-License-Identifier: MIT
2 
3 //! ## Opaque wrappers
4 //!
5 //! The cell types from the previous section are useful at the boundaries
6 //! of code that requires interior mutability.  When writing glue code that
7 //! interacts directly with C structs, however, it is useful to operate
8 //! at a lower level.
9 //!
10 //! C functions often violate Rust's fundamental assumptions about memory
11 //! safety by modifying memory even if it is shared.  Furthermore, C structs
12 //! often start their life uninitialized and may be populated lazily.
13 //!
14 //! For this reason, this module provides the [`Opaque<T>`] type to opt out
15 //! of Rust's usual guarantees about the wrapped type. Access to the wrapped
16 //! value is always through raw pointers, obtained via methods like
17 //! [`as_mut_ptr()`](Opaque::as_mut_ptr) and [`as_ptr()`](Opaque::as_ptr). These
18 //! pointers can then be passed to C functions or dereferenced; both actions
19 //! require `unsafe` blocks, making it clear where safety guarantees must be
20 //! manually verified. For example
21 //!
22 //! ```ignore
23 //! unsafe {
24 //!     let state = Opaque::<MyStruct>::uninit();
25 //!     qemu_struct_init(state.as_mut_ptr());
26 //! }
27 //! ```
28 //!
29 //! [`Opaque<T>`] will usually be wrapped one level further, so that
30 //! bridge methods can be added to the wrapper:
31 //!
32 //! ```ignore
33 //! pub struct MyStruct(Opaque<bindings::MyStruct>);
34 //!
35 //! impl MyStruct {
36 //!     fn new() -> Pin<Box<MyStruct>> {
37 //!         let result = Box::pin(unsafe { Opaque::uninit() });
38 //!         unsafe { qemu_struct_init(result.as_mut_ptr()) };
39 //!         result
40 //!     }
41 //! }
42 //! ```
43 //!
44 //! This pattern of wrapping bindgen-generated types in [`Opaque<T>`] provides
45 //! several advantages:
46 //!
47 //! * The choice of traits to be implemented is not limited by the
48 //!   bindgen-generated code.  For example, [`Drop`] can be added without
49 //!   disabling [`Copy`] on the underlying bindgen type
50 //!
51 //! * [`Send`] and [`Sync`] implementations can be controlled by the wrapper
52 //!   type rather than being automatically derived from the C struct's layout
53 //!
54 //! * Methods can be implemented in a separate crate from the bindgen-generated
55 //!   bindings
56 //!
57 //! * [`Debug`](std::fmt::Debug) and [`Display`](std::fmt::Display)
58 //!   implementations can be customized to be more readable than the raw C
59 //!   struct representation
60 //!
61 //! The [`Opaque<T>`] type does not include BQL validation; it is possible to
62 //! assert in the code that the right lock is taken, to use it together
63 //! with a custom lock guard type, or to let C code take the lock, as
64 //! appropriate.  It is also possible to use it with non-thread-safe
65 //! types, since by default (unlike [`BqlCell`] and [`BqlRefCell`]
66 //! it is neither `Sync` nor `Send`.
67 //!
68 //! While [`Opaque<T>`] is necessary for C interop, it should be used sparingly
69 //! and only at FFI boundaries. For QEMU-specific types that need interior
70 //! mutability, prefer [`BqlCell`] or [`BqlRefCell`].
71 //!
72 //! [`BqlCell`]: ../../bql/cell/struct.BqlCell.html
73 //! [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html
74 use std::{cell::UnsafeCell, fmt, marker::PhantomPinned, mem::MaybeUninit, ptr::NonNull};
75 
76 /// Stores an opaque value that is shared with C code.
77 ///
78 /// Often, C structs can changed when calling a C function even if they are
79 /// behind a shared Rust reference, or they can be initialized lazily and have
80 /// invalid bit patterns (e.g. `3` for a [`bool`]).  This goes against Rust's
81 /// strict aliasing rules, which normally prevent mutation through shared
82 /// references.
83 ///
84 /// Wrapping the struct with `Opaque<T>` ensures that the Rust compiler does not
85 /// assume the usual constraints that Rust structs require, and allows using
86 /// shared references on the Rust side.
87 ///
88 /// `Opaque<T>` is `#[repr(transparent)]`, so that it matches the memory layout
89 /// of `T`.
90 #[repr(transparent)]
91 pub struct Opaque<T> {
92     value: UnsafeCell<MaybeUninit<T>>,
93     // PhantomPinned also allows multiple references to the `Opaque<T>`, i.e.
94     // one `&mut Opaque<T>` can coexist with a `&mut T` or any number of `&T`;
95     // see https://docs.rs/pinned-aliasable/latest/pinned_aliasable/.
96     _pin: PhantomPinned,
97 }
98 
99 impl<T> Opaque<T> {
100     /// Creates a new shared reference from a C pointer
101     ///
102     /// # Safety
103     ///
104     /// The pointer must be valid, though it need not point to a valid value.
105     pub unsafe fn from_raw<'a>(ptr: *mut T) -> &'a Self {
106         let ptr = NonNull::new(ptr).unwrap().cast::<Self>();
107         // SAFETY: Self is a transparent wrapper over T
108         unsafe { ptr.as_ref() }
109     }
110 
111     /// Creates a new opaque object with uninitialized contents.
112     ///
113     /// # Safety
114     ///
115     /// Ultimately the pointer to the returned value will be dereferenced
116     /// in another `unsafe` block, for example when passing it to a C function,
117     /// but the functions containing the dereference are usually safe.  The
118     /// value returned from `uninit()` must be initialized and pinned before
119     /// calling them.
120     pub const unsafe fn uninit() -> Self {
121         Self {
122             value: UnsafeCell::new(MaybeUninit::uninit()),
123             _pin: PhantomPinned,
124         }
125     }
126 
127     /// Creates a new opaque object with zeroed contents.
128     ///
129     /// # Safety
130     ///
131     /// Ultimately the pointer to the returned value will be dereferenced
132     /// in another `unsafe` block, for example when passing it to a C function,
133     /// but the functions containing the dereference are usually safe.  The
134     /// value returned from `uninit()` must be pinned (and possibly initialized)
135     /// before calling them.
136     pub const unsafe fn zeroed() -> Self {
137         Self {
138             value: UnsafeCell::new(MaybeUninit::zeroed()),
139             _pin: PhantomPinned,
140         }
141     }
142 
143     /// Returns a raw mutable pointer to the opaque data.
144     pub const fn as_mut_ptr(&self) -> *mut T {
145         UnsafeCell::get(&self.value).cast()
146     }
147 
148     /// Returns a raw pointer to the opaque data.
149     pub const fn as_ptr(&self) -> *const T {
150         self.as_mut_ptr().cast_const()
151     }
152 
153     /// Returns a raw pointer to the opaque data that can be passed to a
154     /// C function as `void *`.
155     pub const fn as_void_ptr(&self) -> *mut std::ffi::c_void {
156         UnsafeCell::get(&self.value).cast()
157     }
158 
159     /// Converts a raw pointer to the wrapped type.
160     pub const fn raw_get(slot: *mut Self) -> *mut T {
161         // Compare with Linux's raw_get method, which goes through an UnsafeCell
162         // because it takes a *const Self instead.
163         slot.cast()
164     }
165 }
166 
167 impl<T> fmt::Debug for Opaque<T> {
168     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169         let mut name: String = "Opaque<".to_string();
170         name += std::any::type_name::<T>();
171         name += ">";
172         f.debug_tuple(&name).field(&self.as_ptr()).finish()
173     }
174 }
175 
176 impl<T: Default> Opaque<T> {
177     /// Creates a new opaque object with default contents.
178     ///
179     /// # Safety
180     ///
181     /// Ultimately the pointer to the returned value will be dereferenced
182     /// in another `unsafe` block, for example when passing it to a C function,
183     /// but the functions containing the dereference are usually safe.  The
184     /// value returned from `uninit()` must be pinned before calling them.
185     pub unsafe fn new() -> Self {
186         Self {
187             value: UnsafeCell::new(MaybeUninit::new(T::default())),
188             _pin: PhantomPinned,
189         }
190     }
191 }
192 
193 /// Annotates [`Self`] as a transparent wrapper for another type.
194 ///
195 /// Usually defined via the [`crate::Wrapper`] derive macro.
196 ///
197 /// # Examples
198 ///
199 /// ```
200 /// # use std::mem::ManuallyDrop;
201 /// # use common::opaque::Wrapper;
202 /// #[repr(transparent)]
203 /// pub struct Example {
204 ///     inner: ManuallyDrop<String>,
205 /// }
206 ///
207 /// unsafe impl Wrapper for Example {
208 ///     type Wrapped = String;
209 /// }
210 /// ```
211 ///
212 /// # Safety
213 ///
214 /// `Self` must be a `#[repr(transparent)]` wrapper for the `Wrapped` type,
215 /// whether directly or indirectly.
216 ///
217 /// # Methods
218 ///
219 /// By convention, types that implement Wrapper also implement the following
220 /// methods:
221 ///
222 /// ```ignore
223 /// pub const unsafe fn from_raw<'a>(value: *mut Self::Wrapped) -> &'a Self;
224 /// pub const unsafe fn as_mut_ptr(&self) -> *mut Self::Wrapped;
225 /// pub const unsafe fn as_ptr(&self) -> *const Self::Wrapped;
226 /// pub const unsafe fn raw_get(slot: *mut Self) -> *const Self::Wrapped;
227 /// ```
228 ///
229 /// They are not defined here to allow them to be `const`.
230 pub unsafe trait Wrapper {
231     type Wrapped;
232 }
233 
234 unsafe impl<T> Wrapper for Opaque<T> {
235     type Wrapped = T;
236 }
237