Commit graph

60 commits

Author SHA1 Message Date
Paolo Bonzini
af68b41d40 rust: pl011: only leave embedded object initialization in instance_init
Leave IRQ and MMIO initialization to instance_post_init.  In Rust the
two callbacks are more distinct, because only instance_post_init has a
fully initialized object available.

While at it, add a wrapper for sysbus_init_mmio so that accesses to
the SysBusDevice correctly use shared references.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-01-10 23:34:43 +01:00
Paolo Bonzini
33aa660575 rust: qom: automatically use Drop trait to implement instance_finalize
Replace the customizable INSTANCE_FINALIZE with a generic function
that drops the Rust object.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-01-10 23:34:43 +01:00
Paolo Bonzini
7f65d4e58b rust: add a utility module for compile-time type checks
It is relatively common in the low-level qemu_api code to assert that
a field of a struct has a specific type; for example, it can be used
to ensure that the fields match what the qemu_api and C code expects
for safety.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-01-10 23:34:43 +01:00
Paolo Bonzini
ca0d60a6ad rust: qom: add ParentField
Add a type that, together with the C function object_deinit, ensures the
correct drop order for QOM objects relative to their superclasses.

Right now it is not possible to implement the Drop trait for QOM classes
that are defined in Rust, as the drop() function would not be called when
the object goes away; instead what is called is ObjectImpl::INSTANCE_FINALIZE.
It would be nice for INSTANCE_FINALIZE to just drop the object, but this has
a problem: suppose you have

   pub struct MySuperclass {
       parent: DeviceState,
       field: Box<MyData>,
       ...
   }

   impl Drop for MySuperclass {
       ...
   }

   pub struct MySubclass {
       parent: MySuperclass,
       ...
   }

and an instance_finalize implementation that is like

    unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut Object) {
        unsafe { std::ptr::drop_in_place(obj.cast::<T>()) }
    }

When instance_finalize is called for MySubclass, it will walk the struct's
list of fields and call the drop method for MySuperclass.  Then, object_deinit
recurses to the superclass and calls the same drop method again.  This
will cause double-freeing of the Box<Data>.

What's happening here is that QOM wants to control the drop order of
MySuperclass and MySubclass's fields.  To do so, the parent field must
be marked ManuallyDrop<>, which is quite ugly.  Instead, add a wrapper
type ParentField<> that is specific to QOM.  This hides the implementation
detail of *what* is special about the ParentField, and will also be easy
to check in the #[derive(Object)] macro.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-01-10 23:34:43 +01:00
Paolo Bonzini
122748c83d rust: fix --enable-debug-mutex
--feature is an option for cargo but not for rustc.

Reported-by: Bernhard Beschow <shentey@gmail.com>
Reviewed-by: Bernhard Beschow <shentey@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-01-07 10:18:53 +01:00
Paolo Bonzini
6b4f7b0705 rust: pl011: fix migration stream
The Rust vmstate macros lack the type-safety of their C equivalents (so
safe, much abstraction), and therefore they were predictably wrong.

The registers have already been changed to 32-bits in the previous patch,
but read_pos/read_count/read_trigger also have to be u32 instead of usize.
The easiest way to do so is to let the FIFO use u32 indices instead
of usize.

My plan for making VMStateField typesafe is to have a trait to retrieve
a basic VMStateField; for example something like vmstate_uint32 would
become an implementation of the VMState trait on u32.  Then you'd write
something like "vmstate_of!(Type, field).with_version_id(2)".  That is,
vmstate_of retrieves the basic VMStateField and fills in the offset,
and then more changes can be applied on top.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:38 +01:00
Paolo Bonzini
e05fbacd20 rust: qemu-api: add a module to wrap functions and zero-sized closures
One recurring issue when writing Rust bindings is how to convert a Rust
function ("fn" or "impl Fn") to a C function, and how to pass around
"self" to a C function that only takes a void*.

An easy solution would be to store on the heap a pair consisting of
a pointer to the Rust function and the pointer to "self", but it is
possible to do better.  If an "Fn" has zero size (that is, if it is a
zero-capture closures or a function pointer---which in turn includes all
methods), it is possible to build a generic Rust function that calls it
even if you only have the type; you don't need either the pointer to the
function itself (because the address of the code is part of the type)
or any closure data (because it has size zero).

Introduce a wrapper that provides the functionality of calling the
function given only its type.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
ba3b81f3b6 rust: qom: add initial subset of methods on Object
Add an example of implementing instance methods and converting the
result back to a Rust type.  In this case the returned types are a
string (actually a Cow<str>; but that's transparent as long as it derefs
to &str) and a QOM class.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
f50cd85c84 rust: qom: add casting functionality
Add traits that let client cast typecast safely between object types.
In particular, an upcast is compile-time guaranteed to succeed, and a
YOLO C-style downcast must be marked as unsafe.

