From nobody Mon Jun 8 11:01:13 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44C52478E5F for ; Fri, 29 May 2026 18:37:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079845; cv=none; b=WWxrl9Bi8oQlWG9CplV9TNDnApHtXcrz0LNyoOotJiRKMxgk/5bdlHMl9wGEODqrl0sMNfhTnJCX6KYlYZX9jp8jgb6HJaryY2iuCF+46rG/bXxZCjrczxza/W9PnjxWhEm1WUdR0xOpu4oTENwSiDrw2OIEQVouI+oGKdoKvqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079845; c=relaxed/simple; bh=A3BK2WnGiGinC8G8uh44KNuTg0qtxi2s9zDoOZWxO6Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cZa/mg3xdNlsCT6mYgT6mgbdbHwf/+54oCmyqwPsQMR1DZPBYakN6DrnBwHBJ8mchY1ODyFc7xzKodTmcqK6cNUKeoBIokb4h1taigmO0+MmOZyT796Rx90C6/GxOG5mZ2CiR6xUMOsb0ngkO+AKpYeqZ8jtQ/SYdCRVRfNWqiI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=D9QBH26k; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="D9QBH26k" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780079840; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=35xOY5UpjGtZddGUxJfTOaK/u/wc0iWDPCGCXs5Om6w=; b=D9QBH26ks/vlBKvSFzyazVuw9ZMZcu934RRF+3Xk4ht1EIxes/UMydkPsfsWRANrxTuy68 GPBlQCF38EqHoDanhItPHtIFm3t+Kxh9PzdqZmfdra1+z0uToEtmhzNaVy/v4GiRQsYzpW hXdfpvTghNZDhxKwlQzTCfoJ27y/AlI= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-384-VLIRDv4IP3exfw8E8q8HAg-1; Fri, 29 May 2026 14:37:16 -0400 X-MC-Unique: VLIRDv4IP3exfw8E8q8HAg-1 X-Mimecast-MFC-AGG-ID: VLIRDv4IP3exfw8E8q8HAg_1780079834 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 804B01956089; Fri, 29 May 2026 18:37:13 +0000 (UTC) Received: from GoldenWind.redhat.com (unknown [10.22.89.101]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B23801686; Fri, 29 May 2026 18:37:09 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org Cc: Alexandre Courbot , Gary Guo , =?UTF-8?q?Christian=20K=C3=B6nig?= , driver-core@lists.linux.dev, Miguel Ojeda , Maarten Lankhorst , Alice Ryhl , Simona Vetter , linux-kernel@vger.kernel.org, Sumit Semwal , linux-media@vger.kernel.org, "Rafael J . Wysocki" , Thomas Zimmermann , Maxime Ripard , David Airlie , Benno Lossin , linaro-mm-sig@lists.linaro.org, Danilo Krummrich , Mukesh Kumar Chaurasiya , Asahi Lina , Daniel Almeida , Lyude Paul , Greg Kroah-Hartman Subject: [PATCH v15 1/6] rust: gem: shmem: Fix Default implementation for ObjectConfig Date: Fri, 29 May 2026 14:33:59 -0400 Message-ID: <20260529183702.677677-2-lyude@redhat.com> In-Reply-To: <20260529183702.677677-1-lyude@redhat.com> References: <20260529183702.677677-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" I completely forgot when coming up with this type that #[derive(Default)] only works if all generics mentioned in the type implement Default (and T usually doesn't). This being said: We don't use `T` for anything besides using it for a reference type, so whether or not it implements `Default` shouldn't actually need to matter. So, fix this by just manually implementing Default instead of deriving it. Signed-off-by: Lyude Paul --- rust/kernel/drm/gem/shmem.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index e1b648920d2f6..8b7de136ab1f9 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -39,7 +39,6 @@ /// /// This is used with [`Object::new()`] to control various properties that= can only be set when /// initially creating a shmem-backed GEM object. -#[derive(Default)] pub struct ObjectConfig<'a, T: DriverObject> { /// Whether to set the write-combine map flag. pub map_wc: bool, @@ -50,6 +49,16 @@ pub struct ObjectConfig<'a, T: DriverObject> { pub parent_resv_obj: Option<&'a Object>, } =20 +impl<'a, T: DriverObject> Default for ObjectConfig<'a, T> { + #[inline(always)] + fn default() -> Self { + Self { + map_wc: false, + parent_resv_obj: None, + } + } +} + /// A shmem-backed GEM object. /// /// # Invariants --=20 2.54.0 From nobody Mon Jun 8 11:01:13 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AFA9147AF6E for ; Fri, 29 May 2026 18:37:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079850; cv=none; b=ROc5MCjYPnZIDTVZpjbYKVIGVmmVq1oYBl8N8F0RRsAgoK+J9Rjsgmuf5JnbVt3kmC/Md3nn8+6CYOivIM/zq2mVNUZwDNYg+EBE1wQIlVMAtlsZTQtVbt8mDPuBQgrjWmAsuO3tTrvq6dOSioQp/byRLfAjEnObJytscUt2ynU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079850; c=relaxed/simple; bh=zMcjO7ihcoZk5wDoPdCIM8BBGLPEZ3tF+HA3S1Djtcs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QUkyC7HSxfiVYcoIyXV0D84UNnKBrK6NTOtzUiSZw6uA+9kFZIiK34tj9GPhQBBgjz6pOGOpE9SeOCrLOA5gSJpyU8tz1JUCcEhdo+utDa2aFEdsspKU7Ujr3TXLYo4367d2/3QFhq2LjaBHq2uISZ+YOufm0TS8qX93MajvV+o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=aMOGEhxV; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="aMOGEhxV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780079843; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a/7mQeFXAswtNMl7FgMd29VC1UT1l6NcPQS0ZRAe3HI=; b=aMOGEhxVzHGPpNo4mZ45z2pXNfAaJEn3s4HsCH3aBC0B0FP2ym3bkL5RChQaJoFZcgcYT7 NUTeWycKt3yDRtWEB2LdONEYjgcdFGWdYSG8DvnckCHYiIMqp89RgfmUDNNpNs6XfLNXqB qXX32tIX4DwGzT2eqsmT4+LQnpailqM= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-180-UD-9UEbMPOyM73EmN8uYHg-1; Fri, 29 May 2026 14:37:20 -0400 X-MC-Unique: UD-9UEbMPOyM73EmN8uYHg-1 X-Mimecast-MFC-AGG-ID: UD-9UEbMPOyM73EmN8uYHg_1780079837 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2514F19560AA; Fri, 29 May 2026 18:37:17 +0000 (UTC) Received: from GoldenWind.redhat.com (unknown [10.22.89.101]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B0ED91688; Fri, 29 May 2026 18:37:13 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org Cc: Alexandre Courbot , Gary Guo , =?UTF-8?q?Christian=20K=C3=B6nig?= , driver-core@lists.linux.dev, Miguel Ojeda , Maarten Lankhorst , Alice Ryhl , Simona Vetter , linux-kernel@vger.kernel.org, Sumit Semwal , linux-media@vger.kernel.org, "Rafael J . Wysocki" , Thomas Zimmermann , Maxime Ripard , David Airlie , Benno Lossin , linaro-mm-sig@lists.linaro.org, Danilo Krummrich , Mukesh Kumar Chaurasiya , Asahi Lina , Daniel Almeida , Lyude Paul , Greg Kroah-Hartman Subject: [PATCH v15 2/6] rust: drm: gem/shmem: Add DmaResvGuard helper Date: Fri, 29 May 2026 14:34:00 -0400 Message-ID: <20260529183702.677677-3-lyude@redhat.com> In-Reply-To: <20260529183702.677677-1-lyude@redhat.com> References: <20260529183702.677677-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" Just a temporary holdover to make locking/unlocking the dma_resv lock much easier. Signed-off-by: Lyude Paul Co-authored-by: Alexandre Courbot Signed-off-by: Alexandre Courbot --- rust/kernel/drm/gem/shmem.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index 8b7de136ab1f9..a116b0752e46a 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -27,7 +27,10 @@ Deref, DerefMut, // }, - ptr::NonNull, + ptr::{ + self, + NonNull, // + }, }; use gem::{ BaseObjectPrivate, @@ -233,3 +236,29 @@ impl driver::AllocImpl for Object { dumb_map_offset: None, }; } + +/// Private helper-type for holding the `dma_resv` object for a GEM shmem = object. +/// +/// When this is dropped, the `dma_resv` lock is dropped as well. +/// +// TODO: This should be replace with a WwMutex equivalent once we have suc= h bindings in the kernel. +struct DmaResvGuard<'a, T: DriverObject>(&'a Object); + +impl<'a, T: DriverObject> DmaResvGuard<'a, T> { + #[inline(always)] + #[expect(unused)] + fn new(obj: &'a Object) -> Self { + // SAFETY: This lock is initialized throughout the lifetime of `ob= ject`. + unsafe { bindings::dma_resv_lock(obj.raw_dma_resv(), ptr::null_mut= ()) }; + + Self(obj) + } +} + +impl<'a, T: DriverObject> Drop for DmaResvGuard<'a, T> { + #[inline(always)] + fn drop(&mut self) { + // SAFETY: We are releasing the lock grabbed during the creation o= f this object. + unsafe { bindings::dma_resv_unlock(self.0.raw_dma_resv()) }; + } +} --=20 2.54.0 From nobody Mon Jun 8 11:01:13 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7CDA47DD63 for ; Fri, 29 May 2026 18:37:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079866; cv=none; b=CIISZ/JjqQ6YrUQ+nIGVvXFMEsTFBUmm17QGBNL0DO7nBBgFBW+Z79m3Li+928WVbAdgscmp6EiugswMGEMDu2z0iRdVeCuufMkauopcMgt+nwtY+Jh8PVDmwufY56bX71t6ilckiwtnabxRwn7EIw/vnpyeL88WC+FMUk4rkZ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079866; c=relaxed/simple; bh=hkkHK3YU/CsnW7PqEeT2/btKCEK8QPIdn9JwJ/xW3H0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QCxvkchkwOMxDNhtJZfuWuzWm/TSlq1/8If9GK++pD8ghT0CN6TdA/TQjVBleyHfEFY/nOhGMsr4YLwBtDdKPiev06UMLTyWzOaBxISyF48bm8WOhGpjprj2JzOYXseELg1fM1T+7lld/XePY8x+W6EINIeW2uOuljGjhASkX3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=he9MIQY1; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="he9MIQY1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780079860; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HrXdDu/InkB9sLGHJzoqpWF/Pn0ivIvjVzrsBZWeZKY=; b=he9MIQY1l0UJ3DKmANIGRLo7qLK78JtCI84bbYLutUMnFlHSjOLp/lUqikGmQPZbkN0hQk 57Mwt83Gyc/l88/2VfBv+itaFBpKLVJujcwXK/YqvbqH6gfFIg4tilqrMsmUZHhTd8Sjkt RqcOpDDC/s/uOLXI/bgHmScRZuH4tFM= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-445-5igLbPZuPgy1vA7zCI_VRA-1; Fri, 29 May 2026 14:37:24 -0400 X-MC-Unique: 5igLbPZuPgy1vA7zCI_VRA-1 X-Mimecast-MFC-AGG-ID: 5igLbPZuPgy1vA7zCI_VRA_1780079841 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AD62D180056E; Fri, 29 May 2026 18:37:20 +0000 (UTC) Received: from GoldenWind.redhat.com (unknown [10.22.89.101]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 55D121686; Fri, 29 May 2026 18:37:17 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org Cc: Alexandre Courbot , Gary Guo , =?UTF-8?q?Christian=20K=C3=B6nig?= , driver-core@lists.linux.dev, Miguel Ojeda , Maarten Lankhorst , Alice Ryhl , Simona Vetter , linux-kernel@vger.kernel.org, Sumit Semwal , linux-media@vger.kernel.org, "Rafael J . Wysocki" , Thomas Zimmermann , Maxime Ripard , David Airlie , Benno Lossin , linaro-mm-sig@lists.linaro.org, Danilo Krummrich , Mukesh Kumar Chaurasiya , Asahi Lina , Daniel Almeida , Lyude Paul , Greg Kroah-Hartman Subject: [PATCH v15 3/6] rust: drm: gem: Add vmap functions to shmem bindings Date: Fri, 29 May 2026 14:34:01 -0400 Message-ID: <20260529183702.677677-4-lyude@redhat.com> In-Reply-To: <20260529183702.677677-1-lyude@redhat.com> References: <20260529183702.677677-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" One of the more obvious use cases for gem shmem objects is the ability to create mappings into their contents. So, let's hook this up in our rust bindings. Similar to how we handle SGTables, we make sure there's two different types of mappings: owned mappings (kernel::drm::gem::shmem::VMap) and borrowed mappings (kernel::drm::gem::shmem::VMapRef). Signed-off-by: Lyude Paul --- V7: * Switch over to the new iosys map bindings that use the Io trait V8: * Get rid of iosys_map bindings for now, only support non-iomem types * s/as_shmem()/as_raw_shmem() V9: * Get rid of some outdated comments I missed * Add missing SIZE check to raw_vmap() * Add a proper unit test that ensures that we actually validate SIZE at compile-time. Turns out it takes only 34 lines to make a boilerplate DRM driver for a kunit test :) * Add unit tests * Add some missing #[inline]s V10: * Correct issue with iomem error path We previously called raw_vunmap() if we got an iomem allocation, but raw_vunmap() was written such that it assumed all allocations were sysmem allocations. Fix this by just making raw_vunmap() accept a iosys_map. V11: * Use Alexandre's clever solution to remove the macros we were using for maintaining two different VMap types. * Change the order of items in Object to ensure that sgt_res is always dropped before obj. * Fix typo in Object.raw_vmap() * s/raw_vmap()/make_vmap()/ Deduplicate code a bit more as well by using more generics here V15: * Add these patches back * We only have one VMap type now! * Use ObjectConfig::default() in unit tests since we unbroke it. rust/kernel/drm/gem/shmem.rs | 433 +++++++++++++++++++++++++++++++++-- 1 file changed, 418 insertions(+), 15 deletions(-) diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index a116b0752e46a..494e0d0d8d0d6 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -11,18 +11,39 @@ =20 use crate::{ container_of, + device::{ + self, + Bound, // + }, + devres::*, drm::{ - device, driver, gem, - private::Sealed, // + private::Sealed, + Device, // + }, + error::{ + from_err_ptr, + to_result, // + }, + io::{ + Io, + IoCapable, + IoKnownSize, // }, - error::to_result, prelude::*, - sync::aref::ARef, + scatterlist, + sync::{ + aref::ARef, + new_lazy_init, + LazyInit, + LazyInitError, // + }, types::Opaque, // }; use core::{ + ffi::c_void, + mem::MaybeUninit, // ops::{ Deref, DerefMut, // @@ -33,6 +54,7 @@ }, }; use gem::{ + BaseObject, BaseObjectPrivate, DriverObject, IntoGEMObject, // @@ -75,6 +97,9 @@ pub struct Object { obj: Opaque, /// Parent object that owns this object's DMA reservation object. parent_resv_obj: Option>>, + /// Devres object for unmapping any SGTable on driver-unbind. + #[pin] + sgt_res: LazyInit>>, #[pin] inner: T, } @@ -118,7 +143,7 @@ fn as_raw_shmem(&self) -> *mut bindings::drm_gem_shmem_= object { /// /// Additional config options can be specified using `config`. pub fn new( - dev: &device::Device, + dev: &Device, size: usize, config: ObjectConfig<'_, T>, args: T::Args, @@ -127,6 +152,7 @@ pub fn new( try_pin_init!(Self { obj <- Opaque::init_zeroed(), parent_resv_obj: config.parent_resv_obj.map(|p| p.into()), + sgt_res <- new_lazy_init!(), inner <- T::new(dev, size, args), }), GFP_KERNEL, @@ -160,9 +186,9 @@ pub fn new( } =20 /// Returns the `Device` that owns this GEM object. - pub fn dev(&self) -> &device::Device { + pub fn dev(&self) -> &Device { // SAFETY: `dev` will have been initialized in `Self::new()` by `d= rm_gem_shmem_init()`. - unsafe { device::Device::from_raw((*self.as_raw()).dev) } + unsafe { Device::from_raw((*self.as_raw()).dev) } } =20 extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) { @@ -170,22 +196,123 @@ extern "C" fn free_callback(obj: *mut bindings::drm_= gem_object) { // - DRM always passes a valid gem object here // - We used drm_gem_shmem_create() in our create_gem_object callb= ack, so we know that // `obj` is contained within a drm_gem_shmem_object - let this =3D unsafe { container_of!(obj, bindings::drm_gem_shmem_o= bject, base) }; - - // SAFETY: - // - We're in free_callback - so this function is safe to call. - // - We won't be using the gem resources on `this` after this call. - unsafe { bindings::drm_gem_shmem_release(this) }; + let base =3D unsafe { container_of!(obj, bindings::drm_gem_shmem_o= bject, base) }; =20 // SAFETY: // - We verified above that `obj` is valid, which makes `this` val= id // - This function is set in AllocOps, so we know that `this` is c= ontained within a // `Object` - let this =3D unsafe { container_of!(Opaque::cast_from(this), Self,= obj) }.cast_mut(); + let this =3D unsafe { container_of!(Opaque::cast_from(base), Self,= obj) }.cast_mut(); + + // We need to reset `sgt_res` first, since doing so requires that = the GEM object is still + // alive. + // SAFETY: + // - We verified above that `this` is valid. + // - `&mut (*this)` does not implement Unpin. + unsafe { Pin::new_unchecked(&mut (*this).sgt_res) }.reset(); + + // SAFETY: + // - We're in free_callback - so this function is safe to call. + // - We won't be using the gem resources on `this` after this call. + unsafe { bindings::drm_gem_shmem_release(base) }; =20 // SAFETY: We're recovering the Kbox<> we created in gem_create_ob= ject() let _ =3D unsafe { KBox::from_raw(this) }; } + + /// Attempt to create a vmap from the gem object, and confirm the size= of said vmap. + fn make_vmap<'a, R, const SIZE: usize>(&'a self) -> Result> + where + R: Deref + From<&'a Self>, + { + // INVARIANT: We check here that the gem object is at least as lar= ge as `SIZE`. + if self.size() < SIZE { + return Err(ENOSPC); + } + + let mut map: MaybeUninit =3D MaybeUninit::uni= nit(); + let guard =3D DmaResvGuard::new(self); + + // SAFETY: drm_gem_shmem_vmap can be called with the DMA reservati= on lock held + to_result(unsafe { + bindings::drm_gem_shmem_vmap_locked(self.as_raw_shmem(), map.a= s_mut_ptr()) + })?; + + // Drop the guard explicitly here, since we may need to call raw_v= unmap() (which re-acquires + // the lock). + drop(guard); + + // SAFETY: The call to drm_gem_shmem_vmap_locked succeeded above, = so we are guaranteed that + // map is properly initialized. + let map =3D unsafe { map.assume_init() }; + + // XXX: We don't currently support iomem allocations + if map.is_iomem { + // SAFETY: + // - The vmap operation above succeeded, guaranteeing that `ma= p` points to a valid + // memory mapping. + // - We checked that this is an iomem allocation, making it sa= fe to read vaddr_iomem + unsafe { self.raw_vunmap(map) }; + + Err(ENOTSUPP) + } else { + Ok(VMap { + // SAFETY: We checked that this is not an iomem allocation= , making it safe to read + // vaddr + addr: unsafe { map.__bindgen_anon_1.vaddr }, + owner: self.into(), + }) + } + } + + /// Unmap a vmap from the gem object. + /// + /// # Safety + /// + /// - The caller promises that `map` is a valid vmap on this gem objec= t. + /// - The caller promises that the memory pointed to by map will no lo= nger be accesed through + /// this instance. + unsafe fn raw_vunmap(&self, mut map: bindings::iosys_map) { + let _guard =3D DmaResvGuard::new(self); + + // SAFETY: + // - This function is safe to call with the DMA reservation lock h= eld. + // - Our `ARef` is proof that the underlying gem object here is in= itialized and thus safe to + // dereference. + unsafe { bindings::drm_gem_shmem_vunmap_locked(self.as_raw_shmem()= , &mut map) }; + } + + /// Creates and returns a virtual kernel memory mapping for this objec= t. + #[inline] + pub fn vmap(&self) -> Result> { + self.make_vmap() + } + + /// Creates and returns an owned reference to a virtual kernel memory = mapping for this object. + #[inline] + pub fn owned_vmap(&self) -> Result> { + self.make_vmap() + } + + /// Creates (if necessary) and returns an immutable reference to a sca= tter-gather table of DMA + /// pages for this object. + /// + /// This will pin the object in memory. It is expected that `dev` shou= ld be a pointer to the + /// same [`device::Device`] which `self` belongs to, otherwise this fu= nction will return + /// `Err(EINVAL)`. + pub fn sg_table<'a>( + &'a self, + dev: &'a device::Device, + ) -> Result<&'a scatterlist::SGTable> { + if dev.as_raw() !=3D self.dev().as_ref().as_raw() { + return Err(EINVAL); + } + + match self.sgt_res.init(Devres::new(dev, SGTableMap::new(self))) { + Ok(ret) | Err(LazyInitError::AlreadyInit(ret)) =3D> Ok(ret.acc= ess(dev)?), + Err(LazyInitError::DuringInit(e)) =3D> Err(e), + } + } } =20 impl Deref for Object { @@ -246,7 +373,6 @@ impl driver::AllocImpl for Object { =20 impl<'a, T: DriverObject> DmaResvGuard<'a, T> { #[inline(always)] - #[expect(unused)] fn new(obj: &'a Object) -> Self { // SAFETY: This lock is initialized throughout the lifetime of `ob= ject`. unsafe { bindings::dma_resv_lock(obj.raw_dma_resv(), ptr::null_mut= ()) }; @@ -262,3 +388,280 @@ fn drop(&mut self) { unsafe { bindings::dma_resv_unlock(self.0.raw_dma_resv()) }; } } + +macro_rules! impl_vmap_io_capable { + ($impl:ident, $ty:ty) =3D> { + impl IoCapable<$ty> for $impl + where + D: DriverObject, + R: Deref>, + { + #[inline(always)] + unsafe fn io_read(&self, address: usize) -> $ty { + let ptr =3D address as *mut $ty; + + // SAFETY: The safety contract of `io_read` guarantees tha= t address is a valid + // address within the bounds of `Self` of at least the siz= e of $ty, and is properly + // aligned. + unsafe { ptr::read(ptr) } + } + + #[inline(always)] + unsafe fn io_write(&self, value: $ty, address: usize) { + let ptr =3D address as *mut $ty; + + // SAFETY: The safety contract of `io_write` guarantees th= at address is a valid + // address within the bounds of `Self` of at least the siz= e of $ty, and is properly + // aligned. + unsafe { ptr::write(ptr, value) } + } + } + }; +} + +/// A reference to a virtual mapping for an shmem-based GEM object in kern= el address space. +/// +/// # Invariants +/// +/// - The size of `owner` is >=3D SIZE. +/// - The memory pointed to by addr remains valid at least until this obje= ct is dropped. +pub struct VMap +where + D: DriverObject, + R: Deref>, +{ + addr: *mut c_void, + owner: R, +} + +/// An alias type for a reference to a shmem-based GEM object's VMap. +pub type VMapRef<'a, D, const SIZE: usize =3D 0> =3D VMap= , SIZE>; + +/// An alias type for an owned reference to a shmem-based GEM object's VMa= p. +pub type VMapOwned =3D VMap>= , SIZE>; + +impl VMap +where + D: DriverObject, + R: Deref>, +{ + /// Borrows a reference to the object that owns this virtual mapping. + #[inline(always)] + pub fn owner(&self) -> &Object { + &self.owner + } +} + +impl Drop for VMap +where + D: DriverObject, + R: Deref>, +{ + #[inline(always)] + fn drop(&mut self) { + // SAFETY: + // - Our existence is proof that this map was previously created u= sing self.owner. + // - Since we are in Drop, we are guaranteed that no one will acce= ss the memory + // through this mapping after calling this. + unsafe { + self.owner.raw_vunmap(bindings::iosys_map { + is_iomem: false, + __bindgen_anon_1: bindings::iosys_map__bindgen_ty_1 { vadd= r: self.addr }, + }) + }; + } +} + +impl Io for VMap +where + D: DriverObject, + R: Deref>, +{ + #[inline(always)] + fn addr(&self) -> usize { + self.addr as usize + } + + #[inline(always)] + fn maxsize(&self) -> usize { + self.owner.size() + } +} + +impl IoKnownSize for VMap +where + D: DriverObject, + R: Deref>, +{ + const MIN_SIZE: usize =3D SIZE; +} + +impl_vmap_io_capable!(VMap, u8); +impl_vmap_io_capable!(VMap, u16); +impl_vmap_io_capable!(VMap, u32); +#[cfg(CONFIG_64BIT)] +impl_vmap_io_capable!(VMap, u64); + +/// A reference to a GEM object that is known to have a mapped [`SGTable`]. +/// +/// This is used by the Rust bindings with [`Devres`] in order to ensure t= hat mappings for SGTables +/// on GEM shmem objects are revoked on driver-unbind. +/// +/// # Invariants +/// +/// - `self.obj` always points to a valid GEM object. +/// - This object is proof that `self.obj.owner.sgt` has an initialized an= d valid +/// [`scatterlist::SGTable`]. +pub struct SGTableMap { + obj: NonNull>, +} + +impl Deref for SGTableMap { + type Target =3D scatterlist::SGTable; + + fn deref(&self) -> &Self::Target { + // SAFETY: + // - The NonNull is guaranteed to be valid via our type invariants. + // - The sgt field is guaranteed to be initialized and valid via o= ur type invariants. + unsafe { scatterlist::SGTable::from_raw((*self.obj.as_ref().as_raw= _shmem()).sgt) } + } +} + +impl Drop for SGTableMap { + fn drop(&mut self) { + // SAFETY: `obj` is always valid via our type invariants + let obj =3D unsafe { self.obj.as_ref() }; + let _lock =3D DmaResvGuard::new(obj); + + // SAFETY: We acquired the lock needed for calling this function a= bove + unsafe { bindings::__drm_gem_shmem_free_sgt_locked(obj.as_raw_shme= m()) }; + } +} + +impl SGTableMap { + fn new(obj: &Object) -> impl Init { + // INVARIANT: + // - We call drm_gem_shmem_get_pages_sgt_locked below and check wh= ether or not it + // succeeds, fulfilling the invariant of SGTableMap that the obj= ect's `sgt` field is + // initialized. + // SAFETY: + // - `obj` is fully initialized, making this function safe to call. + from_err_ptr(unsafe { bindings::drm_gem_shmem_get_pages_sgt(obj.as= _raw_shmem()) })?; + + Ok(Self { obj: obj.into() }) + } +} + +// SAFETY: The NonNull in SGTableMap is guaranteed valid by our type invar= iants, and the GEM object +// it points to is guaranteed to be thread-safe. +unsafe impl Send for SGTableMap {} +// SAFETY: The NonNull in SGTableMap is guaranteed valid by our type invar= iants, and the GEM object +// it points to is guaranteed to be thread-safe. +unsafe impl Sync for SGTableMap {} + +#[kunit_tests(rust_drm_gem_shmem)] +mod tests { + use super::*; + use crate::{ + drm, + faux, + page::PAGE_SIZE, // + }; + + // The bare minimum needed to create a fake drm driver for kunit + + #[pin_data] + struct KunitData {} + struct KunitDriver; + struct KunitFile; + #[pin_data] + struct KunitObject {} + + const INFO: drm::DriverInfo =3D drm::DriverInfo { + major: 0, + minor: 0, + patchlevel: 0, + name: c"kunit", + desc: c"Kunit", + }; + + impl drm::file::DriverFile for KunitFile { + type Driver =3D KunitDriver; + + fn open(_dev: &drm::Device) -> Result>= > { + Ok(KBox::new(Self, GFP_KERNEL)?.into()) + } + } + + impl gem::DriverObject for KunitObject { + type Driver =3D KunitDriver; + type Args =3D (); + + fn new( + _dev: &drm::Device, + _size: usize, + _args: Self::Args, + ) -> impl PinInit { + try_pin_init!(KunitObject {}) + } + } + + #[vtable] + impl drm::Driver for KunitDriver { + type Data =3D KunitData; + type File =3D KunitFile; + type Object =3D Object; + + const INFO: drm::DriverInfo =3D INFO; + const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor] =3D &[]; + } + + fn create_drm_dev() -> Result<(faux::Registration, ARef>)> { + // Create a faux DRM device so we can test gem object creation. + let data =3D try_pin_init!(KunitData {}); + let dev =3D faux::Registration::new(c"Kunit", None)?; + let drm =3D drm::Device::::new(dev.as_ref(), data)?; + + Ok((dev, drm)) + } + + #[test] + fn compile_time_vmap_sizes() -> Result { + let (_dev, drm) =3D create_drm_dev()?; + + let obj =3D Object::::new(&drm, PAGE_SIZE, ObjectConf= ig::default(), ())?; + + // Try creating a normal vmap + obj.vmap::()?; + + // Try creating a vmap that's smaller then the size we specified + obj.vmap::<{ PAGE_SIZE - 100 }>()?; + + // Make sure creating a vmap that's too large fails + assert!(obj.vmap::<{ PAGE_SIZE + 200 }>().is_err()); + + Ok(()) + } + + #[test] + fn vmap_io() -> Result { + let (_dev, drm) =3D create_drm_dev()?; + + let obj =3D Object::::new(&drm, PAGE_SIZE, ObjectConf= ig::default(), ())?; + + let vmap =3D obj.vmap::()?; + + vmap.write8(0xDE, 0x0); + assert_eq!(vmap.read8(0x0), 0xDE); + vmap.write32(0xFFFFFFFF, 0x20); + + assert_eq!(vmap.read32(0x20), 0xFFFFFFFF); + + assert_eq!(vmap.read8(0x20), 0xFF); + assert_eq!(vmap.read8(0x21), 0xFF); + assert_eq!(vmap.read8(0x22), 0xFF); + assert_eq!(vmap.read8(0x23), 0xFF); + + Ok(()) + } +} --=20 2.54.0 From nobody Mon Jun 8 11:01:13 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 388F1478E5A for ; Fri, 29 May 2026 18:37:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079860; cv=none; b=dfn5PGig1xnPbSYYh/yILavFC42+eeokG/O9VaQ5VQ3l+Lf7R/+RdcLjGPNk91EUmnf22l1vbOGCEF1cq6hDybnBTLDwxZ75O1mqAEbYygBFwHBNAjwX4hmt+lowm0toy1hsQZgKT4LSGihhxxKEtedHkldIkmjb147psLQo7ww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079860; c=relaxed/simple; bh=NfValsT13B9XTlXeTicbkDGTa8+Fj2v0hJKR8oGpyBc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i8uiWjLt8Q0YvsoiSjl2fZMbxI78kN4o6QnZm7mxZpXOjIvHtxK5qfE3XpGo5Eaj06crdMh7bJN8s1FwTHPFre33vZdjcF5HKhzYcgCqWl0E7yUjl9Wy8Y7Bnhwr8VXU9L2oW94eqe9Fmf8wxhumHJfeG3qyFWQura/vJRqVaeg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Z6T5wZXY; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Z6T5wZXY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780079853; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cF/fCKGGsVn6l967F1Qq9M9WKaqTKMJ/A9UZOUtdnUs=; b=Z6T5wZXYKrC4NQSZcsV5kAiSDsDsHCt86s/9Cl81z+0ea0GxDzlz/TMLC5WeyEoJR2xio4 CBKkV+HM/+m1m1kgUWpleK5F7CcZlhT+c4uSf3y2rWgWePxnJGIFSnaRhYyhG6FnsKv53b l2vYjZ8/Hm/RHLjHGkKbORanE2D/8MQ= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-574-luTdiZlOM6a9-dwZsVaUpA-1; Fri, 29 May 2026 14:37:27 -0400 X-MC-Unique: luTdiZlOM6a9-dwZsVaUpA-1 X-Mimecast-MFC-AGG-ID: luTdiZlOM6a9-dwZsVaUpA_1780079844 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6653518002CF; Fri, 29 May 2026 18:37:24 +0000 (UTC) Received: from GoldenWind.redhat.com (unknown [10.22.89.101]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 13D901686; Fri, 29 May 2026 18:37:20 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org Cc: Alexandre Courbot , Gary Guo , =?UTF-8?q?Christian=20K=C3=B6nig?= , driver-core@lists.linux.dev, Miguel Ojeda , Maarten Lankhorst , Alice Ryhl , Simona Vetter , linux-kernel@vger.kernel.org, Sumit Semwal , linux-media@vger.kernel.org, "Rafael J . Wysocki" , Thomas Zimmermann , Maxime Ripard , David Airlie , Benno Lossin , linaro-mm-sig@lists.linaro.org, Danilo Krummrich , Mukesh Kumar Chaurasiya , Asahi Lina , Daniel Almeida , Lyude Paul , Greg Kroah-Hartman Subject: [PATCH v15 4/6] rust: faux: Allow retrieving a bound Device Date: Fri, 29 May 2026 14:34:02 -0400 Message-ID: <20260529183702.677677-5-lyude@redhat.com> In-Reply-To: <20260529183702.677677-1-lyude@redhat.com> References: <20260529183702.677677-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" When writing up some rust code that used faux devices for unit testing, I noticed that we never actually added the Bound device context to faux::Registration's AsRef implementation. This being said: the Registration object itself is proof that a driver is bound to the device - so this should be safe. Signed-off-by: Lyude Paul --- rust/kernel/faux.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rust/kernel/faux.rs b/rust/kernel/faux.rs index 43b4974f48cd2..e0856b2964a2c 100644 --- a/rust/kernel/faux.rs +++ b/rust/kernel/faux.rs @@ -25,7 +25,8 @@ /// /// # Invariants /// -/// `self.0` always holds a valid pointer to an initialized and registered= [`struct faux_device`]. +/// - `self.0` always holds a valid pointer to an initialized and register= ed [`struct faux_device`]. +/// - This object is proof that the object described by this `Registration= ` is bound to a device. /// /// [`struct faux_device`]: srctree/include/linux/device/faux.h pub struct Registration(NonNull); @@ -59,8 +60,8 @@ fn as_raw(&self) -> *mut bindings::faux_device { } } =20 -impl AsRef for Registration { - fn as_ref(&self) -> &device::Device { +impl AsRef> for Registration { + fn as_ref(&self) -> &device::Device { // SAFETY: The underlying `device` in `faux_device` is guaranteed = by the C API to be // a valid initialized `device`. unsafe { device::Device::from_raw(addr_of_mut!((*self.as_raw()).de= v)) } --=20 2.54.0 From nobody Mon Jun 8 11:01:13 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A8464219FF for ; Fri, 29 May 2026 18:37:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079859; cv=none; b=PVHWJtKweCVomH9+LvCiQajB2sabzI1k9WHOhKvYuomgBq0azMSFwH1/yqHqKZsaEMqVUFwWNFCHYVF/zOAHLJmODAj3V+w8J7HtpDAE1gApvjprpHPgY3rqtZaJYhC0la9mJBzaltFzwiJNcYPXdqDXZu44l+nhYYkkAWSQqOU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079859; c=relaxed/simple; bh=m/ZuTvDTd2RiJVeIWiH9JqSGrSiIRaTy3fvE3xM5Oqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BXuPzOlLUHl4f1Rh7dyMomYcGx7mX1DPnJy0rVhW2L/GRm+7fY+9AqQC/sUaOWks9PTkvmZynuApm0qpIa/rkpmV22c9dvja9WfNOrzZgeefduMPT7TZEADpIsoxz40qD1OCFLmmaTaHD2hrq50+Wj7Js6ONaayk1GssMNzLqN0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=PnTFwVJT; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="PnTFwVJT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780079855; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9iRHxmN/dnU79hS18x4XdzAf0Ghs0AIzOreSmFvd9Ao=; b=PnTFwVJTRngJk9m6Qr3FefeRj7fpGiN1SQ7c2ZN8bzOpFedB4I4iGOycuffBtYK3OP0C9Y uPXcU7NcPXMCi7pqASxn3Nz/5QzQ7YHJ7au3vfWwzdvcnjVsr/fraJNo0O+8c+MvGfvUHL a/ICkFXhy9nO9OYO7jaYunKEURNLYVo= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-136-knbq1hdOPo-qIGV8Qr4TAw-1; Fri, 29 May 2026 14:37:31 -0400 X-MC-Unique: knbq1hdOPo-qIGV8Qr4TAw-1 X-Mimecast-MFC-AGG-ID: knbq1hdOPo-qIGV8Qr4TAw_1780079848 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D10D719560AA; Fri, 29 May 2026 18:37:27 +0000 (UTC) Received: from GoldenWind.redhat.com (unknown [10.22.89.101]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 979E91773; Fri, 29 May 2026 18:37:24 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org Cc: Alexandre Courbot , Gary Guo , =?UTF-8?q?Christian=20K=C3=B6nig?= , driver-core@lists.linux.dev, Miguel Ojeda , Maarten Lankhorst , Alice Ryhl , Simona Vetter , linux-kernel@vger.kernel.org, Sumit Semwal , linux-media@vger.kernel.org, "Rafael J . Wysocki" , Thomas Zimmermann , Maxime Ripard , David Airlie , Benno Lossin , linaro-mm-sig@lists.linaro.org, Danilo Krummrich , Mukesh Kumar Chaurasiya , Asahi Lina , Daniel Almeida , Lyude Paul , Greg Kroah-Hartman Subject: [PATCH v15 5/6] drm/gem/shmem: Introduce __drm_gem_shmem_free_sgt_locked() Date: Fri, 29 May 2026 14:34:03 -0400 Message-ID: <20260529183702.677677-6-lyude@redhat.com> In-Reply-To: <20260529183702.677677-1-lyude@redhat.com> References: <20260529183702.677677-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" One of the complications of trying to use the shmem helpers to create a scatterlist for shmem objects is that we need to be able to provide a guarantee that the driver cannot be unbound for the lifetime of the scatterlist. The easiest way of handling this seems to be just hooking up an unmap operation to devres the first time we create a scatterlist, which allows us to still take advantage of gem shmem facilities without breaking that guarantee. To allow for this, we extract __drm_gem_shmem_free_sgt_locked() - which allows a caller (e.g. the rust bindings) to manually unmap the sgt for a gem object as needed. Signed-off-by: Lyude Paul Reviewed-by: Alexandre Courbot --- V10: * Fix incorrect function name in documentation for __drm_gem_shmem_release_sgt_locked() drivers/gpu/drm/drm_gem_shmem_helper.c | 32 +++++++++++++++++++++----- include/drm/drm_gem_shmem_helper.h | 1 + 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_g= em_shmem_helper.c index 545933c7f7121..c989459eb2159 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -158,6 +158,30 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(stru= ct drm_device *dev, size_t } EXPORT_SYMBOL_GPL(drm_gem_shmem_create); =20 +/** + * __drm_gem_shmem_release_sgt_locked - Unpin and DMA unmap pages, and rel= ease the + * cached scatter/gather table for an shmem GEM object. + * @shmem: shmem GEM object + * + * If the passed shmem object has an active scatter/gather table for driver + * usage, this function will unmap it and release the memory associated wi= th it. + * It is the responsibility of the caller to ensure it holds the dma_resv_= lock + * for this object. + * + * Drivers should not need to call this function themselves, it is mainly + * intended for usage in the Rust shmem bindings. + */ +void __drm_gem_shmem_free_sgt_locked(struct drm_gem_shmem_object *shmem) +{ + dma_resv_assert_held(shmem->base.resv); + + dma_unmap_sgtable(shmem->base.dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); + sg_free_table(shmem->sgt); + kfree(shmem->sgt); + shmem->sgt =3D NULL; +} +EXPORT_SYMBOL_GPL(__drm_gem_shmem_free_sgt_locked); + /** * drm_gem_shmem_release - Release resources associated with a shmem GEM o= bject. * @shmem: shmem GEM object @@ -176,12 +200,8 @@ void drm_gem_shmem_release(struct drm_gem_shmem_object= *shmem) =20 drm_WARN_ON(obj->dev, refcount_read(&shmem->vmap_use_count)); =20 - if (shmem->sgt) { - dma_unmap_sgtable(obj->dev->dev, shmem->sgt, - DMA_BIDIRECTIONAL, 0); - sg_free_table(shmem->sgt); - kfree(shmem->sgt); - } + if (shmem->sgt) + __drm_gem_shmem_free_sgt_locked(shmem); if (shmem->pages) drm_gem_shmem_put_pages_locked(shmem); =20 diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem= _helper.h index 5ccdae21b94a9..b2c23af628e1a 100644 --- a/include/drm/drm_gem_shmem_helper.h +++ b/include/drm/drm_gem_shmem_helper.h @@ -111,6 +111,7 @@ int drm_gem_shmem_init(struct drm_device *dev, struct d= rm_gem_shmem_object *shme struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, = size_t size); void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem); void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem); +void __drm_gem_shmem_free_sgt_locked(struct drm_gem_shmem_object *shmem); =20 void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem); int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem); --=20 2.54.0 From nobody Mon Jun 8 11:01:13 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9A2847DD64 for ; Fri, 29 May 2026 18:37:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079866; cv=none; b=szrgvIZSYUTaljndBP/YWze87R6IBfj0T+yfkD7QAV7Gbl6OYjMQs1u+NFPIKsVGPHVDePYCLW2cAzG8jP8eTLvqbRUc/xI0xasr+BF1oTiMTqkhEXF02lCXW1zwmFPA4rTklRcApxgH9PKjPlROtNPR1OHm3huvwrhyPM/kumE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780079866; c=relaxed/simple; bh=4cjwe87q/t7s3dmQsDYYrUXGLi6ANKnSrefxeksGMpo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uXjVcGEK+Uo/yzEKZjz0ZxMBaRAZtF0/DvEsmU2IR8CC5NgpEqID/kBnJbLYDzw/QhCE6PKqSS2ihfjEuhWlPUjex988BqWWVKaxOADXjFKVHpwGn43lRT4jtKiGpb6lZ4ZGwhNjP+9+7Sc68u8WD95XeWqLsGYMdYmPdqa7YUo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=adwZv9Jx; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="adwZv9Jx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780079861; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FW4muBq04eUEQ5DPUv/MIH2aGLX2hNQSawY7hFA7cfc=; b=adwZv9JxVjkP8z+M8+Nc1LwCWPXA7NTJsxPzWazFYcozU3J8PmckDuyYOVCd1zxjxouFQd S5jKsFESOKKap8yQq+5FDNX3B898aDEK1eRVc/gu7nnXG/5WVfYILEBt0XoLaL+304hyr+ KxUt93aGzeueliOfZc25LkGLYfkIydc= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-297-kMqJ3efKP_6-3Cyqrp-ceg-1; Fri, 29 May 2026 14:37:34 -0400 X-MC-Unique: kMqJ3efKP_6-3Cyqrp-ceg-1 X-Mimecast-MFC-AGG-ID: kMqJ3efKP_6-3Cyqrp-ceg_1780079851 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 25A85195608B; Fri, 29 May 2026 18:37:31 +0000 (UTC) Received: from GoldenWind.redhat.com (unknown [10.22.89.101]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0DCF21776; Fri, 29 May 2026 18:37:27 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, nouveau@lists.freedesktop.org Cc: Alexandre Courbot , Gary Guo , =?UTF-8?q?Christian=20K=C3=B6nig?= , driver-core@lists.linux.dev, Miguel Ojeda , Maarten Lankhorst , Alice Ryhl , Simona Vetter , linux-kernel@vger.kernel.org, Sumit Semwal , linux-media@vger.kernel.org, "Rafael J . Wysocki" , Thomas Zimmermann , Maxime Ripard , David Airlie , Benno Lossin , linaro-mm-sig@lists.linaro.org, Danilo Krummrich , Mukesh Kumar Chaurasiya , Asahi Lina , Daniel Almeida , Lyude Paul , Greg Kroah-Hartman Subject: [PATCH v15 6/6] rust: drm: gem: Introduce shmem::Object::sg_table() Date: Fri, 29 May 2026 14:34:04 -0400 Message-ID: <20260529183702.677677-7-lyude@redhat.com> In-Reply-To: <20260529183702.677677-1-lyude@redhat.com> References: <20260529183702.677677-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" In order to do this, we need to be careful to ensure that any interface we expose for scatterlists ensures that any mappings created from one are destroyed on driver-unbind. To do this, we introduce a Devres resource into shmem::Object that we use in order to ensure that we release any SGTable mappings on driver-unbind. There's some other slightly unfortunate caveats of this: * Drivers don't have explicit control at the moment over when unmapping happens (which is exactly the same as the C side atm, so it might not be a problem). * We can't just return `SGTableMap` to the user through an Arc to attempt to fix the last caveat - because that implies the gem object would need to hold a reference count to the scatterlist mapping, which just leaves us with the same problem. Signed-off-by: Lyude Paul --- V3: * Rename OwnedSGTable to shmem::SGTable. Since the current version of the SGTable abstractions now has a `Owned` and `Borrowed` variant, I think renaming this to shmem::SGTable makes things less confusing. We do however, keep the name of owned_sg_table() as-is. V4: * Clarify safety comments for SGTable to explain why the object is thread-safe. * Rename from SGTableRef to SGTable V10: * Use Devres in order to ensure that SGTables are revocable, and are unmapped on driver-unbind. V11: * s/create_sg_table()/get_sg_table() * Get rid of extraneous `ret =3D ` in shmem::Object::get_sg_table() V12: * Actually move sgt_res in this patch and not the next one V13: * Use DmaResvGuard suggestion from Alexander * Use Alexander's (much better) solution for get_sg_table() * Use SetOnce instead of UnsafeCell * s/SGTableRef/SGTableMap * Fix typo in SGTableMap documentation * Create fallible constructor for SGTableMap * Don't reuse dma_resv lock for protecting Object contents, just use Mutex + SetOnce * Drop use of drm_gem_shmem_get_pages_sgt_locked(), since we don't need to hold the dma_resv lock ourselves for anything but this function. * Check that the device we receive in the bounds for sg_table() and owned_sg_table() that said Device is in fact, the correct device. * Remove redundant docs in owned_sg_table(), just point it back to sg_table(). * Implement Deborah's suggestion to fix double-free in free_callback() * Restore original order of Object * Fix doc typo for SGTableMap V14: * Use new InitOnce container over the Mutex/SetOnce horror show we had before. * Start using LazyInit container for storing Devres for sgt unmap * Add some kunit tests for sg_table (not sure why I didn't do this before) using some of the boilerplate code leftover from the vmap bindings * Get rid of the owned SGTable variant for now, we'll add it back in a future patch if people actually need it. * Use new LazyInit container from me to get rid of the horrid Mutex> mess. * Add the best we can do for unit tests w/r/t SGTable at the moment rust/kernel/drm/gem/shmem.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index 494e0d0d8d0d6..5655c2a1ae8fb 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -664,4 +664,28 @@ fn vmap_io() -> Result { =20 Ok(()) } + + // TODO: I would love to actually test the success paths of sg_table()= , but that would require + // also implementing dummy dma_ops so that trying to create a mapping = doesn't explode. So, leave + // that for someone else. + + // Ensures that passing the wrong device to sg_table() fails as we exp= ect, and also ensure it + // skips initializing `sgt_res` since we could otherwise create `sgt_r= es` with the wrong device + // bound to it. + #[test] + fn fail_sg_table_on_wrong_dev() -> Result { + let (_dev, drm) =3D create_drm_dev()?; + let wrong_dev =3D faux::Registration::new(c"EvilKunit", None)?; + + let obj =3D Object::::new(&drm, PAGE_SIZE, ObjectConf= ig::default(), ())?; + + assert_eq!(obj.sg_table(wrong_dev.as_ref()).err().unwrap(), EINVAL= ); + + // If sgt_res was not initialized mistakenly with the wrong device= , this should still fail. + assert_eq!(obj.sg_table(wrong_dev.as_ref()).err().unwrap(), EINVAL= ); + + // TODO: Someday, we should test that creating an sg_table here st= ill succeeds. + + Ok(()) + } } --=20 2.54.0