This introduces a new flag "secure" against the Type/TypeInfo
structs, and helpers to check this against the ObjectClass
struct.
If an object is considered to provide a security boundary to
protect against untrusted code, the "secure" flag must be
explicitly set to true.
If it is set to false, or left unset, this indicates that
the object does not intend to provide a security boundary.
Bugs related to this object class will be ineligible for
CVE assignment.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
The clippy::complexity category includes manual_div_ceil, which triggers
with e.g. bindgen 0.73.2. It is not really relevant to automatically
generated code so drop it from all bindgen crates, but keep it
enabled on purpose for other code.
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This is reported by Clippy in the latest nightly builds. Take
a reference instead of cloning.
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
When removing target specific sections (#ifdef TARGET_X), we started
exposing types for different targets in the same file.
Previously, we implemented a filter based on interfaces, but it
proved to be too cumbersome, requiring duplication across architectures.
To simplify it, we add a new callback, is_available, to TypeInfo, that
will replace the existing filtering mechanism.
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Tested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260901202043.26532-2-pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
There are a few special cases of vmstate usage:
The vmstate_msix and vmstate_scsi_device have fields that contain no
data, only a vmstate_info structure.
The VMSTATE_VALIDATE macro serves only to invoke the .field_exists
routine for validation.
Regardless whether these scenarios are valid, add a separate flag to
identify them so we can enforce common constraints for the normal
vmstates such as having a size greater than zero.
Note that n_elems is hardcoded to 1 for all vmstates, except
VMS_[V]ARRAY, so VMSTATE_VALIDATE needed to set VMS_ARRAY to be able
to force n_elems to 0. This patch now checks the flag at
vmstate_n_elems().
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Remove the VMS_VARRAY and VMS_VBUFFER flags that became redundant due
to the previous commit which stores the size of the vmstate offset
variables along with the offset itself.
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
When migrating a buffer or array, the vmstate code needs to know the
size of the buffer and the number of elements of the array. Today a
vmstate writer can choose from a number of macros that take as last
input the name of a struct member from where the size/num will be
read.
At load time, the code will access those values via an opaque pointer
to the migrated data and therefore it needs to also know the size of
the struct member at that offset.
Currently that information is communicated by means of the
VMS_VARRAY_* and VMS_VBUFFER_* flags, where each possible type is
represented by a flag.
So far, that's all fine, but since the vmstate code makes heavy use of
macros, handling several types individually (i.e. by name: int,
int32_t, etc) requires several versions of a same macro, one for each
type. E.g: VMSTATE_VBUFFER_ALLOC_UINT32
^
This creates a pattern where the vmstate writer has to match the macro
name to the data type and has resulted in the code having a tendency
of having one macro version for each type, for each type of vmstate.
There is also some cognitive load to deal with, e.g.
VMSTATE_VARRAY_INT32 doesn't hold an array of int32, it holds an array
of something else and the number of elements for the array is stored
in a variable of type int32.
We're now dealing with the scenario where the code has been expecting
int32_t at some places, but a uint64_t macro variant has been added
without the code being updated.
To address all these situations, introduce a new struct that will hold
the offset of the struct members, but also their size, so the various
extra macros can all be removed and the person writing the vmstate
doesn't need to care about type-checking. Still, keep a minimum check
that those fields are at least integers and fit into 64 bits.
What changes:
1) type checking changes from individual types to a single check for
all integers;
2) there are new ways to access the offsets;
num_offset -> num_indirect.offset
size_offset -> size_indirect.offset
[new] num_indirect.size
[new] size_indirect.size
2) reading the offsets goes from checking the VMS_VARRAY_* flags in an
if/elseif block to comparing offset.size against the hardcoded
sizes in bytes;
3) the VMS_VARRAY_* and VMS_VBUFFER_* flags become obsolete. Removed
in the next patch;
4) memory usage increases +1 byte per vmstate;
Reported-by: Seungjung Kim <seungjung0711@gmail.com>
Fixes: CVE-2026-6426
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3675
Acked-by: Peter Xu <peterx@redhat.com>
[fixed up vmstate_read_from_offset to work on BE host]
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Nightly clippy is a bit smarter and recognizes one more loop
that it wants to be written with iterators.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The bilge crate is heavily reliant on traits and, because trait functions
are never const, bilge and const mix about as well as water and oil.
In addition, it has support for the zerocopy crate that only works for an
older version, and is hard to update because the implementation doesn't
like that zerocopy::FromBits and bilge::FromBits are the same name.
zerocopy is definitely something that QEMU could use in the future.
The bitfield-struct crate, instead, is built from the ground up to
support const. Its use is pretty much the same (device code does not
change at all, only register declarations do), with some things being
more verbose and others being simpler. The code for the crate itself
is much smaller, too.
It does have two disadvantages: it does not let you annotate enums
as bitfields, and it does not integrate with arbitrary-int. Thus, it
requires manual size annotations for anything that is not a bool, iNN
or uNN. Lack of support for arbitrary-int is a very small deal, while
enums are a bit more annoying because they require some repetition
and an implementation of two functions from_bits() and into_bits().
However, the latter is already provided by the "bits!" and
"#[derive(common::TryInto)]" utilities, and thus is not manual
in QEMU's case.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Finally, automatic parsing of Cargo.toml is also possible for QEMU's own
crates, not just for subprojects. This removes the need to list the
dependencies and language editions in both Cargo.toml and meson.build
files.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Let Meson parse Cargo.lock and Cargo.toml and figure out the set
of Rust build dependencies. For now, the only change is that
subprojects are retrieved with "cargo_ws.subproject('NAME')"
instead of "subproject('NAME-API-rs')". However, just calling
"import('rust').workspace()" enables extra functionality that
operates by parsing Cargo.toml; it will be introduced a step
at a time in subsequent commits.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Extract RamDiscardManager and RamDiscardSource from system/memory.c into
dedicated a unit.
This reduces coupling and allows code that only needs the
RamDiscardManager interface to avoid pulling in all of memory.h
dependencies.
rust-sys bindings are no longer generated for RamDiscardSourceClass at
this point, thus we drop the unneeded InterfaceClass use.
Reviewed-by: Peter Xu <peterx@redhat.com>
Acked-by: David Hildenbrand <david@kernel.org>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260604-rdm5-v5-2-5768e6a0943d@redhat.com
Signed-off-by: Peter Xu <peterx@redhat.com>
Misc HW patches
- Build hw/avr/ as common unit files
- Header cleanups around 'cpu.h', 'qemu/audio.h' or duplicated lines
- Remove obsolete TPMIfClass::ppi_enabled field
- Cleanups around load/store API
- Restrict 'compat' properties API to system emulation
- Correct TPM PPCI ACPI for Windows guests on ARM Virt machine
- Simplify physical_memory_range_includes_clean()
- Avoid including CONFIG_DEVICES in hw/arm/smmuv3
- Initialize bus frequency in PPC e500 device tree blob
- More ATI VGA fixes
- Fix fuzzing issues on AVR power controller and SH4 MCU
- MAINTAINERS updates
- Machine compat array for v11.0.0 release
- USB EHCI cleanups
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmnrxC4ACgkQ4+MsLN6t
# wN4Qvw/9FjyoP38tsif1KtdoYm269IFNyriunJ9bh3rCyknVoA03I0tbmMlkHaNE
# UsorLSKdbvhFM5Fq4pa0xuu2bmXZMe5xxm4SHzeJF//ejOQkWqW7NJo/tTsXLhpX
# ZdkouHDM+VGhNjEnBCWQeXDECiVQNXDmDfHIMh6/ufTlF9XTr6rfIEw/uIkzw6HD
# ebCwiMQa+dBQE7WrTtSR2qkqyFN9MGqpJ9bQFgDLw/iDiRqDmZwLtKW2aFMAaPxf
# Wmlz+bvp/tIC0ZNdmGFS5mTS2SN5uP4msP/4EvE6Odcd+CapCGW0CBgXFi9M7OJD
# /4MoIhpuH8cd4wPwQZjY3Lobug8ctxItBzjZeUkQsjUrt5rtLI5+iElkEPfLdCPD
# FX6gCGZxeg7ME7C+A22ZRbXh9gpsoQhmjAn0GvAVuMkaIohPczqLilem3nAWQCEx
# tMvO+M0QIbY8W6aQUQpOLkZMbagaiz8wF3cbnvnZaA+ZrbHt6R2nz/i+H8FGww4c
# ccMoGIRmaST1uWU9t5+/DqhLAgAMuT5ZcbQmRUxHNjZXABUQoz/o0N+gTO3MGyHX
# UCI15p4PTa3pmBMBr9eRFgMbE00k9QdxAi816RlvFtXh1dBYsf5bKPsgzluN27Y2
# QwpTaSLlMTzQbFpSMLujOk+T/HMnMAUP4CMsXFOmXoTSkBLodEI=
# =bA6W
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 24 Apr 2026 15:27:42 EDT
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* tag 'hw-misc-20260422' of https://github.com/philmd/qemu: (62 commits)
MAINTAINERS: Transfer CI maintenance to Pierrick
MAINTAINERS: Maintain MIPS Boston
MAINTAINERS: Remove PhilMD from NVMe Block Driver
MAINTAINERS: Remove my disfunctional emails
MAINTAINERS: Remove my unused git tree locations
MAINTAINERS: Cover hexloader tests under the Generic Loader section
MAINTAINERS: Merge PCIe DOE section within SPDM
hw/usb/hcd-ehci: Introduce common properties macro for sysbus and pci
hw/usb/hcd-ehci: Replace DPRINTF debug logs with trace events
hw/usb/hcd-ehci.c: Replace fprintf(stderr, ...) with qemu_log_mask(LOG_GUEST_ERROR)
hw/usb/hcd-ehci.c: Fix coding style issues reported by checkpatch
hw/usb/hcd-ehci.h: Fix coding style issues reported by checkpatch
hw/usb/hcd-ehci: Remove unused EHCIfstn structure and dead code
hw/arm/virt: Do not select Kconfig symbol PCI_EXPRESS
hw/cxl: Define cxl_fmws_get_all_sorted() stub
hw/sh4/sh7750: Remove forgotten abort() in the MM_ITLB_DATA handler
hw/misc: Fix the valid access size to the avr-power device
hw/ppc/amigaone: remove duplicate include
hw/hyperv: remove duplicate include
hw/virtio/virtio-iommu: remove duplicate include
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
While most of QEMU files use the QOM concept, few of them
use the compatibility properties API (mostly use in system
emulation). Move its prototype to a new "qom/compat-properties.h"
header, keeping "qom/object.h" for generic QOM.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Message-Id: <20260325151728.45378-5-philmd@linaro.org>
All other handlers now have _errp() variants. Should we go this way
for .post_save()? Actually it's rather strange, when the vmstate do
successful preparations in .pre_save(), then successfully save all
sections and subsections, end then fail when all the state is
successfully transferred to the target.
Happily, we have only three .post_save() realizations, all always
successful. Let's make this a rule.
Also note, that we call .post_save() in two places, and handle
its (theoretical) failure inconsistently. Fix that too.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com> #rust
Link: https://lore.kernel.org/qemu-devel/20260304212303.667141-4-vsementsov@yandex-team.ru
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Each timer block occupies 32 bytes, but they only start at
offset 256 of the 1024-byte MMIO register space. Therefore
the correct limit for HPET_MAX_TIMERS is 24, not 32.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The HPETState::hpet_offset_saved boolean was only set in the
hw_compat_2_11[] array, via the 'hpet-offset-saved=false'
property. We removed all machines using that array, let's remove
that property and all the code around it.
Message-ID: <20250501230129.2596-6-philmd@linaro.org>
[thuth: Adapted the rust part to the current master branch]
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20260306093134.27789-1-thuth@redhat.com>
There is a gotcha with qemu_log() usage in a threaded process.
If fragments of a log message are output via qemu_log() it is
possible for messages from two threads to get mixed up. To
prevent this qemu_log_trylock() should be used, along with
fprintf(f) calls.
This is a subtle problem that needs to be explained in the
API docs to ensure correct usage.
In the Rust code, the log_mask_ln method which is conceptually
equivalent to the C qemu_log() call will unconditionally append
a newline so must only ever be used for complete log messages.
Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This inverts the dependency from hwcore to system, replacing it with
a dependency from system to hwcore. It also matches how hw/core/sysbus.h
is part of the system-sys crate, and hw/core/sysbus.c is part of system_ss
on the C side.
This fixes a linker error in hwcore integration tests on msys2.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Move raw FFI bindings generation to separate crates. This makes it
possible to reuse bindgen declarations for a header file in its
dependencies (this was not the case before this change), while keeping
multiple -sys crates to avoid rebuilding all the code whenever
something changes.
Because the -sys crates are generated in dependency order, this also
enforces that the crates are organized in something that resembles
the dependencies between C headers.
The meson.build for rust-safe crates becomes simpler, and it should be
possible in the future to let Meson's cargo support handle most of it.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[General cleanup and Python script. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Prepare for having ObjectClass, DeviceClass and SysbusDeviceClass
defined outside the hwcore and qom crates. It then becomes
impossible to add a method to them.
Extracted from a patch by Marc-André Lureau.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Even though they are not used, rustc does not elide its symbols on msys2.
This causes a linker error.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
The PL011 component is only built / used by ARM targets, which
are only built in little endianness. Thus we only ever built
as little endian, never testing the big-endian possibility of
the DEVICE_NATIVE_ENDIAN definition. Simplify by only keeping
the little endian variant.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-Id: <20251224134644.85582-7-philmd@linaro.org>
The HPET component is only built / used by X86 targets, which
are only built in little endianness. Thus we only ever built
as little endian, never testing the big-endian possibility of
the DEVICE_NATIVE_ENDIAN definition. Simplify by only keeping
the little endian variant.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-Id: <20251224134644.85582-6-philmd@linaro.org>
Otherwise, the Rust crates require the corresponding C code
(e.g. migration/ for rust/migration/) but the dependencies of
that C code, for example the trace files, have not been built.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Do not include libqemuutil in the device crates for the same
reason as in the previous commit. Static libraries like qemuutil
are sensitive to their position on the command line and rustc does not
always get it right.
If rustc places the library too early on the command line, the stubs
are included in the final link product, which results in duplicate
symbols.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Commit de037ab8d83d removed qemuutil dependency from chardev and util
rust crates. However it stayed in the _util_rs static library. The
dependency is also defined as `link_with`, which is fine for C targets,
where the resulting archive gets linked as another parameter on the
command line when it is a static library.
However, when a C library is linked into a Rust rlib, rustc remembers
the dependency into the metadata and adds the library to the linker
command line.
Unfortunately, static libraries are sensitive to their
position on the command line and rustc does not always get it right.
Fortunately, simply removing it from dependencies of any rust libraries
and instead adding them into the dependencies of executables and
doctests fixes the behaviour.
Without this patch the error I get is:
FAILED: [code=1] rust/tests/rust-integration
...
= note: rust-lld: error: unable to find library -l:libqemuutil.a
rust-lld: error: unable to find library -l:libvhost-user-glib.a
rust-lld: error: unable to find library -l:libvhost-user.a
rust-lld: error: unable to find library -l:libqemuutil.a
rust-lld: error: unable to find library -l:libvhost-user-glib.a
rust-lld: error: unable to find library -l:libvhost-user.a
rust-lld: error: unable to find library -l:libqemuutil.a
rust-lld: error: unable to find library -l:libvhost-user-glib.a
rust-lld: error: unable to find library -l:libvhost-user.a
rust-lld: error: unable to find library -l:libqemuutil.a
rust-lld: error: unable to find library -l:libvhost-user-glib.a
rust-lld: error: unable to find library -l:libvhost-user.a
rust-lld: error: unable to find library -l:libqemuutil.a
rust-lld: error: unable to find library -l:libvhost-user-glib.a
rust-lld: error: unable to find library -l:libvhost-user.a
rust-lld: error: unable to find library -l:libqemuutil.a
rust-lld: error: unable to find library -l:libvhost-user-glib.a
rust-lld: error: unable to find library -l:libvhost-user.a
collect2: error: ld returned 1 exit status
Meson could work around it itself by never adding these static libraries
to the rlibs (after all, Meson tracks the transitive dependencies already
and knows how to add them to dependents of those rlibs); at least for now,
do it in QEMU: never link C libraries into Rust rlibs, and add them to the
final build products only.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Implement DTrace/SystemTap SDT by emitting the following:
- The probe crate's probe!() macro is used to emit a DTrace/SystemTap
SDT probe.
- Every trace event gets a corresponding trace_<name>_enabled() -> bool
generated function that Rust code can use to avoid expensive
computation when a trace event is disabled. This API works for other
trace backends too.
`#[allow(dead_code)]` additions are necessary for QEMU's dstate in
generated trace-<dir>.rs files since they are unused by the dtrace
backend. `./configure --enable-trace-backends=` can enable multiple
backends, so keep it simple and just silence the warning instead of
trying to detect the condition when generating the dstate code can be
skipped.
The tracetool tests are updated. Take a look at
tests/tracetool/dtrace.rs to see what the new generated code looks like.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Link: https://lore.kernel.org/r/20251119205200.173170-5-stefanha@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Before using Mutex<> to protect HPETRegisters, it's necessary to apply
Migratable<> wrapper and ToMigrationState first since there's no
pre-defined VMState for Mutex<>.
In addition, this allows to move data from HPETRegisters' vmstate
to HPETTimer's, so as to preserve the original migration format of the C
implementation. To do that, HPETTimer is wrapped with Migratable<>
as well but the implementation of ToMigrationStateShared is
hand-written.
Note that even though the HPETRegistersMigration struct is
generated by ToMigrationState macro, its VMState still needs to be
implemented by hand.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20251113051937.4017675-21-zhao1.liu@intel.com
[Added HPETTimer implementation and restored compatible migration format. - Paolo]
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Timer is a complex struct, allow adding it to a struct that
uses #[derive(ToMigrationState)]; similar to vmstate_timer, only
the expiration time has to be preserved.
In fact, because it is thread-safe, ToMigrationStateShared can
also be implemented without needing a cell or mutex that wraps
the timer.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
These are needed to implement ToMigrationStateShared for timers,
and thus allow including them in Migratable<> structs.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Likewise, do not separate hpet_offset from the other registers.
However, because it is migrated in a subsection it is necessary
to copy it out of HPETRegisters and into a BqlCell<>.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
HPETTimer now has all of its state stored in HPETRegisters, so it does not
need its own BqlRefCell anymore.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Do not separate visible and hidden state; both of them are used in the
same circumstances and it's easiest to place both of them under the
same BqlRefCell.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Lockless IO requires to lock the registers during MMIO access. So it's
necessary to get (or borrow) registers data at top level, and not to
borrow again in child function calls.
Change the argument types from BqlRefCell<HPETRegisters> to
&HPETRegisters/&mut HPETRegisters in child methods, and do borrow the
data once at top level.
This allows BqlRefCell<HPETRegisters> to be directly replaced with
Mutex<HPETRegisters> in subsequent steps without causing lock reentrancy
issues.
Note, passing reference instead of BqlRef/BqlRefMut because BqlRefMut
cannot be re-borrowed as BqlRef, though BqlRef/BqlRefMut themselves play
as the "guard". Passing reference is directly and the extra
bql::is_locked check could help to consolidate safety guarantee.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20251113051937.4017675-19-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>