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