Commit graph

33 commits

Author SHA1 Message Date
Paolo Bonzini
345bef46a1 rust: qom: change instance_init to take a ParentInit<>
This removes undefined behavior associated to writing to uninitialized
fields, and makes it possible to remove "unsafe" from the instance_init
implementation.

However, the init function itself is still unsafe, because it must promise
(as a sort as MaybeUninit::assume_init) that all fields have been
initialized.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-06-17 09:54:52 +02:00
Paolo Bonzini
eb64a0c6ae rust: hpet: fully initialize object during instance_init
The array of BqlRefCell<HPETTimer> is not initialized yet at the
end of instance_init.  In particular, the "state" field is NonNull
and therefore it is invalid to have it as zero bytes.

Note that MaybeUninit is necessary because assigning to self.timers[index]
would trigger Drop of the old value.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-06-17 09:54:51 +02:00
Zhao Liu
869b0afa4f rust/hpet: Drop BqlCell wrapper for num_timers
Now that the num_timers field is initialized as a property, someone may
change its default value using qdev_prop_set_uint8(), but the value is
fixed after the Rust code sees it first.  Since there is no need to modify
it after realize(), it is not to be necessary to have a BqlCell wrapper.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250520152750.2542612-4-zhao1.liu@intel.com
[Remove .into() as well. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-06-06 14:32:54 +02:00
Paolo Bonzini
4d2fec89cb rust/hpet: return errors from realize if properties are incorrect
Match the code in hpet.c; this also allows removing the
BqlCell from the num_timers field.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-06-06 14:32:54 +02:00
Paolo Bonzini
b3bf86b893 rust/hpet: change type of num_timers to usize
Remove the need to convert after every read of the BqlCell.  Because the
vmstate uses a u8 as the size of the VARRAY, this requires switching
the VARRAY to use num_timers_save; which in turn requires ensuring that
the num_timers_save is always there.  For simplicity do this by
removing support for version 1, which QEMU has not been producing for
~15 years.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-06-06 14:32:54 +02:00
Paolo Bonzini
4b66abead9 rust: qdev: support returning errors from realize
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-06-06 14:32:53 +02:00
Paolo Bonzini
734a1e9eee rust: hpet: rename hpet module to "device"
Follow a similar convention as pl011.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-27 19:21:18 +02:00
Zhao Liu
86c54a3a41 rust: Fix Zhao's email address
No one could find Zhao Liu via zhai1.liu@intel.com.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250520152750.2542612-5-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-26 18:04:27 +02:00
Paolo Bonzini
f117857b39 rust: replace c_str! with c"" literals
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-06 16:02:04 +02:00
Paolo Bonzini
b134a09ffa rust: remove offset_of replacement
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-06 16:02:04 +02:00
Paolo Bonzini
5df3fe062f rust: enable clippy::ptr_cast_constness
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-06 16:02:04 +02:00
Paolo Bonzini
0823837224 rust: use MaybeUninit::zeroed() in const context
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-05-06 16:02:04 +02:00
Paolo Bonzini
e4fb0be1d1 rust: use std::ffi instead of std::os::raw
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>
2025-05-06 16:02:04 +02:00
Stefan Zabka
ffd5a60e9b rust: centralize config in workspace root
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>
2025-05-02 23:37:55 +02:00
Zhao Liu
db46654af8 rust/hpet: Support migration
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>
2025-05-02 17:37:46 +02:00
Zhao Liu
ad3ab01bb7 rust/hpet: Fix a clippy error
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>
2025-04-23 10:35:23 +02:00
Zhao Liu
64e1256b21 rust/hpet: convert HPETTimer index to u8 type
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>
2025-04-23 10:35:23 +02:00
Zhao Liu
8163eeee4e rust/hpet: convert num_timers to u8 type
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>
2025-04-23 10:35:23 +02:00
Paolo Bonzini
64acc23c97 rust: hpet: fix decoding of timer registers
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>
2025-03-21 19:34:36 +01:00
Paolo Bonzini
7bda68e8e2 qdev, rust/hpet: fix type of HPET "timers" property
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-03-20 12:14:45 +01:00
Peter Maydell
d1368344bc rust: Kconfig: Factor out whether HPET is Rust or C
Currently we require everywhere that wants to know if there
is an HPET device to check for "CONFIG_HPET || CONFIG_X_HPET_RUST".
Factor out whether the HPET device is Rust or C into a separate
Kconfig stanza, so that CONFIG_HPET means "there is an HPET",
and whether this has pulled in CONFIG_X_HPET_RUST or CONFIG_HPET_C
is something the rest of QEMU can ignore.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Link: https://lore.kernel.org/r/20250319193110.1565578-3-peter.maydell@linaro.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-03-20 09:23:24 +01:00
Paolo Bonzini
519088b7cf rust: hpet: decode HPET registers into enums
Generalize timer_and_addr() to decode all registers into a single enum
HPETRegister, and use the TryInto derive to separate valid and
invalid values.

The main advantage lies in checking that all registers are enumerated
in the "match" statements.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-03-06 12:44:47 +01:00
Paolo Bonzini
09fda8f5dc rust: hpet: do not access fields of SysBusDevice
Fields of SysBusDevice must only be accessed with the BQL taken.  Add
a wrapper that verifies that.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-03-06 12:44:47 +01:00
Paolo Bonzini
a32b239699 rust: timer: wrap QEMUTimer with Opaque<> and express pinning requirements
Timers must be pinned in memory, because modify() stores a pointer to them
in the TimerList.  To express this requirement, change init_full() to take
a pinned reference.  Because the only way to obtain a Timer is through
Timer::new(), which is unsafe, modify() can assume that the timer it got
was later initialized; and because the initialization takes a Pin<&mut
Timer> modify() can assume that the timer is pinned.  In the future the
pinning requirement will be expressed through the pin_init crate instead.

Note that Timer is a bit different from other users of Opaque, in that
it is created in Rust code rather than C code.  This is why it has to
use the unsafe constructors provided by Opaque; and in fact Timer::new()
is also unsafe, because it leaves it to the caller to invoke init_full()
before modify().  Without a call to init_full(), modify() will cause a
NULL pointer dereference.

An alternative could be to combine new() + init_full() by returning a
pinned box; however, using a reference makes it easier to express
the requirement that the opaque outlives the timer.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-03-06 12:44:46 +01:00
Paolo Bonzini
e8dc87fef2 rust: hpet: embed Timer without the Option and Box indirection
This simplifies things for migration, since Option<Box<QEMUTimer>> does not
implement VMState.

This also shows a soundness issue because Timer::new() will leave a NULL
timer list pointer, which can then be dereferenced by Timer::modify().  It
will be fixed shortly.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-03-06 12:44:46 +01:00
Paolo Bonzini
d556226d69 rust: qom: get rid of ClassInitImpl
Complete the conversion from the ClassInitImpl trait to class_init() methods.
This will provide more freedom to split the qemu_api crate in separate parts.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-25 16:18:12 +01:00
Paolo Bonzini
4551f342fe rust: qom: add ObjectImpl::CLASS_INIT
As shown in the PL011 device, the orphan rules required a manual
implementation of ClassInitImpl for anything not in the qemu_api crate;
this gets in the way of moving system emulation-specific code (including
DeviceClass, which as a blanket ClassInitImpl<DeviceClass> implementation)
into its own crate.

Make ClassInitImpl optional, at the cost of having to specify the CLASS_INIT
member by hand in every implementation of ObjectImpl.  The next commits will
get rid of it, replacing all the "impl<T> ClassInitImpl<Class> for T" blocks
with a generic class_init<T> method on Class.

Right now the definition is always the same, but do not provide a default
as that will not be true once ClassInitImpl goes away.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-25 16:18:12 +01:00
Paolo Bonzini
3212da0033 rust: add SysBusDeviceImpl
The only function, right now, is to ensure that anything with a
SysBusDeviceClass class is a SysBusDevice.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-25 16:18:12 +01:00
Zhao Liu
9ee4886700 i386: Fix the missing Rust HPET configuration option
The configuration option of Rust HPET is missing, so that PC machine
can't boot with "hpet=on" when QEMU Rust support is enabled.

Add the Rust HPET configuration option.

Fixes: d128c341a7 ("i386: enable rust hpet for pc when rust is enabled")
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250217154416.3144571-1-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-25 10:49:23 +01:00
Zhao Liu
d128c341a7 i386: enable rust hpet for pc when rust is enabled
Add HPET configuration in PC's Kconfig options, and select HPET device
(Rust version) if Rust is supported.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250210030051.2562726-11-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-13 12:51:34 +01:00
Zhao Liu
6e90a8f813 rust/timer/hpet: add qom and qdev APIs support
Implement QOM & QAPI support for HPET device.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250210030051.2562726-10-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-13 12:51:34 +01:00
Zhao Liu
269a8f155c rust/timer/hpet: add basic HPET timer and HPETState
Add the HPETTimer and HPETState (HPET timer block), along with their
basic methods and register definitions.

This is in preparation for supporting the QAPI interfaces.

Note, wrap all items in HPETState that may be changed in the callback
called by C code into the BqlCell/BqlRefCell.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250210030051.2562726-9-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-13 12:51:34 +01:00
Zhao Liu
0534248a6b rust/timer/hpet: define hpet_fw_cfg
Define HPETFwEntry structure with the same memory layout as
hpet_fw_entry in C.

Further, define the global hpet_cfg variable in Rust which is the
same as the C version. This hpet_cfg variable in Rust will replace
the C version one and allows both Rust code and C code to access it.

The Rust version of hpet_cfg is self-contained, avoiding unsafe
access to C code.

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250210030051.2562726-8-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2025-02-13 12:51:34 +01:00