qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <bonzini@gnu.org>
To: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Cc: qemu-devel <qemu-devel@nongnu.org>,
	qemu-rust@nongnu.org, "Alex Bennée" <alex.bennee@linaro.org>,
	"Daniel Berrange" <berrange@redhat.com>,
	"Kevin Wolf" <kwolf@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>
Subject: Re: Rust in QEMU update, April 2025
Date: Mon, 5 May 2025 15:44:58 +0200	[thread overview]
Message-ID: <7101782c-f642-41e6-8f3a-7061ca722c99@gnu.org> (raw)
In-Reply-To: <CAAjaMXZhq_uv-w_9TT3++HAcO7r_OhriJA0RKWs8YqY_ryjK4w@mail.gmail.com>

On 5/5/25 14:26, Manos Pitsidianakis wrote:
>>     Something I do notice is that there's some inconsistency in
>>     how we've structured things between the two devices, e.g.:
>>
>>     * the pl011 main source file is device.rs, but the hpet one
>>       is hpet.rs
>>
>>     * some places we use the actual names of bits in registers
>>       (eg Interrupt's OE, BE, etc consts), and some places we
>>       seem to have renamed them (e.g. pl011 Flags has clear_to_send
>>       not CTS, etc)
>>
>>     * pl011 has defined named fields for its registers, but hpet does
>>       things like::
>>
>>          self.config.get() & (1 << HPET_CFG_LEG_RT_SHIFT) != 0
>>
>>     * pl011 has a split between PL011State and PL011Registers,
>>       but HPET does not. As I mentioned in an email thread a
>>       little while back, I feel like the State/Registers split
>>       is something we should either make a more clear deliberate
>>       formalised separation that's part of how we recommend
>>       device models should be designed
>>
>>     [...]
>>
>>     I think it would be good to figure out what we think is the
>>     right, best style, for writing this kind of thing, and be
>>     consistent. We have long standing problems in the C device
>>     models where there are multiple different styles for how
>>     we write them, and it would be good to try to aim for
>>     more uniformity on the Rust side.
> 
> The pl011 stuff was deliberate decisions:
> 
> - device.rs vs pl011.rs: the device was written as a crate, so it's
> essentially its own library, plus pl011/src/pl011.rs would be
> redundant :)

Right, I think Peter's comment was more about moving hpet.rs to 
device.rs, and merging PL011's device_class.rs into its device.rs.

>    That said, it's not important, we can choose either convention. I
> like the less redundancy and separation of concerns: if pl011 gets
> converted into a module in a future refactor, it could keep its
> functionality split into different submodules and `pl011.rs` or
> `pl011/mod.rs` would be the device module.

I think it's okay to decide that Rust devices will have mini 
directories: it's just the style of the language and Cargo more or less 
relies on having lib.rs.

In a vacuum I would prefer to have hw/char/pl011.rs for what is now 
rust/hw/char/pl011/lib.rs, and place the other files in hw/char/pl011; 
IIRC rustc accepts that style.  However we still rely on Cargo for some 
things(*), and as long as we do there's not much we can do about it.

     (*) notably "cargo fmt".  Everything else is more or less handled
         by Meson starting with 1.8.0.

> - Using typed registers instead of constants: yes coming from C I can
> understand it can feel unfamiliar. I specifically wanted to make the
> register fields typed to avoid making the implementation a "C port",
> and I think it's worthwhile to use the type system as much as
> possible.

Peter's comments (especially the second and third) were about two kinds 
of inconsistencies:

1) HPET not using bilge.  This was because Zhao looked at HPET from the 
opposite direction compared to what you did on pl011, namely avoiding 
unsafe and modeling the BQL properly, and sacrificed a bit the usage of 
idiomatic code like what bilge provides.

I think that you made the right choice for the first device and he made 
the right choice for the second device.  But now someone should look at 
HPET and do the work that you did to adopt bilge.

2) The choice between bilge on one side, and bitflags or integers on the 
other.  For pl011 you kept interrupt bits as integers for example, and 
this is related to the topic of (non-)availability of const in traits...

>    A straight C port would result into integer constants with integer
> typed fields everywhere for registers/flags.
>    Yes, From/Into aren't const, at least yet, but it's not really a
> hotpath performance wise. I think non-dynamically dispatched trait
> methods can be inlined by annotating the `fn from(..)` impl with a
> `#[inline(always)]` hint but I haven't confirmed this, just
> speculation.

It's not about hot paths, it's more that 1) you cannot use From/Into in 
a "static"'s initializer 2) bilge relies a lot on non-const methods in 
its internal implementation, which makes it quite messy to use it in 
some places.  See for example this thing for which I take all the blame:

     impl Data {
         // bilge is not very const-friendly, unfortunately
         pub const BREAK: Self = Self { value: 1 << 10 };
     }

and the same would be true of interrupt constants and the IRQMASK array.

The separate bilge and bitflags worlds are what bothers me the most in 
the experimental devices.  I can see why they would be very confusing 
for someone who's not had much experience with Rust, and therefore 
doesn't know *why* they are separate.

>    Again, no strong opinions here. I like the "everything is typed"
> approach and I think it's worth it to explore it because it allows us
> to "make invalid/illegal states unrepresentable" as one sage article
> goes.

I agree, and it's why I think you made the right choice using it for 
pl011.  With all the unsafe code that you had to use, strong-typing at 
least showed *something* that Rust could provide compared to C(*).  And 
I like the strong typing too, even if I'm not sure I like bilge's 
*implementation* that much anymore.

I'm not really up for rewriting it, but then I've also done more stupid 
rewrites in the past. :)

    (*) when we were discussing safety vs. unsafety last summer, I may
        have sounded dismissive of this kind of benefit.  My point at the
        time was that unsafe code was so much more complex than C, that
        the benefit of strong-typing wasn't enough to *offset* the
        complexity of unsafe code.  But it is absolutely present.

>> Related to this I have found recently the `attrs crate
>> <https://docs.rs/attrs/>`__, which provides an easy way to parse the
>> contents of attributes in a procedural macro.
> 
> I actually have some WIP patches for this I put a pause on and can
> continue e.g. https://gitlab.com/epilys/rust-for-qemu/-/commit/c2c97caaaf03273fabc14aee5a4d1499668ddbe3

The repository is private, but I look forward to seeing it!  If you want 
to post an RFC without even any code, just to show what the device code 
looks like, that would be helpful as it will catch stuff like lack of 
type safety.

BTW, if you need it to model reflection better I think it is acceptable 
to assume const_refs_to_static is present.

Paolo


  reply	other threads:[~2025-05-05 13:45 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-02 12:13 Rust in QEMU update, April 2025 Paolo Bonzini
2025-05-05 12:26 ` Manos Pitsidianakis
2025-05-05 13:44   ` Paolo Bonzini [this message]
2025-05-05 14:03     ` Peter Maydell
2025-05-06  8:40     ` Manos Pitsidianakis
2025-05-14 13:16       ` Paolo Bonzini
2025-05-20 16:23 ` Zhao Liu
2025-05-20 17:48   ` Paolo Bonzini
2025-05-21  8:42     ` Zhao Liu
2025-05-21  8:36       ` Paolo Bonzini
2025-05-21  9:35         ` Manos Pitsidianakis
2025-05-21 10:51           ` Paolo Bonzini
2025-05-21 21:00         ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7101782c-f642-41e6-8f3a-7061ca722c99@gnu.org \
    --to=bonzini@gnu.org \
    --cc=alex.bennee@linaro.org \
    --cc=berrange@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=manos.pitsidianakis@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-rust@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).