From patchwork Thu Feb 27 14:38:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994731 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 1FEEC23BCE3; Thu, 27 Feb 2025 14:39:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667188; cv=none; b=FeTceNZnDbkYL50WuYJ1gAT4ljR0R5JIzLthKIa7sj2p4MA70Alagek+7+Kot+7aoE/YphjRIhN4JV9WbSFjVdkU2Bw4JRIvgu7KuuD8IC1AYzlA1DZ2XoBM4jX3xBUcgKWxbTeoKsE3Yxs81tr0tWiQFapjFCpMKTcuEZqokQQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667188; c=relaxed/simple; bh=9xEh8xnuonl+Y4DJJTe3psqTruSkTcctIO2KOz8LZ3U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dV0G8Y+DpZ2DMkI0C37cVOuuwBt0iC+lJ6nHqWC5IiGLNQ2+uKiLZ+CvGiHnCrYP14h8G86tAvyhWeSNGujzT5xv9s1X1iU01ZcCxyxQ3Zi81s0Q/b7vMq7J+lzZGlxXxJvVx6kQUT+iLCCHO3ytjwUJerFg30AlqQcwmdKlB2U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FOlhyc63; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FOlhyc63" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1AF35C4CEE9; Thu, 27 Feb 2025 14:39:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667187; bh=9xEh8xnuonl+Y4DJJTe3psqTruSkTcctIO2KOz8LZ3U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FOlhyc63NdTvMRnEoTKfKrBjtuf99xMXITmk8vn+5L376KocYDLukN+HFCaX/rgCW 5t2SXyNf33h8lnRwWXJtKYi+MoEISMK5U1gz1qhIQyFT1n/W1feor0njQzmJoQcXbm NaOa3YGBuD445tb6MWpt0vdHH03bHSJUdQh8SrO/g3/+Ae5sqfxqpLICah9V4gUWry XjtHd3n6ttmWwh5tvrdMLHF1gnmmfokMfoofsTlMk9dG5sNiCQb/Sygd0d0OdeVEwl /dokBoIy1QHi71WM47bpJKxw4KRPnQz6303E1H20AllBPux82NP5zk4R1Adc5MnrE1 KT7coRs5T1jAw== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:07 +0100 Subject: [PATCH v8 1/7] rust: str: implement `PartialEq` for `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-1-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=911; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=9xEh8xnuonl+Y4DJJTe3psqTruSkTcctIO2KOz8LZ3U=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjQmudfccCCA3TVrg15lT/He0OPHIxRmsZZ+ L7YWtBKcOSJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B40AAKCRDhuBo+eShj d0rpD/wMpVT+8AVIxXiBvtFG3pZADIaZoJ24E0rNtHqYQypZA7B2alFifWZZw4ddWAxdFX0qeYq 5YrOQSx/euZCaVbHbOPTGmzY2S4zItr2Dp6BOElkXL1LshFw5uE9yOkwVCPymSy2dFqjqTHavyK +ZlA0w4tViBL6WZbk3zvAqxqtig5Q6YbkClnP0UJQbtW35GUcaYrdotmPXPLQb9Z/cIkWO9LJFQ d21DzzNLrBmhXe0J2fuxG6d/5JzqBOi0UnZCLz2u1rOVZ4oqcr44h2ajLMPf26BLhYNkRoupi9f TzHZ2SdpVgzoMOd3B+1RH4bCSZcnY7xggFIx3s/R4KVuigmNe2TMSyBIWzW6VYka/Wne6Xpd2Ql gQBjCcgzm7ciiOwuaP3XIe3FBglnT4QG9A68+E7MjIzWmW/7CxH86soDQP563Brgevm0+KXFPu3 T9DnDklxvccRZNQQp9OJ8IzXGZKfVkD3nELOSYyjJKxz+QmrQqn84yXICTSliBnYAqw6YTwMfzX MdHy2I2zGPf/D1k/+BtWEDxSWXlglNsi+xD95cnKmD6D352Ms4/BwRUtyk5HeJppn7o073Cv+IH g1hQPdxSx5o1vGEw1O2kTME/nuMzlLrjt5snEaykkrNNglkoRKY4n4jbOepR4L7DjEXnyyvV1In 0AT3Y7F66VjQAOQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `PartialEq` for `BStr` by comparing underlying byte slices. Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo Reviewed-by: Daniel Almeida Tested-by: Daniel Almeida Signed-off-by: Andreas Hindborg --- rust/kernel/str.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 28e2201604d6..002dcddf7c76 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -108,6 +108,12 @@ fn deref(&self) -> &Self::Target { } } +impl PartialEq for BStr { + fn eq(&self, other: &Self) -> bool { + self.deref().eq(other.deref()) + } +} + /// Creates a new [`BStr`] from a string literal. /// /// `b_str!` converts the supplied string literal to byte string, so non-ASCII From patchwork Thu Feb 27 14:38:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994730 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6D758236435; Thu, 27 Feb 2025 14:39:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667181; cv=none; b=NDI1HvmnR0GgpQb2aqls/zvH3fWq4kwTg0AfdqJhTP4+PPV9hIo2kGw5YTkLn4Fxo/dBrwaSA9lkQxK+2fXfq1oWmyns85gFDh602OMO0PaASPd/dx70AkijpapQpKs+J0eu1M6JGOZv5ZOHc9wQlFAgUlaWEwCSXqLvym/Tx2g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667181; c=relaxed/simple; bh=M5A9CbtSctHEgOcj2zrV2KphF+Jjyb2nnPlybeaE3OM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fluFVVb6cVT4rd32BScaCuSympPwTNIkaC+SKXbhHpd3PwdjtLAm6wrEQkVEPvx6m8XJHAjmc6SH0tGcvyxyU9FWc6MKlk5+i4tRld/d7hDiN9PiQyZu6ul+drvOGfWq4Slnw+n6eKs7FaHlgzWtUYJVRBRjsVPjjRfWJNJSQXk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IWlRcwVO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IWlRcwVO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A02C3C4CEDD; Thu, 27 Feb 2025 14:39:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667181; bh=M5A9CbtSctHEgOcj2zrV2KphF+Jjyb2nnPlybeaE3OM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IWlRcwVOc+TAmjwEZ/ByAfglNpcGDzR0g5rAtA87u3IMoWG9uwJnT0jBzMes/E+XC 0ilVNKkc6d7FPF9jmweEqogNpMgX6mpK2smUdu6MrJtM7BcE7s7oed994K4Idmulb2 2VB2FxZnGDI+8DXpelhu5znImKhqdd7SO8zlaBGmp3JsNovA1Z6mNd9vYqdK96x/2j VSmsEH/gc0Y7RwWQGdEVVGcOxZaizoDcymE1u99dR+FFE8GqoLw9vWJJZiAtGtCrCL X9jmHPXhSPVAIevxab/7EtgIwushl4SRR75PBrgBWjE2HRroqLq2FeWqviU8N68CnX 6zkUI2GaXuoBQ== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:08 +0100 Subject: [PATCH v8 2/7] rust: str: implement `Index` for `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-2-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1112; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=M5A9CbtSctHEgOcj2zrV2KphF+Jjyb2nnPlybeaE3OM=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjRKeyyfaKxrJbA8R7hdevR5EtBatPUaJ8f8 TQQ2HJ746OJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B40QAKCRDhuBo+eShj d33KD/wOboHDofwhau5kg5su/fiNGZfBgeG0XU9/kRdFP3NwMTcuPJbbVAodbO87uTyklTIpYxy 0GsTHOGYiwkpe0IeXljHKblDXE3Hv9ThWS/qafNOIHFsqUkqKIjS5CaBi3Wna6quc7uNIS/mEmf WL1d9RvG/07doamWa3DZF08FztimRJiDe/lKLNX7NdDr2D2iE08JfIb7HHZctjXz1LXj/b7G4J7 KIZONs4P80Mw5R9zivGIYuJwRIUaV9x+C9iSRXHDuM/8V8FN6WHK7oK1Fe2ZhfE4dPEgyUANR/6 BMgtIFY4QmYFzM+7XUQou2r8rt3FOc4aq841pb2YtClTvezDqUj2q2fd1KdGda0LdaeX4HjeX/Q PeffS3ZO9L5BjUJhahlcL3al9wutq9TxFPPLI8CDjzmb14VMijDXbdm2ud2sd+xeHjNXqD1qAm0 n2cqjSr4gJ/limNoZUAyScZJAKyR9lfWZ2DeS+rmZiiYFMNW+afG/WKwK80QHDnhNKVxkdRzYvv mHVfPHYEFIYlCr2SaVZ82OU/lRldacD52DJrpqftoUGC8Dg57zSv+eTTUSJdfFPBGSKTgJlehQ1 5VhI7kzKjwSe2U/TOU/X+mdPKmyYs/PIwxwyypHCOfFfLcDLEqtQ07eDGU6yha3J0EKspgYE882 ywZqbSnKXInVbaQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 The `Index` implementation on `BStr` was lost when we switched `BStr` from a type alias of `[u8]` to a newtype. Add back `Index` by implementing `Index` for `BStr` when `Index` would be implemented for `[u8]`. Reviewed-by: Daniel Almeida Tested-by: Daniel Almeida Reviewed-by: Fiona Behrens Signed-off-by: Andreas Hindborg --- rust/kernel/str.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index 002dcddf7c76..ba6b1a5c4f99 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -114,6 +114,17 @@ fn eq(&self, other: &Self) -> bool { } } +impl Index for BStr +where + [u8]: Index, +{ + type Output = Self; + + fn index(&self, index: Idx) -> &Self::Output { + BStr::from_bytes(&self.0[index]) + } +} + /// Creates a new [`BStr`] from a string literal. /// /// `b_str!` converts the supplied string literal to byte string, so non-ASCII From patchwork Thu Feb 27 14:38:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994727 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 DE86A236425; Thu, 27 Feb 2025 14:39:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667163; cv=none; b=CPb57hDYZXacbj0aGQScNrCUPmA3v47jztV3VHmBrUktmnCCxcoHk2QzbuE2QNt1aN1+6T5P8jJNiEVizIMZCTUVAjhNF6Vn2sFxvboDoUbRMf/VV2v7x0+p0M98vCY7Wr8UYEbUXMqi1yZz0Tvo8Tur6hrDnHSKRYHrUp2OwOs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667163; c=relaxed/simple; bh=y61tYQBOzvQT13se+wj4PsD5CpV5viHok2MH3MQVUsw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DbmHjTtLAcTmJb0wwZH6CeRQQ6uV8TjnVV6qkpNyqOdWpnX+LEc1WkmAhlM4ZCr1GhJ3pj+9NYwW0+TCv3CtJUSH4/Lpr2U8PHVcykCCo/E20NPJxwatNr4Dsz6/fPnml5DCPwrk0koHqyNA2iBDZ75O7eStxRIzO9UctCzIJjk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QA4tL/L0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QA4tL/L0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05250C4CEDD; Thu, 27 Feb 2025 14:39:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667162; bh=y61tYQBOzvQT13se+wj4PsD5CpV5viHok2MH3MQVUsw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=QA4tL/L05Yy3kZT2LhyG/ajf57qo2SGAErx034vB89DrdQ4SNakcQHhwfbQ3we90J Bxtk9YOLY8J0lEg76YFeD/vUh0ZnBESTIKiizf5La3cAUHITehNNp5LXOmovrMSlxh 3IIbqqohDh9LoFpjENxLJcD3lpNuELsSukWgsfzqArTokkwZb0M1mvWgHz/t32nbGl zJ3JPZdabVE3IPobp/oQONZ7DQxHhggkUUjKmPamKqP3emW/vdvHSEbVkHMuDgTgeR 5FaYqp5n+yPb+GlsF23mWzIIVDjVOA/Bkl4yiCMALkvwrRo2zJeQf0AD0COClIqOGq pL+gqqawbPzTQ== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:09 +0100 Subject: [PATCH v8 3/7] rust: str: implement `AsRef` for `[u8]` and `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-3-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1002; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=y61tYQBOzvQT13se+wj4PsD5CpV5viHok2MH3MQVUsw=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjSLiqwqmIm6F5SfrtT7rO15l7n0S0sY1Fne wmWAtG2mhSJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B40gAKCRDhuBo+eShj dyKhEACm1VAvi9EwhBdVdbF6jykLLlxpF5TrA52pr63Q0BUvMrammDD+I+zpzRp5OOkrtVRsk1o G28P+Waxuj+uup1uu21fB8qgRPUvVzGy97g9zUgzxkRXsBRVnbEXR73AzUHpXXaFmwIcdM8HdMH KSCiR7zZtVLUtQJw00ThsViULXCRjq4ygmFtjXYj/WKfjSFz57i1sRO6HpUTOKcA4tku/1wVw1X juJEZEfqziyE4ktlx3zh1/raTWFp+sW4IN/kJMunrT3J9HiokyAeZ2WU/EY7O0wQPl5N3Z0Eh7r sk48w01w5pkivKNr3S2MQ//LmhdnrIymlsbSku/6+yVpEwLRAkh9q32RK/wH+F0sSHnoMMVZgNG soin67nssp5Q7nBPOt/DGhpCWnvJWiLN81BwtLPDY7jUnjeihM4t1bekga8V5XGBk672B0cvidT XxRfgc20xjn2DtJRZE7XdEUTDKjq2iNQ8UTWhuymjLw5yWqCqw8MYIu52nb/90lUQwWX3uESVel LF/KQRupGqVfqGI1z9YIoG+yfvi3V72R/8zPXqQ9Bywr8DjDwEy1HXChaw8k9h+hiztFgfX65C+ JwIlwR92VkoinrYGv0dugRU64Fe7AdZ6dM7DAo8kqUeEx+jC1aPqYiXgFIUBhZJ3zOAmDxX7EW6 ezjZ8a5tkRN2ThA== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `AsRef` for `[u8]` and `BStr` so these can be used interchangeably for operations on `BStr`. Reviewed-by: Gary Guo Tested-by: Daniel Almeida Reviewed-by: Daniel Almeida Signed-off-by: Andreas Hindborg --- rust/kernel/str.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index ba6b1a5c4f99..c6bd2c69543d 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -125,6 +125,18 @@ fn index(&self, index: Idx) -> &Self::Output { } } +impl AsRef for [u8] { + fn as_ref(&self) -> &BStr { + BStr::from_bytes(self) + } +} + +impl AsRef for BStr { + fn as_ref(&self) -> &BStr { + self + } +} + /// Creates a new [`BStr`] from a string literal. /// /// `b_str!` converts the supplied string literal to byte string, so non-ASCII From patchwork Thu Feb 27 14:38:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994732 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 2C2D3238D34; Thu, 27 Feb 2025 14:39:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667194; cv=none; b=gyfqWNRGaeLA2Ri//WD0r/Rh5yy1XpzuWsrb9cYSOMYDBbCzjTnkf+xuzVo/X5PrLnIVbJUvYbd6HDmRg2IdRoDGTMcZ+p/2C2fkUfE13FurYCmcp/sxGE1ac/ULAsJywKWf4jbFITFhJCf4v+njTHtdYqRwSTemvrnqgz9jwoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667194; c=relaxed/simple; bh=K318bV0GaEBm1LLBOaM7D6mMUZFcC9BNiYbR/qpbYnw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=a2mmP6u0l2KK/0fdww5y4Kqkh5k7PQzfwHh4Y1iQq/ybHhGTXlZ5OhsTYjKgDLyvtSbvyD7J3gNIihYsBx7oBBvKkYZq1/Ax3hlq8HXmYQTFZh0rt/Y0gZFDzmPU7rG4z82UyVWL4OdVLwUvocW7iaemHuZCKK8Q8FKCH98QwNY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W8Qa5Wd2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="W8Qa5Wd2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3DA55C4CEDD; Thu, 27 Feb 2025 14:39:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667193; bh=K318bV0GaEBm1LLBOaM7D6mMUZFcC9BNiYbR/qpbYnw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=W8Qa5Wd2dvUlpzK3EzbqyGoeIYK0Wu/gk9f2fs1FwZYmbJPnY1ST66O0fKK38lJVw mo9aNWKASJy9NX/Db0nJD6vXYKZFsWnMSipjPAl8VUJ7lKcAJkUgYCTjnMbv61pWJQ GAVfk6XlWk2FsIBIM/UkUWCcAr0ABvgI0Vk03ZRyRMTnQXtz8Hs/1isDlPf4kxUooG +R8Sde37o/WGLqywkgRuwvcrxo4DtzVwybr9DRIAncNMKfAvsdardMtYCLy8jZR0Ur nudSb5e0uxG1uZqQHI02U34elc8kzCvpE6583kva8v6lnO6nloUuMZBzK+a2RDmNpX oIvP8GldpoDfw== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:10 +0100 Subject: [PATCH v8 4/7] rust: str: implement `strip_prefix` for `BStr` Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-4-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1719; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=K318bV0GaEBm1LLBOaM7D6mMUZFcC9BNiYbR/qpbYnw=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjTVMvjPqeTRD5th5GEu03/Xwxi8SJ2/Zi0r wVlKT5/bK+JAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B40wAKCRDhuBo+eShj dwJAEACx/RHG4m20bbfs0jUSPCZ7+sbyD47sY3x7apz9kc//edLA7IkDUEltGLb7TWh9yCG7KA8 BgHt+MdnLDJOGgwDAaUwE1XDh1p0lygvUaJDmygfQGsvLuhK+uyCOjQdPgY74ozjUsQweBhgnIL H+mekQ+0w21YdItK+EZvOJhkwhSWdq2D8rJpvR7C0/K5k1cS61aBmJuocaog3SZUZlHOobLVtLD GQUhw95rLOEOmejVzONC80GDqa4uLN0FuGUd1S2OLDDQkfVb24s+/9387QwE6PxzafJ/i+3xBRl k29iGWekEe5E9hqBJv9twO6J444wwE7xGdVEYvjK+ctUFg2qd274BUeBHpi2BQyW+VIXuBhyRzj tM6tXTIkddZ0+Xjr1QSGGRHfgO3u0LhsP9zjwi9Tk+1OGYYhKbg1UrRNTYNRri9s8LNjlJWbc/f cLxyrBUgNXKJwW1gyepiDY4lf5gyts4QKw/S1r/0lnrmNzjDLqd8hb5yE3JSe6PIses8udO+Nw9 MLTDQRUQh//zP/v3IHEHNE15u8yu3r8wvll9JVk2eWvw4ufDSVvqHyySUyCs1cFNOQ45VlvSC7B 8agJPgR/Or3KtoxhU2SIk0nRm9D4Zfjq4xBYg3NFs6GDYiCXXZ/SHn62hM2O5KuvdFmvfC3nRW4 HUrGvsfrKxxPc2A== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Implement `strip_prefix` for `BStr` by deferring to `slice::strip_prefix` on the underlying `&[u8]`. Reviewed-by: Gary Guo Reviewed-by: Alice Ryhl Reviewed-by: Daniel Almeida Tested-by: Daniel Almeida Signed-off-by: Andreas Hindborg --- It is also possible to get this method by implementing `core::slice::SlicePattern` for `BStr`. `SlicePattern` is unstable, so this seems more reasonable. --- rust/kernel/str.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index c6bd2c69543d..db272d2198fc 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -31,6 +31,22 @@ pub const fn from_bytes(bytes: &[u8]) -> &Self { // SAFETY: `BStr` is transparent to `[u8]`. unsafe { &*(bytes as *const [u8] as *const BStr) } } + + /// Strip a prefix from `self`. Delegates to [`slice::strip_prefix`]. + /// + /// # Example + /// ``` + /// use kernel::b_str; + /// assert_eq!(Some(b_str!("bar")), b_str!("foobar").strip_prefix(b_str!("foo"))); + /// assert_eq!(None, b_str!("foobar").strip_prefix(b_str!("bar"))); + /// assert_eq!(Some(b_str!("foobar")), b_str!("foobar").strip_prefix(b_str!(""))); + /// assert_eq!(Some(b_str!("")), b_str!("foobar").strip_prefix(b_str!("foobar"))); + /// ``` + pub fn strip_prefix(&self, pattern: impl AsRef) -> Option<&BStr> { + self.deref() + .strip_prefix(pattern.as_ref().deref()) + .map(Self::from_bytes) + } } impl fmt::Display for BStr { From patchwork Thu Feb 27 14:38:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994726 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 BA10D2376EC; Thu, 27 Feb 2025 14:39:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667156; cv=none; b=StAGfNOK4ovixSwnGO6rT4WKrf+4r/4vyecyC6U9ADRjE/YK8TrLKKh9aGSxBk3/DWDDt392e4sXxNPPMAMD5HfmgkPttF5uYCHOBGOamCsXwaFqi8wHyJVL9aJ1pDKCGlyESWcfKRUUj3p41mUsHK6FiyyBE6Ir1s4baX/oLyI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667156; c=relaxed/simple; bh=OySWTm574DZzpwLkR2PCYrng2IQgljsEmaIYlLs8Xyo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VxlNmmFJgqI/UWziCnUY+TZGnBCWVi12v4HFuGgVIPd6u0hhKhX+cvS1OJnvqnmpJ6b7KaPnqTPrktMCu6L8rR4wtmoWU/G3EL95/RGcUzUzIeKwcrx7tVLNCG2BL3fkNDXuiC8lY9SVHywF9fkYkNG+6JeyEZCTpkRfr+mxWl0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kHC7U99n; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kHC7U99n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B5B32C4CEDD; Thu, 27 Feb 2025 14:39:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667156; bh=OySWTm574DZzpwLkR2PCYrng2IQgljsEmaIYlLs8Xyo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kHC7U99nsxRozj7g/9YoNg8IYWqzNASaEgfu4ZBow02Hel2KROPLrHuv13oImerrP qzQHU1TvlW9A4FC5x+GNRa2KUD+AwlthxxFmB+Q32fGPyauk5gJXewy4TG6DHxpZqL +KoX/+lbdh6hz9JsEJ/oZbyurme2bHY0rvzLKWQkX7S3z5sLlImQA12SuXpBH1cb4l hVJkDKI9F+5gmDFVp21rkl9TTQLJMgL0pQrK5w89gzqRx9GQCMgb3vwFjFdvxk/BeP 0WRFyGciE2aR3HsCjwTgmRgxUBdepeLcjwhj0JfE2Y97gZM2M6u3FzBGFgutc5eF1o tJB9AWXVfzl2g== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:11 +0100 Subject: [PATCH v8 5/7] rust: str: add radix prefixed integer parsing functions Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-5-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=7204; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=OySWTm574DZzpwLkR2PCYrng2IQgljsEmaIYlLs8Xyo=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjUkFkn16gv6H6LSf5baz2a8g4LO8GjvKcTZ RpaXPyAxDSJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B41AAKCRDhuBo+eShj d+71EACdd9f5nUxDwGR7GWeaetwlMaQ93Fwv/l6kSFTxk16CXgrqRfha3ndVq/GZUQTEe/ebE0D nSa6PxAUmrwZzUa9nmqmplONPZ4rDcS+VIVWWCF73g+qIBH5f2VsLPVseSrAb/eMkTcdTQBkRDA 6ah/H0aHBKmkNWe+8Ofa/VAKUyOxi/H9YwJ+2WQYkirirOzoFbfoeJgNgRqjt1rtvvquAkv53fy w4jImwfbzGoKEsT0ZN38BxLf9A1eBGyvxgBV50SCGmHn1IVEaMWa4+VZIIAV51LF4ssHWfbSoiA 9WkqfSf6h7UPHaaq+vTtb05wnokNW2K42hAZQAfMApd/rgLTwG//KZdUHy4lppCPip1corEbG/O aCFtC3+XRBfMSH3pYNokfx3gdV/TSz3wuIMpscHlrtaihoUIP0UWtcDL46gcTZat8zpgsF1L6sx Ba63Al9f99Vo58m/ygh8NY2cs+W5uYHoBWl2o9x/NH/xuhgZzqAqt7pPNezK2oiC4K1p1Anv3nl IS1DhVUIr3cwRBggDds3B6keDarqLW+TsTpT6He2/+kmaBNO7B310KkOX8f6H7kS7UCSSsvmRPH 0AC8/wC2p7B4DFYpbciuLGAAUjqTuXb0MIT2xOJ77KPPJc7lmdjOMLKYiPuMA5vWt7gRdtOLGRv g1tVJEtzNA/Pcdg== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Add the trait `ParseInt` for parsing string representations of integers where the string representations are optionally prefixed by a radix specifier. Implement the trait for the primitive integer types. Tested-by: Daniel Almeida Reviewed-by: Daniel Almeida Signed-off-by: Andreas Hindborg --- rust/kernel/str.rs | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs index db272d2198fc..a708cf219348 100644 --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -945,3 +945,158 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { macro_rules! fmt { ($($f:tt)*) => ( core::format_args!($($f)*) ) } + +pub mod parse_int { + //! Integer parsing functions for parsing signed and unsigned integers + //! potentially prefixed with `0x`, `0o`, or `0b`. + + use crate::prelude::*; + use crate::str::BStr; + use core::ops::Deref; + + // Make `FromStrRadix` a public type with a private name. This seals + // `ParseInt`, that is, prevents downstream users from implementing the + // trait. + mod private { + use crate::str::BStr; + + /// Trait that allows parsing a [`&BStr`] to an integer with a radix. + /// + /// [`&BStr`]: kernel::str::BStr + // This is required because the `from_str_radix` function on the primitive + // integer types is not part of any trait. + pub trait FromStrRadix: Sized { + /// Parse `src` to `Self` using radix `radix`. + fn from_str_radix(src: &BStr, radix: u32) -> Result; + + /// Return the absolute value of Self::MIN. + fn abs_min() -> u64; + + /// Perform bitwise 2's complement on `self`. + /// + /// Note: This function does not make sense for unsigned integers. + fn complement(self) -> Self; + } + } + + /// Extract the radix from an integer literal optionally prefixed with + /// one of `0x`, `0X`, `0o`, `0O`, `0b`, `0B`, `0`. + fn strip_radix(src: &BStr) -> (u32, &BStr) { + match src.deref() { + [b'0', b'x' | b'X', rest @ ..] => (16, rest.as_ref()), + [b'0', b'o' | b'O', rest @ ..] => (8, rest.as_ref()), + [b'0', b'b' | b'B', rest @ ..] => (2, rest.as_ref()), + // NOTE: We are including the leading zero to be able to parse + // literal 0 here. If we removed it as a radix prefix, we would not + // be able to parse `0`. + [b'0', ..] => (8, src), + _ => (10, src), + } + } + + /// Trait for parsing string representations of integers. + /// + /// Strings beginning with `0x`, `0o`, or `0b` are parsed as hex, octal, or + /// binary respectively. Strings beginning with `0` otherwise are parsed as + /// octal. Anything else is parsed as decimal. A leading `+` or `-` is also + /// permitted. Any string parsed by [`kstrtol()`] or [`kstrtoul()`] will be + /// successfully parsed. + /// + /// [`kstrtol()`]: https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#c.kstrtol + /// [`kstrtoul()`]: https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#c.kstrtoul + /// + /// # Example + /// ``` + /// use kernel::str::parse_int::ParseInt; + /// use kernel::b_str; + /// + /// assert_eq!(Ok(0), u8::from_str(b_str!("0"))); + /// + /// assert_eq!(Ok(0xa2u8), u8::from_str(b_str!("0xa2"))); + /// assert_eq!(Ok(-0xa2i32), i32::from_str(b_str!("-0xa2"))); + /// + /// assert_eq!(Ok(-0o57i8), i8::from_str(b_str!("-0o57"))); + /// assert_eq!(Ok(0o57i8), i8::from_str(b_str!("057"))); + /// + /// assert_eq!(Ok(0b1001i16), i16::from_str(b_str!("0b1001"))); + /// assert_eq!(Ok(-0b1001i16), i16::from_str(b_str!("-0b1001"))); + /// + /// assert_eq!(Ok(127), i8::from_str(b_str!("127"))); + /// assert!(i8::from_str(b_str!("128")).is_err()); + /// assert_eq!(Ok(-128), i8::from_str(b_str!("-128"))); + /// assert!(i8::from_str(b_str!("-129")).is_err()); + /// assert_eq!(Ok(255), u8::from_str(b_str!("255"))); + /// assert!(u8::from_str(b_str!("256")).is_err()); + /// ``` + pub trait ParseInt: private::FromStrRadix + TryFrom { + /// Parse a string according to the description in [`Self`]. + fn from_str(src: &BStr) -> Result { + match src.deref() { + [b'-', rest @ ..] => { + let (radix, digits) = strip_radix(rest.as_ref()); + // 2's complement values range from -2^(b-1) to 2^(b-1)-1. + // So if we want to parse negative numbers as positive and + // later multiply by -1, we have to parse into a larger + // integer. We choose u64 as sufficiently large. NOTE: 128 + // bit integers are not available on all platforms, hence + // the choice of 64 bit. + let val = u64::from_str_radix( + core::str::from_utf8(digits).map_err(|_| EINVAL)?, + radix, + ) + .map_err(|_| EINVAL)?; + + if val > Self::abs_min() { + return Err(EINVAL); + } + + // SAFETY: We checked that `val` will fit in `Self` above. + let val: Self = unsafe { val.try_into().unwrap_unchecked() }; + + Ok(val.complement()) + } + _ => { + let (radix, digits) = strip_radix(src); + Self::from_str_radix(digits, radix).map_err(|_| EINVAL) + } + } + } + } + + macro_rules! impl_parse_int { + ($ty:ty) => { + impl private::FromStrRadix for $ty { + fn from_str_radix(src: &BStr, radix: u32) -> Result { + <$ty>::from_str_radix(core::str::from_utf8(src).map_err(|_| EINVAL)?, radix) + .map_err(|_| EINVAL) + } + + fn abs_min() -> u64 { + #[allow(unused_comparisons)] + if Self::MIN < 0 { + 1u64 << (Self::BITS - 1) + } else { + 0 + } + } + + fn complement(self) -> Self { + (!self).wrapping_add((1 as $ty)) + } + } + + impl ParseInt for $ty {} + }; + } + + impl_parse_int!(i8); + impl_parse_int!(u8); + impl_parse_int!(i16); + impl_parse_int!(u16); + impl_parse_int!(i32); + impl_parse_int!(u32); + impl_parse_int!(i64); + impl_parse_int!(u64); + impl_parse_int!(isize); + impl_parse_int!(usize); +} From patchwork Thu Feb 27 14:38:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994725 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 79DA0270032; Thu, 27 Feb 2025 14:39:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667150; cv=none; b=ZIR5SvqcqM2SWJ7yYypqElmMfIaV2PopQisHs/otG+WgzkNd/yr/+1ku1c011ir/2gIRvpabzJh9wXWgkDF9Jadcl3W5g51DOwRiHXWEe+mnS2VX56yb8JGEEZgkI459bpjSeb2btO2Nlz5xMJCD+3Zm4MwDoabmzF8+dFq9x/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667150; c=relaxed/simple; bh=ttgs/YpJ0rHLb7Cc1B0bfNPNLpHlHwxbwzwKM5Hx0Gk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iQbqhWZdHoMllF/plCjkg8605u9xmQAJ94ojuDF3BPITGLxlozE3aS9yFIdcvo0t+IgSrmUIkQrRuQYbKGwGIEJ32wx+rbQulFFwxvomz91a95iKKC7Jon7oc5RyNDiGNQY/avRueAYMv4fzfK8Ui9ri8sT2T94OSe7exQ6fMzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IaI2wxXh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IaI2wxXh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 217ACC4CEDD; Thu, 27 Feb 2025 14:39:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667149; bh=ttgs/YpJ0rHLb7Cc1B0bfNPNLpHlHwxbwzwKM5Hx0Gk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IaI2wxXhBqMwTEmQokfHmVQlbUagtOmaZ3Urs3yc0atk0mJC1I5cK/PkNSflosaOy bi55Dj901cV48E8gSgYa5dkcssO46McYTODJzDnDRt+HeYAhvrwuk2uPfLoXXghuxK 6T1HFCDktZOd3wlSHNnojWQ5oDfipgbQ/8MTA7rcQNoOyAJblNcc43lSQ1Yzl6Djmm h3uhI0M5K7ZP/bqeKWD01B1Z4JgnlowCqwua7Mm9igRbz0VYc2sbfPjvOEKvtQb6/M kEVtDifIaMwgqESjhLVGGAlP16QyMCmV3uQuJJXab5eDY3+pPQjSSTngqESYjuubjb bB9mgdpElFyvw== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:12 +0100 Subject: [PATCH v8 6/7] rust: add parameter support to the `module!` macro Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-6-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=24297; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=ttgs/YpJ0rHLb7Cc1B0bfNPNLpHlHwxbwzwKM5Hx0Gk=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjVL3ddBanVpueQP+bgDqpNys4AChwOhHpBZ DpckFodptqJAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B41QAKCRDhuBo+eShj d/aiEACMvPxfn6shD/wmclbN+XQl8nbh2YnhP3/Unev1DgNmUoC4epKcHQkJKRrZR7AApDGjR1O t9rlVptvvsEH3ir2//UexAelKviXPS9w8erw7tD6S7Gku0XTwt5uyJHQ3g1yJgAxM7Wkinp03GW P/vFznVh1xW8ZWJFsTu9Rxfr1+FLAWWtR4G8HRLJP7E7NbOvmAOoCwiXzaAV0IaYOxDQffjkwRS HdfLeq2nhayN3Y+g81Oc+IBanQBz8dckPhlUItdF+dS2jZymSbjc/KBZDFTtFX5g5Q+CRfWHzxC XYZ9eyUn/W4o03mKRFVgHZJg1tqzEvZNxBWmbWkF0OMTI6IsyejQhjF3aDtVY9IzwvUT2ovIxoL DYhhRKIrEIq9vJlwMnbSFOJ9JipkK9FrjrxdB05GIiGFMRWWIiyfPuCOhZKoegwjaFZf4TVF1Rm t+K0jW3HpGctnsoPG/owRMZCQ6MrtTRn9HkQ2TX9lNtCjGASew1MedbfhvEg8QmnJ5dliuqF9sD 11WmVKRzXRWK04GBKNY+4RnpxPIvAg3tPBOgVtWXFL0nTD25pV8GdUTJicOwTKevV/9r0TvC8Et LV9q72cue9esSJYsbmhMRKAfhNpEXHRL/ofivimHPzcACeMS+LsAU03rHQ/2yM+4jinnFtBmRxF 4FYLvTYm/ODHIFQ== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 Add support for module parameters to the `module!` macro. Implement read only support for integer types without `sysfs` support. Acked-by: Petr Pavlu # from modules perspective Signed-off-by: Andreas Hindborg --- rust/kernel/lib.rs | 1 + rust/kernel/module_param.rs | 221 +++++++++++++++++++++++++++++++++++++++++++ rust/macros/helpers.rs | 25 +++++ rust/macros/lib.rs | 31 ++++++ rust/macros/module.rs | 191 +++++++++++++++++++++++++++++++++---- samples/rust/rust_minimal.rs | 10 ++ 6 files changed, 461 insertions(+), 18 deletions(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 496ed32b0911..aec04df2bac9 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -57,6 +57,7 @@ pub mod kunit; pub mod list; pub mod miscdevice; +pub mod module_param; #[cfg(CONFIG_NET)] pub mod net; pub mod of; diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs new file mode 100644 index 000000000000..0f153aa64dae --- /dev/null +++ b/rust/kernel/module_param.rs @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Support for module parameters. +//! +//! C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h) + +use crate::prelude::*; +use crate::str::BStr; + +/// Newtype to make `bindings::kernel_param` [`Sync`]. +#[repr(transparent)] +#[doc(hidden)] +pub struct RacyKernelParam(pub ::kernel::bindings::kernel_param); + +// SAFETY: C kernel handles serializing access to this type. We never access it +// from Rust module. +unsafe impl Sync for RacyKernelParam {} + +/// Types that can be used for module parameters. +pub trait ModuleParam: Sized { + /// The [`ModuleParam`] will be used by the kernel module through this type. + /// + /// This may differ from `Self` if, for example, `Self` needs to track + /// ownership without exposing it or allocate extra space for other possible + /// parameter values. + // This is required to support string parameters in the future. + type Value: ?Sized; + + /// Parse a parameter argument into the parameter value. + /// + /// `Err(_)` should be returned when parsing of the argument fails. + /// + /// Parameters passed at boot time will be set before [`kmalloc`] is + /// available (even if the module is loaded at a later time). However, in + /// this case, the argument buffer will be valid for the entire lifetime of + /// the kernel. So implementations of this method which need to allocate + /// should first check that the allocator is available (with + /// [`crate::bindings::slab_is_available`]) and when it is not available + /// provide an alternative implementation which doesn't allocate. In cases + /// where the allocator is not available it is safe to save references to + /// `arg` in `Self`, but in other cases a copy should be made. + /// + /// [`kmalloc`]: srctree/include/linux/slab.h + fn try_from_param_arg(arg: &'static BStr) -> Result; +} + +/// Set the module parameter from a string. +/// +/// Used to set the parameter value at kernel initialization, when loading +/// the module or when set through `sysfs`. +/// +/// See `struct kernel_param_ops.set`. +/// +/// # Safety +/// +/// - If `val` is non-null then it must point to a valid null-terminated string. +/// The `arg` field of `param` must be an instance of `T`. +/// - `param.arg` must be a pointer to valid `*mut T` as set up by the +/// [`module!`] macro. +/// +/// # Invariants +/// +/// Currently, we only support read-only parameters that are not readable +/// from `sysfs`. Thus, this function is only called at kernel +/// initialization time, or at module load time, and we have exclusive +/// access to the parameter for the duration of the function. +/// +/// [`module!`]: macros::module +unsafe extern "C" fn set_param( + val: *const kernel::ffi::c_char, + param: *const crate::bindings::kernel_param, +) -> core::ffi::c_int +where + T: ModuleParam, +{ + // NOTE: If we start supporting arguments without values, val _is_ allowed + // to be null here. + if val.is_null() { + // TODO: Use pr_warn_once available. + crate::pr_warn!("Null pointer passed to `module_param::set_param`"); + return EINVAL.to_errno(); + } + + // SAFETY: By function safety requirement, val is non-null and + // null-terminated. By C API contract, `val` is live and valid for reads + // for the duration of this function. + let arg = unsafe { CStr::from_char_ptr(val) }; + + crate::error::from_result(|| { + let new_value = T::try_from_param_arg(arg)?; + + // SAFETY: `param` is guaranteed to be valid by C API contract + // and `arg` is guaranteed to point to an instance of `T`. + let old_value = unsafe { (*param).__bindgen_anon_1.arg as *mut T }; + + // SAFETY: `old_value` is valid for writes, as we have exclusive + // access. `old_value` is pointing to an initialized static, and + // so it is properly initialized. + unsafe { core::ptr::replace(old_value, new_value) }; + Ok(0) + }) +} + +/// Drop the parameter. +/// +/// Called when unloading a module. +/// +/// # Safety +/// +/// The `arg` field of `param` must be an initialized instance of `T`. +unsafe extern "C" fn free(arg: *mut core::ffi::c_void) +where + T: ModuleParam, +{ + // SAFETY: By function safety requirement, `arg` is an initialized + // instance of `T`. By C API contract, `arg` will not be used after + // this function returns. + unsafe { core::ptr::drop_in_place(arg as *mut T) }; +} + +macro_rules! impl_int_module_param { + ($ty:ident) => { + impl ModuleParam for $ty { + type Value = $ty; + + fn try_from_param_arg(arg: &'static BStr) -> Result { + <$ty as crate::str::parse_int::ParseInt>::from_str(arg) + } + } + }; +} + +impl_int_module_param!(i8); +impl_int_module_param!(u8); +impl_int_module_param!(i16); +impl_int_module_param!(u16); +impl_int_module_param!(i32); +impl_int_module_param!(u32); +impl_int_module_param!(i64); +impl_int_module_param!(u64); +impl_int_module_param!(isize); +impl_int_module_param!(usize); + +/// A wrapper for kernel parameters. +/// +/// This type is instantiated by the [`module!`] macro when module parameters are +/// defined. You should never need to instantiate this type directly. +/// +/// Note: This type is `pub` because it is used by module crates to access +/// parameter values. +#[repr(transparent)] +pub struct ModuleParamAccess { + data: core::cell::UnsafeCell, +} + +// SAFETY: We only create shared references to the contents of this container, +// so if `T` is `Sync`, so is `ModuleParamAccess`. +unsafe impl Sync for ModuleParamAccess {} + +impl ModuleParamAccess { + #[doc(hidden)] + pub const fn new(value: T) -> Self { + Self { + data: core::cell::UnsafeCell::new(value), + } + } + + /// Get a shared reference to the parameter value. + // Note: When sysfs access to parameters are enabled, we have to pass in a + // held lock guard here. + pub fn get(&self) -> &T { + // SAFETY: As we only support read only parameters with no sysfs + // exposure, the kernel will not touch the parameter data after module + // initialization. + unsafe { &*self.data.get() } + } + + /// Get a mutable pointer to the parameter value. + pub const fn as_mut_ptr(&self) -> *mut T { + self.data.get() + } +} + +#[doc(hidden)] +#[macro_export] +/// Generate a static [`kernel_param_ops`](srctree/include/linux/moduleparam.h) struct. +/// +/// # Examples +/// +/// ```ignore +/// make_param_ops!( +/// /// Documentation for new param ops. +/// PARAM_OPS_MYTYPE, // Name for the static. +/// MyType // A type which implements [`ModuleParam`]. +/// ); +/// ``` +macro_rules! make_param_ops { + ($ops:ident, $ty:ty) => { + /// + /// Static [`kernel_param_ops`](srctree/include/linux/moduleparam.h) + /// struct generated by `make_param_ops` + #[doc = concat!("for [`", stringify!($ty), "`].")] + pub static $ops: $crate::bindings::kernel_param_ops = $crate::bindings::kernel_param_ops { + flags: 0, + set: Some(set_param::<$ty>), + get: None, + free: Some(free::<$ty>), + }; + }; +} + +make_param_ops!(PARAM_OPS_I8, i8); +make_param_ops!(PARAM_OPS_U8, u8); +make_param_ops!(PARAM_OPS_I16, i16); +make_param_ops!(PARAM_OPS_U16, u16); +make_param_ops!(PARAM_OPS_I32, i32); +make_param_ops!(PARAM_OPS_U32, u32); +make_param_ops!(PARAM_OPS_I64, i64); +make_param_ops!(PARAM_OPS_U64, u64); +make_param_ops!(PARAM_OPS_ISIZE, isize); +make_param_ops!(PARAM_OPS_USIZE, usize); diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs index 563dcd2b7ace..ffc9f0cccddc 100644 --- a/rust/macros/helpers.rs +++ b/rust/macros/helpers.rs @@ -10,6 +10,17 @@ pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option { } } +pub(crate) fn try_sign(it: &mut token_stream::IntoIter) -> Option { + let peek = it.clone().next(); + match peek { + Some(TokenTree::Punct(punct)) if punct.as_char() == '-' => { + let _ = it.next(); + Some(punct.as_char()) + } + _ => None, + } +} + pub(crate) fn try_literal(it: &mut token_stream::IntoIter) -> Option { if let Some(TokenTree::Literal(literal)) = it.next() { Some(literal.to_string()) @@ -107,6 +118,20 @@ pub(crate) struct Generics { pub(crate) ty_generics: Vec, } +/// Parse a token stream of the form `expected_name: "value",` and return the +/// string in the position of "value". +/// +/// # Panics +/// +/// - On parse error. +pub(crate) fn expect_string_field(it: &mut token_stream::IntoIter, expected_name: &str) -> String { + assert_eq!(expect_ident(it), expected_name); + assert_eq!(expect_punct(it), ':'); + let string = expect_string(it); + assert_eq!(expect_punct(it), ','); + string +} + /// Parses the given `TokenStream` into `Generics` and the rest. /// /// The generics are not present in the rest, but a where clause might remain. diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index d61bc6a56425..2778292f8cee 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -24,6 +24,30 @@ /// The `type` argument should be a type which implements the [`Module`] /// trait. Also accepts various forms of kernel metadata. /// +/// The `params` field describe module parameters. Each entry has the form +/// +/// ```ignore +/// parameter_name: type { +/// default: default_value, +/// description: "Description", +/// } +/// ``` +/// +/// `type` may be one of +/// +/// - [`i8`] +/// - [`u8`] +/// - [`i8`] +/// - [`u8`] +/// - [`i16`] +/// - [`u16`] +/// - [`i32`] +/// - [`u32`] +/// - [`i64`] +/// - [`u64`] +/// - [`isize`] +/// - [`usize`] +/// /// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h) /// /// [`Module`]: ../kernel/trait.Module.html @@ -40,6 +64,12 @@ /// description: "My very own kernel module!", /// license: "GPL", /// alias: ["alternate_module_name"], +/// params: { +/// my_parameter: i64 { +/// default: 1, +/// description: "This parameter has a default of 1", +/// }, +/// }, /// } /// /// struct MyModule(i32); @@ -48,6 +78,7 @@ /// fn init(_module: &'static ThisModule) -> Result { /// let foo: i32 = 42; /// pr_info!("I contain: {}\n", foo); +/// pr_info!("i32 param is: {}\n", module_parameters::my_parameter.read()); /// Ok(Self(foo)) /// } /// } diff --git a/rust/macros/module.rs b/rust/macros/module.rs index cdf94f4982df..e6af3ae5fe80 100644 --- a/rust/macros/module.rs +++ b/rust/macros/module.rs @@ -26,6 +26,7 @@ struct ModInfoBuilder<'a> { module: &'a str, counter: usize, buffer: String, + param_buffer: String, } impl<'a> ModInfoBuilder<'a> { @@ -34,10 +35,11 @@ fn new(module: &'a str) -> Self { module, counter: 0, buffer: String::new(), + param_buffer: String::new(), } } - fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { + fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) { let string = if builtin { // Built-in modules prefix their modinfo strings by `module.`. format!( @@ -51,8 +53,14 @@ fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { format!("{field}={content}\0", field = field, content = content) }; + let buffer = if param { + &mut self.param_buffer + } else { + &mut self.buffer + }; + write!( - &mut self.buffer, + buffer, " {cfg} #[doc(hidden)] @@ -75,20 +83,116 @@ fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { self.counter += 1; } - fn emit_only_builtin(&mut self, field: &str, content: &str) { - self.emit_base(field, content, true) + fn emit_only_builtin(&mut self, field: &str, content: &str, param: bool) { + self.emit_base(field, content, true, param) } - fn emit_only_loadable(&mut self, field: &str, content: &str) { - self.emit_base(field, content, false) + fn emit_only_loadable(&mut self, field: &str, content: &str, param: bool) { + self.emit_base(field, content, false, param) } fn emit(&mut self, field: &str, content: &str) { - self.emit_only_builtin(field, content); - self.emit_only_loadable(field, content); + self.emit_internal(field, content, false); + } + + fn emit_internal(&mut self, field: &str, content: &str, param: bool) { + self.emit_only_builtin(field, content, param); + self.emit_only_loadable(field, content, param); + } + + fn emit_param(&mut self, field: &str, param: &str, content: &str) { + let content = format!("{param}:{content}", param = param, content = content); + self.emit_internal(field, &content, true); + } + + fn emit_params(&mut self, info: &ModuleInfo) { + let Some(params) = &info.params else { + return; + }; + + for param in params { + let ops = param_ops_path(¶m.ptype); + + // Note: The spelling of these fields is dictated by the user space + // tool `modinfo`. + self.emit_param("parmtype", ¶m.name, ¶m.ptype); + self.emit_param("parm", ¶m.name, ¶m.description); + + write!( + self.param_buffer, + " + pub(crate) static {param_name}: + ::kernel::module_param::ModuleParamAccess<{param_type}> = + ::kernel::module_param::ModuleParamAccess::new({param_default}); + + #[link_section = \"__param\"] + #[used] + static __{module_name}_{param_name}_struct: + ::kernel::module_param::RacyKernelParam = + ::kernel::module_param::RacyKernelParam(::kernel::bindings::kernel_param {{ + name: if cfg!(MODULE) {{ + ::kernel::c_str!(\"{param_name}\").as_bytes_with_nul() + }} else {{ + ::kernel::c_str!(\"{module_name}.{param_name}\").as_bytes_with_nul() + }}.as_ptr(), + // SAFETY: `__this_module` is constructed by the kernel at load time + // and will not be freed until the module is unloaded. + #[cfg(MODULE)] + mod_: unsafe {{ + (&::kernel::bindings::__this_module + as *const ::kernel::bindings::module) + .cast_mut() + }}, + #[cfg(not(MODULE))] + mod_: ::core::ptr::null_mut(), + ops: &{ops} as *const ::kernel::bindings::kernel_param_ops, + perm: 0, // Will not appear in sysfs + level: -1, + flags: 0, + __bindgen_anon_1: + ::kernel::bindings::kernel_param__bindgen_ty_1 {{ + arg: {param_name}.as_mut_ptr().cast() + }}, + }}); + ", + module_name = info.name, + param_type = param.ptype, + param_default = param.default, + param_name = param.name, + ops = ops, + ) + .unwrap(); + } + } +} + +fn param_ops_path(param_type: &str) -> &'static str { + match param_type { + "i8" => "::kernel::module_param::PARAM_OPS_I8", + "u8" => "::kernel::module_param::PARAM_OPS_U8", + "i16" => "::kernel::module_param::PARAM_OPS_I16", + "u16" => "::kernel::module_param::PARAM_OPS_U16", + "i32" => "::kernel::module_param::PARAM_OPS_I32", + "u32" => "::kernel::module_param::PARAM_OPS_U32", + "i64" => "::kernel::module_param::PARAM_OPS_I64", + "u64" => "::kernel::module_param::PARAM_OPS_U64", + "isize" => "::kernel::module_param::PARAM_OPS_ISIZE", + "usize" => "::kernel::module_param::PARAM_OPS_USIZE", + t => panic!("Unsupported parameter type {}", t), } } +fn expect_param_default(param_it: &mut token_stream::IntoIter) -> String { + assert_eq!(expect_ident(param_it), "default"); + assert_eq!(expect_punct(param_it), ':'); + let sign = try_sign(param_it); + let default = try_literal(param_it).expect("Expected default param value"); + assert_eq!(expect_punct(param_it), ','); + let mut value = sign.map(String::from).unwrap_or_default(); + value.push_str(&default); + value +} + #[derive(Debug, Default)] struct ModuleInfo { type_: String, @@ -98,6 +202,50 @@ struct ModuleInfo { description: Option, alias: Option>, firmware: Option>, + params: Option>, +} + +#[derive(Debug)] +struct Parameter { + name: String, + ptype: String, + default: String, + description: String, +} + +fn expect_params(it: &mut token_stream::IntoIter) -> Vec { + let params = expect_group(it); + assert_eq!(params.delimiter(), Delimiter::Brace); + let mut it = params.stream().into_iter(); + let mut parsed = Vec::new(); + + loop { + let param_name = match it.next() { + Some(TokenTree::Ident(ident)) => ident.to_string(), + Some(_) => panic!("Expected Ident or end"), + None => break, + }; + + assert_eq!(expect_punct(&mut it), ':'); + let param_type = expect_ident(&mut it); + let group = expect_group(&mut it); + assert_eq!(group.delimiter(), Delimiter::Brace); + assert_eq!(expect_punct(&mut it), ','); + + let mut param_it = group.stream().into_iter(); + let param_default = expect_param_default(&mut param_it); + let param_description = expect_string_field(&mut param_it, "description"); + expect_end(&mut param_it); + + parsed.push(Parameter { + name: param_name, + ptype: param_type, + default: param_default, + description: param_description, + }) + } + + parsed } impl ModuleInfo { @@ -112,6 +260,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self { "license", "alias", "firmware", + "params", ]; const REQUIRED_KEYS: &[&str] = &["type", "name", "license"]; let mut seen_keys = Vec::new(); @@ -140,6 +289,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self { "license" => info.license = expect_string_ascii(it), "alias" => info.alias = Some(expect_string_array(it)), "firmware" => info.firmware = Some(expect_string_array(it)), + "params" => info.params = Some(expect_params(it)), _ => panic!( "Unknown key \"{}\". Valid keys are: {:?}.", key, EXPECTED_KEYS @@ -183,28 +333,30 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { let info = ModuleInfo::parse(&mut it); let mut modinfo = ModInfoBuilder::new(info.name.as_ref()); - if let Some(author) = info.author { - modinfo.emit("author", &author); + if let Some(author) = &info.author { + modinfo.emit("author", author); } - if let Some(description) = info.description { - modinfo.emit("description", &description); + if let Some(description) = &info.description { + modinfo.emit("description", description); } modinfo.emit("license", &info.license); - if let Some(aliases) = info.alias { + if let Some(aliases) = &info.alias { for alias in aliases { - modinfo.emit("alias", &alias); + modinfo.emit("alias", alias); } } - if let Some(firmware) = info.firmware { + if let Some(firmware) = &info.firmware { for fw in firmware { - modinfo.emit("firmware", &fw); + modinfo.emit("firmware", fw); } } // Built-in modules also export the `file` modinfo string. let file = std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable"); - modinfo.emit_only_builtin("file", &file); + modinfo.emit_only_builtin("file", &file, false); + + modinfo.emit_params(&info); format!( " @@ -362,14 +514,17 @@ unsafe fn __exit() {{ __MOD.assume_init_drop(); }} }} - {modinfo} }} }} + mod module_parameters {{ + {params} + }} ", type_ = info.type_, name = info.name, modinfo = modinfo.buffer, + params = modinfo.param_buffer, initcall_section = ".initcall6.init" ) .parse() diff --git a/samples/rust/rust_minimal.rs b/samples/rust/rust_minimal.rs index 4aaf117bf8e3..cbe8c6346648 100644 --- a/samples/rust/rust_minimal.rs +++ b/samples/rust/rust_minimal.rs @@ -10,6 +10,12 @@ author: "Rust for Linux Contributors", description: "Rust minimal sample", license: "GPL", + params: { + test_parameter: i64 { + default: 1, + description: "This parameter has a default of 1", + }, + }, } struct RustMinimal { @@ -20,6 +26,10 @@ impl kernel::Module for RustMinimal { fn init(_module: &'static ThisModule) -> Result { pr_info!("Rust minimal sample (init)\n"); pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); + pr_info!( + "test_parameter: {}\n", + *module_parameters::test_parameter.get() + ); let mut numbers = KVec::new(); numbers.push(72, GFP_KERNEL)?; From patchwork Thu Feb 27 14:38:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Hindborg X-Patchwork-Id: 13994729 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 82A6C235C1E; Thu, 27 Feb 2025 14:39:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667175; cv=none; b=rH9msMWJjeEJZPWrj4Jbhsg212A4QgKe2QY30IUBuCPUKtcGcSq759g829KM2Le4hc33doiDTrbiIUjIgUmulbwNmsIhC5EGZCvEhgby1KdPxbERra3OANNCkuRu80zSV0lvyFP3wnk9VBG3lSP9+rXBt1BaCKnDhCqZ5HQYH0Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740667175; c=relaxed/simple; bh=IR3xh6hJj0KU0ZzHcQJSsYTm8/JMrsZrW8buOuX8o4g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iOlQvmherdbC5vNleqBYj0I1La6oyJ1ncKOzRuNXKX7jfCynmSH8CfCnglcD2xhk69PEZeNDq99npfyV6I+FXxmDk6BXCc6W/0nB0UL6QtsteYkRw/ImKlX924fu2d9CBMN/RzBYyRgHoYFBxrmqqzpjQ4V5IRaue5C3kIP6p0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S78kSn8R; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="S78kSn8R" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83E7EC4CEF3; Thu, 27 Feb 2025 14:39:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740667174; bh=IR3xh6hJj0KU0ZzHcQJSsYTm8/JMrsZrW8buOuX8o4g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=S78kSn8RSEvaqrzgCxHEUKNJuQprbCxU0D1KO6AtI8PEB57hssB6ocUznd7ZeYwdL 877tscl3lo1ArOU62F1ZqqxXlF+fZ6sote/uB/i9uxmTVqbevIhIBlTFsw4vxq36ir /MFq0x5/nazaHY3O49cp2OBW6Bqpmk5vdL8WW9RPR4gONWkFAqAH0FwcVRgXn270hI sUEGQwksfamoEPMGBvQzdTGn0Ql3Sr0zSeJvUmowUdzWt7U4xEl9oGXGNvw8crsmae 3qDeY92OLzOURCafvcRsUqgko/urh8cFN34PLLp5gXr7Jho9DbS5QEvMHBxWvJEB6t f1BNATY3VJpZw== From: Andreas Hindborg Date: Thu, 27 Feb 2025 15:38:13 +0100 Subject: [PATCH v8 7/7] modules: add rust modules files to MAINTAINERS Precedence: bulk X-Mailing-List: linux-kbuild@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250227-module-params-v3-v8-7-ceeee85d9347@kernel.org> References: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> In-Reply-To: <20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org> To: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Alice Ryhl , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Luis Chamberlain Cc: Trevor Gross , Adam Bratschi-Kaye , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, Petr Pavlu , Sami Tolvanen , Daniel Gomez , Simona Vetter , Greg KH , Fiona Behrens , Daniel Almeida , linux-modules@vger.kernel.org, Andreas Hindborg X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=728; i=a.hindborg@kernel.org; h=from:subject:message-id; bh=IR3xh6hJj0KU0ZzHcQJSsYTm8/JMrsZrW8buOuX8o4g=; b=owEBbQKS/ZANAwAIAeG4Gj55KGN3AcsmYgBnwHjW7Rwp1CwiEEM6Ci+GDQQ8wAF3xBytnLCGk gTS4hA9cj2JAjMEAAEIAB0WIQQSwflHVr98KhXWwBLhuBo+eShjdwUCZ8B41gAKCRDhuBo+eShj d3pMD/4kJz/1hY96K6isBfT82GxFzWUlGYYvJ4RHtjW77HggFfQ5riqHEr7nOl0OF4C/eSsxxdq Q939WQMMvc80TkptTq7TKuQAUe2nmXpx3XGWiUnTak8ee79giIc1sTTqm0dVbrCO9q37wQt9LUv hXoGH4m6FBr7LzGKnHQkeb7grzEzILCeZf1Fn2qesJE26G7L6u4NawWp/WBPDXT/stmQMEFeDHx EJH9DdI7Sgctd82gorSFMqSzWoVbb+a3Tl/QtHbgg/3gGEr6HWpK975KInbwS/A/byXXnvTbp4r DXZKK0NgEqVdlOQFZwYd7cWhPOT5cMssmYICDrKvOEnPX1gCZHO7bQTMqoJvtmS6eegTOS7q7Rc /bY2Bg8yf3Zg/jjMVXGuBXPjm6+zYTITO79aznLM0xEk1hfUVc9G5coE/OWhiqDGWXFgUpDRHUM nAtak3WI5MKPSmULt61EG6ZRJHH3Se95qW3oXIDPSoiDVi2ifMl6hMXnyWSWkGwi80zd2GOqdhf awdWarZh827sg6qoCEQf8kLvMX12uUsUJOXZr2zQUoPQW+/WjPIY9ghA8dnXycuiQ/IaizkKFwL QFlkO9sdcI5wUvezjsK+e1paTbQwzzg06S5TY3FhhQDU6e6s56XWEyeF1TKhTxxs5DqzUNSRY6a TMsbiIMdxSXowiw== X-Developer-Key: i=a.hindborg@kernel.org; a=openpgp; fpr=3108C10F46872E248D1FB221376EB100563EF7A7 The module subsystem people agreed to maintain rust support for modules [1]. Thus, add entries for relevant files to modules entry in MAINTAINERS. Link: https://lore.kernel.org/all/0d9e596a-5316-4e00-862b-fd77552ae4b5@suse.com/ [1] Signed-off-by: Andreas Hindborg --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 896a307fa065..ff65178f6e06 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15991,6 +15991,8 @@ F: include/linux/kmod.h F: include/linux/module*.h F: kernel/module/ F: lib/test_kmod.c +F: rust/kernel/module_param.rs +F: rust/macros/module.rs F: scripts/module* F: tools/testing/selftests/kmod/