| .. |msrv| replace:: 1.63.0 | 
 |  | 
 | Rust in QEMU | 
 | ============ | 
 |  | 
 | Rust in QEMU is a project to enable using the Rust programming language | 
 | to add new functionality to QEMU. | 
 |  | 
 | Right now, the focus is on making it possible to write devices that inherit | 
 | from ``SysBusDevice`` in `*safe*`__ Rust.  Later, it may become possible | 
 | to write other kinds of devices (e.g. PCI devices that can do DMA), | 
 | complete boards, or backends (e.g. block device formats). | 
 |  | 
 | __ https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html | 
 |  | 
 | Building the Rust in QEMU code | 
 | ------------------------------ | 
 |  | 
 | The Rust in QEMU code is included in the emulators via Meson.  Meson | 
 | invokes rustc directly, building static libraries that are then linked | 
 | together with the C code.  This is completely automatic when you run | 
 | ``make`` or ``ninja``. | 
 |  | 
 | However, QEMU's build system also tries to be easy to use for people who | 
 | are accustomed to the more "normal" Cargo-based development workflow. | 
 | In particular: | 
 |  | 
 | * the set of warnings and lints that are used to build QEMU always | 
 |   comes from the ``rust/Cargo.toml`` workspace file | 
 |  | 
 | * it is also possible to use ``cargo`` for common Rust-specific coding | 
 |   tasks, in particular to invoke ``clippy``, ``rustfmt`` and ``rustdoc``. | 
 |  | 
 | To this end, QEMU includes a ``build.rs`` build script that picks up | 
 | generated sources from QEMU's build directory and puts it in Cargo's | 
 | output directory (typically ``rust/target/``).  A vanilla invocation | 
 | of Cargo will complain that it cannot find the generated sources, | 
 | which can be fixed in different ways: | 
 |  | 
 | * by using Makefile targets, provided by Meson, that run ``clippy`` or | 
 |   ``rustdoc``: | 
 |  | 
 |     make clippy | 
 |     make rustdoc | 
 |  | 
 | A target for ``rustfmt`` is also declared in ``rust/meson.build``: | 
 |  | 
 |     make rustfmt | 
 |  | 
 | * by invoking ``cargo`` through the Meson `development environment`__ | 
 |   feature:: | 
 |  | 
 |     pyvenv/bin/meson devenv -w ../rust cargo clippy --tests | 
 |     pyvenv/bin/meson devenv -w ../rust cargo fmt | 
 |  | 
 |   If you are going to use ``cargo`` repeatedly, ``pyvenv/bin/meson devenv`` | 
 |   will enter a shell where commands like ``cargo fmt`` just work. | 
 |  | 
 | __ https://mesonbuild.com/Commands.html#devenv | 
 |  | 
 | * by pointing the ``MESON_BUILD_ROOT`` to the top of your QEMU build | 
 |   tree.  This third method is useful if you are using ``rust-analyzer``; | 
 |   you can set the environment variable through the | 
 |   ``rust-analyzer.cargo.extraEnv`` setting. | 
 |  | 
 | As shown above, you can use the ``--tests`` option as usual to operate on test | 
 | code.  Note however that you cannot *build* or run tests via ``cargo``, because | 
 | they need support C code from QEMU that Cargo does not know about.  Tests can | 
 | be run via ``meson test`` or ``make``:: | 
 |  | 
 |    make check-rust | 
 |  | 
 | Note that doctests require all ``.o`` files from the build to be available. | 
 |  | 
 | Supported tools | 
 | ''''''''''''''' | 
 |  | 
 | QEMU supports rustc version 1.77.0 and newer.  Notably, the following features | 
 | are missing: | 
 |  | 
 | * inline const expression (stable in 1.79.0), currently worked around with | 
 |   associated constants in the ``FnCall`` trait. | 
 |  | 
 | * associated constants have to be explicitly marked ``'static`` (`changed in | 
 |   1.81.0`__) | 
 |  | 
 | * ``&raw`` (stable in 1.82.0).  Use ``addr_of!`` and ``addr_of_mut!`` instead, | 
 |   though hopefully the need for raw pointers will go down over time. | 
 |  | 
 | * ``new_uninit`` (stable in 1.82.0).  This is used internally by the ``pinned_init`` | 
 |   crate, which is planned for inclusion in QEMU, but it can be easily patched | 
 |   out. | 
 |  | 
 | * referencing statics in constants (stable in 1.83.0).  For now use a const | 
 |   function; this is an important limitation for QEMU's migration stream | 
 |   architecture (VMState).  Right now, VMState lacks type safety because | 
 |   it is hard to place the ``VMStateField`` definitions in traits. | 
 |  | 
 | * NUL-terminated file names with ``#[track_caller]`` are scheduled for | 
 |   inclusion as ``#![feature(location_file_nul)]``, but it will be a while | 
 |   before QEMU can use them.  For now, there is special code in | 
 |   ``util/error.c`` to support non-NUL-terminated file names. | 
 |  | 
 | * associated const equality would be nice to have for some users of | 
 |   ``callbacks::FnCall``, but is still experimental.  ``ASSERT_IS_SOME`` | 
 |   replaces it. | 
 |  | 
 | __ https://github.com/rust-lang/rust/pull/125258 | 
 |  | 
 | QEMU also supports version 0.60.x of bindgen, which is missing option | 
 | ``--generate-cstr``.  This option requires version 0.66.x and will | 
 | be adopted as soon as supporting these older versions is not necessary | 
 | anymore. | 
 |  | 
 | Writing Rust code in QEMU | 
 | ------------------------- | 
 |  | 
 | QEMU includes four crates: | 
 |  | 
 | * ``qemu_api`` for bindings to C code and useful functionality | 
 |  | 
 | * ``qemu_api_macros`` defines several procedural macros that are useful when | 
 |   writing C code | 
 |  | 
 | * ``pl011`` (under ``rust/hw/char/pl011``) and ``hpet`` (under ``rust/hw/timer/hpet``) | 
 |   are sample devices that demonstrate ``qemu_api`` and ``qemu_api_macros``, and are | 
 |   used to further develop them.  These two crates are functional\ [#issues]_ replacements | 
 |   for the ``hw/char/pl011.c`` and ``hw/timer/hpet.c`` files. | 
 |  | 
 | .. [#issues] The ``pl011`` crate is synchronized with ``hw/char/pl011.c`` | 
 |    as of commit 3e0f118f82.  The ``hpet`` crate is synchronized as of | 
 |    commit 1433e38cc8.  Both are lacking tracing functionality. | 
 |  | 
 | This section explains how to work with them. | 
 |  | 
 | Status | 
 | '''''' | 
 |  | 
 | Modules of ``qemu_api`` can be defined as: | 
 |  | 
 | - *complete*: ready for use in new devices; if applicable, the API supports the | 
 |   full functionality available in C | 
 |  | 
 | - *stable*: ready for production use, the API is safe and should not undergo | 
 |   major changes | 
 |  | 
 | - *proof of concept*: the API is subject to change but allows working with safe | 
 |   Rust | 
 |  | 
 | - *initial*: the API is in its initial stages; it requires large amount of | 
 |   unsafe code; it might have soundness or type-safety issues | 
 |  | 
 | The status of the modules is as follows: | 
 |  | 
 | ================ ====================== | 
 | module           status | 
 | ================ ====================== | 
 | ``assertions``   stable | 
 | ``bitops``       complete | 
 | ``callbacks``    complete | 
 | ``cell``         stable | 
 | ``errno``        complete | 
 | ``error``        stable | 
 | ``irq``          complete | 
 | ``log``          proof of concept | 
 | ``memory``       stable | 
 | ``module``       complete | 
 | ``qdev``         stable | 
 | ``qom``          stable | 
 | ``sysbus``       stable | 
 | ``timer``        stable | 
 | ``vmstate``      proof of concept | 
 | ``zeroable``     stable | 
 | ================ ====================== | 
 |  | 
 | .. note:: | 
 |   API stability is not a promise, if anything because the C APIs are not a stable | 
 |   interface either.  Also, ``unsafe`` interfaces may be replaced by safe interfaces | 
 |   later. | 
 |  | 
 | Naming convention | 
 | ''''''''''''''''' | 
 |  | 
 | C function names usually are prefixed according to the data type that they | 
 | apply to, for example ``timer_mod`` or ``sysbus_connect_irq``.  Furthermore, | 
 | both function and structs sometimes have a ``qemu_`` or ``QEMU`` prefix. | 
 | Generally speaking, these are all removed in the corresponding Rust functions: | 
 | ``QEMUTimer`` becomes ``timer::Timer``, ``timer_mod`` becomes ``Timer::modify``, | 
 | ``sysbus_connect_irq`` becomes ``SysBusDeviceMethods::connect_irq``. | 
 |  | 
 | Sometimes however a name appears multiple times in the QOM class hierarchy, | 
 | and the only difference is in the prefix.  An example is ``qdev_realize`` and | 
 | ``sysbus_realize``.  In such cases, whenever a name is not unique in | 
 | the hierarchy, always add the prefix to the classes that are lower in | 
 | the hierarchy; for the top class, decide on a case by case basis. | 
 |  | 
 | For example: | 
 |  | 
 | ========================== ========================================= | 
 | ``device_cold_reset()``    ``DeviceMethods::cold_reset()`` | 
 | ``pci_device_reset()``     ``PciDeviceMethods::pci_device_reset()`` | 
 | ``pci_bridge_reset()``     ``PciBridgeMethods::pci_bridge_reset()`` | 
 | ========================== ========================================= | 
 |  | 
 | Here, the name is not exactly the same, but nevertheless ``PciDeviceMethods`` | 
 | adds the prefix to avoid confusion, because the functionality of | 
 | ``device_cold_reset()`` and ``pci_device_reset()`` is subtly different. | 
 |  | 
 | In this case, however, no prefix is needed: | 
 |  | 
 | ========================== ========================================= | 
 | ``device_realize()``       ``DeviceMethods::realize()`` | 
 | ``sysbus_realize()``       ``SysbusDeviceMethods::sysbus_realize()`` | 
 | ``pci_realize()``          ``PciDeviceMethods::pci_realize()`` | 
 | ========================== ========================================= | 
 |  | 
 | Here, the lower classes do not add any functionality, and mostly | 
 | provide extra compile-time checking; the basic *realize* functionality | 
 | is the same for all devices.  Therefore, ``DeviceMethods`` does not | 
 | add the prefix. | 
 |  | 
 | Whenever a name is unique in the hierarchy, instead, you should | 
 | always remove the class name prefix. | 
 |  | 
 | Common pitfalls | 
 | ''''''''''''''' | 
 |  | 
 | Rust has very strict rules with respect to how you get an exclusive (``&mut``) | 
 | reference; failure to respect those rules is a source of undefined behavior. | 
 | In particular, even if a value is loaded from a raw mutable pointer (``*mut``), | 
 | it *cannot* be casted to ``&mut`` unless the value was stored to the ``*mut`` | 
 | from a mutable reference.  Furthermore, it is undefined behavior if any | 
 | shared reference was created between the store to the ``*mut`` and the load:: | 
 |  | 
 |     let mut p: u32 = 42; | 
 |     let p_mut = &mut p;                              // 1 | 
 |     let p_raw = p_mut as *mut u32;                   // 2 | 
 |  | 
 |     // p_raw keeps the mutable reference "alive" | 
 |  | 
 |     let p_shared = &p;                               // 3 | 
 |     println!("access from &u32: {}", *p_shared); | 
 |  | 
 |     // Bring back the mutable reference, its lifetime overlaps | 
 |     // with that of a shared reference. | 
 |     let p_mut = unsafe { &mut *p_raw };              // 4 | 
 |     println!("access from &mut 32: {}", *p_mut); | 
 |  | 
 |     println!("access from &u32: {}", *p_shared);     // 5 | 
 |  | 
 | These rules can be tested with `MIRI`__, for example. | 
 |  | 
 | __ https://github.com/rust-lang/miri | 
 |  | 
 | Almost all Rust code in QEMU will involve QOM objects, and pointers to these | 
 | objects are *shared*, for example because they are part of the QOM composition | 
 | tree.  This creates exactly the above scenario: | 
 |  | 
 | 1. a QOM object is created | 
 |  | 
 | 2. a ``*mut`` is created, for example as the opaque value for a ``MemoryRegion`` | 
 |  | 
 | 3. the QOM object is placed in the composition tree | 
 |  | 
 | 4. a memory access dereferences the opaque value to a ``&mut`` | 
 |  | 
 | 5. but the shared reference is still present in the composition tree | 
 |  | 
 | Because of this, QOM objects should almost always use ``&self`` instead | 
 | of ``&mut self``; access to internal fields must use *interior mutability* | 
 | to go from a shared reference to a ``&mut``. | 
 |  | 
 | Whenever C code provides you with an opaque ``void *``, avoid converting it | 
 | to a Rust mutable reference, and use a shared reference instead.  The | 
 | ``qemu_api::cell`` module provides wrappers that can be used to tell the | 
 | Rust compiler about interior mutability, and optionally to enforce locking | 
 | rules for the "Big QEMU Lock".  In the future, similar cell types might | 
 | also be provided for ``AioContext``-based locking as well. | 
 |  | 
 | In particular, device code will usually rely on the ``BqlRefCell`` and | 
 | ``BqlCell`` type to ensure that data is accessed correctly under the | 
 | "Big QEMU Lock".  These cell types are also known to the ``vmstate`` | 
 | crate, which is able to "look inside" them when building an in-memory | 
 | representation of a ``struct``'s layout.  Note that the same is not true | 
 | of a ``RefCell`` or ``Mutex``. | 
 |  | 
 | Bindings code instead will usually use the ``Opaque`` type, which hides | 
 | the contents of the underlying struct and can be easily converted to | 
 | a raw pointer, for use in calls to C functions.  It can be used for | 
 | example as follows:: | 
 |  | 
 |     #[repr(transparent)] | 
 |     #[derive(Debug, qemu_api_macros::Wrapper)] | 
 |     pub struct Object(Opaque<bindings::Object>); | 
 |  | 
 | where the special ``derive`` macro provides useful methods such as | 
 | ``from_raw``, ``as_ptr`, ``as_mut_ptr`` and ``raw_get``.  The bindings will | 
 | then manually check for the big QEMU lock with assertions, which allows | 
 | the wrapper to be declared thread-safe:: | 
 |  | 
 |     unsafe impl Send for Object {} | 
 |     unsafe impl Sync for Object {} | 
 |  | 
 | Writing bindings to C code | 
 | '''''''''''''''''''''''''' | 
 |  | 
 | Here are some things to keep in mind when working on the ``qemu_api`` crate. | 
 |  | 
 | **Look at existing code** | 
 |   Very often, similar idioms in C code correspond to similar tricks in | 
 |   Rust bindings.  If the C code uses ``offsetof``, look at qdev properties | 
 |   or ``vmstate``.  If the C code has a complex const struct, look at | 
 |   ``MemoryRegion``.  Reuse existing patterns for handling lifetimes; | 
 |   for example use ``&T`` for QOM objects that do not need a reference | 
 |   count (including those that can be embedded in other objects) and | 
 |   ``Owned<T>`` for those that need it. | 
 |  | 
 | **Use the type system** | 
 |   Bindings often will need access information that is specific to a type | 
 |   (either a builtin one or a user-defined one) in order to pass it to C | 
 |   functions.  Put them in a trait and access it through generic parameters. | 
 |   The ``vmstate`` module has examples of how to retrieve type information | 
 |   for the fields of a Rust ``struct``. | 
 |  | 
 | **Prefer unsafe traits to unsafe functions** | 
 |   Unsafe traits are much easier to prove correct than unsafe functions. | 
 |   They are an excellent place to store metadata that can later be accessed | 
 |   by generic functions.  C code usually places metadata in global variables; | 
 |   in Rust, they can be stored in traits and then turned into ``static`` | 
 |   variables.  Often, unsafe traits can be generated by procedural macros. | 
 |  | 
 | **Document limitations due to old Rust versions** | 
 |   If you need to settle for an inferior solution because of the currently | 
 |   supported set of Rust versions, document it in the source and in this | 
 |   file.  This ensures that it can be fixed when the minimum supported | 
 |   version is bumped. | 
 |  | 
 | **Keep locking in mind**. | 
 |   When marking a type ``Sync``, be careful of whether it needs the big | 
 |   QEMU lock.  Use ``BqlCell`` and ``BqlRefCell`` for interior data, | 
 |   or assert ``bql_locked()``. | 
 |  | 
 | **Don't be afraid of complexity, but document and isolate it** | 
 |   It's okay to be tricky; device code is written more often than bindings | 
 |   code and it's important that it is idiomatic.  However, you should strive | 
 |   to isolate any tricks in a place (for example a ``struct``, a trait | 
 |   or a macro) where it can be documented and tested.  If needed, include | 
 |   toy versions of the code in the documentation. | 
 |  | 
 | Writing procedural macros | 
 | ''''''''''''''''''''''''' | 
 |  | 
 | By conventions, procedural macros are split in two functions, one | 
 | returning ``Result<proc_macro2::TokenStream, MacroError>`` with the body of | 
 | the procedural macro, and the second returning ``proc_macro::TokenStream`` | 
 | which is the actual procedural macro.  The former's name is the same as | 
 | the latter with the ``_or_error`` suffix.  The code for the latter is more | 
 | or less fixed; it follows the following template, which is fixed apart | 
 | from the type after ``as`` in the invocation of ``parse_macro_input!``:: | 
 |  | 
 |     #[proc_macro_derive(Object)] | 
 |     pub fn derive_object(input: TokenStream) -> TokenStream { | 
 |         let input = parse_macro_input!(input as DeriveInput); | 
 |         let expanded = derive_object_or_error(input).unwrap_or_else(Into::into); | 
 |  | 
 |         TokenStream::from(expanded) | 
 |     } | 
 |  | 
 | The ``qemu_api_macros`` crate has utility functions to examine a | 
 | ``DeriveInput`` and perform common checks (e.g. looking for a struct | 
 | with named fields).  These functions return ``Result<..., MacroError>`` | 
 | and can be used easily in the procedural macro function:: | 
 |  | 
 |     fn derive_object_or_error(input: DeriveInput) -> | 
 |         Result<proc_macro2::TokenStream, MacroError> | 
 |     { | 
 |         is_c_repr(&input, "#[derive(Object)]")?; | 
 |  | 
 |         let name = &input.ident; | 
 |         let parent = &get_fields(&input, "#[derive(Object)]")?[0].ident; | 
 |         ... | 
 |     } | 
 |  | 
 | Use procedural macros with care.  They are mostly useful for two purposes: | 
 |  | 
 | * Performing consistency checks; for example ``#[derive(Object)]`` checks | 
 |   that the structure has ``#[repr[C])`` and that the type of the first field | 
 |   is consistent with the ``ObjectType`` declaration. | 
 |  | 
 | * Extracting information from Rust source code into traits, typically based | 
 |   on types and attributes.  For example, ``#[derive(TryInto)]`` builds an | 
 |   implementation of ``TryFrom``, and it uses the ``#[repr(...)]`` attribute | 
 |   as the ``TryFrom`` source and error types. | 
 |  | 
 | Procedural macros can be hard to debug and test; if the code generation | 
 | exceeds a few lines of code, it may be worthwhile to delegate work to | 
 | "regular" declarative (``macro_rules!``) macros and write unit tests for | 
 | those instead. | 
 |  | 
 |  | 
 | Coding style | 
 | '''''''''''' | 
 |  | 
 | Code should pass clippy and be formatted with rustfmt. | 
 |  | 
 | Right now, only the nightly version of ``rustfmt`` is supported.  This | 
 | might change in the future.  While CI checks for correct formatting via | 
 | ``cargo fmt --check``, maintainers can fix this for you when applying patches. | 
 |  | 
 | It is expected that ``qemu_api`` provides full ``rustdoc`` documentation for | 
 | bindings that are in their final shape or close. | 
 |  | 
 | Adding dependencies | 
 | ------------------- | 
 |  | 
 | Generally, the set of dependent crates is kept small.  Think twice before | 
 | adding a new external crate, especially if it comes with a large set of | 
 | dependencies itself.  Sometimes QEMU only needs a small subset of the | 
 | functionality; see for example QEMU's ``assertions`` module. | 
 |  | 
 | On top of this recommendation, adding external crates to QEMU is a | 
 | slightly complicated process, mostly due to the need to teach Meson how | 
 | to build them.  While Meson has initial support for parsing ``Cargo.lock`` | 
 | files, it is still highly experimental and is therefore not used. | 
 |  | 
 | Therefore, external crates must be added as subprojects for Meson to | 
 | learn how to build them, as well as to the relevant ``Cargo.toml`` files. | 
 | The versions specified in ``rust/Cargo.lock`` must be the same as the | 
 | subprojects; note that the ``rust/`` directory forms a Cargo `workspace`__, | 
 | and therefore there is a single lock file for the whole build. | 
 |  | 
 | __ https://doc.rust-lang.org/cargo/reference/workspaces.html#virtual-workspace | 
 |  | 
 | Choose a version of the crate that works with QEMU's minimum supported | 
 | Rust version (|msrv|). | 
 |  | 
 | Second, a new ``wrap`` file must be added to teach Meson how to download the | 
 | crate.  The wrap file must be named ``NAME-SEMVER-rs.wrap``, where ``NAME`` | 
 | is the name of the crate and ``SEMVER`` is the version up to and including the | 
 | first non-zero number.  For example, a crate with version ``0.2.3`` will use | 
 | ``0.2`` for its ``SEMVER``, while a crate with version ``1.0.84`` will use ``1``. | 
 |  | 
 | Third, the Meson rules to build the crate must be added at | 
 | ``subprojects/NAME-SEMVER-rs/meson.build``.  Generally this includes: | 
 |  | 
 | * ``subproject`` and ``dependency`` lines for all dependent crates | 
 |  | 
 | * a ``static_library`` or ``rust.proc_macro`` line to perform the actual build | 
 |  | 
 | * ``declare_dependency`` and a ``meson.override_dependency`` lines to expose | 
 |   the result to QEMU and to other subprojects | 
 |  | 
 | Remember to add ``native: true`` to ``dependency``, ``static_library`` and | 
 | ``meson.override_dependency`` for dependencies of procedural macros. | 
 | If a crate is needed in both procedural macros and QEMU binaries, everything | 
 | apart from ``subproject`` must be duplicated to build both native and | 
 | non-native versions of the crate. | 
 |  | 
 | It's important to specify the right compiler options.  These include: | 
 |  | 
 | * the language edition (which can be found in the ``Cargo.toml`` file) | 
 |  | 
 | * the ``--cfg`` (which have to be "reverse engineered" from the ``build.rs`` | 
 |   file of the crate). | 
 |  | 
 | * usually, a ``--cap-lints allow`` argument to hide warnings from rustc | 
 |   or clippy. | 
 |  | 
 | After every change to the ``meson.build`` file you have to update the patched | 
 | version with ``meson subprojects update --reset ``NAME-SEMVER-rs``.  This might | 
 | be automated in the future. | 
 |  | 
 | Also, after every change to the ``meson.build`` file it is strongly suggested to | 
 | do a dummy change to the ``.wrap`` file (for example adding a comment like | 
 | ``# version 2``), which will help Meson notice that the subproject is out of date. | 
 |  | 
 | As a last step, add the new subproject to ``scripts/archive-source.sh``, | 
 | ``scripts/make-release`` and ``subprojects/.gitignore``. |