mbox series

[00/26] rust: bundle of prerequisites for HPET implementation

Message ID 20241209123717.99077-1-pbonzini@redhat.com (mailing list archive)
Headers show
Series rust: bundle of prerequisites for HPET implementation | expand

Message

Paolo Bonzini Dec. 9, 2024, 12:36 p.m. UTC
These are the initial set of bindings and support code that are needed
to apply Zhao's posted HPET implementation, and for him to apply
my review comments.  They include:

- QOM cleanups (already posted)

- interrupts sources and cells (posted and reviewed)

- bit deposit and extract operations (new)

- QOM generalization beyond DeviceState (new)

- callbacks system (new)

This is the code that I aim at integrating in QEMU 10.0, and is also
what is needed to develop additional bindings (for e.g. timers) more
or less independently.  I'll focus here on the changes to QOM because they
represent the bulk of the patches.  The bit operations and callbacks are
just one or two patches each, and better explained by the doc comments
in the patch itself.

With respect to qdev, some of this was already explained in the "Rust
in QEMU roadmap".  The patches are split in two series, corresponding
to patches 7-14 and 15-24.

The first and previously posted part mostly removes code duplication,
while keeping the focus very much on four elements of DeviceClass
(realize, legacy reset, properties, vmstate).

The second instead starts to establish a correspondence between the
QOM class hierarchy and the Rust trait system.  The hierarchy of classes
is visible as an ObjectImpl::ParentType associated type, and also present
in the implementation of the ClassInitImpl<ClassType> trait.  The
ClassInitImpl trait is implemented for each Rust-defined QOM class as
before, but now its implementation is split over multiple blanket impls,
one for each superclass.  This allows code reuse of the class_init
wrappers, and is implemented in patches 15-18.

After a brief cleanup intermission in patches 19-21, patches 22-23 provide
the method invocation infrastructure.  Taking inspiration from glib-rs's
GObject bindings, an IsA<> trait declares what is a subclass of what,
which allows two things:

- safe and efficient typecasts, which are compile-time checked so that
  it is an error if the destination type is not a superclass.

