xref: /openbmc/qemu/docs/devel/rust.rst (revision 1843a0c01d06049f517fea7e155e5236e7287276)
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