12590c02aSPaolo Bonzini.. |msrv| replace:: 1.63.0 22590c02aSPaolo Bonzini 32590c02aSPaolo BonziniRust in QEMU 42590c02aSPaolo Bonzini============ 52590c02aSPaolo Bonzini 62590c02aSPaolo BonziniRust in QEMU is a project to enable using the Rust programming language 72590c02aSPaolo Bonzinito add new functionality to QEMU. 82590c02aSPaolo Bonzini 92590c02aSPaolo BonziniRight now, the focus is on making it possible to write devices that inherit 102590c02aSPaolo Bonzinifrom ``SysBusDevice`` in `*safe*`__ Rust. Later, it may become possible 112590c02aSPaolo Bonzinito write other kinds of devices (e.g. PCI devices that can do DMA), 122590c02aSPaolo Bonzinicomplete boards, or backends (e.g. block device formats). 132590c02aSPaolo Bonzini 142590c02aSPaolo Bonzini__ https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html 152590c02aSPaolo Bonzini 162590c02aSPaolo BonziniBuilding the Rust in QEMU code 172590c02aSPaolo Bonzini------------------------------ 182590c02aSPaolo Bonzini 192590c02aSPaolo BonziniThe Rust in QEMU code is included in the emulators via Meson. Meson 202590c02aSPaolo Bonziniinvokes rustc directly, building static libraries that are then linked 212590c02aSPaolo Bonzinitogether with the C code. This is completely automatic when you run 222590c02aSPaolo Bonzini``make`` or ``ninja``. 232590c02aSPaolo Bonzini 242590c02aSPaolo BonziniHowever, QEMU's build system also tries to be easy to use for people who 252590c02aSPaolo Bonziniare accustomed to the more "normal" Cargo-based development workflow. 262590c02aSPaolo BonziniIn particular: 272590c02aSPaolo Bonzini 282590c02aSPaolo Bonzini* the set of warnings and lints that are used to build QEMU always 292590c02aSPaolo Bonzini comes from the ``rust/Cargo.toml`` workspace file 302590c02aSPaolo Bonzini 312590c02aSPaolo Bonzini* it is also possible to use ``cargo`` for common Rust-specific coding 322590c02aSPaolo Bonzini tasks, in particular to invoke ``clippy``, ``rustfmt`` and ``rustdoc``. 332590c02aSPaolo Bonzini 342590c02aSPaolo BonziniTo this end, QEMU includes a ``build.rs`` build script that picks up 352590c02aSPaolo Bonzinigenerated sources from QEMU's build directory and puts it in Cargo's 362590c02aSPaolo Bonzinioutput directory (typically ``rust/target/``). A vanilla invocation 372590c02aSPaolo Bonziniof Cargo will complain that it cannot find the generated sources, 382590c02aSPaolo Bonziniwhich can be fixed in different ways: 392590c02aSPaolo Bonzini 402590c02aSPaolo Bonzini* by using special shorthand targets in the QEMU build directory:: 412590c02aSPaolo Bonzini 422590c02aSPaolo Bonzini make clippy 432590c02aSPaolo Bonzini make rustfmt 442590c02aSPaolo Bonzini make rustdoc 452590c02aSPaolo Bonzini 462590c02aSPaolo Bonzini* by invoking ``cargo`` through the Meson `development environment`__ 472590c02aSPaolo Bonzini feature:: 482590c02aSPaolo Bonzini 492590c02aSPaolo Bonzini pyvenv/bin/meson devenv -w ../rust cargo clippy --tests 502590c02aSPaolo Bonzini pyvenv/bin/meson devenv -w ../rust cargo fmt 512590c02aSPaolo Bonzini 522590c02aSPaolo Bonzini If you are going to use ``cargo`` repeatedly, ``pyvenv/bin/meson devenv`` 532590c02aSPaolo Bonzini will enter a shell where commands like ``cargo clippy`` just work. 542590c02aSPaolo Bonzini 552590c02aSPaolo Bonzini__ https://mesonbuild.com/Commands.html#devenv 562590c02aSPaolo Bonzini 572590c02aSPaolo Bonzini* by pointing the ``MESON_BUILD_ROOT`` to the top of your QEMU build 582590c02aSPaolo Bonzini tree. This third method is useful if you are using ``rust-analyzer``; 592590c02aSPaolo Bonzini you can set the environment variable through the 602590c02aSPaolo Bonzini ``rust-analyzer.cargo.extraEnv`` setting. 612590c02aSPaolo Bonzini 622590c02aSPaolo BonziniAs shown above, you can use the ``--tests`` option as usual to operate on test 632590c02aSPaolo Bonzinicode. Note however that you cannot *build* or run tests via ``cargo``, because 642590c02aSPaolo Bonzinithey need support C code from QEMU that Cargo does not know about. Tests can 652590c02aSPaolo Bonzinibe run via ``meson test`` or ``make``:: 662590c02aSPaolo Bonzini 672590c02aSPaolo Bonzini make check-rust 682590c02aSPaolo Bonzini 692590c02aSPaolo BonziniBuilding Rust code with ``--enable-modules`` is not supported yet. 702590c02aSPaolo Bonzini 712590c02aSPaolo BonziniSupported tools 722590c02aSPaolo Bonzini''''''''''''''' 732590c02aSPaolo Bonzini 742590c02aSPaolo BonziniQEMU supports rustc version 1.63.0 and newer. Notably, the following features 752590c02aSPaolo Bonziniare missing: 762590c02aSPaolo Bonzini 772590c02aSPaolo Bonzini* ``core::ffi`` (1.64.0). Use ``std::os::raw`` and ``std::ffi`` instead. 782590c02aSPaolo Bonzini 792590c02aSPaolo Bonzini* ``cast_mut()``/``cast_const()`` (1.65.0). Use ``as`` instead. 802590c02aSPaolo Bonzini 812590c02aSPaolo Bonzini* "let ... else" (1.65.0). Use ``if let`` instead. This is currently patched 822590c02aSPaolo Bonzini in QEMU's vendored copy of the bilge crate. 832590c02aSPaolo Bonzini 842590c02aSPaolo Bonzini* Generic Associated Types (1.65.0) 852590c02aSPaolo Bonzini 862590c02aSPaolo Bonzini* ``CStr::from_bytes_with_nul()`` as a ``const`` function (1.72.0). 872590c02aSPaolo Bonzini 882590c02aSPaolo Bonzini* "Return position ``impl Trait`` in Traits" (1.75.0, blocker for including 892590c02aSPaolo Bonzini the pinned-init create). 902590c02aSPaolo Bonzini 912590c02aSPaolo Bonzini* ``MaybeUninit::zeroed()`` as a ``const`` function (1.75.0). QEMU's 922590c02aSPaolo Bonzini ``Zeroable`` trait can be implemented without ``MaybeUninit::zeroed()``, 932590c02aSPaolo Bonzini so this would be just a cleanup. 942590c02aSPaolo Bonzini 952590c02aSPaolo Bonzini* ``c"" literals`` (stable in 1.77.0). QEMU provides a ``c_str!()`` macro 962590c02aSPaolo Bonzini to define ``CStr`` constants easily 972590c02aSPaolo Bonzini 982590c02aSPaolo Bonzini* ``offset_of!`` (stable in 1.77.0). QEMU uses ``offset_of!()`` heavily; it 992590c02aSPaolo Bonzini provides a replacement in the ``qemu_api`` crate, but it does not support 1002590c02aSPaolo Bonzini lifetime parameters and therefore ``&'a Something`` fields in the struct 1012590c02aSPaolo Bonzini may have to be replaced by ``NonNull<Something>``. *Nested* ``offset_of!`` 1022590c02aSPaolo Bonzini was only stabilized in Rust 1.82.0, but it is not used. 1032590c02aSPaolo Bonzini 1042590c02aSPaolo Bonzini* inline const expression (stable in 1.79.0), currently worked around with 1052590c02aSPaolo Bonzini associated constants in the ``FnCall`` trait. 1062590c02aSPaolo Bonzini 1072590c02aSPaolo Bonzini* associated constants have to be explicitly marked ``'static`` (`changed in 1082590c02aSPaolo Bonzini 1.81.0`__) 1092590c02aSPaolo Bonzini 1102590c02aSPaolo Bonzini* ``&raw`` (stable in 1.82.0). Use ``addr_of!`` and ``addr_of_mut!`` instead, 1112590c02aSPaolo Bonzini though hopefully the need for raw pointers will go down over time. 1122590c02aSPaolo Bonzini 1132590c02aSPaolo Bonzini* ``new_uninit`` (stable in 1.82.0). This is used internally by the ``pinned_init`` 1142590c02aSPaolo Bonzini crate, which is planned for inclusion in QEMU, but it can be easily patched 1152590c02aSPaolo Bonzini out. 1162590c02aSPaolo Bonzini 1172590c02aSPaolo Bonzini* referencing statics in constants (stable in 1.83.0). For now use a const 1182590c02aSPaolo Bonzini function; this is an important limitation for QEMU's migration stream 1192590c02aSPaolo Bonzini architecture (VMState). Right now, VMState lacks type safety because 1202590c02aSPaolo Bonzini it is hard to place the ``VMStateField`` definitions in traits. 1212590c02aSPaolo Bonzini 1222590c02aSPaolo Bonzini* associated const equality would be nice to have for some users of 1232590c02aSPaolo Bonzini ``callbacks::FnCall``, but is still experimental. ``ASSERT_IS_SOME`` 1242590c02aSPaolo Bonzini replaces it. 1252590c02aSPaolo Bonzini 1262590c02aSPaolo Bonzini__ https://github.com/rust-lang/rust/pull/125258 1272590c02aSPaolo Bonzini 1282590c02aSPaolo BonziniIt is expected that QEMU will advance its minimum supported version of 1292590c02aSPaolo Bonzinirustc to 1.77.0 as soon as possible; as of January 2025, blockers 1302590c02aSPaolo Bonzinifor that right now are Debian bookworm and 32-bit MIPS processors. 1312590c02aSPaolo BonziniThis unfortunately means that references to statics in constants will 1322590c02aSPaolo Bonziniremain an issue. 1332590c02aSPaolo Bonzini 1342590c02aSPaolo BonziniQEMU also supports version 0.60.x of bindgen, which is missing option 1352590c02aSPaolo Bonzini``--generate-cstr``. This option requires version 0.66.x and will 1362590c02aSPaolo Bonzinibe adopted as soon as supporting these older versions is not necessary 1372590c02aSPaolo Bonzinianymore. 1382590c02aSPaolo Bonzini 1392590c02aSPaolo BonziniWriting Rust code in QEMU 1402590c02aSPaolo Bonzini------------------------- 1412590c02aSPaolo Bonzini 14229b9a66fSPaolo BonziniQEMU includes four crates: 1432590c02aSPaolo Bonzini 1442590c02aSPaolo Bonzini* ``qemu_api`` for bindings to C code and useful functionality 1452590c02aSPaolo Bonzini 1462590c02aSPaolo Bonzini* ``qemu_api_macros`` defines several procedural macros that are useful when 1472590c02aSPaolo Bonzini writing C code 1482590c02aSPaolo Bonzini 14929b9a66fSPaolo Bonzini* ``pl011`` (under ``rust/hw/char/pl011``) and ``hpet`` (under ``rust/hw/timer/hpet``) 15029b9a66fSPaolo Bonzini are sample devices that demonstrate ``qemu_api`` and ``qemu_api_macros``, and are 15129b9a66fSPaolo Bonzini used to further develop them. These two crates are functional\ [#issues]_ replacements 15229b9a66fSPaolo Bonzini for the ``hw/char/pl011.c`` and ``hw/timer/hpet.c`` files. 15329b9a66fSPaolo Bonzini 15429b9a66fSPaolo Bonzini.. [#issues] The ``pl011`` crate is synchronized with ``hw/char/pl011.c`` 15529b9a66fSPaolo Bonzini as of commit 02b1f7f61928. The ``hpet`` crate is synchronized as of 15629b9a66fSPaolo Bonzini commit f32352ff9e. Both are lacking tracing functionality; ``hpet`` 15729b9a66fSPaolo Bonzini is also lacking support for migration. 1582590c02aSPaolo Bonzini 1592590c02aSPaolo BonziniThis section explains how to work with them. 1602590c02aSPaolo Bonzini 1612590c02aSPaolo BonziniStatus 1622590c02aSPaolo Bonzini'''''' 1632590c02aSPaolo Bonzini 1642590c02aSPaolo BonziniModules of ``qemu_api`` can be defined as: 1652590c02aSPaolo Bonzini 1662590c02aSPaolo Bonzini- *complete*: ready for use in new devices; if applicable, the API supports the 1672590c02aSPaolo Bonzini full functionality available in C 1682590c02aSPaolo Bonzini 1692590c02aSPaolo Bonzini- *stable*: ready for production use, the API is safe and should not undergo 1702590c02aSPaolo Bonzini major changes 1712590c02aSPaolo Bonzini 1722590c02aSPaolo Bonzini- *proof of concept*: the API is subject to change but allows working with safe 1732590c02aSPaolo Bonzini Rust 1742590c02aSPaolo Bonzini 1752590c02aSPaolo Bonzini- *initial*: the API is in its initial stages; it requires large amount of 1762590c02aSPaolo Bonzini unsafe code; it might have soundness or type-safety issues 1772590c02aSPaolo Bonzini 1782590c02aSPaolo BonziniThe status of the modules is as follows: 1792590c02aSPaolo Bonzini 1802590c02aSPaolo Bonzini================ ====================== 1812590c02aSPaolo Bonzinimodule status 1822590c02aSPaolo Bonzini================ ====================== 1832590c02aSPaolo Bonzini``assertions`` stable 1842590c02aSPaolo Bonzini``bitops`` complete 1852590c02aSPaolo Bonzini``callbacks`` complete 1862590c02aSPaolo Bonzini``cell`` stable 1872590c02aSPaolo Bonzini``c_str`` complete 1888a420dd1SPaolo Bonzini``errno`` complete 1892590c02aSPaolo Bonzini``irq`` complete 190590faa03SPaolo Bonzini``memory`` stable 1912590c02aSPaolo Bonzini``module`` complete 1922590c02aSPaolo Bonzini``offset_of`` stable 1932590c02aSPaolo Bonzini``qdev`` stable 1942590c02aSPaolo Bonzini``qom`` stable 1952590c02aSPaolo Bonzini``sysbus`` stable 196eadb83f9SZhao Liu``timer`` stable 1972590c02aSPaolo Bonzini``vmstate`` proof of concept 1982590c02aSPaolo Bonzini``zeroable`` stable 1992590c02aSPaolo Bonzini================ ====================== 2002590c02aSPaolo Bonzini 2012590c02aSPaolo Bonzini.. note:: 2022590c02aSPaolo Bonzini API stability is not a promise, if anything because the C APIs are not a stable 2032590c02aSPaolo Bonzini interface either. Also, ``unsafe`` interfaces may be replaced by safe interfaces 2042590c02aSPaolo Bonzini later. 2052590c02aSPaolo Bonzini 206df45e26aSPaolo BonziniNaming convention 207df45e26aSPaolo Bonzini''''''''''''''''' 208df45e26aSPaolo Bonzini 209df45e26aSPaolo BonziniC function names usually are prefixed according to the data type that they 210df45e26aSPaolo Bonziniapply to, for example ``timer_mod`` or ``sysbus_connect_irq``. Furthermore, 211df45e26aSPaolo Bonziniboth function and structs sometimes have a ``qemu_`` or ``QEMU`` prefix. 212df45e26aSPaolo BonziniGenerally speaking, these are all removed in the corresponding Rust functions: 213df45e26aSPaolo Bonzini``QEMUTimer`` becomes ``timer::Timer``, ``timer_mod`` becomes ``Timer::modify``, 214df45e26aSPaolo Bonzini``sysbus_connect_irq`` becomes ``SysBusDeviceMethods::connect_irq``. 215df45e26aSPaolo Bonzini 216df45e26aSPaolo BonziniSometimes however a name appears multiple times in the QOM class hierarchy, 217df45e26aSPaolo Bonziniand the only difference is in the prefix. An example is ``qdev_realize`` and 218df45e26aSPaolo Bonzini``sysbus_realize``. In such cases, whenever a name is not unique in 219df45e26aSPaolo Bonzinithe hierarchy, always add the prefix to the classes that are lower in 220df45e26aSPaolo Bonzinithe hierarchy; for the top class, decide on a case by case basis. 221df45e26aSPaolo Bonzini 222df45e26aSPaolo BonziniFor example: 223df45e26aSPaolo Bonzini 224df45e26aSPaolo Bonzini========================== ========================================= 225df45e26aSPaolo Bonzini``device_cold_reset()`` ``DeviceMethods::cold_reset()`` 226df45e26aSPaolo Bonzini``pci_device_reset()`` ``PciDeviceMethods::pci_device_reset()`` 227df45e26aSPaolo Bonzini``pci_bridge_reset()`` ``PciBridgeMethods::pci_bridge_reset()`` 228df45e26aSPaolo Bonzini========================== ========================================= 229df45e26aSPaolo Bonzini 230df45e26aSPaolo BonziniHere, the name is not exactly the same, but nevertheless ``PciDeviceMethods`` 231df45e26aSPaolo Bonziniadds the prefix to avoid confusion, because the functionality of 232df45e26aSPaolo Bonzini``device_cold_reset()`` and ``pci_device_reset()`` is subtly different. 233df45e26aSPaolo Bonzini 234df45e26aSPaolo BonziniIn this case, however, no prefix is needed: 235df45e26aSPaolo Bonzini 236df45e26aSPaolo Bonzini========================== ========================================= 237df45e26aSPaolo Bonzini``device_realize()`` ``DeviceMethods::realize()`` 238df45e26aSPaolo Bonzini``sysbus_realize()`` ``SysbusDeviceMethods::sysbus_realize()`` 239df45e26aSPaolo Bonzini``pci_realize()`` ``PciDeviceMethods::pci_realize()`` 240df45e26aSPaolo Bonzini========================== ========================================= 241df45e26aSPaolo Bonzini 242df45e26aSPaolo BonziniHere, the lower classes do not add any functionality, and mostly 243df45e26aSPaolo Bonziniprovide extra compile-time checking; the basic *realize* functionality 244df45e26aSPaolo Bonziniis the same for all devices. Therefore, ``DeviceMethods`` does not 245df45e26aSPaolo Bonziniadd the prefix. 246df45e26aSPaolo Bonzini 247df45e26aSPaolo BonziniWhenever a name is unique in the hierarchy, instead, you should 248df45e26aSPaolo Bonzinialways remove the class name prefix. 249df45e26aSPaolo Bonzini 2502590c02aSPaolo BonziniCommon pitfalls 2512590c02aSPaolo Bonzini''''''''''''''' 2522590c02aSPaolo Bonzini 2532590c02aSPaolo BonziniRust has very strict rules with respect to how you get an exclusive (``&mut``) 2542590c02aSPaolo Bonzinireference; failure to respect those rules is a source of undefined behavior. 2552590c02aSPaolo BonziniIn particular, even if a value is loaded from a raw mutable pointer (``*mut``), 2562590c02aSPaolo Bonziniit *cannot* be casted to ``&mut`` unless the value was stored to the ``*mut`` 2572590c02aSPaolo Bonzinifrom a mutable reference. Furthermore, it is undefined behavior if any 2582590c02aSPaolo Bonzinishared reference was created between the store to the ``*mut`` and the load:: 2592590c02aSPaolo Bonzini 2602590c02aSPaolo Bonzini let mut p: u32 = 42; 2612590c02aSPaolo Bonzini let p_mut = &mut p; // 1 2622590c02aSPaolo Bonzini let p_raw = p_mut as *mut u32; // 2 2632590c02aSPaolo Bonzini 2642590c02aSPaolo Bonzini // p_raw keeps the mutable reference "alive" 2652590c02aSPaolo Bonzini 2662590c02aSPaolo Bonzini let p_shared = &p; // 3 2672590c02aSPaolo Bonzini println!("access from &u32: {}", *p_shared); 2682590c02aSPaolo Bonzini 2692590c02aSPaolo Bonzini // Bring back the mutable reference, its lifetime overlaps 2702590c02aSPaolo Bonzini // with that of a shared reference. 2712590c02aSPaolo Bonzini let p_mut = unsafe { &mut *p_raw }; // 4 2722590c02aSPaolo Bonzini println!("access from &mut 32: {}", *p_mut); 2732590c02aSPaolo Bonzini 2742590c02aSPaolo Bonzini println!("access from &u32: {}", *p_shared); // 5 2752590c02aSPaolo Bonzini 2762590c02aSPaolo BonziniThese rules can be tested with `MIRI`__, for example. 2772590c02aSPaolo Bonzini 2782590c02aSPaolo Bonzini__ https://github.com/rust-lang/miri 2792590c02aSPaolo Bonzini 2802590c02aSPaolo BonziniAlmost all Rust code in QEMU will involve QOM objects, and pointers to these 2812590c02aSPaolo Bonziniobjects are *shared*, for example because they are part of the QOM composition 2822590c02aSPaolo Bonzinitree. This creates exactly the above scenario: 2832590c02aSPaolo Bonzini 2842590c02aSPaolo Bonzini1. a QOM object is created 2852590c02aSPaolo Bonzini 2862590c02aSPaolo Bonzini2. a ``*mut`` is created, for example as the opaque value for a ``MemoryRegion`` 2872590c02aSPaolo Bonzini 2882590c02aSPaolo Bonzini3. the QOM object is placed in the composition tree 2892590c02aSPaolo Bonzini 2902590c02aSPaolo Bonzini4. a memory access dereferences the opaque value to a ``&mut`` 2912590c02aSPaolo Bonzini 2922590c02aSPaolo Bonzini5. but the shared reference is still present in the composition tree 2932590c02aSPaolo Bonzini 2942590c02aSPaolo BonziniBecause of this, QOM objects should almost always use ``&self`` instead 2952590c02aSPaolo Bonziniof ``&mut self``; access to internal fields must use *interior mutability* 2962590c02aSPaolo Bonzinito go from a shared reference to a ``&mut``. 2972590c02aSPaolo Bonzini 2982590c02aSPaolo BonziniWhenever C code provides you with an opaque ``void *``, avoid converting it 2990b9d05e3SPaolo Bonzinito a Rust mutable reference, and use a shared reference instead. The 3000b9d05e3SPaolo Bonzini``qemu_api::cell`` module provides wrappers that can be used to tell the 3010b9d05e3SPaolo BonziniRust compiler about interior mutability, and optionally to enforce locking 3020b9d05e3SPaolo Bonzinirules for the "Big QEMU Lock". In the future, similar cell types might 3030b9d05e3SPaolo Bonzinialso be provided for ``AioContext``-based locking as well. 3042590c02aSPaolo Bonzini 3050b9d05e3SPaolo BonziniIn particular, device code will usually rely on the ``BqlRefCell`` and 3060b9d05e3SPaolo Bonzini``BqlCell`` type to ensure that data is accessed correctly under the 3070b9d05e3SPaolo Bonzini"Big QEMU Lock". These cell types are also known to the ``vmstate`` 3080b9d05e3SPaolo Bonzinicrate, which is able to "look inside" them when building an in-memory 3090b9d05e3SPaolo Bonzinirepresentation of a ``struct``'s layout. Note that the same is not true 3100b9d05e3SPaolo Bonziniof a ``RefCell`` or ``Mutex``. 3110b9d05e3SPaolo Bonzini 3120b9d05e3SPaolo BonziniBindings code instead will usually use the ``Opaque`` type, which hides 3130b9d05e3SPaolo Bonzinithe contents of the underlying struct and can be easily converted to 3140b9d05e3SPaolo Bonzinia raw pointer, for use in calls to C functions. It can be used for 3150b9d05e3SPaolo Bonziniexample as follows:: 3160b9d05e3SPaolo Bonzini 3170b9d05e3SPaolo Bonzini #[repr(transparent)] 318*f07a5674SPaolo Bonzini #[derive(Debug, qemu_api_macros::Wrapper)] 3190b9d05e3SPaolo Bonzini pub struct Object(Opaque<bindings::Object>); 3200b9d05e3SPaolo Bonzini 321*f07a5674SPaolo Bonziniwhere the special ``derive`` macro provides useful methods such as 322*f07a5674SPaolo Bonzini``from_raw``, ``as_ptr`, ``as_mut_ptr`` and ``raw_get``. The bindings will 323*f07a5674SPaolo Bonzinithen manually check for the big QEMU lock with assertions, which allows 324*f07a5674SPaolo Bonzinithe wrapper to be declared thread-safe:: 3250b9d05e3SPaolo Bonzini 3260b9d05e3SPaolo Bonzini unsafe impl Send for Object {} 3270b9d05e3SPaolo Bonzini unsafe impl Sync for Object {} 3282590c02aSPaolo Bonzini 3292590c02aSPaolo BonziniWriting bindings to C code 3302590c02aSPaolo Bonzini'''''''''''''''''''''''''' 3312590c02aSPaolo Bonzini 3322590c02aSPaolo BonziniHere are some things to keep in mind when working on the ``qemu_api`` crate. 3332590c02aSPaolo Bonzini 3342590c02aSPaolo Bonzini**Look at existing code** 3352590c02aSPaolo Bonzini Very often, similar idioms in C code correspond to similar tricks in 3362590c02aSPaolo Bonzini Rust bindings. If the C code uses ``offsetof``, look at qdev properties 3372590c02aSPaolo Bonzini or ``vmstate``. If the C code has a complex const struct, look at 3382590c02aSPaolo Bonzini ``MemoryRegion``. Reuse existing patterns for handling lifetimes; 3392590c02aSPaolo Bonzini for example use ``&T`` for QOM objects that do not need a reference 3402590c02aSPaolo Bonzini count (including those that can be embedded in other objects) and 3412590c02aSPaolo Bonzini ``Owned<T>`` for those that need it. 3422590c02aSPaolo Bonzini 3432590c02aSPaolo Bonzini**Use the type system** 3442590c02aSPaolo Bonzini Bindings often will need access information that is specific to a type 3452590c02aSPaolo Bonzini (either a builtin one or a user-defined one) in order to pass it to C 3462590c02aSPaolo Bonzini functions. Put them in a trait and access it through generic parameters. 3472590c02aSPaolo Bonzini The ``vmstate`` module has examples of how to retrieve type information 3482590c02aSPaolo Bonzini for the fields of a Rust ``struct``. 3492590c02aSPaolo Bonzini 3502590c02aSPaolo Bonzini**Prefer unsafe traits to unsafe functions** 3512590c02aSPaolo Bonzini Unsafe traits are much easier to prove correct than unsafe functions. 3522590c02aSPaolo Bonzini They are an excellent place to store metadata that can later be accessed 3532590c02aSPaolo Bonzini by generic functions. C code usually places metadata in global variables; 3542590c02aSPaolo Bonzini in Rust, they can be stored in traits and then turned into ``static`` 3552590c02aSPaolo Bonzini variables. Often, unsafe traits can be generated by procedural macros. 3562590c02aSPaolo Bonzini 3572590c02aSPaolo Bonzini**Document limitations due to old Rust versions** 3582590c02aSPaolo Bonzini If you need to settle for an inferior solution because of the currently 3592590c02aSPaolo Bonzini supported set of Rust versions, document it in the source and in this 3602590c02aSPaolo Bonzini file. This ensures that it can be fixed when the minimum supported 3612590c02aSPaolo Bonzini version is bumped. 3622590c02aSPaolo Bonzini 3632590c02aSPaolo Bonzini**Keep locking in mind**. 3642590c02aSPaolo Bonzini When marking a type ``Sync``, be careful of whether it needs the big 3652590c02aSPaolo Bonzini QEMU lock. Use ``BqlCell`` and ``BqlRefCell`` for interior data, 3662590c02aSPaolo Bonzini or assert ``bql_locked()``. 3672590c02aSPaolo Bonzini 3682590c02aSPaolo Bonzini**Don't be afraid of complexity, but document and isolate it** 3692590c02aSPaolo Bonzini It's okay to be tricky; device code is written more often than bindings 3702590c02aSPaolo Bonzini code and it's important that it is idiomatic. However, you should strive 3712590c02aSPaolo Bonzini to isolate any tricks in a place (for example a ``struct``, a trait 3722590c02aSPaolo Bonzini or a macro) where it can be documented and tested. If needed, include 3732590c02aSPaolo Bonzini toy versions of the code in the documentation. 3742590c02aSPaolo Bonzini 3752590c02aSPaolo BonziniWriting procedural macros 3762590c02aSPaolo Bonzini''''''''''''''''''''''''' 3772590c02aSPaolo Bonzini 3782590c02aSPaolo BonziniBy conventions, procedural macros are split in two functions, one 3797a2e4086SPaolo Bonzinireturning ``Result<proc_macro2::TokenStream, MacroError>`` with the body of 3802590c02aSPaolo Bonzinithe procedural macro, and the second returning ``proc_macro::TokenStream`` 3812590c02aSPaolo Bonziniwhich is the actual procedural macro. The former's name is the same as 3822590c02aSPaolo Bonzinithe latter with the ``_or_error`` suffix. The code for the latter is more 3832590c02aSPaolo Bonzinior less fixed; it follows the following template, which is fixed apart 3842590c02aSPaolo Bonzinifrom the type after ``as`` in the invocation of ``parse_macro_input!``:: 3852590c02aSPaolo Bonzini 3862590c02aSPaolo Bonzini #[proc_macro_derive(Object)] 3872590c02aSPaolo Bonzini pub fn derive_object(input: TokenStream) -> TokenStream { 3882590c02aSPaolo Bonzini let input = parse_macro_input!(input as DeriveInput); 3892590c02aSPaolo Bonzini let expanded = derive_object_or_error(input).unwrap_or_else(Into::into); 3902590c02aSPaolo Bonzini 3912590c02aSPaolo Bonzini TokenStream::from(expanded) 3922590c02aSPaolo Bonzini } 3932590c02aSPaolo Bonzini 3942590c02aSPaolo BonziniThe ``qemu_api_macros`` crate has utility functions to examine a 3952590c02aSPaolo Bonzini``DeriveInput`` and perform common checks (e.g. looking for a struct 3962590c02aSPaolo Bonziniwith named fields). These functions return ``Result<..., MacroError>`` 3972590c02aSPaolo Bonziniand can be used easily in the procedural macro function:: 3982590c02aSPaolo Bonzini 3992590c02aSPaolo Bonzini fn derive_object_or_error(input: DeriveInput) -> 4002590c02aSPaolo Bonzini Result<proc_macro2::TokenStream, MacroError> 4012590c02aSPaolo Bonzini { 4022590c02aSPaolo Bonzini is_c_repr(&input, "#[derive(Object)]")?; 4032590c02aSPaolo Bonzini 4042590c02aSPaolo Bonzini let name = &input.ident; 4052590c02aSPaolo Bonzini let parent = &get_fields(&input, "#[derive(Object)]")?[0].ident; 4062590c02aSPaolo Bonzini ... 4072590c02aSPaolo Bonzini } 4082590c02aSPaolo Bonzini 4092590c02aSPaolo BonziniUse procedural macros with care. They are mostly useful for two purposes: 4102590c02aSPaolo Bonzini 4112590c02aSPaolo Bonzini* Performing consistency checks; for example ``#[derive(Object)]`` checks 4122590c02aSPaolo Bonzini that the structure has ``#[repr[C])`` and that the type of the first field 4132590c02aSPaolo Bonzini is consistent with the ``ObjectType`` declaration. 4142590c02aSPaolo Bonzini 4152590c02aSPaolo Bonzini* Extracting information from Rust source code into traits, typically based 4162590c02aSPaolo Bonzini on types and attributes. For example, ``#[derive(TryInto)]`` builds an 4172590c02aSPaolo Bonzini implementation of ``TryFrom``, and it uses the ``#[repr(...)]`` attribute 4182590c02aSPaolo Bonzini as the ``TryFrom`` source and error types. 4192590c02aSPaolo Bonzini 4202590c02aSPaolo BonziniProcedural macros can be hard to debug and test; if the code generation 4212590c02aSPaolo Bonziniexceeds a few lines of code, it may be worthwhile to delegate work to 4222590c02aSPaolo Bonzini"regular" declarative (``macro_rules!``) macros and write unit tests for 4232590c02aSPaolo Bonzinithose instead. 4242590c02aSPaolo Bonzini 4252590c02aSPaolo Bonzini 4262590c02aSPaolo BonziniCoding style 4272590c02aSPaolo Bonzini'''''''''''' 4282590c02aSPaolo Bonzini 4292590c02aSPaolo BonziniCode should pass clippy and be formatted with rustfmt. 4302590c02aSPaolo Bonzini 4312590c02aSPaolo BonziniRight now, only the nightly version of ``rustfmt`` is supported. This 4322590c02aSPaolo Bonzinimight change in the future. While CI checks for correct formatting via 4332590c02aSPaolo Bonzini``cargo fmt --check``, maintainers can fix this for you when applying patches. 4342590c02aSPaolo Bonzini 4352590c02aSPaolo BonziniIt is expected that ``qemu_api`` provides full ``rustdoc`` documentation for 4362590c02aSPaolo Bonzinibindings that are in their final shape or close. 4372590c02aSPaolo Bonzini 4382590c02aSPaolo BonziniAdding dependencies 4392590c02aSPaolo Bonzini------------------- 4402590c02aSPaolo Bonzini 4412590c02aSPaolo BonziniGenerally, the set of dependent crates is kept small. Think twice before 4422590c02aSPaolo Bonziniadding a new external crate, especially if it comes with a large set of 4432590c02aSPaolo Bonzinidependencies itself. Sometimes QEMU only needs a small subset of the 4442590c02aSPaolo Bonzinifunctionality; see for example QEMU's ``assertions`` or ``c_str`` modules. 4452590c02aSPaolo Bonzini 4462590c02aSPaolo BonziniOn top of this recommendation, adding external crates to QEMU is a 4472590c02aSPaolo Bonzinislightly complicated process, mostly due to the need to teach Meson how 4482590c02aSPaolo Bonzinito build them. While Meson has initial support for parsing ``Cargo.lock`` 4492590c02aSPaolo Bonzinifiles, it is still highly experimental and is therefore not used. 4502590c02aSPaolo Bonzini 4512590c02aSPaolo BonziniTherefore, external crates must be added as subprojects for Meson to 4522590c02aSPaolo Bonzinilearn how to build them, as well as to the relevant ``Cargo.toml`` files. 4532590c02aSPaolo BonziniThe versions specified in ``rust/Cargo.lock`` must be the same as the 4542590c02aSPaolo Bonzinisubprojects; note that the ``rust/`` directory forms a Cargo `workspace`__, 4552590c02aSPaolo Bonziniand therefore there is a single lock file for the whole build. 4562590c02aSPaolo Bonzini 4572590c02aSPaolo Bonzini__ https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace 4582590c02aSPaolo Bonzini 4592590c02aSPaolo BonziniChoose a version of the crate that works with QEMU's minimum supported 4602590c02aSPaolo BonziniRust version (|msrv|). 4612590c02aSPaolo Bonzini 4622590c02aSPaolo BonziniSecond, a new ``wrap`` file must be added to teach Meson how to download the 4632590c02aSPaolo Bonzinicrate. The wrap file must be named ``NAME-SEMVER-rs.wrap``, where ``NAME`` 4642590c02aSPaolo Bonziniis the name of the crate and ``SEMVER`` is the version up to and including the 4652590c02aSPaolo Bonzinifirst non-zero number. For example, a crate with version ``0.2.3`` will use 4662590c02aSPaolo Bonzini``0.2`` for its ``SEMVER``, while a crate with version ``1.0.84`` will use ``1``. 4672590c02aSPaolo Bonzini 4682590c02aSPaolo BonziniThird, the Meson rules to build the crate must be added at 4692590c02aSPaolo Bonzini``subprojects/NAME-SEMVER-rs/meson.build``. Generally this includes: 4702590c02aSPaolo Bonzini 4712590c02aSPaolo Bonzini* ``subproject`` and ``dependency`` lines for all dependent crates 4722590c02aSPaolo Bonzini 4732590c02aSPaolo Bonzini* a ``static_library`` or ``rust.proc_macro`` line to perform the actual build 4742590c02aSPaolo Bonzini 4752590c02aSPaolo Bonzini* ``declare_dependency`` and a ``meson.override_dependency`` lines to expose 4762590c02aSPaolo Bonzini the result to QEMU and to other subprojects 4772590c02aSPaolo Bonzini 4782590c02aSPaolo BonziniRemember to add ``native: true`` to ``dependency``, ``static_library`` and 4792590c02aSPaolo Bonzini``meson.override_dependency`` for dependencies of procedural macros. 4802590c02aSPaolo BonziniIf a crate is needed in both procedural macros and QEMU binaries, everything 4812590c02aSPaolo Bonziniapart from ``subproject`` must be duplicated to build both native and 4822590c02aSPaolo Bonzininon-native versions of the crate. 4832590c02aSPaolo Bonzini 4842590c02aSPaolo BonziniIt's important to specify the right compiler options. These include: 4852590c02aSPaolo Bonzini 4862590c02aSPaolo Bonzini* the language edition (which can be found in the ``Cargo.toml`` file) 4872590c02aSPaolo Bonzini 4882590c02aSPaolo Bonzini* the ``--cfg`` (which have to be "reverse engineered" from the ``build.rs`` 4892590c02aSPaolo Bonzini file of the crate). 4902590c02aSPaolo Bonzini 4912590c02aSPaolo Bonzini* usually, a ``--cap-lints allow`` argument to hide warnings from rustc 4922590c02aSPaolo Bonzini or clippy. 4932590c02aSPaolo Bonzini 4942590c02aSPaolo BonziniAfter every change to the ``meson.build`` file you have to update the patched 4952590c02aSPaolo Bonziniversion with ``meson subprojects update --reset ``NAME-SEMVER-rs``. This might 4962590c02aSPaolo Bonzinibe automated in the future. 4972590c02aSPaolo Bonzini 4982590c02aSPaolo BonziniAlso, after every change to the ``meson.build`` file it is strongly suggested to 4992590c02aSPaolo Bonzinido a dummy change to the ``.wrap`` file (for example adding a comment like 5002590c02aSPaolo Bonzini``# version 2``), which will help Meson notice that the subproject is out of date. 5012590c02aSPaolo Bonzini 5022590c02aSPaolo BonziniAs a last step, add the new subproject to ``scripts/archive-source.sh``, 5032590c02aSPaolo Bonzini``scripts/make-release`` and ``subprojects/.gitignore``. 504