The traits are based on an IsA<> trait that declares what
is a subclass of what, which is an idea taken from glib-rs
(https://docs.rs/glib/latest/glib/object/trait.IsA.html).
The four primitives are also taken from there
(https://docs.rs/glib/latest/glib/object/trait.Cast.html).  However,
the implementation of casting itself is a bit different and uses the
Deref trait.

This removes some pointer arithmetic from the pl011 device; it is also a
prerequisite for the definition of methods, so that they can be invoked
on all subclass structs.  This will use the IsA<> trait to detect the
structs that support the methods.

glib also has a "monadic" casting trait which could be implemented on
Option (as in https://docs.rs/glib/latest/glib/object/trait.CastNone.html)
and perhaps even Result.  For now I'm leaving it out, as the patch is
already big enough and the benefit seems debatable.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
c2f41c1b15 rust: tests: allow writing more than one test
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
d4873c5d4f bql: add a "mock" BQL for Rust unit tests
Right now, the stub BQL in stubs/iothread-lock.c always reports itself as
unlocked.  However, Rust would like to run its tests in an environment where
the BQL *is* locked.  Provide an extremely dirty function that flips the
return value of bql_is_locked() to true.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
716d89f9cc rust: re-export C types from qemu-api submodules
Long term we do not want device code to use "bindings" at all, so make it
possible to get the relevant types from the other modules of qemu-api.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
4aed0296b3 rust: rename qemu-api modules to follow C code a bit more
A full match would mean calling them qom::object and hw::core::qdev.  For now,
keep the names shorter but still a bit easier to find.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
cb36da9bd8 rust: qom: add possibility of overriding unparent
Add a blanket definition of ClassInitImpl<ObjectClass> that thunks
ObjectImpl::UNPARENT and overrides it in ObjectClass if it is not
None.

ClassInitImpl<DeviceClass> can now call its superclass's ClassInitImpl,
so that the C and Rust hierarchies match more closely.

This is mostly done as an example of implementing the metaclass
hierarchy under ClassInitImpl.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Paolo Bonzini
6dd818fbbb rust: qom: put class_init together from multiple ClassInitImpl<>
Parameterize the implementation of ClassInitImpl so that it is
possible to call up the chain of implementations, one superclass at
a time starting at ClassInitImpl<Self::Class>.

In order to avoid having to implement (for example)
ClassInitImpl<PL011Class>, also remove the dummy PL011Class and
PL011LuminaryClass structs and specify the same ObjectType::Class as
the superclass.  In the future this default behavior can be handled by
a procedural macro, by looking at the first field in the struct.

Note that the new trait is safe: the calls are started by
rust_class_init<>(), which is not public and can convert the class
pointer to a Rust reference.

Since CLASS_BASE_INIT applies to the type that is being defined,
and only to it, move it to ObjectImpl.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00
Richard Henderson
5f99764869 rust/qemu-api: Use device_class_set_props_n
This means we can update declare_properties to drop the
zero terminator at the end of the array as well.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Lei Yang <leiyang@redhat.com>
Link: https://lore.kernel.org/r/20241218134251.4724-18-richard.henderson@linaro.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:35:25 +01:00
Paolo Bonzini
166e8a1fd1 rust: qom: change the parent type to an associated type
Avoid duplicated code to retrieve the QOM type strings from the
Rust type.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-11 15:57:19 +01:00
Paolo Bonzini
7bd8e3ef63 rust: qom: split ObjectType from ObjectImpl trait
Define a separate trait for fields that also applies to classes that are
defined by C code.  This makes it possible to add metadata to core classes,
which has multiple uses:

- it makes it possible to access the parent struct's TYPE_* for types
  that are defined in Rust code, and to avoid repeating it in every subclass

- implementors of ObjectType will be allowed to implement the IsA<> trait and
  therefore to perform typesafe casts from one class to another.

- in the future, an ObjectType could be created with Foo::new() in a type-safe
  manner, without having to pass a TYPE_* constant.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-11 15:56:54 +01:00
Paolo Bonzini
1f9d52c938 rust: qom: move bridge for TypeInfo functions out of pl011
Allow the ObjectImpl trait to expose Rust functions that avoid raw
pointers (though INSTANCE_INIT for example is still unsafe).
ObjectImpl::TYPE_INFO adds thunks around the functions in
ObjectImpl.

While at it, document `TypeInfo`.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-11 10:32:15 +01:00
Paolo Bonzini
f75fb90ff2 rust: qdev: move bridge for realize and reset functions out of pl011
Allow the DeviceImpl trait to expose safe Rust functions.
rust_device_class_init<> adds thunks around the functions
in DeviceImpl.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
8c80c472da rust: qdev: move device_class_init! body to generic function, ClassInitImpl implementation to macro
Use a trait to access the former parameters to device_class_init!.
This allows hiding the details of the class_init implementation behind
a generic function and makes higher-level functionality available from
qemu_api.

The implementation of ClassInitImpl is then the same for all devices and
is easily macroized.  Later on, we can remove the need to implement
ClassInitImpl by hand for all device types, and stop making
rust_device_class_init<>() public.

While at it, document the members of DeviceImpl.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
c6c4f3e0d9 rust: qom: move ClassInitImpl to the instance side
Put all traits on the instance struct, which makes it possible to reuse
class structs if no new virtual methods or class fields are added.
This is almost always the case for devices (because they are leaf
classes), which is the primary use case for Rust.

This is also simpler: soon we will find the implemented methods without
macros, and this removes the need to go from the class struct to the
instance struct to find the implementation of the *Impl traits.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
3701fb22df rust: qom: convert type_info! macro to an associated const
type_info! is only used in the definition of ObjectImpl::TYPE_INFO, and
in fact in all of them.  Pull type_info!'s definition into the ObjectImpl
trait, thus simplifying the external interface of qemu_api::definitions.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
93ea0896ea rust: qom: rename Class trait to ClassInitImpl
While at it, document it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
b2a4854508 rust: qom: add default definitions for ObjectImpl
Remove a bunch of duplicate const definitions.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
ab870fa106 rust: add a bit operation module
The bindgen supports `static inline` function binding since v0.64.0 as
an experimental feature (`--wrap-static-fns`), and stabilizes it after
v0.70.0.

But the oldest version of bindgen supported by QEMU is v0.60.1, so
there's no way to generate the binding for deposit64() which is `static
inline` (in include/qemu/bitops.h).

Instead, implement it by hand in Rust and make it available for all
unsigned types through an IntegerExt trait. Since it only involves bit
operations, the Rust version of the code is almost identical to the
original C version, but it applies to more types than just u64.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Co-authored-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
4ed4da164c rust: add bindings for interrupt sources
The InterruptSource bindings let us call qemu_set_irq() and sysbus_init_irq()
as safe code.

Interrupt sources, qemu_irq in C code, are pointers to IRQState objects.
They are QOM link properties and can be written to outside the control
of the device (i.e. from a shared reference); therefore they must be
interior-mutable in Rust.  Since thread-safety is provided by the BQL,
what we want here is the newly-introduced BqlCell.  A pointer to the
contents of the BqlCell (an IRQState**, or equivalently qemu_irq*)
is then passed to the C sysbus_init_irq function.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
28d0ad3d42 rust: define prelude
Add a module that will contain frequently used traits and
occasionally structs.  They can be included quickly with
"use qemu_api::prelude::*".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
c596199f63 rust: cell: add BQL-enforcing RefCell variant
Similar to the existing BqlCell, introduce a custom interior mutability
primitive that resembles RefCell but accounts for QEMU's threading model.
Borrowing the RefCell requires proving that the BQL is held, and
attempting to access without the BQL is a runtime panic.

Almost all of the code was taken from Rust's standard library, while
removing unstable features and probably-unnecessary functionality that
amounts to 60% of the original code.  A lot of what's left is documentation,
as well as unit tests in the form of doctests.  These are not yet integrated
in "make check" but can be run with "cargo test --doc".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:26 +01:00
Paolo Bonzini
8e194c0ea5 rust: cell: add BQL-enforcing Cell variant
QEMU objects usually have their pointer shared with the "outside
world" very early in their lifetime, for example when they create their
MemoryRegions.  Because at this point it is not valid anymore to
create a &mut reference to the device, individual parts of the
device struct must be made mutable in a controlled manner.

QEMU's Big Lock (BQL) effectively turns multi-threaded code into
single-threaded code while device code runs, as long as the BQL is not
released while the device is borrowed (because C code could sneak in and
mutate the device).  We can then introduce custom interior mutability primitives
that are semantically similar to the standard library's (single-threaded)
Cell and RefCell, but account for QEMU's threading model.  Accessing
the "BqlCell" or borrowing the "BqlRefCell" requires proving that the
BQL is held, and attempting to access without the BQL is a runtime panic,
similar to RefCell's already-borrowed panic.

With respect to naming I also considered omitting the "Bql" prefix or
moving it to the module, e.g.  qemu_api::bql::{Cell, RefCell}.  However,
this could easily lead to mistakes and confusion; for example rustc could
suggest the wrong import, leading to subtle bugs.

As a start introduce the an equivalent of Cell.  Almost all of the code
was taken from Rust's standard library, while removing unstable features
and probably-unnecessary functionality that constitute a large of the
original code.  A lot of what's left is documentation, as well as unit
tests in the form of doctests.  These are not yet integrated in "make
check" but can be run with "cargo test --doc".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:25 +01:00
Junjie Mao
a3057c52f4 rust/qemu-api: Fix fragment-specifiers in define_property macro
For the matcher of macro, "expr" is used for expressions, while "ident"
is used for variable/function names, and "ty" matches types.

In define_property macro, $field is a member name of type $state, so it
should be defined as "ident", though offset_of! doesn't complain about
this. $type is the type of $field, since it is not used in the macro, so
that no type mismatch error is triggered either.

Fix fragment-specifiers of $field and $type.

Signed-off-by: Junjie Mao <junjie.mao@hotmail.com>
Co-developed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20241017143245.1248589-2-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:24 +01:00
Paolo Bonzini
8a88b55f69 rust: fix doc test syntax
Allow "cargo test --doc" to pass.

Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:49:24 +01:00
Paolo Bonzini
cab1d0bceb rust: build: add "make clippy", "make rustfmt", "make rustdoc"
Abstract common invocations of "cargo", that do not require copying
the generated bindgen file or setting up MESON_BUILD_ROOT.

In the future these could also do completely without cargo and invoke
the underlying programs directly.

Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
2f9eec8f72 rust: build: establish a baseline of lints across all crates
Many lints that default to allow can be helpful in detecting bugs or
keeping the code style homogeneous.  Add them liberally, though perhaps
not as liberally as in hw/char/pl011/src/lib.rs.  In particular, enabling
entire groups can be problematic because of bitrot when new links are
added in the future.

For Clippy, this is actually a feature that is only present in Cargo
1.74.0 but, since we are not using Cargo to *build* QEMU, only developers
will need a new-enough cargo and only to run tools such as clippy.
The requirement does not apply to distros that are building QEMU.

Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
7a35e2fb80 rust: fix a couple style issues from clippy
These are reported as clippy::semicolon_inside_block and clippy::as_ptr_cast_mut.

clippy::semicolon_inside_block can be configured not to lint single-line
blocks; just go with the default.

Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
90868c3dce rust: cargo: store desired warning levels in workspace Cargo.toml
An extra benefit of workspaces is that they allow to place lint level
settings in a single Cargo.toml; the settings are then inherited by
packages in the workspace.

Correspondingly, teach rustc_args.py to get the unexpected_cfgs
configuration from the workspace Cargo.toml.

Note that it is still possible to allow or deny warnings per crate or
module, via the #![] attribute syntax.  The rust/qemu-api/src/bindings.rs
file is an example.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
97ed1e9c8e rust: build: generate lint flags from Cargo.toml
Cargo.toml makes it possible to describe the desired lint level settings
in a nice format.  We can extend this to Meson-built crates, by teaching
rustc_args.py to fetch lint and --check-cfg arguments from Cargo.toml.
--check-cfg arguments come from the unexpected_cfgs lint as well as crate
features

Start with qemu-api, since it already has a [lints.rust] table and
an invocation of rustc_args.py.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
1de82059aa rust: build: restrict --cfg generation to only required symbols
Parse the Cargo.toml file, looking for the unexpected_cfgs
configuration.  When generating --cfg options from the
config-host.h file, only use those that are included in the
configuration.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
f3a6e9bc47 rust: build: move rustc_args.py invocation to qemu-api crate
Only qemu-api needs access to the symbols in config-host.h.  Remove
the temptation to use them elsewhere by limiting the --cfg arguments to
the qemu-api crate.

Per-crate invocation of the script will also be needed to add --check-cfg
options for each crate's features (when more complex, build-time
configurable devices are added in the future).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
cb7ada5409 rust: allow using build-root bindings.rs from cargo
Right now, using cargo with QEMU requires copying by hand the bindings.rs to the
source tree.  Instead, we can use an include file to escape the cage of cargo's
mandated source directory structure.

By running cargo within meson's "devenv" and adding a MESON_BUILD_ROOT
environment variable, it is easy for build.rs to find the file.  However, the
file must be symlinked into cargo's output directory for rust-analyzer to find
it.

Suggested-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
8c28667503 rust: apply --cfg MESON to all crates
We might have more uses for --cfg MESON, even though right now it's only
qemu-api that has generated files.  Since we're going to add more flags
to the add_project_arguments calls for Rust, it makes sense to also add
--cfg MESON everywhere.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-10 18:44:06 +01:00
Paolo Bonzini
ce4a144cf8 rust: do not use --generate-cstr
--generate-cstr is a good idea and generally the right thing to do,
but it is not available in Debian 12 and Ubuntu 22.04.  Work around
the absence.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:17 +01:00
Paolo Bonzini
bb42965dd4 rust: do not use MaybeUninit::zeroed()
MaybeUninit::zeroed() is handy but is not available as a "const" function
until Rust 1.75.0.

Remove the default implementation of Zeroable::ZERO, and write by hand
the definitions for those types that need it.  It may be possible to
add automatic implementation of the trait, via a procedural macro and/or
a trick similar to offset_of!, but do it the easy way for now.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:17 +01:00
Junjie Mao
f351840088 rust: introduce alternative implementation of offset_of!
offset_of! was stabilized in Rust 1.77.0.  Use an alternative implemenation
that was found on the Rust forums, and whose author agreed to license as
MIT for use in QEMU.

The alternative allows only one level of field access, but apart
from this can be used just by replacing core::mem::offset_of! with
qemu_api::offset_of!.

The actual implementation of offset_of! is done in a declarative macro,
but for simplicity and to avoid introducing an extra level of indentation,
the trigger is a procedural macro #[derive(offsets)].

The procedural macro is perhaps a bit overengineered, but it helps
introducing some idioms that will be useful in the future as well.

Signed-off-by: Junjie Mao <junjie.mao@hotmail.com>
Co-developed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00
Paolo Bonzini
39c8faefb5 rust: create a cargo workspace
Workspaces allows tracking dependencies for multiple crates at once,
by having a single Cargo.lock file at the top of the rust/ tree.
Because QEMU's Cargo.lock files have to be synchronized with the versions
of crates in subprojects/, using a workspace avoids the need to copy
over the Cargo.lock file when adding a new device (and thus a new crate)
under rust/hw/.

In addition, workspaces let cargo download and build dependencies just
once.  While right now we have one leaf crate (hw/char/pl011), this
will not be the case once more devices are added.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00
Paolo Bonzini
907d2bbb80 rust: synchronize dependencies between subprojects and Cargo.lock
The next commit will introduce a new build.rs dependency for rust/qemu-api,
version_check.  Before adding it, ensure that all dependencies are
synchronized between the Meson- and cargo-based build systems.

Note that it's not clear whether in the long term we'll use Cargo for
anything; it seems that the three main uses (clippy, rustfmt, rustdoc)
can all be invoked manually---either via glue code in QEMU, or by
extending Meson to gain the relevant functionality.  However, for
the time being we're stuck with Cargo so it should at least look at
the same code as the rest of the build system.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00
Paolo Bonzini
718e255f0a rust: introduce a c_str macro
This allows CStr constants to be defined easily on Rust 1.63.0, while
checking that there are no embedded NULs.  c"" literals were only
stabilized in Rust 1.77.0.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00
Paolo Bonzini
9f7d4520d6 rust: use std::os::raw instead of core::ffi
core::ffi::c_* types were introduced in Rust 1.64.0.  Use the older types
in std::os::raw, which are now aliases of the types in core::ffi.  There is
no need to compile QEMU as no_std, so this is acceptable as long as we support
a version of Debian with Rust 1.63.0.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00
Manos Pitsidianakis
0a65e4124a rust: add definitions for vmstate
Add a new qemu_api module, `vmstate`. Declare a bunch of Rust
macros declared that are equivalent in spirit to the C macros in
include/migration/vmstate.h.

For example the Rust of equivalent of the C macro:

  VMSTATE_UINT32(field_name, struct_name)

is:

  vmstate_uint32!(field_name, StructName)

This breathtaking development will allow us to reach feature parity between
the Rust and C pl011 implementations.

Extracted from a patch by Manos Pitsidianakis
(https://lore.kernel.org/qemu-devel/20241024-rust-round-2-v1-4-051e7a25b978@linaro.org/).

Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00
Paolo Bonzini
6e50bde1e1 rust: provide safe wrapper for MaybeUninit::zeroed()
MaybeUninit::zeroed() is handy, but it introduces unsafe (and has a
pretty heavy syntax in general).  Introduce a trait that provides the
same functionality while staying within safe Rust.

In addition, MaybeUninit::zeroed() is not available as a "const"
function until Rust 1.75.0, so this also prepares for having handwritten
implementations of the trait until we can assume that version.

Reviewed-by: Junjie Mao <junjie.mao@hotmail.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-11-05 14:18:16 +01:00