All of lore.kernel.org
 help / color / mirror / Atom feed
From: Danilo Krummrich <dakr@kernel.org>
To: Benno Lossin <benno.lossin@proton.me>
Cc: gregkh@linuxfoundation.org, rafael@kernel.org,
	bhelgaas@google.com, ojeda@kernel.org, alex.gaynor@gmail.com,
	boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com,
	a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu,
	linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
	rust-for-linux@vger.kernel.org
Subject: Re: [PATCH 3/4] rust: pci: fix unrestricted &mut pci::Device
Date: Thu, 13 Mar 2025 15:25:55 +0100	[thread overview]
Message-ID: <Z9Lq8xyTbIzfPhRX@pollux> (raw)
In-Reply-To: <D8F2S8YNYGZP.3JQKC7ZMRAB2C@proton.me>

On Thu, Mar 13, 2025 at 10:44:38AM +0000, Benno Lossin wrote:
> On Thu Mar 13, 2025 at 3:13 AM CET, Danilo Krummrich wrote:
> > As by now, pci::Device is implemented as:
> >
> > 	#[derive(Clone)]
> > 	pub struct Device(ARef<device::Device>);
> >
> > This may be convenient, but has the implication that drivers can call
> > device methods that require a mutable reference concurrently at any
> > point of time.
> 
> Which methods take mutable references? The `set_master` method you
> mentioned also took a shared reference before this patch.

Yeah, that's basically a bug that I never fixed (until now), since making it
take a mutable reference would not have changed anything in terms of
accessibility.

> 
> > Instead define pci::Device as
> >
> > 	pub struct Device<Ctx: DeviceContext = Normal>(
> > 		Opaque<bindings::pci_dev>,
> > 		PhantomData<Ctx>,
> > 	);
> >
> > and manually implement the AlwaysRefCounted trait.
> >
> > With this we can implement methods that should only be called from
> > bus callbacks (such as probe()) for pci::Device<Core>. Consequently, we
> > make this type accessible in bus callbacks only.
> >
> > Arbitrary references taken by the driver are still of type
> > ARef<pci::Device> and hence don't provide access to methods that are
> > reserved for bus callbacks.
> >
> > Fixes: 1bd8b6b2c5d3 ("rust: pci: add basic PCI device / driver abstractions")
> > Signed-off-by: Danilo Krummrich <dakr@kernel.org>
> 
> Two small nits below, but it already looks good:
> 
> Reviewed-by: Benno Lossin <benno.lossin@proton.me>
> 
> > ---
> >  drivers/gpu/nova-core/driver.rs |   4 +-
> >  rust/kernel/pci.rs              | 126 ++++++++++++++++++++------------
> >  samples/rust/rust_driver_pci.rs |   8 +-
> >  3 files changed, 85 insertions(+), 53 deletions(-)
> >
> 
> > @@ -351,20 +361,8 @@ fn deref(&self) -> &Self::Target {
> >  }
> >  
> >  impl Device {
> 
> One alternative to implementing `Deref` below would be to change this to
> `impl<Ctx: DeviceContext> Device<Ctx>`. But then one would lose the
> ability to just do `&pdev` to get a `Device` from a `Device<Core>`... So
> I think the deref way is better. Just wanted to mention this in case
> someone re-uses this pattern.
> 
> > -    /// Create a PCI Device instance from an existing `device::Device`.
> > -    ///
> > -    /// # Safety
> > -    ///
> > -    /// `dev` must be an `ARef<device::Device>` whose underlying `bindings::device` is a member of
> > -    /// a `bindings::pci_dev`.
> > -    pub unsafe fn from_dev(dev: ARef<device::Device>) -> Self {
> > -        Self(dev)
> > -    }
> > -
> >      fn as_raw(&self) -> *mut bindings::pci_dev {
> > -        // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device`
> > -        // embedded in `struct pci_dev`.
> > -        unsafe { container_of!(self.0.as_raw(), bindings::pci_dev, dev) as _ }
> > +        self.0.get()
> >      }
> >  
> >      /// Returns the PCI vendor ID.
> 
> >  impl AsRef<device::Device> for Device {
> >      fn as_ref(&self) -> &device::Device {
> > -        &self.0
> > +        // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
> > +        // `struct pci_dev`.
> > +        let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
> > +
> > +        // SAFETY: `dev` points to a valid `struct device`.
> > +        unsafe { device::Device::as_ref(dev) }
> 
> Why not use `&**self` instead (ie go through the `Deref` impl)?

`&**self` gives us a `Device` (i.e. `pci::Device`), not a `device::Device`.

> 
> > @@ -77,7 +77,7 @@ fn probe(pdev: &mut pci::Device, info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>
> >  
> >          let drvdata = KBox::new(
> >              Self {
> > -                pdev: pdev.clone(),
> > +                pdev: (&**pdev).into(),
> 
> It might be possible to do:
> 
>     impl From<&pci::Device<Core>> for ARef<pci::Device> { ... }
> 
> Then this line could become `pdev: pdev.into()`.

Yeah, having to write `&**pdev` was bothering me too, and I actually tried what
you suggest, but it didn't compile -- I'll double check.

  reply	other threads:[~2025-03-13 14:26 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-13  2:13 [PATCH 0/4] Improve soundness of bus device abstractions Danilo Krummrich
2025-03-13  2:13 ` [PATCH 1/4] rust: pci: use to_result() in enable_device_mem() Danilo Krummrich
2025-03-13 10:21   ` Benno Lossin
2025-03-13  2:13 ` [PATCH 2/4] rust: device: implement device context marker Danilo Krummrich
2025-03-13 10:29   ` Benno Lossin
2025-03-13 10:41     ` Danilo Krummrich
2025-03-13 10:52       ` Benno Lossin
2025-03-13 14:20         ` Danilo Krummrich
2025-03-13 14:31           ` Benno Lossin
2025-03-13 10:47     ` Benno Lossin
2025-03-13  2:13 ` [PATCH 3/4] rust: pci: fix unrestricted &mut pci::Device Danilo Krummrich
2025-03-13 10:44   ` Benno Lossin
2025-03-13 14:25     ` Danilo Krummrich [this message]
2025-03-13 14:30       ` Benno Lossin
2025-03-13  2:13 ` [PATCH 4/4] rust: platform: fix unrestricted &mut platform::Device Danilo Krummrich
2025-03-13 10:49   ` Benno Lossin
2025-03-13 14:28     ` Danilo Krummrich
2025-03-13 14:41       ` Benno Lossin
2025-03-13  6:08 ` [PATCH 0/4] Improve soundness of bus device abstractions Boqun Feng

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=Z9Lq8xyTbIzfPhRX@pollux \
    --to=dakr@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bhelgaas@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    /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.