From: Zhao Liu <zhao1.liu@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org
Subject: Re: [PATCH 07/10] rust: pl011: wrap registers with BqlRefCell
Date: Thu, 23 Jan 2025 13:47:04 +0800 [thread overview]
Message-ID: <Z5HX2G0+bt+3vzVB@intel.com> (raw)
In-Reply-To: <20250117092657.1051233-8-pbonzini@redhat.com>
On Fri, Jan 17, 2025 at 10:26:54AM +0100, Paolo Bonzini wrote:
> Date: Fri, 17 Jan 2025 10:26:54 +0100
> From: Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 07/10] rust: pl011: wrap registers with BqlRefCell
> X-Mailer: git-send-email 2.47.1
>
> This is a step towards making memory ops use a shared reference to the
> device type; it's not yet possible due to the calls to character device
> functions.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> rust/hw/char/pl011/src/device.rs | 38 +++++++++++++-------------
> rust/hw/char/pl011/src/device_class.rs | 8 +++---
> rust/hw/char/pl011/src/memory_ops.rs | 2 +-
> 3 files changed, 24 insertions(+), 24 deletions(-)
>
> diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs
> index 476abe765a9..1d3da59e481 100644
> --- a/rust/hw/char/pl011/src/device.rs
> +++ b/rust/hw/char/pl011/src/device.rs
> @@ -102,14 +102,14 @@ pub struct PL011Registers {
> }
>
> #[repr(C)]
> -#[derive(Debug, qemu_api_macros::Object, qemu_api_macros::offsets)]
This is the issue I also met, so why not drive "Debug" for BqlRefCell?
I tried to do this in [*]. Do we need to reconsider this?
[*]: https://lore.kernel.org/qemu-devel/20241205060714.256270-3-zhao1.liu@intel.com/
> +#[derive(qemu_api_macros::Object, qemu_api_macros::offsets)]
> /// PL011 Device Model in QEMU
> pub struct PL011State {
> pub parent_obj: ParentField<SysBusDevice>,
> pub iomem: MemoryRegion,
> #[doc(alias = "chr")]
> pub char_backend: CharBackend,
> - pub regs: PL011Registers,
> + pub regs: BqlRefCell<PL011Registers>,
This is a good example on the usage of BqlRefCell!
//! `BqlRefCell` is best suited for data that is primarily accessed by the
//! device's own methods, where multiple reads and writes can be grouped within
//! a single borrow and a mutable reference can be passed around. "
> /// QEMU interrupts
> ///
> /// ```text
> @@ -530,8 +530,8 @@ fn post_init(&self) {
> }
> }
>
> + #[allow(clippy::needless_pass_by_ref_mut)]
How did you trigger this lint error? I switched to 1.84 and didn't get
any errors (I noticed that 1.84 fixed the issue of ignoring `self` [*],
but it still doesn't seem to work on my side).
[*]: https://github.com/rust-lang/rust-clippy/pull/12693
> pub fn read(&mut self, offset: hwaddr, _size: u32) -> ControlFlow<u64, u64> {
> - let regs = &mut self.regs;
> match RegisterOffset::try_from(offset) {
> Err(v) if (0x3f8..0x400).contains(&(v >> 2)) => {
> let device_id = self.get_class().device_id;
> @@ -541,7 +541,7 @@ pub fn read(&mut self, offset: hwaddr, _size: u32) -> ControlFlow<u64, u64> {
> // qemu_log_mask(LOG_GUEST_ERROR, "pl011_read: Bad offset 0x%x\n", (int)offset);
> ControlFlow::Break(0)
> }
> - Ok(field) => match regs.read(field) {
> + Ok(field) => match self.regs.borrow_mut().read(field) {
> ControlFlow::Break(value) => ControlFlow::Break(value.into()),
> ControlFlow::Continue(value) => {
> self.update();
[snip]
> @@ -603,19 +603,19 @@ pub fn realize(&mut self) {
> }
>
> pub fn reset(&mut self) {
In principle, this place should also trigger `needless_pass_by_ref_mut`.
> - self.regs.reset();
> + self.regs.borrow_mut().reset();
> }
[snip]
> @@ -657,10 +657,10 @@ pub fn post_load(&mut self, _version_id: u32) -> Result<(), ()> {
> pub unsafe extern "C" fn pl011_receive(opaque: *mut c_void, buf: *const u8, size: c_int) {
> unsafe {
> debug_assert!(!opaque.is_null());
> - let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
> + let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
Perhaps we can use NonNull::new and unwrap()? Then debug_assert! is
unnecessary.
let state = unsafe { NonNull::new(opaque.cast::<PL011State>()).unwrap().as_ref() };
> if size > 0 {
> debug_assert!(!buf.is_null());
> - state.as_mut().receive(u32::from(buf.read_volatile()));
> + state.as_ref().receive(u32::from(buf.read_volatile()));
> }
> }
> }
> @@ -673,8 +673,8 @@ pub fn post_load(&mut self, _version_id: u32) -> Result<(), ()> {
> pub unsafe extern "C" fn pl011_event(opaque: *mut c_void, event: QEMUChrEvent) {
> unsafe {
I think we could narrow the unsafe scope next.
> debug_assert!(!opaque.is_null());
> - let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
> - state.as_mut().event(event)
> + let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
> + state.as_ref().event(event)
> }
> }
[snip]
> diff --git a/rust/hw/char/pl011/src/memory_ops.rs b/rust/hw/char/pl011/src/memory_ops.rs
> index c4e8599ba43..8f66c8d492c 100644
> --- a/rust/hw/char/pl011/src/memory_ops.rs
> +++ b/rust/hw/char/pl011/src/memory_ops.rs
> @@ -26,7 +26,7 @@
> unsafe extern "C" fn pl011_read(opaque: *mut c_void, addr: hwaddr, size: c_uint) -> u64 {
> assert!(!opaque.is_null());
> let mut state = unsafe { NonNull::new_unchecked(opaque.cast::<PL011State>()) };
> - let val = unsafe { state.as_mut().read(addr, size) };
> + let val = unsafe { state.as_mut() }.read(addr, size);
Nice cleanup.
> match val {
> std::ops::ControlFlow::Break(val) => val,
> std::ops::ControlFlow::Continue(val) => {
> --
Nice transition! This is an important step. (Even my comments above
didn't affect the main work of the patch :-) )
So,
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
next prev parent reply other threads:[~2025-01-23 5:27 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-17 9:26 [PATCH 00/10] rust: pl011: correctly use interior mutability Paolo Bonzini
2025-01-17 9:26 ` [PATCH 01/10] rust: pl011: remove unnecessary "extern crate" Paolo Bonzini
2025-01-22 13:37 ` Zhao Liu
2025-01-17 9:26 ` [PATCH 02/10] rust: pl011: hide unnecessarily "pub" items from outside pl011::device Paolo Bonzini
2025-01-22 13:39 ` Zhao Liu
2025-01-17 9:26 ` [PATCH 03/10] rust: pl011: extract conversion to RegisterOffset Paolo Bonzini
2025-01-22 14:34 ` Zhao Liu
2025-01-22 15:00 ` Paolo Bonzini
2025-01-22 17:00 ` Zhao Liu
2025-01-17 9:26 ` [PATCH 04/10] rust: pl011: extract CharBackend receive logic into a separate function Paolo Bonzini
2025-01-22 14:59 ` Zhao Liu
2025-01-22 15:04 ` Paolo Bonzini
2025-01-17 9:26 ` [PATCH 05/10] rust: pl011: pull interrupt updates out of read/write ops Paolo Bonzini
2025-01-22 16:50 ` Zhao Liu
2025-01-22 16:49 ` Paolo Bonzini
2025-01-17 9:26 ` [PATCH 06/10] rust: pl011: extract PL011Registers Paolo Bonzini
2025-01-23 3:44 ` Zhao Liu
2025-01-23 8:07 ` Paolo Bonzini
2025-01-17 9:26 ` [PATCH 07/10] rust: pl011: wrap registers with BqlRefCell Paolo Bonzini
2025-01-23 5:47 ` Zhao Liu [this message]
2025-01-23 8:05 ` Paolo Bonzini
2025-01-23 9:24 ` Zhao Liu
2025-01-23 11:39 ` Paolo Bonzini
2025-01-17 9:26 ` [PATCH 08/10] rust: pl011: remove duplicate definitions Paolo Bonzini
2025-01-23 6:12 ` Zhao Liu
2025-01-17 9:26 ` [PATCH 09/10] rust: pl011: pull device-specific code out of MemoryRegionOps callbacks Paolo Bonzini
2025-01-23 6:18 ` Zhao Liu
2025-01-17 9:26 ` [PATCH 10/10] rust: qdev: make reset take a shared reference Paolo Bonzini
2025-01-23 6:19 ` Zhao Liu
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=Z5HX2G0+bt+3vzVB@intel.com \
--to=zhao1.liu@intel.com \
--cc=pbonzini@redhat.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.