- automatically making methods available to all subclasses.  This is done
  through another blanket implementation of a trait, as in glib-rs (see
  https://gtk-rs.org/gtk4-rs/stable/latest/docs/src/gtk4/auto/widget.rs.html#5377),
  though the details are a bit different.

The differences with glib-rs are not small, but fortunately it is the QEMU
version that is simpler.  QEMU does not use a complicated macro like glib's
(https://gtk-rs.org/gtk-rs-core/git/docs/glib/macro.wrapper.html)  to
wrap all subclasses of GObject with an opaque Rust type.  While macros
in general, and procedural macros in particular, may be a useful tool(*),
for now I prefer to ensure that the infrastructure is usable and readable
even without any macro magic.

The two pieces allow defining QOM class hierarchies entirely in Rust;
patch 24 for example gives TYPE_PL011 its own class type PL011Class,
and stores the device id in PL011Class instead of PL011State.

I understand that this is a lot of code, and a lot of added lines in
particular.  Fortunately about 40% of it is docs, which is definitely
a change for QEMU's standards. :)  Also all except the last two patches
have already been used by Zhao, who did not report any particular problem
adopting them.

Excepting the docs, the bulk of the new code is in the BqlCell and
BqlRefCell implementations, as well as in patch 22.  Fortunately these
patches are also relatively boring.  The more interesting patches to
review are patch 15-18 for QOM, and 25 for the callbacks.  Patch 25 is
also the trickiest to explain from the point of view of using advanced
language features; (**) I tried to explain that in the doc comments
and commit messages but please ask for more if necessary.

This series is available at branch rust-next of
https://gitlab.com/bonzini/qemu.git.
Thanks,

Paolo

(*) For example they could automate the declaration of various traits,
many of which are "unsafe" as a reminder that they interact with C code.
This should be pretty easy, considering that the amount of code required
to write QOM types is already smaller in Rust than in C.  qdev properties
are also a useful target, as exemplified by Manos's previously posted
series.

(**) In particular, zero-sized types and the Fn trait.


Paolo Bonzini (26):
  bql: check that the BQL is not dropped within marked sections
  rust: cell: add BQL-enforcing Cell variant
  rust: cell: add BQL-enforcing RefCell variant
  rust: define prelude
  rust: add bindings for interrupt sources
  rust: add a bit operation module
  rust: qom: add default definitions for ObjectImpl
  rust: qom: rename Class trait to ClassInitImpl
  rust: qom: convert type_info! macro to an associated const
  rust: qom: move ClassInitImpl to the instance side
  rust: qdev: move device_class_init! body to generic function,
    ClassInitImpl implementation to macro
  rust: qdev: move bridge for realize and reset functions out of pl011
  rust: qom: automatically use Drop trait to implement instance_finalize
  rust: qom: move bridge for TypeInfo functions out of pl011
  rust: qom: split ObjectType from ObjectImpl trait
  rust: qom: change the parent type to an associated type
  rust: qom: put class_init together from multiple ClassInitImpl<>
  rust: qom: add possibility of overriding unparent
  rust: rename qemu-api modules to follow C code a bit more
  rust: re-export C types from qemu-api submodules
  rust: tests: allow writing more than one test
  rust: qom: add casting functionality
  rust: qom: add initial subset of methods on Object
  rust: qom: move device_id to PL011 class side
  rust: qemu-api: add a module to wrap functions and zero-sized closures
  rust: callbacks: allow passing optional callbacks as ()

 include/qemu/main-loop.h               |  15 +
 stubs/iothread-lock.c                  |  15 +
 system/cpus.c                          |  15 +
 rust/Cargo.toml                        |   1 +
 rust/hw/char/pl011/src/device.rs       | 156 ++---
 rust/hw/char/pl011/src/device_class.rs |  34 -
 rust/qemu-api-macros/src/lib.rs        |   2 +-
 rust/qemu-api/Cargo.toml               |   3 +-
 rust/qemu-api/meson.build              |  14 +-
 rust/qemu-api/src/bitops.rs            | 119 ++++
 rust/qemu-api/src/callbacks.rs         | 238 +++++++
 rust/qemu-api/src/cell.rs              | 822 +++++++++++++++++++++++++
 rust/qemu-api/src/definitions.rs       |  91 ---
 rust/qemu-api/src/device_class.rs      |  74 ---
 rust/qemu-api/src/irq.rs               |  91 +++
 rust/qemu-api/src/lib.rs               |  15 +-
 rust/qemu-api/src/module.rs            |  43 ++
 rust/qemu-api/src/prelude.rs           |  18 +
 rust/qemu-api/src/qdev.rs              | 146 +++++
 rust/qemu-api/src/qom.rs               | 556 +++++++++++++++++
 rust/qemu-api/src/sysbus.rs            |  51 ++
 rust/qemu-api/src/vmstate.rs           |   9 +-
 rust/qemu-api/tests/tests.rs           | 208 +++++--
 23 files changed, 2374 insertions(+), 362 deletions(-)
 create mode 100644 rust/qemu-api/src/bitops.rs
 create mode 100644 rust/qemu-api/src/callbacks.rs
 create mode 100644 rust/qemu-api/src/cell.rs
 delete mode 100644 rust/qemu-api/src/definitions.rs
 delete mode 100644 rust/qemu-api/src/device_class.rs
 create mode 100644 rust/qemu-api/src/irq.rs
 create mode 100644 rust/qemu-api/src/module.rs
 create mode 100644 rust/qemu-api/src/prelude.rs
 create mode 100644 rust/qemu-api/src/qdev.rs
 create mode 100644 rust/qemu-api/src/qom.rs
 create mode 100644 rust/qemu-api/src/sysbus.rs

Comments

Philippe Mathieu-Daudé Dec. 9, 2024, 4:24 p.m. UTC | #1
On 9/12/24 13:36, Paolo Bonzini wrote:

> Paolo Bonzini (26):
>    bql: check that the BQL is not dropped within marked sections
>    rust: cell: add BQL-enforcing Cell variant
>    rust: cell: add BQL-enforcing RefCell variant
>    rust: define prelude
>    rust: add bindings for interrupt sources
>    rust: add a bit operation module
>    rust: qom: add default definitions for ObjectImpl
>    rust: qom: rename Class trait to ClassInitImpl
>    rust: qom: convert type_info! macro to an associated const
>    rust: qom: move ClassInitImpl to the instance side
>    rust: qdev: move device_class_init! body to generic function,
>      ClassInitImpl implementation to macro
>    rust: qdev: move bridge for realize and reset functions out of pl011
>    rust: qom: automatically use Drop trait to implement instance_finalize
>    rust: qom: move bridge for TypeInfo functions out of pl011
>    rust: qom: split ObjectType from ObjectImpl trait
>    rust: qom: change the parent type to an associated type
>    rust: qom: put class_init together from multiple ClassInitImpl<>
>    rust: qom: add possibility of overriding unparent
>    rust: rename qemu-api modules to follow C code a bit more
>    rust: re-export C types from qemu-api submodules
>    rust: tests: allow writing more than one test
>    rust: qom: add casting functionality
>    rust: qom: add initial subset of methods on Object
>    rust: qom: move device_id to PL011 class side
>    rust: qemu-api: add a module to wrap functions and zero-sized closures
>    rust: callbacks: allow passing optional callbacks as ()

Am I correct some patches are from Zhao Liu and got the
authorship inadvertently removed?
Paolo Bonzini Dec. 9, 2024, 5:23 p.m. UTC | #2
On Mon, Dec 9, 2024 at 5:24 PM Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> On 9/12/24 13:36, Paolo Bonzini wrote:
>
> > Paolo Bonzini (26):
> >    bql: check that the BQL is not dropped within marked sections
> >    rust: cell: add BQL-enforcing Cell variant
> >    rust: cell: add BQL-enforcing RefCell variant
> >    rust: define prelude
> >    rust: add bindings for interrupt sources
> >    rust: add a bit operation module
> >    rust: qom: add default definitions for ObjectImpl
> >    rust: qom: rename Class trait to ClassInitImpl
> >    rust: qom: convert type_info! macro to an associated const
> >    rust: qom: move ClassInitImpl to the instance side
> >    rust: qdev: move device_class_init! body to generic function,
> >      ClassInitImpl implementation to macro
> >    rust: qdev: move bridge for realize and reset functions out of pl011
> >    rust: qom: automatically use Drop trait to implement instance_finalize
> >    rust: qom: move bridge for TypeInfo functions out of pl011
> >    rust: qom: split ObjectType from ObjectImpl trait
> >    rust: qom: change the parent type to an associated type
> >    rust: qom: put class_init together from multiple ClassInitImpl<>
> >    rust: qom: add possibility of overriding unparent
> >    rust: rename qemu-api modules to follow C code a bit more
> >    rust: re-export C types from qemu-api submodules
> >    rust: tests: allow writing more than one test
> >    rust: qom: add casting functionality
> >    rust: qom: add initial subset of methods on Object
> >    rust: qom: move device_id to PL011 class side
> >    rust: qemu-api: add a module to wrap functions and zero-sized closures
> >    rust: callbacks: allow passing optional callbacks as ()
>
> Am I correct some patches are from Zhao Liu and got the
> authorship inadvertently removed?

Just one, which is co-authored; it has

Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

So I should have put either Co-authored-by him or left him as the
primary author.

Paolo
Zhao Liu Dec. 10, 2024, 2:38 a.m. UTC | #3
On Mon, Dec 09, 2024 at 06:23:21PM +0100, Paolo Bonzini wrote:
> Date: Mon, 9 Dec 2024 18:23:21 +0100
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: Re: [PATCH 00/26] rust: bundle of prerequisites for HPET
>  implementation
> 
> On Mon, Dec 9, 2024 at 5:24 PM Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> >
> > On 9/12/24 13:36, Paolo Bonzini wrote:
> >
> > > Paolo Bonzini (26):
> > >    bql: check that the BQL is not dropped within marked sections
> > >    rust: cell: add BQL-enforcing Cell variant
> > >    rust: cell: add BQL-enforcing RefCell variant
> > >    rust: define prelude
> > >    rust: add bindings for interrupt sources
> > >    rust: add a bit operation module
> > >    rust: qom: add default definitions for ObjectImpl
> > >    rust: qom: rename Class trait to ClassInitImpl
> > >    rust: qom: convert type_info! macro to an associated const
> > >    rust: qom: move ClassInitImpl to the instance side
> > >    rust: qdev: move device_class_init! body to generic function,
> > >      ClassInitImpl implementation to macro
> > >    rust: qdev: move bridge for realize and reset functions out of pl011
> > >    rust: qom: automatically use Drop trait to implement instance_finalize
> > >    rust: qom: move bridge for TypeInfo functions out of pl011
> > >    rust: qom: split ObjectType from ObjectImpl trait
> > >    rust: qom: change the parent type to an associated type
> > >    rust: qom: put class_init together from multiple ClassInitImpl<>
> > >    rust: qom: add possibility of overriding unparent
> > >    rust: rename qemu-api modules to follow C code a bit more
> > >    rust: re-export C types from qemu-api submodules
> > >    rust: tests: allow writing more than one test
> > >    rust: qom: add casting functionality
> > >    rust: qom: add initial subset of methods on Object
> > >    rust: qom: move device_id to PL011 class side
> > >    rust: qemu-api: add a module to wrap functions and zero-sized closures
> > >    rust: callbacks: allow passing optional callbacks as ()
> >
> > Am I correct some patches are from Zhao Liu and got the
> > authorship inadvertently removed?
> 
> Just one, which is co-authored; it has
> 
> Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> 
> So I should have put either Co-authored-by him or left him as the
> primary author.
> 

Thank you Paolo! You deserve to be credited as the author. It's
completely different from my previous solution, so it's all your
work! HPET will be a user.

Regards,
Zhao