xref: /qemu/rust/qemu-api/src/qom.rs (revision 93ea0896eaa97adfcc664fa65b5b70e555a652ff)
1 // Copyright 2024, Linaro Limited
2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 //! Definitions required by QEMU when registering a device.
6 
7 use std::{ffi::CStr, os::raw::c_void};
8 
9 use crate::bindings::{Object, ObjectClass, TypeInfo};
10 
11 /// Trait a type must implement to be registered with QEMU.
12 pub trait ObjectImpl {
13     type Class;
14     const TYPE_INFO: TypeInfo;
15     const TYPE_NAME: &'static CStr;
16     const PARENT_TYPE_NAME: Option<&'static CStr>;
17     const ABSTRACT: bool = false;
18     const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
19     const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
20     const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
21 }
22 
23 /// Trait used to fill in a class struct.
24 ///
25 /// Each QOM class that has virtual methods describes them in a
26 /// _class struct_.  Class structs include a parent field corresponding
27 /// to the vtable of the parent class, all the way up to [`ObjectClass`].
28 /// Each QOM type has one such class struct.
29 ///
30 /// The Rust implementation of methods will usually come from a trait
31 /// like [`ObjectImpl`].
32 pub trait ClassInitImpl {
33     /// Function that is called after all parent class initialization
34     /// has occurred.  On entry, the virtual method pointers are set to
35     /// the default values coming from the parent classes; the function
36     /// can change them to override virtual methods of a parent class.
37     const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)>;
38 
39     /// Called on descendent classes after all parent class initialization
40     /// has occurred, but before the class itself is initialized.  This
41     /// is only useful if a class is not a leaf, and can be used to undo
42     /// the effects of copying the contents of the parent's class struct
43     /// to the descendants.
44     const CLASS_BASE_INIT: Option<
45         unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void),
46     >;
47 }
48 
49 #[macro_export]
50 macro_rules! module_init {
51     ($type:ident => $body:block) => {
52         const _: () = {
53             #[used]
54             #[cfg_attr(
55                 not(any(target_vendor = "apple", target_os = "windows")),
56                 link_section = ".init_array"
57             )]
58             #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")]
59             #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
60             pub static LOAD_MODULE: extern "C" fn() = {
61                 extern "C" fn init_fn() {
62                     $body
63                 }
64 
65                 extern "C" fn ctor_fn() {
66                     unsafe {
67                         $crate::bindings::register_module_init(
68                             Some(init_fn),
69                             $crate::bindings::module_init_type::$type,
70                         );
71                     }
72                 }
73 
74                 ctor_fn
75             };
76         };
77     };
78 
79     // shortcut because it's quite common that $body needs unsafe {}
80     ($type:ident => unsafe $body:block) => {
81         $crate::module_init! {
82             $type => { unsafe { $body } }
83         }
84     };
85 }
86 
87 #[macro_export]
88 macro_rules! type_info {
89     ($t:ty) => {
90         $crate::bindings::TypeInfo {
91             name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(),
92             parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME {
93                 pname.as_ptr()
94             } else {
95                 ::core::ptr::null_mut()
96             },
97             instance_size: ::core::mem::size_of::<$t>(),
98             instance_align: ::core::mem::align_of::<$t>(),
99             instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT,
100             instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT,
101             instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE,
102             abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT,
103             class_size:  ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(),
104             class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::ClassInitImpl>::CLASS_INIT,
105             class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::ClassInitImpl>::CLASS_BASE_INIT,
106             class_data: ::core::ptr::null_mut(),
107             interfaces: ::core::ptr::null_mut(),
108         };
109     }
110 }
111