This is a standard replacement for Box<dyn Error> which is more efficient (it only
occcupies one word) and provides a backtrace of the error. This could be plumbed
into &error_abort in the future.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
One common thing that device emulation does is manipulate bitmasks, for example
to check whether two bitmaps have common bits. One example in the pl011 crate
is the checks for pending interrupts, where an interrupt cause corresponds to
at least one interrupt source from a fixed set.
Unfortunately, this is one case where Rust *can* provide some kind of
abstraction but it does so with a rather Perl-ish There Is More Way To
Do It. It is not something where a crate like "bilge" helps, because
it only covers the packing of bits in a structure; operations like "are
all bits of Y set in X" almost never make sense for bit-packed structs;
you need something else, there are several crates that do it and of course
we're going to roll our own.
In particular I examined three:
- bitmask (https://docs.rs/bitmask/0.5.0/bitmask/) does not support const
at all. This is a showstopper because one of the ugly things in the
current pl011 code is the ugliness of code that defines interrupt masks
at compile time:
pub const E: Self = Self(Self::OE.0 | Self::BE.0 | Self::PE.0 | Self::FE.0);
or even worse:
const IRQMASK: [u32; 6] = [
Interrupt::E.0 | Interrupt::MS.0 | Interrupt::RT.0 | Interrupt::TX.0 | Interrupt::RX.0,
...
}
You would have to use roughly the same code---"bitmask" only helps with
defining the struct.
- bitmask_enum (https://docs.rs/bitmask-enum/2.2.5/bitmask_enum/) does not
have a good separation of "valid" and "invalid" bits, so for example "!x"
will invert all 16 bits if you choose u16 as the representation -- even if
you only defined 10 bits. This makes it easier to introduce subtle bugs
in comparisons.
- bitflags (https://docs.rs/bitflags/2.6.0/bitflags/) is generally the most
used such crate and is the one that I took most inspiration from with
respect to the syntax. It's a pretty sophisticated implementation,
with a lot of bells and whistles such as an implementation of "Iter"
that returns the bits one at a time.
The main thing that all of them lack, however, is a way to simplify the
ugly definitions like the above. "bitflags" includes const methods that
perform AND/OR/XOR of masks (these are necessary because Rust operator
overloading does not support const yet, and therefore overloaded operators
cannot be used in the definition of a "static" variable), but they become
even more verbose and unmanageable, like
Interrupt::E.union(Interrupt::MS).union(Interrupt::RT).union(Interrupt::TX).union(Interrupt::RX)
This was the main reason to create "bits", which allows something like
bits!(Interrupt: E | MS | RT | TX | RX)
and expands it 1) add "Interrupt::" in front of all identifiers 2) convert
operators to the wordy const functions like "union". It supports boolean
operators "&", "|", "^", "!" and parentheses, with a relatively simple
recursive descent parser that's implemented in qemu_api_macros.
Since I don't remember exactly how the macro was developed, I cannot exclude
that it contains code from "bitflags". Therefore, I am conservatively leaving
in the MIT and Apache 2.0 licenses from bitflags. In fact, I think there
would be a benefit in being able to push code back to "bitflags" anyway
whenever applicable, so that the two libraries do not diverge too much,
so that's another reason to use this.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Meson has support for invoking clippy and rustdoc on all crates (1.7.0 for
clippy, 1.8.0 for rustdoc). Use it instead of the homegrown version; this
requires disabling the multiple_crate_versions lint (the only one that was
enabled from the "cargo" group)---which was not particularly useful anyway
because all dependencies are converted by hand into Meson subprojects.
rustfmt is still not supported.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Doctests are weird. They are essentially integration tests, but they're
"ran" by executing rustdoc --test, which takes a compiler-ish
command line. This is supported by Meson 1.8.0.
Because they run the linker and need all the .o files, run them in the
build jobs rather than the test jobs.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
libqemuutil is not meant be linked as a whole; if modules are enabled, doing
so results in undefined symbols (corresponding to QMP commands) in
rust/qemu-api/rust-qemu-api-integration.
Support for "objects" in Rust executables is available in Meson 1.8.0; use it
to switching to the same dependencies that C targets use: link_with for
libqemuutil, and objects for everything else.
Reported-by: Bernhard Beschow <shentey@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This is produced by recent versions of bindgen:
warning: use of `offset` with a `usize` casted to an `isize`
--> /builds/bonzini/qemu/rust/target/debug/build/qemu_api-35cb647f4db404b8/out/bindings.inc.rs:39:21
|
39 | let byte = *(core::ptr::addr_of!((*this).storage) as *const u8).offset(byte_index as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(core::ptr::addr_of!((*this).storage) as *const u8).add(byte_index)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
= note: `#[warn(clippy::ptr_offset_with_cast)]` on by default
warning: use of `offset` with a `usize` casted to an `isize`
--> /builds/bonzini/qemu/rust/target/debug/build/qemu_api-35cb647f4db404b8/out/bindings.inc.rs:68:13
|
68 | (core::ptr::addr_of_mut!((*this).storage) as *mut u8).offset(byte_index as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(core::ptr::addr_of_mut!((*this).storage) as *mut u8).add(byte_index)`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
This seems to be new in bindgen 0.71.0, possibly related to bindgen
commit 33006185b7878 ("Add raw_ref_macros feature", 2024-11-22).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Crates like "bilge" and "libc" can be shared by more than one directory,
so declare them directly in rust/meson.build. While at it, make their
variable names end with "_rs" and always add a subproject() statement
(as that pinpoints the error better if the subproject is missing and
cannot be downloaded).
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
These typos are found by "cargo spellcheck". Though it outputs a lot of
noise and false positives, there still are some real typos.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250520152750.2542612-6-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Currently the comments in the Rust pl011 register.rs file include
large amounts of text from the PL011 TRM. This is much more
commentary than we typically quote from a device reference manual,
and much of it is not relevant to QEMU. Compress and rephrase the
comments so that we are not quoting such a large volume of TRM text.
We add a URL for the TRM; readers who need more detail on the
function of the register bits can find it there, presented in
context with the overall description of the hardware.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
While we model a 16-elements RX FIFO since the PL011 model was
introduced in commit cdbdb648b7 ("ARM Versatile Platform Baseboard
emulation"), we only read 1 char at a time!
Have can_receive() return how many elements are available, and use that
in receive().
This is the Rust version of commit 3e0f118f82 ("hw/char/pl011: Really
use RX FIFO depth"); but it also adds back a comment that is present
in commit f576e0733c ("hw/char/pl011: Add support for loopback") and
absent in the Rust code.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
In preparation of having a TX FIFO, rename the RX FIFO methods.
This is the Rust version of commit 40871ca758 ("hw/char/pl011:
Rename RX FIFO methods").
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The proposed suggestion is not correct. First it is not necessary for
*all* classes to be Zeroable, only for Rust-defined ones; classes
defined in C never implement ObjectImpl.
Second, the parent class field need not be Zeroable. For example,
ChardevClass's chr_write and chr_be_event fields cannot be NULL,
therefore ChardevClass cannot be Zeroable. However, char_class_init()
initializes them, therefore ChardevClass could be subclassed by Rust code.
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
"let ... else" is useful when visiting syntax trees; it avoids multiple
levels of indentation and places the error close to the pattern.
While at it, use "ref" to avoid moving the syntax tree objects.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This is allowed since Rust 1.64.0.
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit bundles common config option in the workspace
root and applies them through <config>.workspace = true
Signed-off-by: Stefan Zabka <git@zabka.it>
Link: https://lore.kernel.org/r/20250502212748.124953-1-git@zabka.it
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Based on commit 1433e38cc8 ("hpet: do not overwrite properties on
post_load"), add the basic migration support to Rust HPET.
The current migration implementation introduces multiple unsafe
callbacks. Before the vmstate builder, one possible cleanup approach is
to wrap callbacks in the vmstate binding using a method similar to the
vmstate_exist_fn macro.
However, this approach would also create a lot of repetitive code (since
vmstate has so many callbacks: pre_load, post_load, pre_save, post_save,
needed and dev_unplug_pending). Although it would be cleaner, it would
somewhat deviate from the path of the vmstate builder.
Therefore, firstly focus on completing the functionality of HPET, and
those current unsafe callbacks can at least clearly indicate the needed
functionality of vmstate. The next step is to consider refactoring
vmstate to move towards the vmstate builder direction.
Additionally, update rust.rst about Rust HPET can support migration.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-9-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
NANOSECONDS_PER_SECOND is often used in operations with get_ns(), which
currently returns a u64.
Therefore, define a new NANOSECONDS_PER_SECOND binding is with u64 type
to eliminate unnecessary type conversions (from u32 to u64).
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-6-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Currently, if the `num` field of a varray is not a numeric type, such as
being placed in a wrapper, the array variant of assert_field_type will
fail the check.
HPET currently wraps num_timers in BqlCell<>. Although BqlCell<> is not
necessary from strictly speaking, it makes sense for vmstate to respect
BqlCell.
The failure of assert_field_type is because it cannot convert BqlCell<T>
into usize for use as the index. Use a constant 0 instead for the index,
by avoiding $(...)? and extracting the common parts of
assert_field_type! into an internal case.
Commit message based on a patch by Zhao Liu <zhao1.liu@intel.com>.
Link: https://lore.kernel.org/r/20250414144943.1112885-3-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Make vmstate_struct and vmstate_clock more similar; they are basically the
same thing, except for the clock case having a built-in VMStateDescription.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Unfortunately, at present it's not possible to have a const
"with_exist_check" method to append test_fn after vmstate_struct (due
to error on "constant functions cannot evaluate destructors" for `F`).
Before the vmstate builder, the only way to support "test_fn" is to
extend vmstate_struct macro to add the such new optional member (and
fortunately, Rust can still parse the current expansion!).
Abstract the previous callback implementation of vmstate_validate into
a separate macro, and moves it before vmstate_struct for vmstate_struct
to call.
Note that there's no need to add any extra flag for a new test_fn added
in the VMStateField.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-2-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20250424194905.82506-6-philmd@linaro.org>
All callers now correctly expect a const class data.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20250424194905.82506-5-philmd@linaro.org>
Mechanical change using gsed, then style manually adapted
to pass checkpatch.pl script.
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20250424194905.82506-4-philmd@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20250424194905.82506-3-philmd@linaro.org>
Convert the existing includes with sed.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Convert the existing includes with
sed -i ,exec/memory.h,system/memory.h,g
Move the include within cpu-all.h into a !CONFIG_USER_ONLY block.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Carge clippy complained about:
error: casts from `u8` to `u32` can be expressed infallibly using `From`
So use `From` to convert `u8` to `u32`.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-10-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The C version of HPET uses the uint8_t type for timer index ("tn"), and
usize type in Rust version will break migration between the C and Rust
versions.
So convert HPETTimer index' type to u8 (consistent with the C version of
HPET) to make it friendly for vmstate support.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-8-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The C version of HPET uses the uint8_t type for num_timers, and usize
type in Rust version will break migration between the C and Rust
versions.
So convert num_timers' type to u8 (consistent with the C version of
HPET) to make it friendly for vmstate support.
Note the commit 7bda68e8e2 ("qdev, rust/hpet: fix type of HPET
'timers property") supports the usize type property, but the uint8
property has to be re-supported now.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250414144943.1112885-7-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Due to a missing "& 0x18", timer registers are not decoded correctly.
This breaks the tests/functional/test_x86_64_tuxrun.py functional
test.
Fixes: 519088b7cf ("rust: hpet: decode HPET registers into enums", 2025-03-06)
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The use of "bindings::*" masks incomplete path of VMStateFlags.
Include complete crate path of VMStateFlags in vmstate_clock, and clean
up "bindings::*" in device_class.rs of pl011.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250318130219.1799170-16-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Add a unit test to cover some patterns accepted by vmstate_of macro,
which correspond to the following C version macros:
* VMSTATE_POINTER
* VMSTATE_ARRAY_OF_POINTER
Note: Currently, vmstate_struct can't handle the pointer to structure
case. Leave this case as a FIXME and use vmstate_unused as a place
holder.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250318130219.1799170-14-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>