From patchwork Fri Feb 24 10:53:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asahi Lina X-Patchwork-Id: 61258 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp836957wrd; Fri, 24 Feb 2023 03:01:45 -0800 (PST) X-Google-Smtp-Source: AK7set/5L5VKstb9iFA6uRay0OJlTn13EHBUYRBHJRr5dsYW6XT7Aoq4VfRLFTDJjB6uGEVDHYOv X-Received: by 2002:a05:6402:516b:b0:4ac:b32e:b65 with SMTP id d11-20020a056402516b00b004acb32e0b65mr16389281ede.3.1677236505216; Fri, 24 Feb 2023 03:01:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677236505; cv=none; d=google.com; s=arc-20160816; b=j4E5XRKxRgcXr0BnYfSLfGXIGCKLCUk5fFZJfZ2hpkGYE1ALcDkTp/jVivHHsTcMB5 2G0Dv+U9vS0wkXT5nlNkiF0bBPyhoKUeG1NYpupfgOtypfK3Bm1QKIMvzEkW3wZIl0A8 MdOlLEFgXetbOqugKAmV2XqFeTsY+l5W7eW0Hxy0NZyR3n4hS35hl3xzIqtlNtatjjJH CNjvAd+eV4+kwbZQFitYNlOPWD1UvDtU5tZxapoJqt0AWxC6QgWTUktnTYoDeCSHFuc2 XPgkgnfNGO0NnsPit/ZVjq0+uTJ+Svu67fMbW0cMgHP6+nhnq5oLWO7AZYm/VaBqVmrh w34Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=mdddpQs0/EgOX4R0v6PAJaoU90wWq2OTYVG/0XQ5IUQ=; b=ZQYh/M3O5zeqZcpzZS3rfRudOgNhmQUH0ToVI4U0O8IvNV7CSa0po/pRnliKngDK6G ow61XXbwOnEqJQKdalIUIZI2tQqk50Mc1DCqCqJ1oAIY46Fe2DlLuuJoKPVhdkaQq/g4 qR5UxeR9heF3xJjXtuuOzQ7Wbwe8BrIGYQi6kGm1MiiTaxzkOxqSSH+1PU5eZc3+UADr sIjzl/pKIpvOKUDQe1R6DfnwZwskxNNUUDihZnO50XeAJDYlQhqZu5MXf3xtEj6Eg64D H2UcxN4YGZgzgaI9SzoUvZyUFAI8BF+mWJQ/vPqV/Z4iaBQsMKKLYxnuUMQFLb3a6pu4 ZNlg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b="oa1/MEii"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h20-20020a50ed94000000b004acbe83b837si3498296edr.213.2023.02.24.03.01.05; Fri, 24 Feb 2023 03:01:45 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b="oa1/MEii"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230008AbjBXKxu (ORCPT + 99 others); Fri, 24 Feb 2023 05:53:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54220 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229709AbjBXKxq (ORCPT ); Fri, 24 Feb 2023 05:53:46 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A8B2D30E0; Fri, 24 Feb 2023 02:53:45 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id 44C634206F; Fri, 24 Feb 2023 10:53:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677236024; bh=sJXKzM9ye5UpmrgbyuuthZgT+KWJTloP+4kPhG+KQ/k=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=oa1/MEiiXrg9mbqpHfbEKIp8g2n5RxkQB42j1wGBzAU51cFkRJi7ueQBGd/e59Brl 7GoMcsyCOveOh/QgTpe9MahflHSAX3d67TWE2Fkll+LVpC7TmLb2WlFNCThlREjzLD 6GUpv6nT76QR2+qiaVjO8JIWMCYT5kO15bKsbjxwjSY0wh0Cev51ebn/OijewbwjpB /2qDSDR9e03ZKD8m6EG42hw0Jst6DA4Y7tLPtc2WHipqK3rY5QbcvsFPcLPsQM58bK yhVVjgcSEvXz0Lox/JZZk/8axll9MDYOPzV8hitLUmGKRjGCHDuyNKJzDhgwlbFUDR G8/MIhnVT3HKA== From: Asahi Lina Date: Fri, 24 Feb 2023 19:53:13 +0900 Subject: [PATCH 1/5] rust: Add a Sealed trait MIME-Version: 1.0 Message-Id: <20230224-rust-iopt-rtkit-v1-1-49ced3391295@asahilina.net> References: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> In-Reply-To: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Will Deacon , Robin Murphy , Joerg Roedel , Hector Martin , Sven Peter , Arnd Bergmann , Greg Kroah-Hartman Cc: "Rafael J. Wysocki" , Alyssa Rosenzweig , Neal Gompa , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677236013; l=780; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=sJXKzM9ye5UpmrgbyuuthZgT+KWJTloP+4kPhG+KQ/k=; b=2N7EOf9lvtQl1KnhDXXm0FkvG4Na7dWKbQBTLsMk8jqk7B7Y4WPfN/hlCBMv3CBOdYjE0fIKU E+XrQbtCkZPD7FsAJAXaDP50Tbk5LoTqUkrE+GslcgajYZk1801LH+S X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758709945878925873?= X-GMAIL-MSGID: =?utf-8?q?1758709945878925873?= Some traits exposed by the kernel crate may not be intended to be implemented by downstream modules. Add a Sealed trait to allow avoiding this using the sealed trait pattern. Signed-off-by: Asahi Lina --- rust/kernel/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 223564f9f0cc..82dff6f4cf60 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -46,6 +46,11 @@ pub use macros; #[doc(hidden)] pub use build_error::build_error; +pub(crate) mod private { + #[allow(unreachable_pub)] + pub trait Sealed {} +} + /// Prefix to appear before log messages printed from within the `kernel` crate. const __LOG_PREFIX: &[u8] = b"rust_kernel\0"; From patchwork Fri Feb 24 10:53:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asahi Lina X-Patchwork-Id: 61255 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp836572wrd; Fri, 24 Feb 2023 03:01:09 -0800 (PST) X-Google-Smtp-Source: AK7set9hfHNsuT8GC0WZJNSIOeMCXoD7wxJH/4nSj1cqnjhgbE188BxUVOjeqJd7/xo6byBm4ZbE X-Received: by 2002:a05:6402:20c:b0:4ab:1d33:69ba with SMTP id t12-20020a056402020c00b004ab1d3369bamr13608604edv.16.1677236468885; Fri, 24 Feb 2023 03:01:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677236468; cv=none; d=google.com; s=arc-20160816; b=my1s3TChG+QKqhofrTSJIkxTgwyMYxDdv27gQwA291ilZ32l9MtUHYAizFmibP1c4v QR9gJE+IWoequymq+ZNN7ch5Z9QShx9fk3s5Ip7/3YrU0ahqdmN/dGiZ1tFMIreVcf18 uiVLobYV/2ydtA8TtvZEQfezvnKSJbGSupV2sXjDc+DVF0m0CdVQnfD4KLEKoZR5epjR k1ObfipLtf0nLQhA6H/E0qcMWB4gfzWKRKq+BfSNOZ8Le6J+Q+En/AZiqRaXOFauaN1U Mb+bnynlTXBA8igVG/i9wYHuNXLnOgAFiElzvLxGoxLu7XLMzlkkh1QUiCHfsX8FAdmc HTDw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=E45BpH984Exa0fMcJL/obVfS9/NpUGLW4abDz1Bq+Hg=; b=dvMrkHYGNkjrJx0lR/M5sKaJt97KirG+mbHWwtBFSIEDDDG06zJgK+1W4iwmdQ3Jpw jxOzE9ZPRApeVJZGdZ0sdBghja7+92/J3RSqkjSCNnrWtZD79PDWIjheqv2djwyqOC/0 UE3hmbpC/UfVhR4abyqsWKH/0G5V9pa0V6nWAQI6K6d0uESqZC7tR6HGyLUFEJViz6r0 N5fBHimKTwSK1jLXTMUj6X3zua0HWT81Rp82IHLdXBiLO3rhhSZwPgLAERD7rbsVpUOd GFXiiiz0m72Phd46DXOt5FUAE2pN+WBaKNJ5y+1oQSCBD8bkmZNFr8UmbDZt0sha6TEz efuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=S5GfRRLt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id y25-20020a50e619000000b004aef1b3a863si15019470edm.518.2023.02.24.03.00.44; Fri, 24 Feb 2023 03:01:08 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=S5GfRRLt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230148AbjBXKyE (ORCPT + 99 others); Fri, 24 Feb 2023 05:54:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230073AbjBXKyA (ORCPT ); Fri, 24 Feb 2023 05:54:00 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3E7DD149A5; Fri, 24 Feb 2023 02:53:51 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id C3BF64248B; Fri, 24 Feb 2023 10:53:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677236029; bh=XcpgOxW9xbW5RI+qtCoIK9qZZvy3Hmqang8OrPgwtSc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=S5GfRRLtjTEa1GDauhqm4LwpVNGK9hwlbYZMDG1ymiXWS62XPbSGKGYfVdiESMhsi oUWZbjIsVtLtdpjnPlNLc77tt5cg+DOJTJpoB3SVHHaCuQoH8yutbwrBHCwUAni2W1 mqtw2lyg9Mt87jqcgmsl1HYvkyr9NBfRbfvZgjxMbTcr393YYR5lLtfwsxo3q3n7pq ++U2vR8szdn9AXLuHQV+Y5Rvt+zp2PfwNt4/xhZjI/W2vjqvDSw+Fg+khrXomc4NsQ 0TGF7QjLUZgLXGpMl/IEJlXXz2yC5DOQ17LEM+bGey75KDq1KQM6dPemGRxock3Wkv rB9HwMDHJCxtg== From: Asahi Lina Date: Fri, 24 Feb 2023 19:53:14 +0900 Subject: [PATCH 2/5] rust: device: Add a minimal RawDevice trait MIME-Version: 1.0 Message-Id: <20230224-rust-iopt-rtkit-v1-2-49ced3391295@asahilina.net> References: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> In-Reply-To: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Will Deacon , Robin Murphy , Joerg Roedel , Hector Martin , Sven Peter , Arnd Bergmann , Greg Kroah-Hartman Cc: "Rafael J. Wysocki" , Alyssa Rosenzweig , Neal Gompa , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677236013; l=2542; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=soR466tRTXjasiXIM/nVS1quyj2/l4EZ0DnmL76tJBs=; b=lgy1PZ0uyKdd/tM/G8noK7EaD5kUIHfT1uSUmIXZ1IA3ri0x3dNuPzq/TelJO3hm34TrgUqE9 bNEhHLGfh08CnZPIzu2dvrfFa3L9h2u7tHdI6Yy4lBJWvKiNRcLpm1x X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758709907756889089?= X-GMAIL-MSGID: =?utf-8?q?1758709907756889089?= From: Wedson Almeida Filho Add a RawDevice trait which can be implemented by any type representing a device class (such as a PlatformDevice). This is the minimum amount of Device support code required to unblock abstractions that need to take device pointers. Lina: Rewrote commit message, and dropped everything except RawDevice. Co-developed-by: Miguel Ojeda Signed-off-by: Miguel Ojeda Signed-off-by: Wedson Almeida Filho Signed-off-by: Asahi Lina --- rust/bindings/bindings_helper.h | 1 + rust/kernel/device.rs | 23 +++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 3 files changed, 25 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 75d85bd6c592..3632a39a28a6 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -6,6 +6,7 @@ * Sorted alphabetically. */ +#include #include #include diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs new file mode 100644 index 000000000000..9be021e393ca --- /dev/null +++ b/rust/kernel/device.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Generic devices that are part of the kernel's driver model. +//! +//! C header: [`include/linux/device.h`](../../../../include/linux/device.h) + +use crate::bindings; + +/// A raw device. +/// +/// # Safety +/// +/// Implementers must ensure that the `*mut device` returned by [`RawDevice::raw_device`] is +/// related to `self`, that is, actions on it will affect `self`. For example, if one calls +/// `get_device`, then the refcount on the device represented by `self` will be incremented. +/// +/// Additionally, implementers must ensure that the device is never renamed. Commit a5462516aa99 +/// ("driver-core: document restrictions on device_rename()") has details on why `device_rename` +/// should not be used. +pub unsafe trait RawDevice { + /// Returns the raw `struct device` related to `self`. + fn raw_device(&self) -> *mut bindings::device; +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 82dff6f4cf60..de44092718f8 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -29,6 +29,7 @@ compile_error!("Missing kernel configuration for conditional compilation"); #[cfg(not(testlib))] mod allocator; mod build_assert; +pub mod device; pub mod error; pub mod prelude; pub mod print; From patchwork Fri Feb 24 10:53:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asahi Lina X-Patchwork-Id: 61256 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp836581wrd; Fri, 24 Feb 2023 03:01:09 -0800 (PST) X-Google-Smtp-Source: AK7set/yBEqp0b+o89np1MWztd4hLCNTu2yVpfRu4NmL4YDnU/uQlUkJjZMS2LX++vUtBQvBcXhV X-Received: by 2002:a17:906:9f07:b0:8e0:4baf:59bb with SMTP id fy7-20020a1709069f0700b008e04baf59bbmr14100386ejc.22.1677236469731; Fri, 24 Feb 2023 03:01:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677236469; cv=none; d=google.com; s=arc-20160816; b=BwX1yy9TjfBc9LWPQNgDY3u6amCa1UsVKu66hcKde0RpTPx0b23rL7pHhJADVDjN1n AUtr6j28Ms8HYKQu3mzFM8sxWc9dPl3DWYuAq3dvkJlpHB9/UgAO0czsZED2Sqy6Qp5g EkdCHc8YlI9K8jriCnI+5owaAWdhqex1NoJ6gA8DRhemXcv4M+vlI1ZAd8uBdMsPUrBz X2P8ZPdyqUxdBJW/BboGn43uQCYFr3VI8CUQTKoW/nvAnZ5ChrxUnMCCCXmKGc9u8J92 ezREHUDsrge3RpUVMNPExhnPOo5/D2TXWP37DnM6rXeohUGlJkR6QzV2E+bLyfYRsKN1 v3lA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=y9qmuRZ5enjDSfpa8ng+zHskZK1K+C0RkzdskLIm2Kk=; b=yWfWeZmK7K5ySFbhWMcj38f99OSiJ+zyN+tHQJBrq/M7wRl37AOFyTMd2TpbzsGUqz M2hR8aJL8c8/cj0BujxOfxn3JuhbS2bv65jUU/FcVTFlN+xhdr1bH6v+bQEv+B9yUkSJ LANGKI5y34RL2afTGBuUidOKLOywz38fjVkDIsDRAdzFgDzwV0x5YRA4bZNEzJ87MCnw gh9iDSB92Zgk8c7qAWvw5XdXTg32QHR+Fh60Ugbn5EdL3gBIlZAn9kvjx7+4Dh/pZCNW o9DisN5PEbbSqAv0Ekev+UiWbkb3VTNJ59MGRBbxpmaDQPS16V7lA77+LZ1wX5BtHu/8 rqbg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=z4ncFNu8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id qb23-20020a1709077e9700b008f1ce937168si5062053ejc.758.2023.02.24.03.00.45; Fri, 24 Feb 2023 03:01:09 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=z4ncFNu8; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230059AbjBXKyW (ORCPT + 99 others); Fri, 24 Feb 2023 05:54:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229804AbjBXKyK (ORCPT ); Fri, 24 Feb 2023 05:54:10 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0449B60D5E; Fri, 24 Feb 2023 02:53:56 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id 6C3BA424B9; Fri, 24 Feb 2023 10:53:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677236035; bh=NrVqIiH3X9XgjWiOPXyb08yMiHXA6hAq3CWoGWegOsU=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=z4ncFNu82ujl536rci+ZwNDWUFh+JpOeYiio+n69Y/NI3cGdn8gq9c4GuZ7EP8q1I fCBLp8gKeCGt/Ct4n1TYKG3e6vlFlVOg1uDBXKV0GdEkW66azHhCxeYqsK8Y6+bCdl DhxNz2rI1SMRMUju5sZ3mDOr/I7w8HeEDd5O74wraZZjc901j++oKL0iZdGG2QFo66 Bx2ZTiqEOE8oJaPUC6z6ESMDqG5EoE4OyLG6lxdjJFjaJPg8xfpreQq95VSjWD1usy LaIasHjZ9vUE1y6eX5ptPIozRvnzOZTCdY1AOXbAc8yLCLBYKbFXScR0wDMhp2wUpR Yq+vIzcKu/9SQ== From: Asahi Lina Date: Fri, 24 Feb 2023 19:53:15 +0900 Subject: [PATCH 3/5] rust: io_pgtable: Add io_pgtable abstraction MIME-Version: 1.0 Message-Id: <20230224-rust-iopt-rtkit-v1-3-49ced3391295@asahilina.net> References: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> In-Reply-To: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Will Deacon , Robin Murphy , Joerg Roedel , Hector Martin , Sven Peter , Arnd Bergmann , Greg Kroah-Hartman Cc: "Rafael J. Wysocki" , Alyssa Rosenzweig , Neal Gompa , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677236013; l=13923; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=NrVqIiH3X9XgjWiOPXyb08yMiHXA6hAq3CWoGWegOsU=; b=P9OJjQ7AsUwVWHlKKVuH9K+Qw3x4Twvm2E2HX6B8xsfUWQmjTKpiewnwJRmHi+HwymNy1/Yy2 tw0/4bjOLl6BFLJbQJeWSGJXE4wU2Dxn/nVewsuULTqRppTxiCZDFF7 X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758709908329829348?= X-GMAIL-MSGID: =?utf-8?q?1758709908329829348?= The io_pgtable subsystem implements page table management for various IOMMU page table formats. This abstraction allows Rust drivers for devices with an embedded MMU to use this shared code directly. Gather structures are not implemented yet, since we don't have a consumer for that functionality. That can be added and refactored when someone needs it. It's worth noting that although this abstraction is nominally used to manage page tables and mapping physical memory addresses, the abstraction API itself is not unsafe. This is because, by itself, it can only be used to manage page tables in isolation, which have no effect on the system. In Rust, we typically use `unsafe` to mark operations that actually introduce the safety requirements (that is, where the responsibilities are created). Here, that would be actually installing the page table root pointer into a device register (the downstream iomem abstractions are unsafe for this reason, because devices can do DMA). Signed-off-by: Asahi Lina --- rust/bindings/bindings_helper.h | 1 + rust/kernel/io_pgtable.rs | 351 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 2 + 3 files changed, 354 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 3632a39a28a6..88c65431d3ad 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -7,6 +7,7 @@ */ #include +#include #include #include diff --git a/rust/kernel/io_pgtable.rs b/rust/kernel/io_pgtable.rs new file mode 100644 index 000000000000..19029b1fdfd8 --- /dev/null +++ b/rust/kernel/io_pgtable.rs @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! IOMMU page table management +//! +//! C header: [`include/io-pgtable.h`](../../../../include/io-pgtable.h) + +use crate::{ + bindings, device, + error::{code::*, to_result, Result}, + types::{ForeignOwnable, ScopeGuard}, +}; + +use core::marker::PhantomData; +use core::mem; +use core::num::NonZeroU64; + +/// Protection flags used with IOMMU mappings. +pub mod prot { + /// Read access. + pub const READ: u32 = bindings::IOMMU_READ; + /// Write access. + pub const WRITE: u32 = bindings::IOMMU_WRITE; + /// Request cache coherency. + pub const CACHE: u32 = bindings::IOMMU_CACHE; + /// Request no-execute permission. + pub const NOEXEC: u32 = bindings::IOMMU_NOEXEC; + /// MMIO peripheral mapping. + pub const MMIO: u32 = bindings::IOMMU_MMIO; + /// Privileged mapping. + pub const PRIV: u32 = bindings::IOMMU_PRIV; +} + +/// Represents a requested io_pgtable configuration. +pub struct Config { + /// Quirk bitmask (type-specific). + pub quirks: usize, + /// Valid page sizes, as a bitmask of powers of two. + pub pgsize_bitmap: usize, + /// Input address space size in bits. + pub ias: usize, + /// Output address space size in bits. + pub oas: usize, + /// IOMMU uses coherent accesses for page table walks. + pub coherent_walk: bool, +} + +/// IOMMU callbacks for TLB and page table management. +/// +/// Users must implement this trait to perform the TLB flush actions for this IOMMU, if +/// required. +pub trait FlushOps { + /// User-specified type owned by the IOPagetable that will be passed to TLB operations. + type Data: ForeignOwnable + Send + Sync; + + /// Synchronously invalidate the entire TLB context. + fn tlb_flush_all(data: ::Borrowed<'_>); + + /// Synchronously invalidate all intermediate TLB state (sometimes referred to as the "walk + /// cache") for a virtual address range. + fn tlb_flush_walk( + data: ::Borrowed<'_>, + iova: usize, + size: usize, + granule: usize, + ); + + /// Optional callback to queue up leaf TLB invalidation for a single page. + /// + /// IOMMUs that cannot batch TLB invalidation operations efficiently will typically issue + /// them here, but others may decide to update the iommu_iotlb_gather structure and defer + /// the invalidation until iommu_iotlb_sync() instead. + /// + /// TODO: Implement the gather argument for batching. + fn tlb_add_page( + data: ::Borrowed<'_>, + iova: usize, + granule: usize, + ); +} + +/// Inner page table info shared across all table types. +/// # Invariants +/// +/// - [`self.ops`] is valid and non-null. +/// - [`self.cfg`] is valid and non-null. +#[doc(hidden)] +pub struct IoPageTableInner { + ops: *mut bindings::io_pgtable_ops, + cfg: bindings::io_pgtable_cfg, + data: *mut core::ffi::c_void, +} + +/// Helper trait to get the config type for a single page table type from the union. +pub trait GetConfig { + /// Returns the specific output configuration for this page table type. + fn cfg(iopt: &impl IoPageTable) -> &Self + where + Self: Sized; +} + +/// A generic IOMMU page table +pub trait IoPageTable: crate::private::Sealed { + #[doc(hidden)] + const FLUSH_OPS: bindings::iommu_flush_ops; + + #[doc(hidden)] + fn new_fmt( + dev: &dyn device::RawDevice, + format: u32, + config: Config, + data: T::Data, + ) -> Result { + let ptr = data.into_foreign() as *mut _; + let guard = ScopeGuard::new(|| { + // SAFETY: `ptr` came from a previous call to `into_foreign`. + unsafe { T::Data::from_foreign(ptr) }; + }); + + let mut raw_cfg = bindings::io_pgtable_cfg { + quirks: config.quirks.try_into()?, + pgsize_bitmap: config.pgsize_bitmap.try_into()?, + ias: config.ias.try_into()?, + oas: config.oas.try_into()?, + coherent_walk: config.coherent_walk, + tlb: &Self::FLUSH_OPS, + iommu_dev: dev.raw_device(), + // SAFETY: This is an output field which is fine to zero-init. + __bindgen_anon_1: unsafe { mem::zeroed() }, + }; + + // SAFETY: FFI call, all input pointers are valid. + let ops = unsafe { + bindings::alloc_io_pgtable_ops(format as bindings::io_pgtable_fmt, &mut raw_cfg, ptr) + }; + + if ops.is_null() { + return Err(EINVAL); + } + + guard.dismiss(); + Ok(IoPageTableInner { + ops, + cfg: raw_cfg, + data: ptr, + }) + } + + /// Map a range of pages. + fn map_pages( + &mut self, + iova: usize, + paddr: usize, + pgsize: usize, + pgcount: usize, + prot: u32, + ) -> Result { + let mut mapped: usize = 0; + + // SAFETY: FFI call, ops is valid per the type invariant. + to_result(unsafe { + (*self.inner().ops).map_pages.unwrap()( + self.inner().ops, + iova as u64, + paddr as u64, + pgsize, + pgcount, + prot as i32, + bindings::GFP_KERNEL, + &mut mapped, + ) + })?; + + Ok(mapped) + } + + /// Unmap a range of pages. + fn unmap_pages( + &mut self, + iova: usize, + pgsize: usize, + pgcount: usize, + // TODO: gather: *mut iommu_iotlb_gather, + ) -> usize { + // SAFETY: FFI call, ops is valid per the type invariant. + unsafe { + (*self.inner().ops).unmap_pages.unwrap()( + self.inner().ops, + iova as u64, + pgsize, + pgcount, + core::ptr::null_mut(), + ) + } + } + + /// Translate an IOVA to the corresponding physical address, if mapped. + fn iova_to_phys(&self, iova: usize) -> Option { + // SAFETY: FFI call, ops is valid per the type invariant. + NonZeroU64::new(unsafe { + (*self.inner().ops).iova_to_phys.unwrap()(self.inner().ops, iova as u64) + }) + } + + #[doc(hidden)] + fn inner(&self) -> &IoPageTableInner; + + #[doc(hidden)] + fn raw_cfg(&self) -> &bindings::io_pgtable_cfg { + &self.inner().cfg + } +} + +// SAFETY: All abstraction operations either require mutable references or are thread-safe, +// and io_pgtable_ops objects can be passed between threads without issue. +unsafe impl Send for IoPageTableInner {} +unsafe impl Sync for IoPageTableInner {} + +unsafe extern "C" fn tlb_flush_all_callback(cookie: *mut core::ffi::c_void) { + // SAFETY: The cookie is always a ForeignOwnable of the right type, per new_fmt(). + T::tlb_flush_all(unsafe { T::Data::borrow(cookie) }); +} + +unsafe extern "C" fn tlb_flush_walk_callback( + iova: core::ffi::c_ulong, + size: usize, + granule: usize, + cookie: *mut core::ffi::c_void, +) { + // SAFETY: The cookie is always a ForeignOwnable of the right type, per new_fmt(). + T::tlb_flush_walk( + unsafe { T::Data::borrow(cookie) }, + iova as usize, + size, + granule, + ); +} + +unsafe extern "C" fn tlb_add_page_callback( + _gather: *mut bindings::iommu_iotlb_gather, + iova: core::ffi::c_ulong, + granule: usize, + cookie: *mut core::ffi::c_void, +) { + // SAFETY: The cookie is always a ForeignOwnable of the right type, per new_fmt(). + T::tlb_add_page(unsafe { T::Data::borrow(cookie) }, iova as usize, granule); +} + +macro_rules! iopt_cfg { + ($name:ident, $field:ident, $type:ident) => { + /// An IOMMU page table configuration for a specific kind of pagetable. + pub type $name = bindings::$type; + + impl GetConfig for $name { + fn cfg(iopt: &impl IoPageTable) -> &$name { + // SAFETY: The type system ensures we are accessing the right union field. + unsafe { &iopt.raw_cfg().__bindgen_anon_1.$field } + } + } + }; +} + +impl GetConfig for () { + fn cfg(_iopt: &impl IoPageTable) -> &() { + &() + } +} + +macro_rules! iopt_type { + ($type:ident, $cfg:ty, $fmt:ident) => { + /// Represents an IOPagetable of this type. + pub struct $type(IoPageTableInner, PhantomData); + + impl $type { + /// Creates a new IOPagetable implementation of this type. + pub fn new(dev: &dyn device::RawDevice, config: Config, data: T::Data) -> Result { + Ok(Self( + ::new_fmt::(dev, bindings::$fmt, config, data)?, + PhantomData, + )) + } + + /// Get the configuration for this IOPagetable. + pub fn cfg(&self) -> &$cfg { + <$cfg as GetConfig>::cfg(self) + } + } + + impl crate::private::Sealed for $type {} + + impl IoPageTable for $type { + const FLUSH_OPS: bindings::iommu_flush_ops = bindings::iommu_flush_ops { + tlb_flush_all: Some(tlb_flush_all_callback::), + tlb_flush_walk: Some(tlb_flush_walk_callback::), + tlb_add_page: Some(tlb_add_page_callback::), + }; + + fn inner(&self) -> &IoPageTableInner { + &self.0 + } + } + + impl Drop for $type { + fn drop(&mut self) { + // SAFETY: The pointer is valid by the type invariant. + unsafe { bindings::free_io_pgtable_ops(self.0.ops) }; + + // Free context data. + // + // SAFETY: This matches the call to `into_foreign` from `new_fmt`. + unsafe { T::Data::from_foreign(self.0.data) }; + } + } + }; +} + +// Ew, bindgen unions really are quite messy... +iopt_cfg!( + ARMLPAES1Cfg, + arm_lpae_s1_cfg, + io_pgtable_cfg__bindgen_ty_1__bindgen_ty_1 +); +iopt_cfg!( + ARMLPAES2Cfg, + arm_lpae_s2_cfg, + io_pgtable_cfg__bindgen_ty_1__bindgen_ty_2 +); +iopt_cfg!( + ARMv7SCfg, + arm_v7s_cfg, + io_pgtable_cfg__bindgen_ty_1__bindgen_ty_3 +); +iopt_cfg!( + ARMMaliLPAECfg, + arm_mali_lpae_cfg, + io_pgtable_cfg__bindgen_ty_1__bindgen_ty_4 +); +iopt_cfg!( + AppleDARTCfg, + apple_dart_cfg, + io_pgtable_cfg__bindgen_ty_1__bindgen_ty_5 +); + +iopt_type!(ARM32LPAES1, ARMLPAES1Cfg, io_pgtable_fmt_ARM_32_LPAE_S1); +iopt_type!(ARM32LPAES2, ARMLPAES2Cfg, io_pgtable_fmt_ARM_32_LPAE_S2); +iopt_type!(ARM64LPAES1, ARMLPAES1Cfg, io_pgtable_fmt_ARM_64_LPAE_S1); +iopt_type!(ARM64LPAES2, ARMLPAES2Cfg, io_pgtable_fmt_ARM_64_LPAE_S2); +iopt_type!(ARMv7S, ARMv7SCfg, io_pgtable_fmt_ARM_V7S); +iopt_type!(ARMMaliLPAE, ARMMaliLPAECfg, io_pgtable_fmt_ARM_MALI_LPAE); +iopt_type!(AMDIOMMUV1, (), io_pgtable_fmt_AMD_IOMMU_V1); +iopt_type!(AppleDART, AppleDARTCfg, io_pgtable_fmt_APPLE_DART); +iopt_type!(AppleDART2, AppleDARTCfg, io_pgtable_fmt_APPLE_DART2); diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index de44092718f8..9944086d7e09 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -31,6 +31,8 @@ mod allocator; mod build_assert; pub mod device; pub mod error; +#[cfg(CONFIG_IOMMU_IO_PGTABLE)] +pub mod io_pgtable; pub mod prelude; pub mod print; mod static_assert; From patchwork Fri Feb 24 10:53:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asahi Lina X-Patchwork-Id: 61257 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp836617wrd; Fri, 24 Feb 2023 03:01:13 -0800 (PST) X-Google-Smtp-Source: AK7set8qWkIiSvSPdVyjS4LxTCSPo/7onhATR6VodyZSx0Ig+G5PUlwbeYS2CTFLUwZERPbaHqz+ X-Received: by 2002:a17:906:eb18:b0:8b1:7de3:cfaa with SMTP id mb24-20020a170906eb1800b008b17de3cfaamr26240604ejb.3.1677236473446; Fri, 24 Feb 2023 03:01:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677236473; cv=none; d=google.com; s=arc-20160816; b=QIDMoPZKQe8AaXWW414Obl6miiHPJnfF0ZEbv/mZbSHqh2+nfJskWkWTiXWrvMirkm PozZsckBUWiDGX2hGdN2BAZtPag8DY1xy7W4YrbllOWX6/HIS7NAgFC+jiWWZuqK/0gA r1FXFX62saE17zqjSrd1DKuLEdkuNmaVZPRedN0OOOxO/iVwux4SN9I+fSVGGopWu+NE TPEtnPOEmKzC4J/1qK8H7Cvl09uhmit52JPa4ndT0PzZrZvww6WiLurr1Vaq5T9nj4yi wp6AKYpoyPxALohGktGLuT+iPKTPr4xqnt8G+9fNLo6gQA3puyl9/tP5njQnWa6UKoV8 a+Jw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=CGDgMHbDokWuN0dMhHPf86b9XNJRRAjiaM4QUdz4Wvg=; b=raFzs5YJq5CjN3Kv2yFRPrvbBZf/9ho4pIXXLnpLpIoMqccRA74xtA10ncwqpRl1Nf NHJcRDGffcsYinCino5t0scRCPeunDP47A/Uj8A/26OUp4KgGIY6rhKScYuR4vGYs+yQ pwYVOm4kAJOACo2HUwPH85UtbD9NY5ZpqE4H+7PP95NztAxFqBrMzcJY/jcGjTkNudJv dE++6sUf2sTIIiWT8ZGbrHckb7p6rk25W2OAYp4Vb+2whkfrS8BMyQTYe9kBrcIKOJis /jlihZcxjKTImpNZJf92xM8L4X8i4WNxn5xe/OKrpYgPnsT01gfBfvBjdXnr8Yfs7Zy6 ZFfg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=A6Ru0K8e; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id fl5-20020a1709072a8500b008ce419809a0si14491042ejc.217.2023.02.24.03.00.47; Fri, 24 Feb 2023 03:01:13 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=A6Ru0K8e; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230073AbjBXKys (ORCPT + 99 others); Fri, 24 Feb 2023 05:54:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230247AbjBXKyV (ORCPT ); Fri, 24 Feb 2023 05:54:21 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8418164E16; Fri, 24 Feb 2023 02:54:02 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id E917342627; Fri, 24 Feb 2023 10:53:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677236040; bh=s8yg5Qe3Cf1DPHC1UIkVpTHEHGDsFbQ4/QodiHzArtM=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=A6Ru0K8ekFVsvGDAELnpxa6tTrj8c587gyepAco4OyLOpVCnGZFAAC8pzTvEnr8BK ERgbLZBGIJZOiyYEOPzwWb7HiM6Gnb+/buqxYEmBZCTjAyUKHAL3jljF9FMyC1EvdD Q795JgevAi5UnOrlku3tg1TYdXWnX6kb5468++fDi4o0VbLkfBEN4nPCX34XnnvcO9 QX7UOjo47PKDFa4+uFUN4bf4lwt7021J0XN8PI57gXxiUDMt2LhCypHcqSw9oUHMwK ZwIz4ZOANwzmOk3L6j4WCbNzqVfi1XeGxtWC2lLies3au6RfD7cxjEXS9kW/WMZbel Qz4VyAEbABKEw== From: Asahi Lina Date: Fri, 24 Feb 2023 19:53:16 +0900 Subject: [PATCH 4/5] rust: soc: apple: rtkit: Add Apple RTKit abstraction MIME-Version: 1.0 Message-Id: <20230224-rust-iopt-rtkit-v1-4-49ced3391295@asahilina.net> References: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> In-Reply-To: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Will Deacon , Robin Murphy , Joerg Roedel , Hector Martin , Sven Peter , Arnd Bergmann , Greg Kroah-Hartman Cc: "Rafael J. Wysocki" , Alyssa Rosenzweig , Neal Gompa , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677236013; l=11585; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=s8yg5Qe3Cf1DPHC1UIkVpTHEHGDsFbQ4/QodiHzArtM=; b=czVp61paD5NoMTz4vwcTr9lDdsqWjE73xnF7YjvYkIghtw6eScQB6OZFQccW+TpLk15O7XiLU mYioNvRS1+RBDOqpGHh4UMxmwD3NLQvmeW/kCm575MbOzlXnNhTeCpU X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758709912523429363?= X-GMAIL-MSGID: =?utf-8?q?1758709912523429363?= RTKit is Apple's proprietary real-time operating system framework, used across many subdevices on Apple Silicon platforms including NVMe, system management, GPU, etc. Add Rust abstractions for this subsystem, so that it can be used by upcoming Rust drivers. This API is safe under the expectation that all RTKit coprocessors either have no unfiltered access to system memory (SMC), are behind a DART IOMMU (DCP, etc.), or require other unsafe operations to be granted access to arbitrary system memory (GFX, where the coprocessor page tables need to be mutated in bootloader-allocated memory blocks in order to map additional memory, which is a requirement to get it to do anything interesting beyond basic startup.) Note: Although ARM64 support is not yet merged, this can be built on amd64 with CONFIG_COMPILE_TEST=y. Signed-off-by: Asahi Lina --- rust/bindings/bindings_helper.h | 1 + rust/kernel/lib.rs | 1 + rust/kernel/soc/apple/mod.rs | 6 + rust/kernel/soc/apple/rtkit.rs | 259 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/soc/mod.rs | 5 + 5 files changed, 272 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 88c65431d3ad..c920d6242e3a 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -10,6 +10,7 @@ #include #include #include +#include /* `bindgen` gets confused at certain things. */ const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 9944086d7e09..78108cbbf814 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -35,6 +35,7 @@ pub mod error; pub mod io_pgtable; pub mod prelude; pub mod print; +pub mod soc; mod static_assert; #[doc(hidden)] pub mod std_vendor; diff --git a/rust/kernel/soc/apple/mod.rs b/rust/kernel/soc/apple/mod.rs new file mode 100644 index 000000000000..dd69db63677d --- /dev/null +++ b/rust/kernel/soc/apple/mod.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +//! Apple SoC drivers + +#[cfg(CONFIG_APPLE_RTKIT = "y")] +pub mod rtkit; diff --git a/rust/kernel/soc/apple/rtkit.rs b/rust/kernel/soc/apple/rtkit.rs new file mode 100644 index 000000000000..595b9b3dda96 --- /dev/null +++ b/rust/kernel/soc/apple/rtkit.rs @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +//! Support for Apple RTKit coprocessors. +//! +//! C header: [`include/linux/soc/apple/rtkit.h`](../../../../include/linux/gpio/driver.h) + +use crate::{ + bindings, device, + error::{code::*, from_kernel_err_ptr, from_kernel_result, to_result, Result}, + str::CStr, + types::{ForeignOwnable, ScopeGuard}, +}; + +use alloc::boxed::Box; +use core::marker::PhantomData; +use core::ptr; +use macros::vtable; + +/// Trait to represent allocatable buffers for the RTKit core. +/// +/// Users must implement this trait for their own representation of those allocations. +pub trait Buffer { + /// Returns the IOVA (virtual address) of the buffer from RTKit's point of view, or an error if + /// unavailable. + fn iova(&self) -> Result; + + /// Returns a mutable byte slice of the buffer contents, or an + /// error if unavailable. + fn buf(&mut self) -> Result<&mut [u8]>; +} + +/// Callback operations for an RTKit client. +#[vtable] +pub trait Operations { + /// Arbitrary user context type. + type Data: ForeignOwnable + Send + Sync; + + /// Type representing an allocated buffer for RTKit. + type Buffer: Buffer; + + /// Called when RTKit crashes. + fn crashed(_data: ::Borrowed<'_>) {} + + /// Called when a message was received on a non-system endpoint. Called in non-IRQ context. + fn recv_message( + _data: ::Borrowed<'_>, + _endpoint: u8, + _message: u64, + ) { + } + + /// Called in IRQ context when a message was received on a non-system endpoint. + /// + /// Must return `true` if the message is handled, or `false` to process it in + /// the handling thread. + fn recv_message_early( + _data: ::Borrowed<'_>, + _endpoint: u8, + _message: u64, + ) -> bool { + false + } + + /// Allocate a buffer for use by RTKit. + fn shmem_alloc( + _data: ::Borrowed<'_>, + _size: usize, + ) -> Result { + Err(EINVAL) + } + + /// Map an existing buffer used by RTKit at a device-specified virtual address. + fn shmem_map( + _data: ::Borrowed<'_>, + _iova: usize, + _size: usize, + ) -> Result { + Err(EINVAL) + } +} + +/// Represents `struct apple_rtkit *`. +/// +/// # Invariants +/// +/// The rtk pointer is valid. +/// The data pointer is a valid pointer from T::Data::into_foreign(). +pub struct RtKit { + rtk: *mut bindings::apple_rtkit, + data: *mut core::ffi::c_void, + _p: PhantomData, +} + +unsafe extern "C" fn crashed_callback(cookie: *mut core::ffi::c_void) { + // SAFETY: cookie is always a PointerWrapper of the right type, passed in new(). + T::crashed(unsafe { T::Data::borrow(cookie) }); +} + +unsafe extern "C" fn recv_message_callback( + cookie: *mut core::ffi::c_void, + endpoint: u8, + message: u64, +) { + // SAFETY: cookie is always a PointerWrapper of the right type, passed in new(). + T::recv_message(unsafe { T::Data::borrow(cookie) }, endpoint, message); +} + +unsafe extern "C" fn recv_message_early_callback( + cookie: *mut core::ffi::c_void, + endpoint: u8, + message: u64, +) -> bool { + // SAFETY: cookie is always a PointerWrapper of the right type, passed in new(). + T::recv_message_early(unsafe { T::Data::borrow(cookie) }, endpoint, message) +} + +unsafe extern "C" fn shmem_setup_callback( + cookie: *mut core::ffi::c_void, + bfr: *mut bindings::apple_rtkit_shmem, +) -> core::ffi::c_int { + // SAFETY: `bfr` is a valid buffer. + let bfr_mut = unsafe { &mut *bfr }; + + let buf = if bfr_mut.iova != 0 { + bfr_mut.is_mapped = true; + T::shmem_map( + // SAFETY: `cookie` came from a previous call to `into_foreign`. + unsafe { T::Data::borrow(cookie) }, + bfr_mut.iova as usize, + bfr_mut.size, + ) + } else { + bfr_mut.is_mapped = false; + // SAFETY: `cookie` came from a previous call to `into_foreign`. + T::shmem_alloc(unsafe { T::Data::borrow(cookie) }, bfr_mut.size) + }; + + from_kernel_result! { + let mut buf = buf?; + let iova = buf.iova()?; + let slice = buf.buf()?; + + if slice.len() < bfr_mut.size { + return Err(ENOMEM); + } + + bfr_mut.iova = iova as u64; + bfr_mut.buffer = slice.as_mut_ptr() as *mut _; + + // Now box the returned buffer type and stash it in the private pointer of the + // `apple_rtkit_shmem` struct for safekeeping. + bfr_mut.private = Box::into_raw(Box::try_new(buf)?) as *mut _; + Ok(0) + } +} + +unsafe extern "C" fn shmem_destroy_callback( + _cookie: *mut core::ffi::c_void, + bfr: *mut bindings::apple_rtkit_shmem, +) { + // SAFETY: `bfr` is a valid buffer. + let bfr_mut = unsafe { &mut *bfr }; + if !bfr_mut.private.is_null() { + // SAFETY: Per shmem_setup_callback, this has to be a pointer to a Buffer if it is set. + unsafe { + core::mem::drop(Box::from_raw(bfr_mut.private as *mut T::Buffer)); + } + bfr_mut.private = core::ptr::null_mut(); + } +} + +impl RtKit { + const VTABLE: bindings::apple_rtkit_ops = bindings::apple_rtkit_ops { + crashed: Some(crashed_callback::), + recv_message: Some(recv_message_callback::), + recv_message_early: Some(recv_message_early_callback::), + shmem_setup: if T::HAS_SHMEM_ALLOC || T::HAS_SHMEM_MAP { + Some(shmem_setup_callback::) + } else { + None + }, + shmem_destroy: if T::HAS_SHMEM_ALLOC || T::HAS_SHMEM_MAP { + Some(shmem_destroy_callback::) + } else { + None + }, + }; + + /// Creates a new RTKit client for a given device and optional mailbox name or index. + pub fn new( + dev: &dyn device::RawDevice, + mbox_name: Option<&'static CStr>, + mbox_idx: usize, + data: T::Data, + ) -> Result { + let ptr = data.into_foreign() as *mut _; + let guard = ScopeGuard::new(|| { + // SAFETY: `ptr` came from a previous call to `into_foreign`. + unsafe { T::Data::from_foreign(ptr) }; + }); + // SAFETY: This just calls the C init function. + let rtk = unsafe { + from_kernel_err_ptr(bindings::apple_rtkit_init( + dev.raw_device(), + ptr, + match mbox_name { + Some(s) => s.as_char_ptr(), + None => ptr::null(), + }, + mbox_idx.try_into()?, + &Self::VTABLE, + )) + }?; + + guard.dismiss(); + // INVARIANT: `rtk` and `data` are valid here. + Ok(Self { + rtk, + data: ptr, + _p: PhantomData, + }) + } + + /// Boots (wakes up) the RTKit coprocessor. + pub fn boot(&mut self) -> Result { + // SAFETY: `rtk` is valid per the type invariant. + to_result(unsafe { bindings::apple_rtkit_boot(self.rtk) }) + } + + /// Starts a non-system endpoint. + pub fn start_endpoint(&mut self, endpoint: u8) -> Result { + // SAFETY: `rtk` is valid per the type invariant. + to_result(unsafe { bindings::apple_rtkit_start_ep(self.rtk, endpoint) }) + } + + /// Sends a message to a given endpoint. + pub fn send_message(&mut self, endpoint: u8, message: u64) -> Result { + // SAFETY: `rtk` is valid per the type invariant. + to_result(unsafe { + bindings::apple_rtkit_send_message(self.rtk, endpoint, message, ptr::null_mut(), false) + }) + } +} + +// SAFETY: `RtKit` operations require a mutable reference. +unsafe impl Sync for RtKit {} +unsafe impl Send for RtKit {} + +impl Drop for RtKit { + fn drop(&mut self) { + // SAFETY: The pointer is valid by the type invariant. + unsafe { bindings::apple_rtkit_free(self.rtk) }; + + // Free context data. + // + // SAFETY: This matches the call to `into_foreign` from `new` in the success case. + unsafe { T::Data::from_foreign(self.data) }; + } +} diff --git a/rust/kernel/soc/mod.rs b/rust/kernel/soc/mod.rs new file mode 100644 index 000000000000..e3024042e74f --- /dev/null +++ b/rust/kernel/soc/mod.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! SoC drivers + +pub mod apple; From patchwork Fri Feb 24 10:53:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asahi Lina X-Patchwork-Id: 61259 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp836962wrd; Fri, 24 Feb 2023 03:01:45 -0800 (PST) X-Google-Smtp-Source: AK7set8H2Q+m8uZkgWFrVr8ubBBbpOzUr3AzsSHAGe5e6eoDVbBXj7mJGm49GSXwshnNEQPUBCAW X-Received: by 2002:a50:fc05:0:b0:4af:59c0:5a30 with SMTP id i5-20020a50fc05000000b004af59c05a30mr10666092edr.38.1677236505410; Fri, 24 Feb 2023 03:01:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677236505; cv=none; d=google.com; s=arc-20160816; b=w/c11jtKWfE81C0EV7SEcX4MT+6DJov5B2SAouF0ztPOVDqWOXF9s03hocSzI+tUu3 xgaR3xnBuVeXSFYQSwjmWFonc00Nb+VqoRvFnb3VRrrRv3U+hduaz6tzjVoV/eYQJnaU pmk0s645t+JMP1mGetLZg6Ia6w4zO0CXwJPwrOpQvYA6XKad5tosG+yDKfYw6ydsQlqJ GdNMtsXF2JxDEBTwjbaMuNrGEKP/VwNzKrqfZG8POBp9mTssVx2G4Ea4Cr8B5krk3t3p oryXG8EJHhXznLsDbh3bbzfY7MhAPlc++n4vY5dshD6zGDPfeyZt8b4zCBKChc57BJM7 Tm0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=Ib32KPlKkGdBac9Oy/KyJF5GBykuAsqtiUUeH1X66Gs=; b=MkJ0QdhBunNO634rEmXiEF7Gfuc9cKsw5TWfQ+eAdN9tof6j98IiMnk+1ifYaZGxUq I8z1UAwn1+IWhL+7Brg5BQZvxahnMXCWbrnrdud//+rxmdQRHgi3k8g3jA6dvxD2d24L qRWr/xyGX50h9+ES/pUgY/SLYPd4W43eJ0b7M/9oYI1WjF8DMDLqhfaxE7vjStCkcM3K EeWILdmowGUca9xGoKEsfXNlvleoHf/p1M4B8TiKRbtqyR+aGrGfkBR+Ik7RoI0fh2fj wuYeO9AyT0TQA24Un4h5ODnThLyN50SPTaNZOx8RrsH5JL00fCVD4RXIm7Adl9GYDa07 CYdg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=QQ+STDuF; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id fh4-20020a1709073a8400b008cf79b051d8si17106461ejc.558.2023.02.24.03.00.49; Fri, 24 Feb 2023 03:01:45 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=QQ+STDuF; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230232AbjBXKzB (ORCPT + 99 others); Fri, 24 Feb 2023 05:55:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230197AbjBXKyf (ORCPT ); Fri, 24 Feb 2023 05:54:35 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3ADB665CFA; Fri, 24 Feb 2023 02:54:08 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id 70EE74206F; Fri, 24 Feb 2023 10:54:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1677236046; bh=EdCqFOCkFmNCQy+An4xXL1lM8eljicqRMAsCfNlFpXc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=QQ+STDuF5KmAnOI1efDmHlNdV4hDOgItX2AUUxdagG3FUFVa90uZxAGL7b8dUB7Pt 5QjG7nWPiB/Iq8Ltdn2HxdrrDHWPOJb3c0rtMWBaq+tDdwz4TYBgFKoe9oQDJFMyYN LQFz/vE/drpBjenLI8bhQyU/zpctXEnwUdi3m22lq8s0Sai1gZvvwXgMtsCjXAVlm0 7DayCYMhW3AuA7oiut0NtQNjrGvsadhl7fZI5KOY/UHYi42N1QGIR1ieMKtv0PLF1z JEbeIJBkLLKjIgRTi5TFHJpEFpZRr4qxYw16W2LiDqglXiENJ78ZjNj0jDto5vxOt8 hRpzEfbVxlyRg== From: Asahi Lina Date: Fri, 24 Feb 2023 19:53:17 +0900 Subject: [PATCH 5/5] rust: device: Add a stub abstraction for devices MIME-Version: 1.0 Message-Id: <20230224-rust-iopt-rtkit-v1-5-49ced3391295@asahilina.net> References: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> In-Reply-To: <20230224-rust-iopt-rtkit-v1-0-49ced3391295@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Will Deacon , Robin Murphy , Joerg Roedel , Hector Martin , Sven Peter , Arnd Bergmann , Greg Kroah-Hartman Cc: "Rafael J. Wysocki" , Alyssa Rosenzweig , Neal Gompa , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, asahi@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1677236013; l=5017; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=cdKIkyLwKJzj4pWUi4LyfvGZS5F3kfJKVHncm9kraaI=; b=OEIdscGIoIcKDDmhOPjbLGxA2i8Nhrg9rQMhaRWYJa7GQDqVwWSu3E/ZXAwXPBLNGXyvChxkV TnzkvIyCmpxAoIODcjIWil4i3mShoVRVROu+yHknTma9STuRcYVcEqq X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758709945877295962?= X-GMAIL-MSGID: =?utf-8?q?1758709945877295962?= From: Wedson Almeida Filho Add a Device type which represents an owned reference to a generic struct device. This minimal implementation just handles reference counting and allows the user to get the device name. Lina: Rewrote commit message, dropped the Amba bits, and squashed in simple changes to the core Device code from latter commits in rust-for-linux/rust. Also include the rust_helper_dev_get_drvdata helper which will be needed by consumers later on anyway. Co-developed-by: Miguel Ojeda Signed-off-by: Miguel Ojeda Signed-off-by: Wedson Almeida Filho Signed-off-by: Asahi Lina --- rust/helpers.c | 13 +++++++++ rust/kernel/device.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index 04b9be46e887..54954fd80c77 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -65,6 +66,18 @@ long rust_helper_PTR_ERR(__force const void *ptr) } EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR); +void *rust_helper_dev_get_drvdata(struct device *dev) +{ + return dev_get_drvdata(dev); +} +EXPORT_SYMBOL_GPL(rust_helper_dev_get_drvdata); + +const char *rust_helper_dev_name(const struct device *dev) +{ + return dev_name(dev); +} +EXPORT_SYMBOL_GPL(rust_helper_dev_name); + /* * We use `bindgen`'s `--size_t-is-usize` option to bind the C `size_t` type * as the Rust `usize` type, so we can use it in contexts where Rust diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 9be021e393ca..e57da622d817 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -4,7 +4,7 @@ //! //! C header: [`include/linux/device.h`](../../../../include/linux/device.h) -use crate::bindings; +use crate::{bindings, str::CStr}; /// A raw device. /// @@ -20,4 +20,78 @@ use crate::bindings; pub unsafe trait RawDevice { /// Returns the raw `struct device` related to `self`. fn raw_device(&self) -> *mut bindings::device; + + /// Returns the name of the device. + fn name(&self) -> &CStr { + let ptr = self.raw_device(); + + // SAFETY: `ptr` is valid because `self` keeps it alive. + let name = unsafe { bindings::dev_name(ptr) }; + + // SAFETY: The name of the device remains valid while it is alive (because the device is + // never renamed, per the safety requirement of this trait). This is guaranteed to be the + // case because the reference to `self` outlives the one of the returned `CStr` (enforced + // by the compiler because of their lifetimes). + unsafe { CStr::from_char_ptr(name) } + } +} + +/// A ref-counted device. +/// +/// # Invariants +/// +/// `ptr` is valid, non-null, and has a non-zero reference count. One of the references is owned by +/// `self`, and will be decremented when `self` is dropped. +pub struct Device { + pub(crate) ptr: *mut bindings::device, +} + +// SAFETY: `Device` only holds a pointer to a C device, which is safe to be used from any thread. +unsafe impl Send for Device {} + +// SAFETY: `Device` only holds a pointer to a C device, references to which are safe to be used +// from any thread. +unsafe impl Sync for Device {} + +impl Device { + /// Creates a new device instance. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count. + pub unsafe fn new(ptr: *mut bindings::device) -> Self { + // SAFETY: By the safety requirements, ptr is valid and its refcounted will be incremented. + unsafe { bindings::get_device(ptr) }; + // INVARIANT: The safety requirements satisfy all but one invariant, which is that `self` + // owns a reference. This is satisfied by the call to `get_device` above. + Self { ptr } + } + + /// Creates a new device instance from an existing [`RawDevice`] instance. + pub fn from_dev(dev: &dyn RawDevice) -> Self { + // SAFETY: The requirements are satisfied by the existence of `RawDevice` and its safety + // requirements. + unsafe { Self::new(dev.raw_device()) } + } +} + +// SAFETY: The device returned by `raw_device` is the one for which we hold a reference. +unsafe impl RawDevice for Device { + fn raw_device(&self) -> *mut bindings::device { + self.ptr + } +} + +impl Drop for Device { + fn drop(&mut self) { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // relinquish it now. + unsafe { bindings::put_device(self.ptr) }; + } +} + +impl Clone for Device { + fn clone(&self) -> Self { + Device::from_dev(self) + } }