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