xref: /qemu/rust/qemu-api/src/qom.rs (revision c6c4f3e0d90990c642523c087482eac3f42566c1)
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.
12*c6c4f3e0SPaolo Bonzini pub trait ObjectImpl: ClassInitImpl + Sized {
13*c6c4f3e0SPaolo Bonzini     type Class;
145a5110d2SManos Pitsidianakis     const TYPE_NAME: &'static CStr;
155a5110d2SManos Pitsidianakis     const PARENT_TYPE_NAME: Option<&'static CStr>;
16b2a48545SPaolo Bonzini     const ABSTRACT: bool = false;
17b2a48545SPaolo Bonzini     const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
18b2a48545SPaolo Bonzini     const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
19b2a48545SPaolo Bonzini     const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
203701fb22SPaolo Bonzini 
213701fb22SPaolo Bonzini     const TYPE_INFO: TypeInfo = TypeInfo {
223701fb22SPaolo Bonzini         name: Self::TYPE_NAME.as_ptr(),
233701fb22SPaolo Bonzini         parent: if let Some(pname) = Self::PARENT_TYPE_NAME {
243701fb22SPaolo Bonzini             pname.as_ptr()
253701fb22SPaolo Bonzini         } else {
263701fb22SPaolo Bonzini             core::ptr::null_mut()
273701fb22SPaolo Bonzini         },
283701fb22SPaolo Bonzini         instance_size: core::mem::size_of::<Self>(),
293701fb22SPaolo Bonzini         instance_align: core::mem::align_of::<Self>(),
303701fb22SPaolo Bonzini         instance_init: Self::INSTANCE_INIT,
313701fb22SPaolo Bonzini         instance_post_init: Self::INSTANCE_POST_INIT,
323701fb22SPaolo Bonzini         instance_finalize: Self::INSTANCE_FINALIZE,
333701fb22SPaolo Bonzini         abstract_: Self::ABSTRACT,
343701fb22SPaolo Bonzini         class_size: core::mem::size_of::<Self::Class>(),
35*c6c4f3e0SPaolo Bonzini         class_init: <Self as ClassInitImpl>::CLASS_INIT,
36*c6c4f3e0SPaolo Bonzini         class_base_init: <Self as ClassInitImpl>::CLASS_BASE_INIT,
373701fb22SPaolo Bonzini         class_data: core::ptr::null_mut(),
383701fb22SPaolo Bonzini         interfaces: core::ptr::null_mut(),
393701fb22SPaolo Bonzini     };
405a5110d2SManos Pitsidianakis }
415a5110d2SManos Pitsidianakis 
4293ea0896SPaolo Bonzini /// Trait used to fill in a class struct.
4393ea0896SPaolo Bonzini ///
4493ea0896SPaolo Bonzini /// Each QOM class that has virtual methods describes them in a
4593ea0896SPaolo Bonzini /// _class struct_.  Class structs include a parent field corresponding
4693ea0896SPaolo Bonzini /// to the vtable of the parent class, all the way up to [`ObjectClass`].
4793ea0896SPaolo Bonzini /// Each QOM type has one such class struct.
4893ea0896SPaolo Bonzini ///
4993ea0896SPaolo Bonzini /// The Rust implementation of methods will usually come from a trait
5093ea0896SPaolo Bonzini /// like [`ObjectImpl`].
5193ea0896SPaolo Bonzini pub trait ClassInitImpl {
5293ea0896SPaolo Bonzini     /// Function that is called after all parent class initialization
5393ea0896SPaolo Bonzini     /// has occurred.  On entry, the virtual method pointers are set to
5493ea0896SPaolo Bonzini     /// the default values coming from the parent classes; the function
5593ea0896SPaolo Bonzini     /// can change them to override virtual methods of a parent class.
565a5110d2SManos Pitsidianakis     const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)>;
5793ea0896SPaolo Bonzini 
5893ea0896SPaolo Bonzini     /// Called on descendent classes after all parent class initialization
5993ea0896SPaolo Bonzini     /// has occurred, but before the class itself is initialized.  This
6093ea0896SPaolo Bonzini     /// is only useful if a class is not a leaf, and can be used to undo
6193ea0896SPaolo Bonzini     /// the effects of copying the contents of the parent's class struct
6293ea0896SPaolo Bonzini     /// to the descendants.
635a5110d2SManos Pitsidianakis     const CLASS_BASE_INIT: Option<
645a5110d2SManos Pitsidianakis         unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void),
655a5110d2SManos Pitsidianakis     >;
665a5110d2SManos Pitsidianakis }
675a5110d2SManos Pitsidianakis 
685a5110d2SManos Pitsidianakis #[macro_export]
695a5110d2SManos Pitsidianakis macro_rules! module_init {
70e90d4707SPaolo Bonzini     ($type:ident => $body:block) => {
71e90d4707SPaolo Bonzini         const _: () = {
725a5110d2SManos Pitsidianakis             #[used]
734f752191SPaolo Bonzini             #[cfg_attr(
744f752191SPaolo Bonzini                 not(any(target_vendor = "apple", target_os = "windows")),
754f752191SPaolo Bonzini                 link_section = ".init_array"
764f752191SPaolo Bonzini             )]
774f752191SPaolo Bonzini             #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")]
785a5110d2SManos Pitsidianakis             #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
795a5110d2SManos Pitsidianakis             pub static LOAD_MODULE: extern "C" fn() = {
80e90d4707SPaolo Bonzini                 extern "C" fn init_fn() {
815a5110d2SManos Pitsidianakis                     $body
825a5110d2SManos Pitsidianakis                 }
835a5110d2SManos Pitsidianakis 
84e90d4707SPaolo Bonzini                 extern "C" fn ctor_fn() {
855a5110d2SManos Pitsidianakis                     unsafe {
865a5110d2SManos Pitsidianakis                         $crate::bindings::register_module_init(
87e90d4707SPaolo Bonzini                             Some(init_fn),
88e90d4707SPaolo Bonzini                             $crate::bindings::module_init_type::$type,
895a5110d2SManos Pitsidianakis                         );
905a5110d2SManos Pitsidianakis                     }
915a5110d2SManos Pitsidianakis                 }
925a5110d2SManos Pitsidianakis 
93e90d4707SPaolo Bonzini                 ctor_fn
945a5110d2SManos Pitsidianakis             };
955a5110d2SManos Pitsidianakis         };
96e90d4707SPaolo Bonzini     };
97e90d4707SPaolo Bonzini 
98e90d4707SPaolo Bonzini     // shortcut because it's quite common that $body needs unsafe {}
99e90d4707SPaolo Bonzini     ($type:ident => unsafe $body:block) => {
100e90d4707SPaolo Bonzini         $crate::module_init! {
101e90d4707SPaolo Bonzini             $type => { unsafe { $body } }
102e90d4707SPaolo Bonzini         }
103e90d4707SPaolo Bonzini     };
1045a5110d2SManos Pitsidianakis }
105