xref: /qemu/rust/qemu-api/src/qom.rs (revision 93ea0896eaa97adfcc664fa65b5b70e555a652ff)
15a5110d2SManos Pitsidianakis // Copyright 2024, Linaro Limited
25a5110d2SManos Pitsidianakis // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
35a5110d2SManos Pitsidianakis // SPDX-License-Identifier: GPL-2.0-or-later
45a5110d2SManos Pitsidianakis 
55a5110d2SManos Pitsidianakis //! Definitions required by QEMU when registering a device.
65a5110d2SManos Pitsidianakis 
79f7d4520SPaolo Bonzini use std::{ffi::CStr, os::raw::c_void};
85a5110d2SManos Pitsidianakis 
95a5110d2SManos Pitsidianakis use crate::bindings::{Object, ObjectClass, TypeInfo};
105a5110d2SManos Pitsidianakis 
115a5110d2SManos Pitsidianakis /// Trait a type must implement to be registered with QEMU.
125a5110d2SManos Pitsidianakis pub trait ObjectImpl {
135a5110d2SManos Pitsidianakis     type Class;
145a5110d2SManos Pitsidianakis     const TYPE_INFO: TypeInfo;
155a5110d2SManos Pitsidianakis     const TYPE_NAME: &'static CStr;
165a5110d2SManos Pitsidianakis     const PARENT_TYPE_NAME: Option<&'static CStr>;
17b2a48545SPaolo Bonzini     const ABSTRACT: bool = false;
18b2a48545SPaolo Bonzini     const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
19b2a48545SPaolo Bonzini     const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
20b2a48545SPaolo Bonzini     const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
215a5110d2SManos Pitsidianakis }
225a5110d2SManos Pitsidianakis 
23*93ea0896SPaolo Bonzini /// Trait used to fill in a class struct.
24*93ea0896SPaolo Bonzini ///
25*93ea0896SPaolo Bonzini /// Each QOM class that has virtual methods describes them in a
26*93ea0896SPaolo Bonzini /// _class struct_.  Class structs include a parent field corresponding
27*93ea0896SPaolo Bonzini /// to the vtable of the parent class, all the way up to [`ObjectClass`].
28*93ea0896SPaolo Bonzini /// Each QOM type has one such class struct.
29*93ea0896SPaolo Bonzini ///
30*93ea0896SPaolo Bonzini /// The Rust implementation of methods will usually come from a trait
31*93ea0896SPaolo Bonzini /// like [`ObjectImpl`].
32*93ea0896SPaolo Bonzini pub trait ClassInitImpl {
33*93ea0896SPaolo Bonzini     /// Function that is called after all parent class initialization
34*93ea0896SPaolo Bonzini     /// has occurred.  On entry, the virtual method pointers are set to
35*93ea0896SPaolo Bonzini     /// the default values coming from the parent classes; the function
36*93ea0896SPaolo Bonzini     /// can change them to override virtual methods of a parent class.
375a5110d2SManos Pitsidianakis     const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)>;
38*93ea0896SPaolo Bonzini 
39*93ea0896SPaolo Bonzini     /// Called on descendent classes after all parent class initialization
40*93ea0896SPaolo Bonzini     /// has occurred, but before the class itself is initialized.  This
41*93ea0896SPaolo Bonzini     /// is only useful if a class is not a leaf, and can be used to undo
42*93ea0896SPaolo Bonzini     /// the effects of copying the contents of the parent's class struct
43*93ea0896SPaolo Bonzini     /// to the descendants.
445a5110d2SManos Pitsidianakis     const CLASS_BASE_INIT: Option<
455a5110d2SManos Pitsidianakis         unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void),
465a5110d2SManos Pitsidianakis     >;
475a5110d2SManos Pitsidianakis }
485a5110d2SManos Pitsidianakis 
495a5110d2SManos Pitsidianakis #[macro_export]
505a5110d2SManos Pitsidianakis macro_rules! module_init {
51e90d4707SPaolo Bonzini     ($type:ident => $body:block) => {
52e90d4707SPaolo Bonzini         const _: () = {
535a5110d2SManos Pitsidianakis             #[used]
544f752191SPaolo Bonzini             #[cfg_attr(
554f752191SPaolo Bonzini                 not(any(target_vendor = "apple", target_os = "windows")),
564f752191SPaolo Bonzini                 link_section = ".init_array"
574f752191SPaolo Bonzini             )]
584f752191SPaolo Bonzini             #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")]
595a5110d2SManos Pitsidianakis             #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
605a5110d2SManos Pitsidianakis             pub static LOAD_MODULE: extern "C" fn() = {
61e90d4707SPaolo Bonzini                 extern "C" fn init_fn() {
625a5110d2SManos Pitsidianakis                     $body
635a5110d2SManos Pitsidianakis                 }
645a5110d2SManos Pitsidianakis 
65e90d4707SPaolo Bonzini                 extern "C" fn ctor_fn() {
665a5110d2SManos Pitsidianakis                     unsafe {
675a5110d2SManos Pitsidianakis                         $crate::bindings::register_module_init(
68e90d4707SPaolo Bonzini                             Some(init_fn),
69e90d4707SPaolo Bonzini                             $crate::bindings::module_init_type::$type,
705a5110d2SManos Pitsidianakis                         );
715a5110d2SManos Pitsidianakis                     }
725a5110d2SManos Pitsidianakis                 }
735a5110d2SManos Pitsidianakis 
74e90d4707SPaolo Bonzini                 ctor_fn
755a5110d2SManos Pitsidianakis             };
765a5110d2SManos Pitsidianakis         };
77e90d4707SPaolo Bonzini     };
78e90d4707SPaolo Bonzini 
79e90d4707SPaolo Bonzini     // shortcut because it's quite common that $body needs unsafe {}
80e90d4707SPaolo Bonzini     ($type:ident => unsafe $body:block) => {
81e90d4707SPaolo Bonzini         $crate::module_init! {
82e90d4707SPaolo Bonzini             $type => { unsafe { $body } }
83e90d4707SPaolo Bonzini         }
84e90d4707SPaolo Bonzini     };
855a5110d2SManos Pitsidianakis }
865a5110d2SManos Pitsidianakis 
875a5110d2SManos Pitsidianakis #[macro_export]
885a5110d2SManos Pitsidianakis macro_rules! type_info {
895a5110d2SManos Pitsidianakis     ($t:ty) => {
905a5110d2SManos Pitsidianakis         $crate::bindings::TypeInfo {
915a5110d2SManos Pitsidianakis             name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(),
925a5110d2SManos Pitsidianakis             parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME {
935a5110d2SManos Pitsidianakis                 pname.as_ptr()
945a5110d2SManos Pitsidianakis             } else {
955a5110d2SManos Pitsidianakis                 ::core::ptr::null_mut()
965a5110d2SManos Pitsidianakis             },
9700ed18deSPaolo Bonzini             instance_size: ::core::mem::size_of::<$t>(),
9800ed18deSPaolo Bonzini             instance_align: ::core::mem::align_of::<$t>(),
995a5110d2SManos Pitsidianakis             instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT,
1005a5110d2SManos Pitsidianakis             instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT,
1015a5110d2SManos Pitsidianakis             instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE,
1025a5110d2SManos Pitsidianakis             abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT,
10300ed18deSPaolo Bonzini             class_size:  ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(),
104*93ea0896SPaolo Bonzini             class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::ClassInitImpl>::CLASS_INIT,
105*93ea0896SPaolo Bonzini             class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::ClassInitImpl>::CLASS_BASE_INIT,
1065a5110d2SManos Pitsidianakis             class_data: ::core::ptr::null_mut(),
1075a5110d2SManos Pitsidianakis             interfaces: ::core::ptr::null_mut(),
1085a5110d2SManos Pitsidianakis         };
1095a5110d2SManos Pitsidianakis     }
1105a5110d2SManos Pitsidianakis }
111