From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU008.outbound.protection.outlook.com (mail-ukwestazon11020102.outbound.protection.outlook.com [52.101.195.102]) (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 A071A453A55; Wed, 19 Aug 2026 11:10:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.195.102 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137832; cv=fail; b=NCr022u0h8Ln+9vdwkr2cJJVAkPfIRXCl+IGNyYFduNLc9jR8iqXxowSvmYLO2TC/NSZYUrFvKHRFrkZr2uF6LyKC/V/+l5QALgbol7LR8H3fFu4zChXZ8/qAjsTA7vS33pOxjIq0iYbPOSY7NhPpzRQPZrF8f1RuAvcbrNSDww= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137832; c=relaxed/simple; bh=P0E4tPfO7qfgNF+lFWa94pAJ03QSSk+2txS9i3ApG/4=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=RQDuB+V73ptig4uPhiWQvtcgFrhTpVlzEXozmE4oxJ4b5eoe93fSR6Jst6LROZODy3SolgkqbkmybKyMYPf0jdpUrhHE4Zj+r1tSCmig+ZFiRQS+ORm7XG38bDWJd/xNzC31xAzXminXQKAKBJkfU8C9Q2FJ6ihcbS5HqBvyYt0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=fYWqReeR; arc=fail smtp.client-ip=52.101.195.102 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="fYWqReeR" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=NP1E7TfAwlzltwq2YT805db/y5NXRHqHhgvgSwcOlZ7HUsMMSC9vHEpEFkYOIZ152hRN2oYvIz/J0gqINd6yvNdr4JuDlNB2d0mwcq3iKJiIk/GdQRYPe+2P5BAHJb0gdTJ5z/BvG3jXrdS+w6HjG69u49nCoFtcytKh5GoVfoLc9Xi9PFFlYgG9Q2jHdPeU1nAZSB/9nKe0RDIBbO0AeJciXiRkGuxCPRwPcNSHkLAlf45P1QKnqPhWfMqy1/0omIa3WUu56uoWbVWEGizymGfmqUrLT3yyBUiVp9fpa3EI6VMy/0JtrwFzhYfjz5QXr4wb2rJOMLMqcSdAjJC4Gg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=463CuS4BsuRP5CzzIs1yPaKtoEzbEnCCAdL7KAGQ4l4=; b=LtV4xr2Ou0QhzWIrT3tZ3BV/GdQSYlrkX2wlOihnbUmWNwyQBwxVHVWGaeqc2/ZUKgKgh3eedpUlpJpJjekv5Ar/9rQCY5VDCk6eULavJLvytWaHoVViRAQvwou4mc0PgvrDnm0poQg5gO9Wllo5+J9ffQMZTbXEXqKGIBVytF0pq4PVMkd6oFjtLqaPcOEDZ6Y8gSzqHOY58YevzxiHgs480p6MH+m3tZPlfM7WKgeKxZUZNYa+74Q9B/GcrSG4xuez/z4wfGplUYw2yUS4dlSmSpJ/X4URkarCRihJr9xszF/kmlmlZ1ZWJQ07AyNSS2gHS2hJLNa332QlPYgNqg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=463CuS4BsuRP5CzzIs1yPaKtoEzbEnCCAdL7KAGQ4l4=; b=fYWqReeRiiFIxC44xBZWliQYszpouDV0FS0mYvAO9B7j1fVtnNYbrVd11NKofKnvBwmfJvc4/pwhcECxmzvLthwpF2peGE/8Eo/7KjORmh4/rNQz1ozF1YLV1F8q2nWT9zBFIVUkOP1Y3Cl3iRPvhfjnzaflnql92ZBAhUZbhmY= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by LO0P265MB5167.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:283::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:15 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:15 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:09 +0100 Subject: [PATCH v3 01/16] rust: io: register: reimplement as proc macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-1-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=21187; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=P0E4tPfO7qfgNF+lFWa94pAJ03QSSk+2txS9i3ApG/4=; b=m22lD9YsvllFChFefUAUzSSrMb4NUAlRnvEqfw1xt5ZT+aMT4XaTT6Su2xYaKYXkZySf6TNgY eOYcwO6pIFADAxYnpB6905nNtu/PqtG6B2z517V8pbh9kVJVlpWiTSp X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|LO0P265MB5167:EE_ X-MS-Office365-Filtering-Correlation-Id: e31e1659-68f5-4c60-a3ad-08defde27232 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|23010399003|376014|7416014|366016|22082099003|18002099003|921020|10067099003|5023799004|56012099006|3023799007; X-Microsoft-Antispam-Message-Info: GtODGBtj0sgmbW36595CqVe12r9S/VrT2yw/mB/RXQO8lUxPAtDwI4SxrFd4hK3SaOIqCFdx47Im4YaJb71MH8NqjnWOPWiHZMkBGE3OC+dL/1melbQTR8gVbnMqzWAtab5XdhJa9qbkeHNo26PqaQCf2cgpkuQP7kFFNnvapuDUCPHL0iop1fXnkrVHn9usgm7equIEFjiPXaxU6lNGpQK07ULdWgwy5GauL6GiZ3qDZ/sLSm9gyUAlKGRvN8Rt70onO7uX3rmNqs6DnqxdAc74I4cZHqVnCd4jurCsd+XpfQxd53MoxngipgqtyiQbK9HQZslaBxhptuBqO9DaBUMCLOYxjl04NmUfRkpp1RVkSRokcAVwMNdOyARQ5K75ep5h4e+MVDBCkVMYuHZ3X0PUvrcM3TXhmQFOKbvseBr9ktDkfg3COh8caDvwiz9hcWqsQ4jVNrdjBGCckfrWm9rXBDP52zF5DzniBHNsYclJvYREx5y4OK91sDFA9vpTYCc6ETD9QJIc4EZLbu9J13nAyKEm95PYBn0U9CkREsl2vj7t46zg0nsPGP83Y7kHIxJis5kH3h+LtH0z/hmnSR2dumhTX6tkKn5uyZjgPQSDNGEqFApv9AmGUNxqT0HUWYGY+4wYZU2OXvHEwq5uPSQJ9rLrK0y48Wl7RLn4d3Cn+1hYV1aLfk+o7J1MBsaZ2a0k3Nrm/j+4uuIevIGFTg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(1800799024)(23010399003)(376014)(7416014)(366016)(22082099003)(18002099003)(921020)(10067099003)(5023799004)(56012099006)(3023799007);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?S2lvYkNrVXBqU1EyZUpNUi9OKzhkUFlsNHVCQTBtTWVwOXBuN0lPNVZQQjB1?= =?utf-8?B?ZWVRdGEweDlxQmM3OXhVQURDa25xT2FIYlFsN2VjRGU1T3BqZWtkZTJlZHNa?= =?utf-8?B?aVc4VXVKVy9VVXQ0NzEycW56NHdvYkxyMUxkOGJ4blp4S05aY3NMaVlwdnds?= =?utf-8?B?aHFwZVVNSlF1WkRaSmJaSXhUTThIMlZuUGdvQVR2TnY3OUM0c2tnR0h5UUlt?= =?utf-8?B?a25aUlk4RDBiNGt4TWRFcExybFZzYmxZWC9uSS9HUU4rNzZ1Qk9pZEdZa2FN?= =?utf-8?B?UFFnUEtXSHUyT2xkZnJrUHNuUEk2SzJzbTNZZE42RGhhd2FYdnhHTFJFdHlQ?= =?utf-8?B?K3o5VDROK2FoS3FtSDk4d2hyZnk5WFJhdlY2V1FPM2JYaDVaQi8xekdtc1kx?= =?utf-8?B?RXNBb2ZLL09hUTBZNS95VWJxMUlFZ3BCNzF0YUpVeCtuemdtWTBZRHNqYWxh?= =?utf-8?B?clE2d3BleXFsb2ozY2NhamxpMFFRMUx0OHdDV3NwUlhpZlVjcFZicTF3YjRS?= =?utf-8?B?QWFSbFFuNEROOXBoVU93S1NhckhYdkYyRVdZUlFXWVh2anQ1dmtpeFlmaHB5?= =?utf-8?B?WVJYT21laWhna0Y3TmlxNERrMUJnK3JVekM3T3QwbjFmSXJMQUM3K01IcHY4?= =?utf-8?B?Y3ZBSDlyWGdiL0FyTTE0eFpFeGw4VTBZVHJHOWUwZFB2T3BkOEd5dENIWERU?= =?utf-8?B?RnRxN2EwRGtKYzd0MFkrSzROZVBJcUsvelladk9Dd0FTbnVxcWJRSCtkWmIw?= =?utf-8?B?MmhlZDhNMEp0SnAxTGFmMSt1WHlwa0lEeDVGK2hORTZPUTFJaDBxYnNxamhO?= =?utf-8?B?cE52enJwZmpmWEM1OHlVcVBGYTFjVFFQN1MreVBma1RFZk5GWk9XZUp1dUo1?= =?utf-8?B?OGpKMGVxNThuQldtcDlITDNIZTkxSTlnaXJtUUFvLzhjcmthZDc3OVFlMVZi?= =?utf-8?B?OEcrMGJuSWtOZW1BeTgrYUpnVnZLNFp0QkZZQWFBMGJNS2ZLemNjNzZveksr?= =?utf-8?B?UVVPTDdib0NjbWNBR0UvMUlhRTdITHo3NDJwRVJpMzhwVHlYbkdmUEh5Zis2?= =?utf-8?B?dXNLMHBLMVZVd0k5cG0xUDlSQndvRHRQQ0NLY1cwdGNXMURIdzUyTmcwSEZZ?= =?utf-8?B?bGJFL0VxRUhvRllsL1o4L0JGRGV6WjFydThSN0xaYXNwdzl6WUViNUhITVo4?= =?utf-8?B?RWJ3WDQ2QkJXQ1k5WkpmZUVDMTJDdFlLOHhwUUdrdSs4U1hxZXp5aTNqRXVh?= =?utf-8?B?bGJOTU1WTkhuUkwvN205Rk05VytDUzZVanRpV1A0M21ubTZQVUY4K2lnenZ0?= =?utf-8?B?dUdMMDdFSkdqM3gxb2pWWmczVmRIYjE1elRNMmpGRnM5Vk8vUVFUU3VESUt4?= =?utf-8?B?aGpyV3M0TVBlUzNCS2J1K3pNRmd4akYvYkMrK1dJWUI2cmd6OFJ4OTQwbXZ1?= =?utf-8?B?Z0dtN1JaQTJLSEpJQ2dlelZQek4rOEhjYUtTakNlWFVZR1pRWGhUNll0UytH?= =?utf-8?B?WEtHUWgvMDgxbTByd3BEeWZZZ1l2V0hHK1hIcFFnbjVWSnFXRTFrRnFSYzR5?= =?utf-8?B?eGtPaE5BMDg2YjBSZVl0ZWRNVXVRNXlaR2N1NWd4QW0vK3gwSmZ5dXBxdXVx?= =?utf-8?B?RVZScWRNZ0VxL20yeDlFNFZ5ZmJ5dVVXWjFaNld4MHB1UEJaMUhTN0tiaXpN?= =?utf-8?B?QjRqaCtHbmM1RUsvM1RiSVp3OXZ6V1NtMmJWTHhVQit2bFVKcTNwSDAvN0ow?= =?utf-8?B?d21XMDdmUzNFU3dVTmlFRFd6WU50TEI3UjhnOFd0Z3NlZFFuT2dBY29kUGJi?= =?utf-8?B?bG1ZMDl5T0Uza3AydmFCVTFpaENwOGRCUkNZWWNhL01teXFhVkJEMUNtV0JU?= =?utf-8?B?TVVNeWcxMlZURlVUWFRjb205V0RJR2dmbGpubnlWUzBKK0F1bGNzZ1hDYVNi?= =?utf-8?B?R2NFVGovTXNqQ3RBQW92OEdSVnM3V0oycUFqcEJncSsrSURKbStvR0dCTDU0?= =?utf-8?B?Y2VOM205aXBOc0NLb29LUnJEWnhtV0RYZXU5TFA4RVVYYkRheXo2dUVBRk95?= =?utf-8?B?cW1qUU5lRXVkN2dka2Z0VE91WDZQNWh2NDRyUXBGUWdML3pDTm5ZUEROeFN1?= =?utf-8?B?emQrdldHQXgzTmFkY1pKTkZmOHVROFo5VGlMRHF2V05LNEJXaDFGRDdEc2Ux?= =?utf-8?B?MWNYcFljUmlURndqNWJoVkdtWHBYZ3o5bnN5dmlwU01vWE9qa1JwQTBYRTNY?= =?utf-8?B?S3lSMzUvbVAxcG9XbU1QQ3JmdUo4OTJKK3BYRXN2K0xnN1RXeFpRV0UwL1Vi?= =?utf-8?B?REl0U2UxYWpMMnVBZVdFRGNuMWdnczJtN1d0QWNLYXgwYTVoTmwzUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: e31e1659-68f5-4c60-a3ad-08defde27232 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:15.4599 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: TWNk4xlVE01CzGEfLDi9Ry+rfoq198Za8kzRLWPExOVnrmJQELF6qS6kicX+YjxfcQW7Mo0j4ioeghDRaMohKw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO0P265MB5167 The existing `register!` macro is implemented as a declarative macro. Reimplement it as proc macro instead, with no functional changes intended. The old implementation produces unhelpful diagnostics when things go wrong. For example, for code like register! { pub(crate) TESTREG(u32) { 31:0 data; } } which misses out the "@ offset" part of the specification, and the following error is produced: error: no rules expected `{` --> test.rs:42:5 | 42 | / register! { 43 | | pub(crate) TESTREG(u32) { 44 | | 31:0 data; ... | 100 | | } | |_____^ no rules expected this token in macro call which isn't very helpful. With the proc macro implementation, the following error is produced: error: expected `@` or `=3D>` --> tests.rs:43:33 | 43 | pub(crate) TESTREG(u32) { | ^ which is much more helpful. Apart from diagnostics, proc macro also has a benefit of not having follow-set restrictions, which makes syntax like register!(name: ty @ offset); possible; declarative macro will reject this as `@` is not in the follow-set of "ty" metavariable kind. Signed-off-by: Gary Guo --- MAINTAINERS | 1 + rust/kernel/io/register.rs | 224 +------------------------------------- rust/macros/io/mod.rs | 3 + rust/macros/io/register.rs | 263 +++++++++++++++++++++++++++++++++++++++++= ++++ rust/macros/lib.rs | 10 ++ 5 files changed, 279 insertions(+), 222 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 637bdf68135e..c9f11fa9f2b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7486,6 +7486,7 @@ F: rust/kernel/io.rs F: rust/kernel/io/ F: rust/kernel/irq.rs F: rust/kernel/irq/ +F: rust/macros/io/ =20 DEVICE RESOURCE MANAGEMENT HELPERS M: Hans de Goede diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 03dfd2ff48c7..6a19552ffb95 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -801,227 +801,7 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// ``` #[macro_export] macro_rules! register { - // Entry point for the macro, allowing multiple registers to be define= d in one call. - // It matches all possible register declaration patterns to dispatch t= hem to corresponding - // `@reg` rule that defines a single register. - // - // TODO: change `alias:ident` to `alias:path` once relative registers = are replaced by I/O - // projections. - ( - $( - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - $([ $size:expr $(, stride =3D $stride:expr)? ])? - $(@ $($base:ident +)? $offset:literal)? - $(=3D> $alias:ident $(+ $alias_offset:ident)? $([$alias_id= x:expr])? )? - { $($fields:tt)* } - )* - ) =3D> { - $( - $crate::register!( - @reg $(#[$attr])* $vis $name ($storage) $([$size $(, stride = =3D $stride)?])? - $(@ $($base +)? $offset)? - $(=3D> $alias $(+ $alias_offset)? $([$alias_idx])? )? - { $($fields)* } - ); - )* - }; - - // All the rules below are private helpers. - - // Creates a register at a fixed offset of the MMIO space. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $offse= t:literal - { $($fields:tt)* } - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); - $crate::register!(@io_fixed $(#[$attr])* $vis $name); - }; - - // Creates an alias register of fixed offset register `alias` with its= own fields. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $al= ias:path - { $($fields:tt)* } - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name($storage) @ - <$alias as $crate::io::register::Register>::OFFSET - ); - $crate::register!(@io_fixed $(#[$attr])* $vis $name); - }; - - // Creates a register at a relative offset from a base address provide= r. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $base:= ident + $offset:literal - { $($fields:tt)* } - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); - $crate::register!(@io_relative $name @ $base); - }; - - // Creates an alias register of relative offset register `alias` with = its own fields. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $ba= se:ident + $alias:ident - { $($fields:tt)* } - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name($storage) @ <$alias as $crate::io::register::Re= gister>::OFFSET - ); - $crate::register!(@io_relative $name @ $base); - }; - - // Creates an array of registers at a fixed offset of the MMIO space. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - [ $size:expr, stride =3D $stride:expr ] @ $offset:literal { $(= $fields:tt)* } - ) =3D> { - $crate::build_assert::static_assert!(::core::mem::size_of::<$stora= ge>() <=3D $stride); - - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); - $crate::register!(@io_array $name [ $size, stride =3D $stride ]); - }; - - // Shortcut for contiguous array of registers (stride =3D=3D size of e= lement). - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:= expr ] @ $offset:literal - { $($fields:tt)* } - ) =3D> { - $crate::register!( - @reg $(#[$attr])* $vis $name($storage) - [ $size, stride =3D ::core::mem::size_of::<$storage>() ] - @ $offset { $($fields)* } - ); - }; - - // Creates an alias of register `idx` of array of registers `alias` wi= th its own fields. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $al= ias:path [ $idx:expr ] - { $($fields:tt)* } - ) =3D> { - $crate::build_assert::static_assert!( - $idx < <$alias as $crate::io::register::RegisterArray>::SIZE - ); - - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name($storage) @ - <$alias as $crate::io::register::Register>::OFFSET - + $idx * <$alias as $crate::io::register::RegisterArray>::= STRIDE - ); - $crate::register!(@io_fixed $(#[$attr])* $vis $name); - }; - - // Creates an array of registers at a relative offset from a base addr= ess provider. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - [ $size:expr, stride =3D $stride:expr ] - @ $base:ident + $offset:literal { $($fields:tt)* } - ) =3D> { - $crate::build_assert::static_assert!(::core::mem::size_of::<$stora= ge>() <=3D $stride); - - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); - $crate::register!(@io_relative_array $name [ $size, stride =3D $st= ride ] @ $base); - }; - - // Shortcut for contiguous array of relative registers (stride =3D=3D = size of element). - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:= expr ] - @ $base:ident + $offset:literal { $($fields:tt)* } - ) =3D> { - $crate::register!( - @reg $(#[$attr])* $vis $name($storage) - [ $size, stride =3D ::core::mem::size_of::<$storage>() ] - @ $base + $offset { $($fields)* } - ); - }; - - // Creates an alias of register `idx` of relative array of registers `= alias` with its own - // fields. - ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - =3D> $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)*= } - ) =3D> { - $crate::build_assert::static_assert!( - $idx < <$alias as $crate::io::register::RegisterArray>::SIZE - ); - - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name($storage) @ - <$alias as $crate::io::register::Register>::OFFSET + - $idx * <$alias as $crate::io::register::RegisterArray>::ST= RIDE - ); - $crate::register!(@io_relative $name @ $base); - }; - - // Generates the bitfield for the register. - // - // `#[allow(non_camel_case_types)]` is added since register names typi= cally use - // `SCREAMING_CASE`. - ( - @bitfield $(#[$attr:meta])* $vis:vis struct $name:ident($storage:t= y) { $($fields:tt)* } - ) =3D> { - $crate::bitfield!( - #[allow(non_camel_case_types)] - $(#[$attr])* $vis struct $name($storage) { $($fields)* } - ); - }; - - // Implementations shared by all registers types. - (@io_base $name:ident($storage:ty) @ $offset:expr) =3D> { - impl $crate::io::register::Register for $name { - type Storage =3D $storage; - - const OFFSET: usize =3D $offset; - } - }; - - // Implementations of fixed registers. - (@io_fixed $(#[$attr:meta])* $vis:vis $name:ident) =3D> { - impl $crate::io::register::FixedRegister for $name {} - - $(#[$attr])* - $vis const $name: $crate::io::register::FixedRegisterLoc<$name> = =3D - $crate::io::register::FixedRegisterLoc::<$name>::new(); - }; - - // Implementations of relative registers. - (@io_relative $name:ident @ $base:ident) =3D> { - impl $crate::io::register::WithBase for $name { - type BaseFamily =3D $base; - } - - impl $crate::io::register::RelativeRegister for $name {} - }; - - // Implementations of register arrays. - (@io_array $name:ident [ $size:expr, stride =3D $stride:expr ]) =3D> { - impl $crate::io::register::Array for $name {} - - impl $crate::io::register::RegisterArray for $name { - const SIZE: usize =3D $size; - const STRIDE: usize =3D $stride; - } - }; - - // Implementations of relative array registers. - ( - @io_relative_array $name:ident [ $size:expr, stride =3D $stride:ex= pr ] @ $base:ident - ) =3D> { - impl $crate::io::register::WithBase for $name { - type BaseFamily =3D $base; - } - - impl $crate::io::register::RegisterArray for $name { - const SIZE: usize =3D $size; - const STRIDE: usize =3D $stride; - } - - impl $crate::io::register::RelativeRegisterArray for $name {} + ($($tt:tt)*) =3D> { + $crate::macros::register!($($tt)*); }; } diff --git a/rust/macros/io/mod.rs b/rust/macros/io/mod.rs new file mode 100644 index 000000000000..39fa5bc302ba --- /dev/null +++ b/rust/macros/io/mod.rs @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +pub(crate) mod register; diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs new file mode 100644 index 000000000000..61d076ab570a --- /dev/null +++ b/rust/macros/io/register.rs @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 + +use proc_macro2::{ + Group, + Literal, + Span, + TokenStream, // +}; +use quote::{ + quote, + quote_spanned, // +}; +use syn::{ + bracketed, + parenthesized, + parse::Parse, + spanned::Spanned, + token, + Attribute, + Expr, + Ident, + Path, + Result, + Token, + Type, + Visibility, // +}; + +mod kw { + syn::custom_keyword!(stride); +} + +struct RegArrayDef { + size: Expr, + stride: Option, +} + +enum RegOffset { + /// Register is located at fixed address. + Fixed { offset: Literal }, + /// Register is an alias of a fixed register. + Alias { alias: Path }, + /// Register is an alias of an element of a register array. + ElementAlias { alias: Path, idx: Expr }, +} + +struct Reg { + attrs: Vec, + vis: Visibility, + name: Ident, + storage: Type, + array: Option, + relative_base: Option, + offset: RegOffset, + bitfield_args: Group, +} + +impl Parse for Reg { + fn parse(input: syn::parse::ParseStream<'_>) -> Result { + let attrs =3D input.call(Attribute::parse_outer)?; + let vis =3D input.parse()?; + let name =3D input.parse()?; + let storage =3D { + let content; + parenthesized!(content in input); + content.parse()? + }; + let array =3D if input.peek(token::Bracket) { + let content; + bracketed!(content in input); + let size =3D content.parse()?; + let stride =3D if content.peek(Token![,]) { + let _: Token![,] =3D content.parse()?; + let _: kw::stride =3D content.parse()?; + let _: Token![=3D] =3D content.parse()?; + Some(content.parse()?) + } else { + None + }; + Some(RegArrayDef { size, stride }) + } else { + None + }; + + let lh =3D input.lookahead1(); + let mut relative_base =3D None; + let offset =3D if lh.peek(Token![@]) { + let _: Token![@] =3D input.parse()?; + + if input.peek(Ident) { + relative_base =3D Some(input.parse()?); + let _: Token![+] =3D input.parse()?; + } + + RegOffset::Fixed { + offset: input.parse()?, + } + } else if lh.peek(Token![=3D>]) { + let _: Token![=3D>] =3D input.parse()?; + let mut alias: Path =3D input.parse()?; + if input.peek(Token![+]) { + let _: Token![+] =3D input.parse()?; + relative_base =3D Some(alias); + alias =3D input.parse()?; + } + + if input.peek(token::Bracket) { + let content; + bracketed!(content in input); + RegOffset::ElementAlias { + alias, + idx: content.parse()?, + } + } else { + RegOffset::Alias { alias } + } + } else { + Err(lh.error())? + }; + + let lh =3D input.lookahead1(); + let bitfield_args =3D if lh.peek(token::Brace) { + input.parse()? + } else { + Err(lh.error())? + }; + + Ok(Self { + attrs, + vis, + name, + storage, + array, + relative_base, + offset, + bitfield_args, + }) + } +} + +pub(crate) struct RegDef { + regs: Vec, +} + +impl Parse for RegDef { + fn parse(input: syn::parse::ParseStream<'_>) -> Result { + let mut regs =3D Vec::new(); + while !input.is_empty() { + regs.push(input.parse()?); + } + Ok(RegDef { regs }) + } +} + +pub(crate) fn register(def: RegDef) -> Result { + let mut outputs =3D TokenStream::new(); + + for reg in def.regs { + let Reg { + attrs, + vis, + name, + storage, + array, + relative_base, + offset, + bitfield_args, + } =3D reg; + + // Use register name's span for generated code, so error messages = (if any) can point to it + // instead of the entire register allocation. + let span =3D name.span().resolved_at(Span::mixed_site()); + + let offset =3D match offset { + RegOffset::Fixed { offset } =3D> quote!(#offset), + RegOffset::Alias { alias } =3D> { + quote_spanned!(alias.span().resolved_at(span) =3D> + <#alias as ::kernel::io::register::Register>::OFFSET + ) + } + RegOffset::ElementAlias { alias, idx } =3D> { + outputs.extend(quote_spanned!(idx.span().resolved_at(span)= =3D> + ::kernel::build_assert::static_assert!( + #idx < <#alias as ::kernel::io::register::Register= Array>::SIZE + ); + )); + quote_spanned!(alias.span().resolved_at(span) =3D> + <#alias as ::kernel::io::register::Register>::OFFSET + + #idx * <#alias as ::kernel::io::register::Regist= erArray>::STRIDE + ) + } + }; + + outputs.extend(quote_spanned!(span =3D> + ::kernel::bitfield!( + // `#[allow(non_camel_case_types)]` is added since registe= r names typically use + // `SCREAMING_CASE`. + #[allow(non_camel_case_types)] + #(#attrs)* #vis struct #name(#storage) #bitfield_args + ); + + impl ::kernel::io::register::Register for #name { + type Storage =3D #storage; + + const OFFSET: usize =3D #offset; + } + )); + + match array { + None =3D> match relative_base { + None =3D> outputs.extend(quote_spanned!(span =3D> + impl ::kernel::io::register::FixedRegister for #name {} + + #(#attrs)* #vis const #name: ::kernel::io::register::F= ixedRegisterLoc<#name> =3D + ::kernel::io::register::FixedRegisterLoc::<#name>:= :new(); + )), + Some(relative_base) =3D> outputs.extend(quote_spanned!(spa= n =3D> + impl ::kernel::io::register::WithBase for #name { + type BaseFamily =3D #relative_base; + } + + impl ::kernel::io::register::RelativeRegister for #nam= e {} + )), + }, + + Some(def) =3D> { + let size =3D &def.size; + let stride =3D if let Some(stride) =3D &def.stride { + outputs.extend(quote_spanned!(stride.span().resolved_a= t(span) =3D> + ::kernel::build_assert::static_assert!( + ::core::mem::size_of::<#storage>() <=3D #stride + ); + )); + quote!(#stride) + } else { + quote_spanned!(span =3D> ::core::mem::size_of::<#stora= ge>()) + }; + + outputs.extend(quote_spanned!(span =3D> + impl ::kernel::io::register::RegisterArray for #name { + const SIZE: usize =3D #size; + const STRIDE: usize =3D #stride; + } + )); + + match relative_base { + None =3D> outputs.extend(quote_spanned!(span =3D> + impl ::kernel::io::register::Array for #name {} + )), + Some(relative_base) =3D> outputs.extend(quote_spanned!= (span =3D> + impl ::kernel::io::register::WithBase for #name { + type BaseFamily =3D #relative_base; + } + + impl ::kernel::io::register::RelativeRegisterArray= for #name {} + )), + } + } + }; + } + + Ok(outputs) +} diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 24f96feaeb34..5807dee84747 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -19,6 +19,7 @@ mod fmt; mod for_lt; mod helpers; +mod io; mod kunit; mod module; mod paste; @@ -481,6 +482,15 @@ pub fn paste(input: TokenStream) -> TokenStream { .into() } =20 +#[doc(hidden)] // Documented in `kernel` crate. +#[proc_macro] +#[allow(non_snake_case)] +pub fn register(input: TokenStream) -> TokenStream { + io::register::register(parse_macro_input!(input)) + .unwrap_or_else(|e| e.into_compile_error()) + .into() +} + /// Registers a KUnit test suite and its test cases using a user-space lik= e syntax. /// /// This macro should be used on modules. If `CONFIG_KUNIT` (in `.config`)= is `n`, the target module --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU008.outbound.protection.outlook.com (mail-ukwestazon11020102.outbound.protection.outlook.com [52.101.195.102]) (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 74F7445198D; Wed, 19 Aug 2026 11:10:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.195.102 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137826; cv=fail; b=WXVFO25HnhRwb7Z2t2jvrUiS4obIM3D1TpmIhTYJFHhTPJJkX1GNRL5LHvo7i1EdFMHTYqEmp0dUz9GZy7ivFTnAWVpUAr4NK/4mwTwl+WfdYlyVJgLlGkaQMdTYcydfy7JTvoz0onrF0h96TLoD9JNjZyZmPHJ9JDvGf0RiLfg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137826; c=relaxed/simple; bh=/+a4W0EpGM9iIdiFpZAgXA9sUvO3Bcy2QewtWPPtr+c=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=H9kevyJcQ4ttcDEUfxfAtM3q64MD2Z/V0Fi7n7Uj1ehtTqZ3ii5Lxh3rWgm7Q02sFz7LOdUmoY4PdG3nqZ7QEN99gYIYNrfxUpsnfV3EgdWP0yrcWX/8ppBEYw9rJjI1VDdUGqgW6XORm/UDgFAU20QCWd9V+pplQyK91pWmm0E= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=K4SfqDZ7; arc=fail smtp.client-ip=52.101.195.102 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="K4SfqDZ7" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=I0ID778MuWSkAw1T7ZwlFIylQqizIQ3YfrxmFdhcfwMzj0GQMAIgIgwPDE83gylnPwwPQqiqpdr0mkbSK8ZEsVFGKTdTNB7UqNK91HEBdmSGhc5Ls9QILufU/2G7/G7xVKHgRxtblLACgXT/LIKK8y5lRsFoYpkgKW9jDCjWCnL7sqBWVCpDD5HdBg1wDOTuQy3HdHjaewiN0bIMhJCgAkFh522oYfTNB/j8TpIzZtu/lxRCE6j9My7UzLv4lQH7HOK+M86nQhABWCpEvB3WbZMFFCJYsQwPTrDU+E7UjWEo3ZfPaJYMGFh3NceiLC6R4ikUXQ+ERWqzCOgdkecMEg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=xb4BzmmZi+TtiXb0nw5NI5UhBRSfDkNUsnD26T2Q3fc=; b=RdtdsEKvQdtDGyIHuouZr4CqWCOjTOKKfljgOg/Zs6U7nIejF1qH5Ianyzo+odfsHQkxHTi/aRRs8ICMl8nrkrz9spFGnviEWSxyEZy8BCYNDTDYyAW6kaYcibxWYhSqilmj6QGN+mTWpP7jxgTZFA7N3QUSM1/KWrq2e8fOrwBn99BckNxsjY3MVRFCclRsHLx37K8qMsQcPqKnC5GTtIc32IO3K7yLYW9V7Zwjhl2pBZVqHnGtHyzKVWOJGLizDglpsaJp+yXzPYh1HmvCqFwbg7/WS7CH0KVbBLpITtcg//lllq9t9We490+y7WBNRU5/emGqYPznt9ni0aVkgw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xb4BzmmZi+TtiXb0nw5NI5UhBRSfDkNUsnD26T2Q3fc=; b=K4SfqDZ7YmRzwFkXRogq2oBPDUysFoY5F1zsVabh2WxGpZ5tWAGZyCYcvcbhi8TYIohheqIAMBSc/et8nikYOnN6uWN8zBBbt4zz1CJB4jnu7EYxzUebpUeQYQpy6vWrK5+YFm5Pp5yOOI4XH63q9QST1BU1I+T8G7sfJ1f4aDQ= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by LO0P265MB5167.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:283::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:16 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:16 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:10 +0100 Subject: [PATCH v3 02/16] rust: mem: add `transmute` with deferred size check Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-2-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=4538; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=/+a4W0EpGM9iIdiFpZAgXA9sUvO3Bcy2QewtWPPtr+c=; b=uD0R51iWnhv6v7MfHRssjYjMBjsgg8zS8dmNZAnBP4Cv4B9ECCnVjVe8O+LjyuWFXdZk3RseE 74s600gPXx8DzTQqn9k8C0RNtmkTae/naqdKX9QzsjTEA0d1Ia37Ov2 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|LO0P265MB5167:EE_ X-MS-Office365-Filtering-Correlation-Id: 7c50ae58-c5cc-4dcc-6b64-08defde2729c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|23010399003|376014|7416014|366016|22082099003|18002099003|921020|10067099003|5023799004|56012099006|6133799003; X-Microsoft-Antispam-Message-Info: y80NK98ec4dDoPxO/6dGc3kRPILyHfnv+7CJpFKq6QlpwhEvIcs1ruEBbZuOPxcBtPQLvxzBveOGh1+jLzNbwSDQQeZZGw5CmJEzdpWLAtYjtwC1xmTBvxmsrXwD3hBSQiZzCwaaSn9MHSxLveaXsXHoYqbwG3ZzRXQRG42U4C2fp3AFP+xah1yS1XQ71xzXu8NBSc3Ku7UG3kxVhmznTXvCA/xI1L191OgyLPu1he9TdfkTB1ezN3MLMGJexMT6bFEbnpm5CpHm99BK7GZ1lyRvQ5rWvr9x8LDTKdQcV4vMpA3r4IA0oXU+tXVS6WmEwwXjgKRzZtkMOWBkw40gBdsw2ucuZ4acIF6PazzM0QNFERzKlWwj+RwN5WeAolBsGTmeBjNZIEzuvaAQQs+qZ7ry7oHOzbMr43tgy+axdX8EWTHV4WfOUpq607vvEnb5WxCQAY3sicAEVx3iNauu8dLXAq5eTYHT/EYrvanbmneZwNsPdOTlpah9MYCLUlzeyiHPMOz3uRNakAEEsoG+I2/ggY5iuQRv/xuWCP0rJH4AqeDMk7NhINmXBv4c1UqmUlasokZoVhyA2OzcxRq0YI9neqIrocs4cj0Uqa/Np9mWN75sYNp1Ag9pp7NOrkGEv9gEWbsqOxHqI3/Fmobyo2BcpIuMtivr/2s7x4RE6Z1tnry5qE0eYr72G+WpHGXo+ZCqGD7oV/QgS7V8jTa8Kw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(1800799024)(23010399003)(376014)(7416014)(366016)(22082099003)(18002099003)(921020)(10067099003)(5023799004)(56012099006)(6133799003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?aFRPVFFEWXAyWHZVSU9NUWQxZEg0a29lQUM4bW5Pd0Nlck42WXNpYThQWXJZ?= =?utf-8?B?ci81TmxZcmhNMUxvNFdLaFEvaW9RcncyaTVPSXRYRk00RSt2TlJxY2hMSGJE?= =?utf-8?B?L0pZakJLaSs2d0ZJTjkyb3V1enJlS0xOOGZuUDYybnQ3ODZXRXR2Sk5pRzVn?= =?utf-8?B?RVRqcEtSOW1YSGhZQ0dxYi84Y2dqYnJib3B4b0crT2hhazU0K29iekxqNlJ4?= =?utf-8?B?L0l5aERyem5QL0lidjlIb3hyU281aEpzcDdhdkxkbnFJbktGdFMwYjRub0hN?= =?utf-8?B?ZDQ4MFBqT1JXaDNMVGtkOVYwN3NQc24xdHlWN3FDY0FVais0akFQSkxuUFIx?= =?utf-8?B?SmtmZXdsek4yY1ZaaGl4blRiTXpVTnlmc3ZEdFFBRnQwMHo1dm8zYmNlODlG?= =?utf-8?B?NDVpRWlFOFJwYVJmUVdhTVVtWFpLTXF1NjMrWWs5N1dyMlVDeStpZ1Npckt0?= =?utf-8?B?bFVTRXVLUm1ZWFFEeTU3UlpNRldoM2xXd0k2M09xQlUzWmhuem5kY290cUF4?= =?utf-8?B?S2NxT3FicDd0SU9qRUEvU1NBVmhPa3VBZmpHb1Nqa3JHV0k3MmtZOVpVdzYw?= =?utf-8?B?RkdRRXdmUEZENVB3Ni9EclVYT1RnRThzeElGSVpacFdHb0Q3eURtZXJqclJ5?= =?utf-8?B?MnpqZkFmQ0dWUTViUWdqOVRJNmROSE5wcUphdVlCa2RaV1pQTUVmQjNwUXFz?= =?utf-8?B?L0lmbVlteE5DM0NGOGZ5NURCVERiRU9IQWVZMitDTlBwRUdkL21nV0NGVGhE?= =?utf-8?B?VUpDdGJvd0pSbjFndm0reE9PMnFzTEJQanM2d1I5OXNWSW1paXZaMGpHNmR3?= =?utf-8?B?N1ZMcnpQZG1qU0xwdW1vdFNwRFlXUWUxYTNqWnpsamk5RHRWRE1nalMrRWRl?= =?utf-8?B?NlhUZFhMK3c4Yk9McS9XU2R1a2NJY0lTTUdSUURJKzNLSjJSbG83N3ZjSGpw?= =?utf-8?B?OWc2eVZWd1lTSG9jZ21lT1Awa2phR0RxL1JqMWdUU2w4RklGaE9IQnlTS2dG?= =?utf-8?B?NngrYVhoTG5TbThjVlFLRHkxbGhuTHF0dG5jd2NuaFpOSUc2S2hoOTA4WTZs?= =?utf-8?B?dk8rREFyOWsvNkZnNzFRRGJnVW1Beng4UU1IV2lYRnhjeXNBNUdRQ285d3By?= =?utf-8?B?a1ZycFUyZERhQVMzWUFOaUtpYkNGcnJPME5hcFQ1NDdXV1o3R2xtZXdBWUVu?= =?utf-8?B?Q3FvOTlpUmVKOHdGMDFxdmNuOUVxYWZlUWpRQWdPQ1JjSVRvUWQ2RFF2aDl2?= =?utf-8?B?VlhkQjZhVk5WQTdjK1dwc21wODAxOVRQUmpNMTB3UVJZNkVqZzNsNjZOdmc0?= =?utf-8?B?SXBDbENCTVZQWEV3bytKNVFQbjZaQjljamw5b1JBd2dNTk9lQXA4VCt0RHNO?= =?utf-8?B?SWFSYk56ODNETmpRMFl6NlJIdUk1dHRoS0lIZHJtTFFWdWNJa3hjeG15QnhV?= =?utf-8?B?THA3R1RIYWM1YVlIdDhXZHg4aFJkaUtQQWJmV290M3NEN2pJVG5XK2cybGEz?= =?utf-8?B?RUUzdG5mMG51R3JBZTgzMjByRjlyN1BhNytyb3U3TmR3cUNtSDhldVBTN1Np?= =?utf-8?B?TmZpbS9rdzF5VmtuODFvbExCcW5iT3hFQzloeVpVY244QmFWalZvbmdSNG93?= =?utf-8?B?U0p6VWliSUFzcmg2M0tzZjJTSGhkbnNwUnlKbDZmczlRRVIzdndnQldFUGpO?= =?utf-8?B?UzlsK2Q2cGFrMVJNSmxkN0wvalExYXpuN0Y0Mjc4OEUwS2dWTTkrZ0NpY1Fn?= =?utf-8?B?Y3V1OElqdDk2NFhsMFNYMlhpdDFpY2R4OFJFenFMTkFscmErb09jVUtCS2tX?= =?utf-8?B?cTBhRGZZa0tWOVVkYWRDQXlnYnpvZlliRWNEcFJSRGdJbWhualdVdXExZklD?= =?utf-8?B?OVo4YklGS2RDWjZBRytSMW1XRkk5cjRIVXkxbThmY1N0V1ZuWG5RZk13ZGJ6?= =?utf-8?B?TjNMYUhzSWR3RnY1cDZRTDQvbFZTSUxOU0R0MDNmeWVhaWdNMnZhdm1ic3ZG?= =?utf-8?B?dmI4WDRiTXR6UHQzQ1BJRWhscGZ4Zlo1bjh1RkpNbDdOS2FSTDEvTVZ1aEZo?= =?utf-8?B?WDdhQ3VRSUY2dmJzNzVEelBQUmRZNHdjTnYzbDArNTUrQkpORkh6T1hTNGNa?= =?utf-8?B?NTlUWHFzSWRUV2VPSksvNnFLTWtnS3k2amF0MmNpOXRoTGNBWmErTFo5Nysy?= =?utf-8?B?WkJ5QnpCMlJ5MDdvMklRcEk2YnFXcWdCc2NuTFJnWDJ1WWFXU0srcXNOZ3pL?= =?utf-8?B?SEozUWk1Uk8xaUVWM3BpQzZHb2tXSXE1RmpqRERsL2thSGdtOGdZOUxIeGxW?= =?utf-8?B?YzlRWmNxR20zS0FQNXYwdEV6VjR0b2gveGRSMXl3cU9ZNFlCQ1B1Zz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 7c50ae58-c5cc-4dcc-6b64-08defde2729c X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:16.1302 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: pZ7JLHWd36XteFk1T6w3iKZUQc6BrET1Z/dOh1s3jpsOs3pxdzIhxBYFn7xupZyXB0QDXVeNve8D8ffFTmz2DA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO0P265MB5167 Implement a `transmute_unchecked/transmute` that checks size at monomorphization time instead of type-checking time. This allows more cases where we know that the size matches but this is not generically checkable. The signature is equivalent to the unstable `transmute_neo` function in the standard library. A safe variant is provided to use with types implementing `FromBytes` and `IntoBytes`. Existing users of `transmute_copy` to bypass size checks are converted. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/device_id.rs | 3 +-- rust/kernel/lib.rs | 1 + rust/kernel/mem.rs | 37 +++++++++++++++++++++++++++++++++++++ rust/kernel/sync/atomic.rs | 4 ++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs index c81fca5b4986..cb8661dec2ab 100644 --- a/rust/kernel/device_id.rs +++ b/rust/kernel/device_id.rs @@ -146,8 +146,7 @@ impl IdArray { /// If the device implements [`RawDeviceIdIndex`], consider using [`Id= Array::new`] instead. pub const fn new_without_index(ids: [T; N]) -> Self { // SAFETY: `T` is layout-wise compatible with `T::RawType`, so is = the array of them. - let raw_ids: [MaybeUninit; N] =3D unsafe { core::mem::= transmute_copy(&ids) }; - core::mem::forget(ids); + let raw_ids: [MaybeUninit; N] =3D unsafe { crate::mem:= :transmute_unchecked(ids) }; =20 Self { ids: raw_ids, diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 4d5c96ddc49c..7225abc64084 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -98,6 +98,7 @@ pub mod kunit; pub mod list; pub mod maple_tree; +pub mod mem; pub mod miscdevice; pub mod mm; pub mod module; diff --git a/rust/kernel/mem.rs b/rust/kernel/mem.rs new file mode 100644 index 000000000000..a0901cbe1b2d --- /dev/null +++ b/rust/kernel/mem.rs @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Basic utilities for dealing with memory, values, and types. + +use crate::prelude::*; + +/// Version of `transmute` that performs size check at monomorphization-ti= me. +/// +/// Use this instead of [`core::mem::transmute`] when it is known that siz= es are identical but this +/// cannot be proven by the compiler during type checking. +/// +/// The signature is equivalent after Rust standard library's unstable `tr= ansmute_neo` and that of +/// [RFC 3844](https://github.com/rust-lang/rfcs/pull/3844). +/// +/// # Safety +/// +/// Same as [`core::mem::transmute`]. +#[inline(always)] +pub const unsafe fn transmute_unchecked(val: Src) -> Dst { + const_assert!(size_of::() =3D=3D size_of::()); + + // SAFETY: This is identical to `transmute` except that we bypassed th= e size check; which we + // used `const_assert!` to check above. + unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(val))= } +} + +/// Safely transmutes a value of one type to a value of another type of th= e same size. +/// +/// The sizes are checked during monomorphization. +/// +/// This can be considered as generic version of [`zerocopy::transmute!`] = macro that defers the size +/// check and thus can be used in more cases. +#[inline(always)] +pub const fn transmute(val: Src) -> Dst { + // SAFETY: transmute is safe with `IntoBytes` and `FromBytes` bounds. + unsafe { transmute_unchecked(val) } +} diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs index 9cd009d57e35..d5f4ef285193 100644 --- a/rust/kernel/sync/atomic.rs +++ b/rust/kernel/sync/atomic.rs @@ -140,7 +140,7 @@ pub unsafe trait AtomicAdd: AtomicType { const fn into_repr(v: T) -> T::Repr { // SAFETY: Per the safety requirement of `AtomicType`, `T` is round-tr= ip transmutable to // `T::Repr`, therefore the transmute operation is sound. - unsafe { core::mem::transmute_copy(&v) } + unsafe { crate::mem::transmute_unchecked(v) } } =20 /// # Safety @@ -149,7 +149,7 @@ const fn into_repr(v: T) -> T::Repr { #[inline(always)] const unsafe fn from_repr(r: T::Repr) -> T { // SAFETY: Per the safety requirement of the function, the transmute o= peration is sound. - unsafe { core::mem::transmute_copy(&r) } + unsafe { crate::mem::transmute_unchecked(r) } } =20 impl Atomic { --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU008.outbound.protection.outlook.com (mail-ukwestazon11020102.outbound.protection.outlook.com [52.101.195.102]) (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 3C2CC46982A; Wed, 19 Aug 2026 11:10:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.195.102 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137842; cv=fail; b=mkEm3jrBBo2VT4d1ojcM6J0LR5WvqU8MJiq/h8mMh3f6hVm6nyXqRXSmCGuU+tDkzmCrmDqF5P9HSCkIkksQqnKmcYRHz8bcakKtRb9uSr+HtAJQh5o8DiSs85U0t6RXgzu++8HF4HXR7pJB39yprpAxluDLcK2QTlPmRKu6bZ0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137842; c=relaxed/simple; bh=kuia1m05caZxtQrixxcme0yfXZ1k7Qjcz0016uORFpA=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=ojk8BZbdZ/V1ED8wpX3XGnX9NYlFqk2p+Lu72jUD+vlTmCx0japC90EG4VSD9stnZOp6+cT6okZA0/5FvAE9z1e7EFEIDHT06Tvi10NN3HtQrrrhAIhPhP7bHN5x30+kEeLfbZ2wQvE0LZmeOpe5han26c5M0Z5XX6imQ0T+Y9s= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=OiBY02N7; arc=fail smtp.client-ip=52.101.195.102 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="OiBY02N7" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=evwZbmhZNwegZEn1rX26KJYR4eXospP5Cpmox4/xi6WpmnirwySwB5lWA9C9ZuS4o1ucqXpZ5YlclvRfEFx2cBJ/LWOeLDgq0J3KkmXWMk1nMcx73AGJ5MHHSFmKRd7TTeH/LFkuOiHIbXvdBMQGxusg0EMGQ9jJzgzIpGc5mwW++AP1L8k7JQxnhuSx8icYxhPsPELMERkX2YAYQPLhvEZUmYd339rtdusr7bgUDeSfbwqeWqFBADrYLOU1pNKO7GE7jbMIkboZMcTJUd6qktB4fsnRFzs85H15xQ+DGEEcOgKx6CuXr1tNi4jRXP1PBVJFg9uGKoehxxExH6PdEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=30L1At75N7BB65GJHrPP7D9EbJKTB7i6elzX9/sM4DM=; b=Ri7ay5vl5uNMqbnzCxlI18D0WjUdORziJ8oL7BnkajOb4XcYo1q6yrUZ4HsIOhWVBRwuZX4/QMdm7Wv5hcPt1MRkYAce+6jmGQjSet5pkx4AXNic+mgk2s3xyNDeyycFaHMTryYHxBH9RbQh634KQJu1AJ4YLgM1CCJswjcJEL/q4Rlx3yBiHlOBwvLdwfBSUNt16z3IYu7A113SzLRl4Qp45NMP6jTeQB15YyMQXPUNCjUah+umAHLkt6oaUwC4jAnGiTkT7HnWUT6P1+sRF9kR57j2JzG/L8V0AKi4G3XCleNideJXNOK+UGuiHH0eegYK69d0iGYrmyVFYawtBw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=30L1At75N7BB65GJHrPP7D9EbJKTB7i6elzX9/sM4DM=; b=OiBY02N7uUCWlXFJaEONNFSvSwVIE51NSSGrwJCEYCz/sH3byaYO+GpiSi54QV+vtKdMWMxFcz6esz08b8jYvrXWDh9D5NrwkFpBsOnDnRYiH15XlZVWqH+CdMDMMHNKRQH3g4VU3mwuUCjRJ40CGt4rLXbh7INGrbVpHu6cf5o= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by LO0P265MB5167.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:283::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:16 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:16 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:11 +0100 Subject: [PATCH v3 03/16] rust: mem: add `AsRepr` and `AsReprMut` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-3-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=6271; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=kuia1m05caZxtQrixxcme0yfXZ1k7Qjcz0016uORFpA=; b=lEX6GVNve9WkDrYqVnlnk/M4i6pxxDZuCycigMll7k7jbeBqMEYUcuCkKfRMpnekuWjUOGE2g P/1EnCp0PcuAJqRnU7GodD8UygmPkG3fxTak1Axy3416ahNxKQ3oJf5 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|LO0P265MB5167:EE_ X-MS-Office365-Filtering-Correlation-Id: 91fafff0-8833-4914-a394-08defde272fc X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|23010399003|376014|7416014|366016|22082099003|18002099003|921020|10067099003|56012099006|6133799003; X-Microsoft-Antispam-Message-Info: Rt4f7Irsf9QUkWOz9J/n5uhw0kY4fmTEVgVKDWFO5TGp2x+ZVle9xc+npYohcPcXjendKccXDZ7zTESq/mgRBHKDj8FsKJrrhhlD+CADbFX13sWUqNuaDBAE/mlw+IEqfuRWui+mpogKShNvWE/f11Ad2604SgdSG6OVDh3bqgnosfUPLvcCVUBHFvxeh2+pLYy2BIWsvHVu9rokP+2Owc4PSLK+s4D+S4/Y5NX30UyASDcgGGXpFmB71rz0hjBi0iRKHBRwD47r9RwBzZxFvW0qmliipSFiG5XeIGnYYQhOGfsjA/ASlY7jlTX8CLmedIUY6genU9n5jN9yo8bcTxa6HzjBmP/FjmM3eKpWSZsRNUbJkYvPj2sApldiUPd9MdrJK/O60hAxUN95J9DZSoozVBIizQyPrxPuDM1++Bb2Qjy7vbjxbGTXSBc7/bNz85zunsfgUTYrIYzrcyfPjdregmVrJh6+2xqf7rFMffs+3INgzKfOA9GZva4h6l25JEDap0T+UTEK3LhhQr71HZ7NgFVF5OA7X66fLSgP9ba5csbSX3YJf2DnhXGGNPSg8aTPrq/yWwHhVc5iROuLOs3hJAqMFP3htM/8XXVM1/DJUBPjnJmZMXtVOdi6eiPjzlYDGanoergDIYwERSkEKO/MIDrK73g5jK6Qodna0nIXhTLpLvG6QcA9nmAmGtsvpJR9vDb2wR0an7dFxWseQA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(1800799024)(23010399003)(376014)(7416014)(366016)(22082099003)(18002099003)(921020)(10067099003)(56012099006)(6133799003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?R1RIMUhmUDBaZjJ0dXdmQitzVDlWS1VUT0VoYVdTcURmV2d2akcvY01mcFEx?= =?utf-8?B?cUtFdlJNTDQwaUxEVC9QNGxUSHlpTnozRTBiT2s1cjUwSjlZNkZFVm5RcVRW?= =?utf-8?B?cW1PKzQ1dEpsNWx4V1VNUEZtcEhDeFo0Uldrb2x0UnZsaGxQanBFS3pVT0FV?= =?utf-8?B?M1JiTjYyaFk0V0s4SUdMdE14VHZCKytsT3NrUTVqNVl0c3MzWjZoUkpEdkdv?= =?utf-8?B?WUEzeE43WDRkWXRxekphd1oyRG9CM2s1b1c3eDgwMlRrK1c4Q3k2UmFYNUk2?= =?utf-8?B?R3M1VllzV1hNMm1QLzJaUnlSdGFOMG92ZGJUZ2tVeTRXWGRuUEsvd0h2VTlZ?= =?utf-8?B?Z2VrSkZjSmJHcys3blFRY2dCaWVYSnNrZVVvR0M3Tk5MQ0RaUGllQmM5Z25y?= =?utf-8?B?NVlYL3NZb3p1WXRmMmZ1anZ6QkdxZkdhSkVrTWxRVmFjallDT1FjZm5qbnRL?= =?utf-8?B?Rzdna3ZLTzlNN3h1YVA4SjJRSUVpSGkvMlVURkJaRUp6MmRVSnp4VGZ2U3ZH?= =?utf-8?B?TlE3UkJ5WC9RK0hyRVlYNjBGN3Q1OE1kaUNzaVA3Tnp3a0YycUE1QWIyVW9q?= =?utf-8?B?bVBiR3EzQkNTdWJJZ3JkQ1ExdmFxZEcyV1dkYkRtbzA2R0VWaUtIU1ZVVVNM?= =?utf-8?B?UUd0QVQ0bmFDakdOcUsvc2dpNHg5dXBDL3JvZ1JDbzRlRldqQW55Tm9SbGtw?= =?utf-8?B?THk3RlpRY3RwMm9MYmZyMWJoNkJGLys0Vy9ETCt1cFpyODVHN1daNjBJWmkv?= =?utf-8?B?bE9IbGtwTjBVRGVwdGhwempDcWxBK0xmT3JjenVqcUFJRUViY2xBeGk1ZmtN?= =?utf-8?B?OXJYOFgrTFpudW5tSDZzeWl4cEFuTGphYm0zZ0Z3VU12Q2JSM2xHRFM1eFlw?= =?utf-8?B?OEg4SkR2dW1KV2Jibkx6M2lybEo1OURiWGRKWm5ONUNDeHFlRlI5UGJzS0Rw?= =?utf-8?B?blBPZFdOMVJGUHJlSkliUkVDZ21NbEN1cjhOWHR3QzRsbWkwdzdlMHhoZzBw?= =?utf-8?B?OFlGYW9sMzZSQWx0bGt2TE4wS2dwTFZzaGhYckt6dkg1QzhCWTVQeVFocU9H?= =?utf-8?B?NUlzWEpHQ25TbTNXNnROZVUyR01jbUFjWmtzbUdpWXdSMTNxZE9Kc21OaFkv?= =?utf-8?B?dFM0TlI2Qi9idkM1TW1QdWVsU0IyMmQwVnZZU1JYYUpvWEJkbGRRUzJ6YVUz?= =?utf-8?B?MTJML2l5YjhmQjY4RU1jVStpSWtUV1NHMmxPd3JzQ25lNHJRSHUxM1ZmRFlW?= =?utf-8?B?MVdLZVFBdjVrVHNZNEpsTTBQbnFTOG5HMjExTWtWaFZCVndHbnZuenhTSzNI?= =?utf-8?B?YlFZcWRTMThqOVoyNU9DY2lCRTA4RU4yRHJUYzRmZzNEZW5MQ2hPRjlZQlA4?= =?utf-8?B?UmVLTSs4cHJPTHNpYmYzQ2MrdUdnUm9tNmZkcVRCZkpnV3p4d2ROUzdDeUNu?= =?utf-8?B?bkVmd0VSMU9ta0xWdWdQVml5UVJsWVB4T09WUWtqcjhScEkxYXgySkZ5ZXVz?= =?utf-8?B?NU1vK0J0UnE3bUc2cHBsZS9CRDNSZWV3czZSVFhhQzJSUlRmTENHVnBRNmRB?= =?utf-8?B?cW1mRjdRK3A4VVlwL1ZDakVqN3VvMFhsUmZpenRCZmJQWG5KaWNTM1gvWHVw?= =?utf-8?B?WlhDVGxNdDdVRzNkTktqWVd5cVN1VndaY2ZDbHdzL0c2WWYrbVZyZUVheFdo?= =?utf-8?B?WHZrdzIrVGd3T2M5WXZ2SGNxb0tmaGd1WHJsOW43WVBHVlFUa1RiRXd4REtB?= =?utf-8?B?RmdXUitRYjVWSlFFNEN0aStwQkRVTVJRZmh2emJWYmFCKzJrQjlMdncvOW9X?= =?utf-8?B?M2R3eUZ2eCs1QVZzL3RXTWp5eDcwL2ZRY2NvQmFyUm8rWXFYem9HMDM4VXpU?= =?utf-8?B?dmxBQmJ1Mi80OWpmQURzRXd6ZUlkMUljN2xUNXVEMG9CZnl3L3VSVGlZVCtC?= =?utf-8?B?V2JKV1pNUE9HVGpPNjBCMTFvRmhFY2RDSW9ReVFJQkZBY3o5anNpaGo1N2du?= =?utf-8?B?RjJaRkRLczV5alV4V1IvS3dDbGdHMGt4NWIvWVM5SFlCdGI1SS9QTnpZeXp6?= =?utf-8?B?ajNPM1h2T3FZUkp2ZkZqQzBmbWF5M2V5WlBHUHVyV0JlMVhFNkxJdTg2RU5q?= =?utf-8?B?ei9JenZpYmFRREhOejVGVE9IeDZDaTBvb3lNRkNtT3VmY1pnWnN4UDJaZ2hl?= =?utf-8?B?OE5FUWttVGg3cmFLME5QWm83bjBRYitVUXV3QmVON25yTDJGZkRlZFd4bllN?= =?utf-8?B?K0dnY2IrWGJjTWxVWmt0VnlMb3JBK29SYUlrNktsSzhoencybjRoTmp4cVBp?= =?utf-8?B?RkxnMlRkTmxKekYwQXNaVXBWQmtFWTRHZkt1U1RuMlhxUyswOEl2Zz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 91fafff0-8833-4914-a394-08defde272fc X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:16.7688 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: RLM+HumRKAQ7v4Ac4y0m9UTpj77ZwYno7qagFFeaSvKbYOkxdjw+BIhzVLBMlKnUU7qRDCNrja1+09hvewJ7Gw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO0P265MB5167 Some API like atomics and I/O operate on primitives only; therefore other types would need to converted to these primitive first. Add two traits `AsRepr` and `AsReprMut` to indicate that the type can be turned into a primitive for these operations. Conceptually, `T: AsRepr` means that `&T` can be viewed as `&T::Repr` and thus it has only a round-trip transmutability requirement. `T: AsReprMut` means that `&mut T` can be viewed as `&mut T::Repr` and thus it needs to support bi-directional transmutability. To avoid duplicating implementation, all repr types are normalized to unsigned integers. Signed-off-by: Gary Guo --- rust/kernel/mem.rs | 148 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 148 insertions(+) diff --git a/rust/kernel/mem.rs b/rust/kernel/mem.rs index a0901cbe1b2d..5bce381d8895 100644 --- a/rust/kernel/mem.rs +++ b/rust/kernel/mem.rs @@ -35,3 +35,151 @@ pub const fn transmute(= val: Src) -> Dst { // SAFETY: transmute is safe with `IntoBytes` and `FromBytes` bounds. unsafe { transmute_unchecked(val) } } + +/// Type that is layout-compatible with a primitive representation. +/// +/// # Round-trip transmutability +/// +/// `T` is round-trip transmutable to `U` if and only if both of these pro= perties hold: +/// +/// - Any valid bit pattern for `T` is also a valid bit pattern for `U`. +/// - Transmuting a value of type `T` to `U` and then to `T` again +/// yields a value that is in all aspects equivalent to the original val= ue. +/// +/// # Safety +/// +/// - [`Self`] must have the same size and alignment as [`Self::Repr`]. +/// - [`Self`] must be [round-trip transmutable] to [`Self::Repr`]. +/// +/// [round-trip transmutable]: AsRepr#round-trip-transmutability +pub unsafe trait AsRepr: Sized { + /// Primitive representation of this type. + type Repr; + + /// Convert from [`AsRepr::Repr`] to `Self`. + /// + /// # Safety + /// + /// `repr` must be a valid bit patern of `Self`. If `repr` is previous= ly obtained using + /// [`AsRepr::into_repr`], then it will always be safe. + #[inline(always)] + unsafe fn from_repr_unchecked(repr: Self::Repr) -> Self { + // SAFETY: Per safety requirement of the trait. + unsafe { transmute_unchecked(repr) } + } + + /// Convert from `Self` to [`AsRepr::Repr`]. + #[inline(always)] + fn into_repr(this: Self) -> Self::Repr { + // SAFETY: Per safety requirement of the trait. + unsafe { transmute_unchecked(this) } + } +} + +/// Type that is bi-directionally transmutable with a primitive representa= tion. +/// +/// # Safety +/// +/// - [`Self`] must be [transmutable] from [`Self::Repr`]. +/// - Note that [`Self::Repr`] must be [transmutable] from `Self` as well,= however that is a +/// requirement of the [`AsRepr`] super trait already. +/// +/// [`transmutable`]: core::mem::transmute +pub unsafe trait AsReprMut: AsRepr { + /// Convert from [`AsRepr::Repr`] to `Self`. + #[inline(always)] + fn from_repr(repr: Self::Repr) -> Self { + // SAFETY: Per safety requirement of the trait. + unsafe { transmute_unchecked(repr) } + } +} + +// SAFETY: `bool` has the same size and alignment as `u8`, and Rust guaran= tees that `bool` has +// only two valid bit patterns: 0 (false) and 1 (true). Those are valid `u= 8` values, so `bool` is +// round-trip transmutable to `u8`. +unsafe impl AsRepr for bool { + type Repr =3D u8; +} + +// SAFETY: `*mut T` has the same size and alignment with `*const c_void`, = and is round-trip +// transmutable to `*const c_void`. +unsafe impl AsRepr for *mut T { + type Repr =3D *const c_void; +} + +// SAFETY: `*mut T` is transmutable from `*const c_void`. +unsafe impl AsReprMut for *mut T {} + +// SAFETY: `*const T` has the same size and alignment with `*const c_void`= , and is round-trip +// transmutable to `*const c_void`. +unsafe impl AsRepr for *const T { + type Repr =3D *const c_void; +} + +// SAFETY: `*const T` is transmutable from `*const c_void`. +unsafe impl AsReprMut for *const T {} + +macro_rules! int_impl { + ($($unsigned:ident $signed:ident ,)*) =3D> {$( + // SAFETY: $unsigned has the same size and alignment with itself, = and is round-trip + // transmutable to itself. + unsafe impl AsRepr for $unsigned { + type Repr =3D $unsigned; + } + + // SAFETY: $unsigned is transmutable from itself. + unsafe impl AsReprMut for $unsigned {} + + // SAFETY: $signed has the same size and alignment with $unsigned,= and is round-trip + // transmutable to it. + unsafe impl AsRepr for $signed { + type Repr =3D $unsigned; + } + + // SAFETY: $signed is transmutable from $unsigned. + unsafe impl AsReprMut for $signed {} + )*}; +} + +int_impl! { + u8 i8, + u16 i16, + u32 i32, + u64 i64, +} + +#[cfg(target_pointer_width =3D "32")] +const _: () =3D { + // SAFETY: usize has the same size and alignment with u32, and is roun= d-trip transmutable to it. + unsafe impl AsRepr for usize { + type Repr =3D u32; + } + + // SAFETY: isize has the same size and alignment with u32, and is roun= d-trip transmutable to it. + unsafe impl AsRepr for isize { + type Repr =3D u32; + } + + // SAFETY: usize is transmutable from u32. + unsafe impl AsReprMut for usize {} + // SAFETY: isize is transmutable from u32. + unsafe impl AsReprMut for isize {} +}; + +#[cfg(target_pointer_width =3D "64")] +const _: () =3D { + // SAFETY: usize has the same size and alignment with u64, and is roun= d-trip transmutable to it. + unsafe impl AsRepr for usize { + type Repr =3D u64; + } + + // SAFETY: isize has the same size and alignment with u64, and is roun= d-trip transmutable to it. + unsafe impl AsRepr for isize { + type Repr =3D u64; + } + + // SAFETY: usize is transmutable from u64. + unsafe impl AsReprMut for usize {} + // SAFETY: isize is transmutable from u64. + unsafe impl AsReprMut for isize {} +}; --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU008.outbound.protection.outlook.com (mail-ukwestazon11020102.outbound.protection.outlook.com [52.101.195.102]) (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 A36A745D5E8; Wed, 19 Aug 2026 11:10:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.195.102 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137846; cv=fail; b=t+i5jhykhfII1t9lbGDlEFoD0K9zVdJk4oZzM7UTM0EBzNZW0AlFBQbanOo81U8D4GefA/ozTZjcqykgpfrYZLoqrXVq7QFRh0iO1Q+OEIhMQ067y1gbU8G7Gc8e6AwVmU9FfrYBe6ieSIErRCEF+NZgkK6HljeMTUPa7kpod6Y= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137846; c=relaxed/simple; bh=mVBAgfzt49nYUC9KtvB97HmFPe/wUfHuf4347t39LVI=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=DFOkzzsXI5sgBqyfUBV0uAvsZaoYDEtTJRPL85bfESKKyN4Hq+I356lMduuBPd5FCvSnQ9+Ja4PnotmLi/XS4nPpZJaBmUmz1qFKTHO0k+LwsIRe+SuYVxca0OXmpU9phm4CiiKXMoAjfFI6rODH1nj2ndyQvINp4hYPh3ZulMk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=mOS0s9zg; arc=fail smtp.client-ip=52.101.195.102 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="mOS0s9zg" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ezdNpazFIycmiEREHutKaEWYbVjlfIOV2Qw4uV6HkjRvgMibVImvkeIhoL0Z5yCioF3tmvnfp65yLrAxv024KKCJ7akN/V39f2wtHft3K5F90AVrNQ5yVOwkMVhqCH2Thw2fBTFKyVJAfu8wczTVBETBhQThQOmmrmqUVi/SDTQlb1EcfXnY5wOqmSFFzbFbmXmKtRtbGmw7K6X/7POgxKrgcFEKYeoaQYg+ajPEQZOlBkyAd5eZDOYQvbeCqn2CcmRztJ0U2d77KSAPdUZTNFEvWrt3fJYv94cPJVmkq1PTuEAWe8LB/7k/BA8EGjcU/uxK/zDPH7Ez3w85P+Nmmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=pedHMMSfiAL+Q+nqp507G/ko3vcUafCgveq9BKAgleg=; b=W0AP1RJX2hLV5R4zw4AGZn4twVVwpWF+88PML0K2n96PgaKQNHBcC9f+5ZpC9qxw+CZ/EaFbxKWYOKgz/DP0Gu36ttWUug6Xrk7PvgSKSrF0tCArPLFQ3Uwjlklxm2d/C3oQwktEjUfRSJKJEJYbUM9uCwyZBh1CQEPdXcJTyDaFOYTH+883POhN7ZnJJgCS2YlYH9ctx7KqWA39ywK0Nmk/HlA6CM9XHaa5EDuDMB0E9iJrpxkLSnGY4JwZGvyictmz6c0oordHXZlWC0mbUfZSOsPtJJ6K20dPF4HFLkP1wWgWPZpauHCLrQm12XEXlKwrpom1/TmmmqcXQatAzg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pedHMMSfiAL+Q+nqp507G/ko3vcUafCgveq9BKAgleg=; b=mOS0s9zgPEKeyDgb+yicPQeftx+PDgeitbLpnwDqAQvGiSlk6zQ+lOii6L3RYjtPSmbeMHRMgOE9TBPtDVMDprIbSobcS4jzLHX1lFlERCtTtHvBro8Zolm2vCuPJSGcqoNk+v3WnbUyF0waMTdCjIe09yypEoPm9EjH83PwLzk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by LO0P265MB5167.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:283::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:17 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:17 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:12 +0100 Subject: [PATCH v3 04/16] rust: io: perform conversions using `AsRepr` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-4-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=18533; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=mVBAgfzt49nYUC9KtvB97HmFPe/wUfHuf4347t39LVI=; b=FbpHfRxaPe6LALKq/vfg5gH65KpjhrqK7paO5jdo0QnE/b6ubQf2gvTNdRGvgKhr5ubOUktv+ cEz9qcLiiWmDaMMjoGcAXhmRlfM5J1kI8u33OsFNjyZ7R6dBEuqemg9 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|LO0P265MB5167:EE_ X-MS-Office365-Filtering-Correlation-Id: 5f43b373-375c-47f4-cf4c-08defde2735e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|23010399003|376014|7416014|366016|22082099003|18002099003|921020|10067099003|5023799004|56012099006|6133799003; X-Microsoft-Antispam-Message-Info: DOX7tVBo5L/hTI04qJ3F5zcD/1lbiMFEaWuAlmrt6Dlg94UEdfkpw4U34BukX7W5R3Zfv1m5LDVLpAhjlLowZTOEJaACE772DGLANbGIZG8mhC6exSXb+Ii4p0awAL38qWvz2r/z9rfvy7ZJLPv9ZGOOgg8HosKhZwo+gTbVzKx0oOW0rxApW1TuMClblfYb+EVjYSQEAbUdpcFyJAbkx1CLooig9uDQgtfSCyHZSAk2AoqUofnjMSepyPQdW0iAXCSgUQBuR5fx5oslVV5/UyZB0Cjjzzi272cFj+ajCl83qbOylbbAdkayFNRHZxD0qkmxcxzTopK2R6VXixAE9OvO2+i6ri51qd7KRxUz1cKIUayJyt1AF3IYzuqCI1gbXaVVO83jnDxB2fpvumdf7RAaY5jbMPBjnHZtpr9Wqg4dEnzqiPCj4pUHGw+GJ1PdIfB+oeclCFmhDbeJbC9iqchGhMxyv5JWjP/K5Nae/lXE82TtIFZjb32OKm9Iikz4n0+0duMQMdZXqZJHjuC4SrpgEwMZqmNRV3TRB9MohlqnHEkT2Wsr627FhEqNjpcrC1jVVdNQ4YzeeznLcT5gy91/dI2gS8IKtTK7j8rb1RqWOetRrQXCUR8Si8GTwunp6UR2rO5AJ0NMOyb4cW+xkWiuWGMYLeX9g0RmE7Qx/CLl7u4WLUInTqH7PYqAmyZ8Ov6FFM/stq1XK4Ry5eeMLA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(1800799024)(23010399003)(376014)(7416014)(366016)(22082099003)(18002099003)(921020)(10067099003)(5023799004)(56012099006)(6133799003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?T0Nnby9oQmhrMHJSQXJCelpnSmRQdk9RMStCUC9FQ3ZBejZUSmt2bXFpNUxz?= =?utf-8?B?WmZVT2k1Q0RCM08xbEExd210NGdNdW5wUWV6ZXZLRHBsWUJJT0VhY2tsZTdK?= =?utf-8?B?bk0wZ3kvbUVqejZrakt1TVprbXZ1aGU2RWJqTTdKbkxRcmRTRy9yR0FCeE11?= =?utf-8?B?alppbkN3c1lIR2dVdUM4UDBwUWU2ZDlLdklPZlRXV3dEVlhSM05KOWx1Y21p?= =?utf-8?B?NnJDakh5NmJianU4K0Q2VlZzdnJNMk9WK1J5WFhRVVFydy8vcWovbXBKVzVW?= =?utf-8?B?RmpjREpsRDdwUjE1WldCYUVadEoxSGJXVnRlbS9hbUhwcDJRaUlOenc0TTZU?= =?utf-8?B?QkNVT3dmT2dFTnljRTBDNVphNUFINUZvZVNFTTlNSU5NRjQvWloyYU5TT3M4?= =?utf-8?B?Qmh1bVJqbE0xZ0xPS3FlTUFDZkEwK245UDJIWWRHalF6Vk1jYXlLVXNvWVNK?= =?utf-8?B?QWhZdVEyd3NHZlVDaTdxQjlvYU5hQ1ZBdWI4cUFNRExic0pJQ2xyTW1rRmFw?= =?utf-8?B?WGJDaWR2RGczbWxsSjhhY3BCa0c4RjM5TDgyMGZTRUZXb1Y0ZUcyWmhHM2Fh?= =?utf-8?B?TnQ2NERxMHdZU2tRbFFmbVRKZFczQlVHWUlDYjE5K2JNeHBsTC95MnJVaHd4?= =?utf-8?B?a0wxblpvNHVSa2JiWW54dGNwTjM2YTB5UWxJRzlJS3BuU0JwazR6TzdJaHFs?= =?utf-8?B?NjBhT001bmJ1a013UHNtcUVsTlBMdytMczdRODAxMXVia0I0ZytQYW95K04w?= =?utf-8?B?Qm1jYmxmaEU5aHhnd1JNU2lqQ1B6VS9VM2RTWDA2SDlSbUxYd2JFdDdONVZQ?= =?utf-8?B?MW9ielhrOFlEL1pudDRNQWxPNlB4MzRLZThvY3ZaQncrTU1VVlJjTmxDVVJF?= =?utf-8?B?eFJKb3J2WE0raTJyOFp4NUFGUGl1aUJIUkFJSm5FeDVncHBQR3JmR1ZCUTA0?= =?utf-8?B?U0RBdlU3Y2hydWdsQ0tRMUMrUTZwYjArNFNsRGxab0lyQzNJek5yUVZrTUhN?= =?utf-8?B?bnZmcEhqUGRqR3hqVEpaTEpneU95b3dMeGxFclVlRmZUT1MvSW90VjRqT0Jk?= =?utf-8?B?aW9FTWtMR2NYNmNma2N6eXk1NzJCSVdac3ZjekQwbHNvV2NndXVxb2FXODFQ?= =?utf-8?B?VHhTMnhIRFZSVm5Tem9tSzdpLzM1RDVUei9hUnpCMXE5N015UklxcFJNSjZi?= =?utf-8?B?dm9yR0hJenFMaHV0L3E4QUtMUGQwOStmUlRUNW94MmZBQ1c2QjRKZW9Cblcr?= =?utf-8?B?TlYva0ptd014bnlNdm9pZFpUWC95eTJlRXBKYzVFZjZVb3ltWlBSZEpSd1By?= =?utf-8?B?aDlTRjNja0VNVnBaYTdOSW5sb3dnVVhMN1R4OVpYVUFJdEM5K1U2STk1WmlS?= =?utf-8?B?NzlXbSt5cVp2U0JCRVdseDI1dTJkQ0liNkwyUXFYb3ArL1VOdFI5OUI3MU5r?= =?utf-8?B?ZjB1OFdQRWFTYWRCZlJ5UWJxNFNNZEEvYWF3R1NvMXY5UGgrRGdobytHZnRa?= =?utf-8?B?RHVJdFVMK1lXcHVydmpVSG5vVWo3cEE2RzNIUlpIYTdnOE9kU2tLcDhTbng3?= =?utf-8?B?WkU5KytCalU0R1V1TlljODY2Sm95VDFIT3VNbUhzdVpIV3NnZXQ1SS83R0Rp?= =?utf-8?B?ZWplcGxyVUh4WGs1SWEyOEh0ME9rd1RIdTgzMm9QTGxoN2N0UGhiZ1BFTk1X?= =?utf-8?B?WVU0QjVjbkZzaUxrZ2VJb0VJM0hxY3d5MlIwOVFLQmRZbEUrVFhLWlBIM3Nx?= =?utf-8?B?M1dvaGRaVWVQVE1XNFl1ZTM5Rzh5b1Rwb0pjVzlBdjFkUE0vQUpHeDRXaHF5?= =?utf-8?B?YmJaa0JBakZaUVl2OTFOOVZkZVFaR0VaRDBBQkNsb0ZpcVorSGVmR3N6ekkw?= =?utf-8?B?aXZtSmVDZ3NUelVJdHhnMFpTcTVBdFJhajd4NWlzMVhlcExXdkNoSWlQNnRm?= =?utf-8?B?cFdiT3RWZWwwbjI5TVhVT0lETXVaTDZnTnljdnVLTFYxbEtzZWlDSWJiY29i?= =?utf-8?B?azl1WDhzRGVyeDIvMFB1R0cvYllEUVFkeGI3L3l3ek1JazdXdDE2MndIQ1Nu?= =?utf-8?B?MHBlRW1jZHFRbkxMVFRSb0hCdDhXSUhWcmoraTJKNDNQTnM2Q2RRNlBENktI?= =?utf-8?B?dlN3YXVMbUpRdzNZa0tNdUtVM1RSdWlwK3dWUkgwRm9WazVoTWNzWDQ3MlFV?= =?utf-8?B?b0k2SDJUenhzUy9ub09SOTVteWF2b0JCajgvclUwdmR1c0w1L3pKQ1VaSXpL?= =?utf-8?B?cjFTVlFsTnRrT0NxUStmaExDd3lvZmxQMzJ4bUN6M2ZPM21ZdUh3cldkdVpC?= =?utf-8?B?eHNMcndCenNxdzUyMFNyM2Qwbi9GY3cxSzhTSElXdVVOMmFadjU3dz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 5f43b373-375c-47f4-cf4c-08defde2735e X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:17.4311 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: LarXTmWVsCNKEW2zXsukKtOL55EX+ouBBzGN4L3PmSybaUsbd7k73EJDYtsCFMQMQe93Fc/7qLVfIgG+ZYm69A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO0P265MB5167 For types that are layout-compatible with an I/O capable type, we would want the ability to use them directly for I/O operations. E.g. bitfield! { pub struct Foo(u32) { ... } } #[repr(C)] struct Bar { foo: Foo, } let mmio: Mmio<'_, Bar> =3D ...; io_read!(mmio, .foo) Currently this feature is available from `register!()` macro but not otherwise available with `io_read!`, `io_write!`. Support this by performing conversions to I/O primitives via the `AsRepr`/`AsReprMut` trait. This makes the `IoLoc::IoType` and `Register::Storage` redundant; thus remove them; also convert register methods to use the `read_val` and `write_val` instead. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/bitfield.rs | 10 ++++ rust/kernel/io.rs | 135 +++++++++++++++++++++++++----------------= ---- rust/kernel/io/register.rs | 15 ----- rust/macros/io/register.rs | 2 - 4 files changed, 86 insertions(+), 76 deletions(-) diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs index a0d089423f21..619c5e2189d1 100644 --- a/rust/kernel/bitfield.rs +++ b/rust/kernel/bitfield.rs @@ -308,6 +308,7 @@ macro_rules! bitfield { $(#[$attr])* #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq)] + #[derive($crate::prelude::FromBytes, $crate::prelude::IntoBytes)] $vis struct $name { inner: $storage, } @@ -346,6 +347,15 @@ fn from(val: $storage) -> $name { Self::from_raw(val) } } + + // SAFETY: `$name` is transparent over `$storage`. + unsafe impl $crate::mem::AsRepr for $name { + // Normalize `$storage` to the canonical repr type in case it = is signed. + type Repr =3D <$storage as $crate::mem::AsRepr>::Repr; + } + + // SAFETY: `$name` is transparent over `$storage`. + unsafe impl $crate::mem::AsReprMut for $name {} }; =20 // Definitions requiring knowledge of individual fields: private and p= ublic field accessors, diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 5ce9fd129068..6c087d30a166 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -11,6 +11,10 @@ =20 use crate::{ bindings, + mem::{ + AsRepr, + AsReprMut, // + }, prelude::*, ptr::{ Alignment, @@ -353,15 +357,12 @@ fn copy_write(view: Self::View<'_, T>, = value: T) { /// /// - The valid `Base` to operate on. For most registers, this should be [= `Region`]. /// - The offset to access (returned by [`IoLoc::offset`]), -/// - The width of the access (determined by [`IoLoc::IoType`]), -/// - The type `T` in which the raw data is returned or provided. +/// - The type `T` in which the data is returned or provided. /// -/// `T` and `IoLoc::IoType` may differ: for instance, a typed register has= `T` =3D the register type -/// with its bitfields, and `IoType` =3D its backing primitive (e.g. `u32`= ). +/// `T` is not necessarily the type for underlying I/O operation. Methods = that take `IoLoc` have `T: +/// AsRepr` bound and the `::Repr` type would be used to perf= orm I/O and converted to +/// `T` instead. pub trait IoLoc { - /// Size ([`u8`], [`u16`], etc) of the I/O performed on the returned [= `offset`](IoLoc::offset). - type IoType: Into + From; - /// Consumes `self` and returns the offset of this location. fn offset(self) -> usize; } @@ -372,8 +373,6 @@ macro_rules! impl_usize_ioloc { ($($ty:ty),*) =3D> { $( impl IoLoc, $ty> for usize { - type IoType =3D $ty; - #[inline(always)] fn offset(self) -> usize { self @@ -498,10 +497,19 @@ fn try_cast(self) -> Result<::View<'a, U>> #[inline] fn read_val(self) -> Self::Target where - Self::Backend: IoCapable, - Self::Target: Sized, + Self::Target: AsReprMut, + Self::Backend: IoCapable<::Repr>, { - Self::Backend::io_read(self.as_view()) + let view =3D self.as_view(); + // SAFETY: `AsRepr` guarantees layout compatibility. + let repr_view =3D unsafe { + Self::Backend::project_view( + view, + Self::Backend::as_ptr(view).cast::<::Repr>(), + ) + }; + + Self::Target::from_repr(Self::Backend::io_read(repr_view)) } =20 /// Write a value to I/O. @@ -520,10 +528,19 @@ fn read_val(self) -> Self::Target #[inline] fn write_val(self, value: Self::Target) where - Self::Backend: IoCapable, - Self::Target: Sized, + Self::Target: AsRepr, + Self::Backend: IoCapable<::Repr>, { - Self::Backend::io_write(self.as_view(), value) + let view =3D self.as_view(); + // SAFETY: `AsRepr` guarantees layout compatibility. + let repr_view =3D unsafe { + Self::Backend::project_view( + view, + Self::Backend::as_ptr(view).cast::<::Repr>(), + ) + }; + + Self::Backend::io_write(repr_view, Self::Target::into_repr(value)) } =20 /// Copy-read from I/O memory. @@ -645,7 +662,7 @@ fn copy_to_slice(self, data: &mut [u8]) #[inline(always)] fn try_read8(self, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_read(offset) @@ -655,7 +672,7 @@ fn try_read8(self, offset: usize) -> Result #[inline(always)] fn try_read16(self, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_read(offset) @@ -665,7 +682,7 @@ fn try_read16(self, offset: usize) -> Result #[inline(always)] fn try_read32(self, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_read(offset) @@ -675,7 +692,7 @@ fn try_read32(self, offset: usize) -> Result #[inline(always)] fn try_read64(self, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_read(offset) @@ -685,7 +702,7 @@ fn try_read64(self, offset: usize) -> Result #[inline(always)] fn try_write8(self, value: u8, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_write(offset, value) @@ -695,7 +712,7 @@ fn try_write8(self, value: u8, offset: usize) -> Result #[inline(always)] fn try_write16(self, value: u16, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_write(offset, value) @@ -705,7 +722,7 @@ fn try_write16(self, value: u16, offset: usize) -> Resu= lt #[inline(always)] fn try_write32(self, value: u32, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_write(offset, value) @@ -715,7 +732,7 @@ fn try_write32(self, value: u32, offset: usize) -> Resu= lt #[inline(always)] fn try_write64(self, value: u64, offset: usize) -> Result where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.try_write(offset, value) @@ -727,7 +744,7 @@ fn try_write64(self, value: u64, offset: usize) -> Resu= lt #[inline(always)] fn read8(self, offset: usize) -> u8 where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.read(offset) @@ -739,7 +756,7 @@ fn read8(self, offset: usize) -> u8 #[inline(always)] fn read16(self, offset: usize) -> u16 where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.read(offset) @@ -751,7 +768,7 @@ fn read16(self, offset: usize) -> u16 #[inline(always)] fn read32(self, offset: usize) -> u32 where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.read(offset) @@ -763,7 +780,7 @@ fn read32(self, offset: usize) -> u32 #[inline(always)] fn read64(self, offset: usize) -> u64 where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.read(offset) @@ -775,7 +792,7 @@ fn read64(self, offset: usize) -> u64 #[inline(always)] fn write8(self, value: u8, offset: usize) where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.write(offset, value) @@ -787,7 +804,7 @@ fn write8(self, value: u8, offset: usize) #[inline(always)] fn write16(self, value: u16, offset: usize) where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.write(offset, value) @@ -799,7 +816,7 @@ fn write16(self, value: u16, offset: usize) #[inline(always)] fn write32(self, value: u32, offset: usize) where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.write(offset, value) @@ -811,7 +828,7 @@ fn write32(self, value: u32, offset: usize) #[inline(always)] fn write64(self, value: u64, offset: usize) where - usize: IoLoc, + usize: IoLoc, Self::Backend: IoCapable, { self.write(offset, value) @@ -843,11 +860,12 @@ fn write64(self, value: u64, offset: usize) #[inline(always)] fn try_read(self, location: L) -> Result where + T: AsReprMut, L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { - let view =3D io_view::(self, location.offset())?; - Ok(Self::Backend::io_read(view).into()) + let view =3D io_view::(self, location.offset())?; + Ok(view.read_val()) } =20 /// Generic fallible write with runtime bounds check. @@ -876,12 +894,12 @@ fn try_read(self, location: L) -> Result #[inline(always)] fn try_write(self, location: L, value: T) -> Result where + T: AsRepr, L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { - let view =3D io_view::(self, location.offset())?; - let io_value =3D value.into(); - Self::Backend::io_write(view, io_value); + let view =3D io_view::(self, location.offset())?; + view.write_val(value); Ok(()) } =20 @@ -920,9 +938,10 @@ fn try_write(self, location: L, value: T) -> Res= ult #[inline(always)] fn try_write_reg(self, value: V) -> Result where + T: AsRepr, L: IoLoc, V: LocatedRegister, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { let (location, value) =3D value.into_io_op(); =20 @@ -954,16 +973,13 @@ fn try_write_reg(self, value: V) -> Result #[inline(always)] fn try_update(self, location: L, f: F) -> Result where + T: AsReprMut, L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, F: FnOnce(T) -> T, { - let view =3D io_view::(self, location.offset())?; - - let value: T =3D Self::Backend::io_read(view).into(); - let io_value =3D f(value).into(); - Self::Backend::io_write(view, io_value); - + let view =3D io_view::(self, location.offset())?; + view.write_val(f(view.read_val())); Ok(()) } =20 @@ -991,11 +1007,12 @@ fn try_update(self, location: L, f: F) -> R= esult #[inline(always)] fn read(self, location: L) -> T where + T: AsReprMut, L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { - let view =3D io_view_assert::(self, location.offs= et()); - Self::Backend::io_read(view).into() + let view =3D io_view_assert::(self, location.offset()); + view.read_val() } =20 /// Generic infallible write with compile-time bounds check. @@ -1022,12 +1039,12 @@ fn read(self, location: L) -> T #[inline(always)] fn write(self, location: L, value: T) where + T: AsRepr, L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { - let view =3D io_view_assert::(self, location.offs= et()); - let io_value =3D value.into(); - Self::Backend::io_write(view, io_value); + let view =3D io_view_assert::(self, location.offset()); + view.write_val(value) } =20 /// Generic infallible write of a fully-located register value. @@ -1064,9 +1081,10 @@ fn write(self, location: L, value: T) #[inline(always)] fn write_reg(self, value: V) where + T: AsRepr, L: IoLoc, V: LocatedRegister, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { let (location, value) =3D value.into_io_op(); =20 @@ -1098,14 +1116,13 @@ fn write_reg(self, value: V) #[inline(always)] fn update(self, location: L, f: F) where + T: AsReprMut, L: IoLoc, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, F: FnOnce(T) -> T, { - let view =3D io_view_assert::(self, location.offs= et()); - let value: T =3D Self::Backend::io_read(view).into(); - let io_value =3D f(value).into(); - Self::Backend::io_write(view, io_value); + let view =3D io_view_assert::(self, location.offset()); + view.write_val(f(view.read_val())); } } =20 diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 6a19552ffb95..45d2e73a92e7 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -117,9 +117,6 @@ =20 /// Trait implemented by all registers. pub trait Register: Sized { - /// Backing primitive type of the register. - type Storage: Into + From; - /// Start offset of the register. /// /// The interpretation of this offset depends on the type of the regis= ter. @@ -135,8 +132,6 @@ impl IoLoc, T> for () where T: FixedRegister, { - type IoType =3D T::Storage; - #[inline(always)] fn offset(self) -> usize { T::OFFSET @@ -149,8 +144,6 @@ impl IoLoc, T> for T where T: FixedRegister, { - type IoType =3D T::Storage; - #[inline(always)] fn offset(self) -> usize { T::OFFSET @@ -174,8 +167,6 @@ impl IoLoc, T> for F= ixedRegisterLoc where T: FixedRegister, { - type IoType =3D T::Storage; - #[inline(always)] fn offset(self) -> usize { T::OFFSET @@ -246,8 +237,6 @@ impl IoLoc, T> fo= r RelativeRegisterLoc + ?Sized, { - type IoType =3D T::Storage; - #[inline(always)] fn offset(self) -> usize { RelativeRegisterLoc::offset(self) @@ -289,8 +278,6 @@ impl IoLoc, T> for R= egisterArrayLoc where T: RegisterArray, { - type IoType =3D T::Storage; - #[inline(always)] fn offset(self) -> usize { T::OFFSET + self.0 * T::STRIDE @@ -377,8 +364,6 @@ impl IoLoc, T> fo= r RelativeRegisterArrayLo T: RelativeRegisterArray, B: RegisterBase + ?Sized, { - type IoType =3D T::Storage; - #[inline(always)] fn offset(self) -> usize { self.0.offset() + self.1 * T::STRIDE diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index 61d076ab570a..8af12caa964b 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -200,8 +200,6 @@ pub(crate) fn register(def: RegDef) -> Result { ); =20 impl ::kernel::io::register::Register for #name { - type Storage =3D #storage; - const OFFSET: usize =3D #offset; } )); --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021087.outbound.protection.outlook.com [52.101.95.87]) (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 D8867459AF9; Wed, 19 Aug 2026 11:10:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.87 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137827; cv=fail; b=I6cQbWd6HO390KSETAzkFbJytkDyqRK3B1HkKeK8i4Ro+jXlK/6aXgNiBexdv3erJg+vJe4wJGA9Zd8NC57kp7einpeiCG8s7SQhyugM5cEwoQiH/CbPKegIHR3xTCnxe6FYdjEeFd5OcWaeuhB5n0JQiA6bQTuE1tivCznQ/tc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137827; c=relaxed/simple; bh=U5eGkkYvQADr4TTFPN+0TCXo9RfXrHMnOeCh7ums5W4=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=CoZSeX+8StnXKwxyosJ8SWBN9lHOkTbAxeBUucWFve2N+6NhlO3fWClWZTW+HDk8TJjazQmis/asSd3x88A1mMb60/yszplRTgGz4BUUKQPgftiEvxRNedeDCZKPr9/78DVxHnvISI0BB1o1rXJemeba0YxF8ay5Ji3pMf2Opr4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=kGfN1xFC; arc=fail smtp.client-ip=52.101.95.87 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="kGfN1xFC" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=zATGqCKUJvWz77W8gP9MZQLeTzr+iccbkX4pgISZ4rrrXrOZm3aE8Bx4H8biCyfTNcpBuVtjEk5yWVexqcbHO/xfaWGPasnIEd2MwAW4xzMBS56YTnc3GVtjf19b9fzWD45uT9pa2IAgWzMxF2hUb3EeizQzWM0GeAfWAU04aK+ERoVv5S+8GxvJETkMFnIxzeGyB5WkL5xuEPb2VxI5nzGJg4k/ULEddXa4RlIaVFL3tH4+yrJnMvDV0UjCIZ63Zd5EUYUtnU1R2pbiCMp7bf6mG9Vk+4Qvgfty7vaxyCT1uFWNiISfr+rptJSNwZeRFPC48A59+36GnrE+Dk3qww== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=lNbnK7EWtcupeD63vJljcXrAq764/NWDK2IMvXG5HMY=; b=CMk33GgL/V79qiuOT9rKjzK3tIn/2LW9eX4GP4bxeJFoUvQ/lKvV++MVY3UNIF1k4DnP0nVG+pLGJOpdOMHZU+PekcnrhPPk28Ppy0RMw6aL00J6sRST+ksYZQa4H+SKXa5V4dfubIDIDnGuyiJOv/b31+ghB2RqMPOOECeNAENSxWNOl2Rb68A7HlzidsRU/a86njn6hM5Xy9yDABo1z940RHVYS06/pzX+qZ5KQ4wzTYENbv3Eu4AU5xJ9h0M7Q0YjH7hWYg/qrTf34pnAPThn02jieSHqB5sxr/IvzCoKOM8tGH11gbR+IyY9u86O5EO/8KJUabep8ibPvq+gxQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=lNbnK7EWtcupeD63vJljcXrAq764/NWDK2IMvXG5HMY=; b=kGfN1xFCW6EcCx6xWkmp1g2vc2lhTvCN5RarFIOGQUCisNPubtO6K5/2tDRdq4CLp0vV/voyTXyEadI7eFjjo3Lm8ndukD+euXv0x5hrldPhSrg0PxwClBAf3QSuucVrFDL7SQMkjzpDtDvZaDYowqe18yGr0J2AslbUmvh5ApI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB7056.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:200::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:18 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:18 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:13 +0100 Subject: [PATCH v3 05/16] rust: io: support register projections Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-5-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=5270; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=U5eGkkYvQADr4TTFPN+0TCXo9RfXrHMnOeCh7ums5W4=; b=ymP3QVpluvwtOhBEWP6phQFPe+xRniP/tw12BolNOftwvfuMdl4OXLsM59rpL+Gs3p4FikWg/ vi1S4XmLftmDSEldxL1O2Q7FGHgaKpISBsPaFdr20snKcYzXnwrT/Fn X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB7056:EE_ X-MS-Office365-Filtering-Correlation-Id: c5be3b55-6bda-42cc-8b1e-08defde273c4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|10070799003|1800799024|7416014|366016|23010399003|10067099003|56012099006|6133799003|5023799004|22082099003|18002099003|921020; X-Microsoft-Antispam-Message-Info: XD8rShmPS/y2APPIWQBuprfLeihH/Iqagh348GoQf8JaUhORtjnfoW/72YeSz9wD0lzld4Yb+k4ywjWCbXHwZa9SvVCAejV5ZzD8lX1szmhvNqPWFrwzSK2zP+1HdOzrTw8FjNbK9Xhb6r5t+58qQ/f1v4j1en1+pShiGQzyDVoPxCjT5qDbOFhzfgogC5k+ckJ2P2LpXAgz5e2G1rgmfJCanUwn9saI2a/517C4MkufSdgYwMsrsAJfulIyC2VvMZXIRGKn0Pg1EEpBbkygrk4AglzS0hkifNgyl1+uyaYli7tIrpJ5gGSwSA/xzU86CJp8Mbxp8OA9HGvVsVZPVmJh5/+PN6kHpUVS5lAylQ5lLi0KMPeIGz3JNSQMBsXtCgHHDR+LtdTHOD0ljVNqo/r+aLtEPtHWY7LKgPfIFrz5FtmCmrVXtaQr/EJQ7ndlfo8cPhedd9VAfuFwEw26H9GOhx8RqkFTeNCY+zDVgERqbPPRLHD2P2/RxHrvfVoSlqhJBDWgYs786CMfHV6ReJmEPoz7BMOu8Vmbtx2669bdEvaTvwrGkxFG4Pmznp8v9SZL1EKcbgrEefRqe2tMdSFb8LufZYrHecrs85nih0BDTWRRpleIt6EiK9vE07LXX6KJ0TtWqLl7H6FNp+yeHd9aGIa452/4I2xdlzqZUcgY949YRRdi6KiJBsEp9KB3QxuZ9z5rvOozK9ltvKx65Q== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(10070799003)(1800799024)(7416014)(366016)(23010399003)(10067099003)(56012099006)(6133799003)(5023799004)(22082099003)(18002099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dWxwUkhxL253RmRneTJnbENqUFB2bFJQcWVSTm5kVzBwU3JFNUZ6aXZleFJJ?= =?utf-8?B?LzkyWnlsQVZuMFhQZnM1T0dadDhCUHRDNGlUUFAxeXVFeEhyV2xVUjlwY1RJ?= =?utf-8?B?alh6R0Z1WUl5VkdSdkVKdXpjMTRQNUhEdDZpYVlBMjFxUEF6aDVKQVpZbmtv?= =?utf-8?B?OFZoeitEdElBQmgxZ1M2VDVYdXpJTlB6bHFNUms4blNpS1ViQlhNR016VVNQ?= =?utf-8?B?TFZBZWlYQksxdXNEOFlKaTgrbXRwSkpEOFI5Y2FYSEwvOWludG5LamhDNC9h?= =?utf-8?B?S042dVRJaVdDR0laM3habGVhK2VXYzR0MUtIVHU2cHVSbjY0UjJLbmhJeUsr?= =?utf-8?B?bVc4Yjdaa0I0aUQxSU5lb2xpV3lSY0l3OTVCYVBuNmI2YWJ5cEpna2lUT1dP?= =?utf-8?B?OFR3ODNBU0tZWURHaVRpSHJha29QaVg0Sk0xZHIybW5SNlduN0U1RFo2WlIw?= =?utf-8?B?UE9RMGtGZDVVSG9Rc1pJVVl5Q1Y5cXEwZUFEbmN1bDB3OC81OFVtYlBzdXlK?= =?utf-8?B?cUpCS1U3UkwwTXhwZ2RHbEUxMTV4UGZlNU01K1NPb1JuMWFxd2RMNmZVckNy?= =?utf-8?B?Y1VSNzA1bWJobHAxbTJUblJTRUJlSFVPVEFlTVFCdXRtbGpkdlZ2aTI4UlR2?= =?utf-8?B?ZzRNSVhXMStVNVlYWnQ1Tks2eDlyeE41YjJGNWxzR2lvSU9VamRPeW1HVGF0?= =?utf-8?B?NHplMG5vVFRQeDhoakJhWTZtT0tpNG1lK3lZMUJsQXBkYmZVb0FIVkV1RzEw?= =?utf-8?B?NkZhQzIyQkdzK2tDcTBXQ1lOUVp3MTcxcE1nWnR6NXpsQXVpeTB2VnkrS2Ju?= =?utf-8?B?VG1BVU85bm12aWZrTkxMdWxXdGliSlF1ZXNkSFJsbFlEMWE4dWJYdkdUL2pv?= =?utf-8?B?NHNrRzJHT1F3REUyM2FNQU14NC82NmxGYitpeDR5akJoNEpiNEhiK1hYaXk3?= =?utf-8?B?NzlEQTJaVUNmUjFzeEZtdU1pUFIyODduS292YTdHeW4xelBGQUJEYWdMb1BQ?= =?utf-8?B?S0NuUk80QTY5RklHZlNmcFZsR3ZzMVFTNGZIQkF6R2U3RkFLVkVEa2I1bmVi?= =?utf-8?B?blNWbzNzaThnd09vRW9PN3g1WnFIWk55MTVObzR3ZU1veEFNcmQxYmNOWFR3?= =?utf-8?B?U1kxYlk4em0ybHBGQXB1NHdwaUpFUURCVUg4Ym8xaWhLVkdsd1h2VGVCWVkv?= =?utf-8?B?U1NqWmVFbXBLZEx0MXRmSFI3aExJU2wvbVVYNFFTdEN3TjFjUnVacHJoQ0NL?= =?utf-8?B?di82cEk5bGdsN210YlpWcXc5bE9TbmNjTnBlVHBGY1VCRElOWU9mVGo0dys1?= =?utf-8?B?bHVqdEttbXZPREJ4b29qVEkzOWFPTEdxN2hxY3J2bEdWWVdkRyt1eFZ4N1FO?= =?utf-8?B?dFlSUFBTNkhnNjl3SG5UUWJTWklBdFQrZEFaaUpYSVlNejJNOVlDaWVGWUph?= =?utf-8?B?NU9WYVByWitzTHg3NC9LSFRYRHJkUU8rNkJ1Z3BwRTdtclBJa0w4aS80V0t2?= =?utf-8?B?dkMreDNoT1lHZ0M5b1Ezb2pYUE45MHJwTjZpbTNnRGtTUlJ5cjlWNEZUM3Nz?= =?utf-8?B?YTlEN2Q1bGVwM0Ztei8wNnM4bTcvM2ZHa29sOU1NeWtvT2NFVjgzWE0yeDhP?= =?utf-8?B?SHhycFk0dmNsVXBTOTVBa1Y4TjV4UDVuSDcxMDh0d3JmUVp0ajdYS0pWUUts?= =?utf-8?B?cSsrQXFaOVJuL054SWhqdUxjbGt1SzFtdld1NDEvT3Bqbm8ySmNGMUhGRnhT?= =?utf-8?B?dDJ3SGU4QzdhVkZINUYvYVZ3Sm5OSXJYRDl3NGMzeVRkQWswWWp4ZWx0RGFE?= =?utf-8?B?TXl5NXN3a2lyUS8yMjNLbisvOFJGbDF3SlFtb1NpZWFpd0owSTJ5Z3FTK3NF?= =?utf-8?B?dXhHbDBQaGI3SnJ0eitMLzAvZlVDVkRscmlxeC85SWN0bTZPRGh4OVllWDRK?= =?utf-8?B?c1lpRFhXeHlGa0VSOVZCQytpMlFLbGdGZ3hEN1ArdGNrUy9Ta0NvZTBlUzVv?= =?utf-8?B?YkRQck5KUWIwNjdEY01XejNEdEwvaExwSFBFUnVqQkgyQSthMjJVUnBtUmNK?= =?utf-8?B?djZwMGNTZFJNbUNVM3puUDRIS01XeHJQSHphNHZtbE5JTGZnaWVwMThJVEJz?= =?utf-8?B?TG5LNE1NZU9BeTF2eklLbzk4T2l5VFY2RXNscFdQRDdLdDVBUHBEOHhkTzJ2?= =?utf-8?B?VXFyY3d2eldKTC9GSUZGMklyN0F0YWJwdE9uVnVxdEJOSm9IVi84WG1jc281?= =?utf-8?B?VXpXS09WMGVWN3RzK3JOTHcwVm12aHVXRXFiUDZoQ2hrM09XUVRMMHlqbkZl?= =?utf-8?B?SVhGSTFXb1ZaK1N1UzM5UC9iQnc1K2RrdzA5RXNEdWZLQk94ZVQxUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: c5be3b55-6bda-42cc-8b1e-08defde273c4 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:18.0905 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Pug5hDbIKvUYnlMuaJLwEHuCMVHc1acZR0DzSNafrv54YEbGm4QB29MGLwbHYbMWUvTGTlz2H5x5DE5y+Nx3jQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB7056 `IoLoc`s themselves just describe a projection from a region to a concrete register. Thus, support it in `io_project` macro too. Also, update methods that operate on `IoLoc` to use I/O projection. Documentation of `io_project!` is not expanded yet as the example works better when `register!` type can specify base type. `io_read!` and `io_write!` gains the ability to operate on registers as corollary of the capability of `io_project!`. Examples are not added because `read` and `write` is still preferrably used instead. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++------= ---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 6c087d30a166..ea072c098b13 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -864,8 +864,7 @@ fn try_read(self, location: L) -> Result L: IoLoc, Self::Backend: IoCapable<::Repr>, { - let view =3D io_view::(self, location.offset())?; - Ok(view.read_val()) + Ok(io_read!(self, try: location)) } =20 /// Generic fallible write with runtime bounds check. @@ -898,8 +897,7 @@ fn try_write(self, location: L, value: T) -> Resu= lt L: IoLoc, Self::Backend: IoCapable<::Repr>, { - let view =3D io_view::(self, location.offset())?; - view.write_val(value); + io_write!(self, try: location, value); Ok(()) } =20 @@ -978,7 +976,7 @@ fn try_update(self, location: L, f: F) -> Resu= lt Self::Backend: IoCapable<::Repr>, F: FnOnce(T) -> T, { - let view =3D io_view::(self, location.offset())?; + let view =3D io_project!(self, try: location); view.write_val(f(view.read_val())); Ok(()) } @@ -1011,8 +1009,7 @@ fn read(self, location: L) -> T L: IoLoc, Self::Backend: IoCapable<::Repr>, { - let view =3D io_view_assert::(self, location.offset()); - view.read_val() + io_read!(self, build: location) } =20 /// Generic infallible write with compile-time bounds check. @@ -1043,8 +1040,7 @@ fn write(self, location: L, value: T) L: IoLoc, Self::Backend: IoCapable<::Repr>, { - let view =3D io_view_assert::(self, location.offset()); - view.write_val(value) + io_write!(self, build: location, value); } =20 /// Generic infallible write of a fully-located register value. @@ -1121,7 +1117,7 @@ fn update(self, location: L, f: F) Self::Backend: IoCapable<::Repr>, F: FnOnce(T) -> T, { - let view =3D io_view_assert::(self, location.offset()); + let view =3D io_project!(self, build: location); view.write_val(f(view.read_val())); } } @@ -1666,6 +1662,25 @@ pub unsafe fn project_view( // SAFETY: Per safety requirement. unsafe { T::Backend::project_view::(self.0, ptr) } } + + #[inline(always)] + pub fn try_project_loc( + self, + location: L, + ) -> Result<::View<'a, U>> + where + L: IoLoc, + { + io_view::<_, U>(self.0, location.offset()) + } + + #[inline(always)] + pub fn project_loc(self, location: L) -> ::View<'a, U> + where + L: IoLoc, + { + io_view_assert::<_, U>(self.0, location.offset()) + } } =20 /// Project an I/O type to a subview of it. @@ -1693,6 +1708,21 @@ pub unsafe fn project_view( #[macro_export] #[doc(hidden)] macro_rules! io_project { + // Register projection + ($io:expr, try: $ioloc:expr) =3D> {{ + #[allow(unused)] + use $crate::io::IoBase as _; + let view =3D $crate::io::ProjectHelper($io.as_view()); + view.try_project_loc($ioloc)? + }}; + ($io:expr, build: $ioloc:expr) =3D> {{ + #[allow(unused)] + use $crate::io::IoBase as _; + let view =3D $crate::io::ProjectHelper($io.as_view()); + view.project_loc($ioloc) + }}; + + // Field or index projection ($io:expr, $($proj:tt)*) =3D> {{ #[allow(unused)] use $crate::io::IoBase as _; @@ -1763,6 +1793,12 @@ macro_rules! io_write { (@parse [$io:expr] [$($proj:tt)*] [[$flavor:ident: $index:expr] $($res= t:tt)*]) =3D> { $crate::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($r= est)*]) }; + (@parse [$io:expr] [] [try: $ioloc:expr, $($rest:tt)*]) =3D> { + $crate::io_write!(@parse [$io] [try: $ioloc] [, $($rest)*]) + }; + (@parse [$io:expr] [] [build: $ioloc:expr, $($rest:tt)*]) =3D> { + $crate::io_write!(@parse [$io] [build: $ioloc] [, $($rest)*]) + }; ($io:expr, $($rest:tt)*) =3D> { $crate::io_write!(@parse [$io] [] [$($rest)*]) }; --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021087.outbound.protection.outlook.com [52.101.95.87]) (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 09AA744E675; Wed, 19 Aug 2026 11:10:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.87 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137825; cv=fail; b=d5az6sqGBCtUIZOclW8zebbrjxZWcFwXrQwke+JeMNxSeORq2HJ+2SvFCa/WuZBWP5L0ZvwVtAlu9oNYdF3Ir8i4ekvLCWkksywL1pUwNmvLr3ow77d0iohPi1z+tRsO/F3QBRoFZgRe+sww3keZ8na94UaoQeZFOph/DbKRlzo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137825; c=relaxed/simple; bh=BW8Pipu9gMJAyQKlc26RqfQ2wmugHrBod8hkXoCWiys=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=K3P9qWAiyokZSrEC9OZ1s71QoUwR69nPcimAcYDObO1VC/3Bewd23hZIkrb3f+PFUKO2jeqVoaR90pfPWlnlG9hwN9TaSljHKicbo4vLHrk/oqi32uxthP0bHLQ1MSn9BrH7i6X6wF4OgpU2WrdhR+9QLMeqJJVVqpa/57pK84Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=IaDFBGNl; arc=fail smtp.client-ip=52.101.95.87 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="IaDFBGNl" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=VeyFwHNwfpzJ62YhSu+SmtXQBaARcnDzcrhU9QtiCpOWFoiTodN8YQ/EFkqhAI7aakxKFAFgCCqhXu6FKwavUbFcGIZrps6H6sh2XrYPaxsB0hbMpsD9ettHqqm5tFUj2wKsCtebvwBbUhTZ/iaMhGRufsI4RvibKElwF4fYtZa+EP5M3nbNn2WYQvXSUhqMkQzhN7EGRhigT/HW9B/QXXYu9/9oXwUb6hv5cpph1jW8m4Ma1VakeXJwkplJdUsDKx8aTxlM2yGLDSLOooL9Pkm/FOL8mFtOXClcmN2pOtvYHuRi0/UShq0QqM/idTLk6z3gpDVU9Hu7TXAhsutpLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=qtNBUdcbGgetYHqUb27b51udo1TjXJe3qFA4gF2kVMM=; b=B1Q+GvhIfXX2njjLRgACAvPwQbRoy47RMUFJSAlZ6RY+s+mmQjAhLd6vPAoBSEUIXFOPIOofBVKAEQAFW0cduFiXppSj2X2w4VJNho4OKL8JXTsINkAT0uUSG6Erp6L+d72lguSBnCAVja+q03DvCfPm7YEW/egwEH6zx9kJJg/0CtemteFKaIHOLRVG7uOZf5QCHjXuxZlSfHPQWWPIfqwBdNaIC78gJSBh1e1eMAF5W76HxxRfbJxOGKl55H8QIrNFJJb56NXdYYih15Kf0OOD/ijTmvfb2RKA4miwTi8rKFMAnMf48MDatCIsBlBalzIGVm8sfwth3mPyuijbJA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=qtNBUdcbGgetYHqUb27b51udo1TjXJe3qFA4gF2kVMM=; b=IaDFBGNlRAy7t9iS8ziIvebHuH3KqTJZM12+RvAWrZsCRNSofoFy7dndThlDIs9rAMGQ9DIkZHr+15sRwQ5NdVNWSLk6vSuvdA5wgtEXXg2DZktLLTvMLvI4n63ug0LLZfAYR0/CAurAaBQwOlA9sgXmjsx/g72C4e4YQ2jaD7Q= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB7056.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:200::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:18 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:18 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:14 +0100 Subject: [PATCH v3 06/16] rust: io: register: allow explicit base type specification Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-6-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=8478; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=BW8Pipu9gMJAyQKlc26RqfQ2wmugHrBod8hkXoCWiys=; b=x3ccwaV/CjmSIMrbYLibNmqdYxyP+CFFg91Gyjg59igKm8Kw/9ZyUgAw7Xt85GHf6a4sBQ8ip 8cAOjS7trSzARESi3XBRrdkYjXdesVHF9EFwbZGy31l9kT9/fBPXcMK X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB7056:EE_ X-MS-Office365-Filtering-Correlation-Id: a6603e59-4c38-4bc7-6fd7-08defde27429 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|10070799003|1800799024|7416014|366016|23010399003|10067099003|56012099006|22082099003|18002099003|921020; X-Microsoft-Antispam-Message-Info: SVwkS6xdY8EbMS90c7ePoBtINdtCZAYX7+s18lGqWLOb5ComkHCyGMkIhRs9odPY20NcXSBc6AH4tu5xvUrDRVoX4x+6+YmOnRW1uJ42ZPiNxWe8Z/8FIv3cY9WEOxn2iysfaClmrPT30qYF4UfTv9w9r+7VC3sXqOlw+Cr7TjYSyNv4gxyRgo9DBuAJkoAtnjpzOg7KIlj7w4buY1+yfvcKyCUeJRmBtZ9pkgUAQt1AEcWf2tWhSmful8meFUONbix6DfIulY5aPqw2Y3FB7fkYKfgbLoIlr4lE1899ZcTgQzRx8vDgdGIeB8Etv6thvoZI1vpWs9p9L8Ne19sWieGxzyVM8nJNFQ7hz6kp9nFimD7Ls/D0wLIxU0sdQOeO3GQXnAyZYY1AlC8oJiBkHInIRDF/PJDnO4Hpze1eGwIRyTy3G8CvrWEXfGbezblSpuQTEHPvu1GJrwYCiiAELuKe5/8ouLAezkIhnIyOWyPwujmkrnYU64mbpe904YvdkqsM6Suq7UoxxEcunJgdgg7D5jtMg27bV30isGrljSPUyCsqG8SGx4bSFdiJ2A9mz6G9f2iFQSxtK8c9gV2umhOKDznnFNqhl4uimU5ETq1Fb8uvrd8fVQkrAH/MwOUBSgXPTrpmZCaICIzoQ+k8bydxKBL6JorVqaFSRwNFcTI/1s3JMYUi2y9gBR5Rh0URUThzY+XXg4luehqoxikyyg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(10070799003)(1800799024)(7416014)(366016)(23010399003)(10067099003)(56012099006)(22082099003)(18002099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?MXRZMDBBcUpXNU54ZmhYM0JjM0YrM2ZOVldQTzV3bHZzK3Q4L0JLM011VWFi?= =?utf-8?B?cU9DUmp4VGlDYUtwdkIyL0lnMy9pbXE4bEtnUnVHRGovMStGZE0wbjlUSUpG?= =?utf-8?B?TEtEbU1GNHhhVDA5WXB5SjFWZWRyVmtPeFBnYkxGTFJmZFcwdS81TXpja1N5?= =?utf-8?B?Z21yaHJOK1BueFNhT2p4bG96dzV2OVlJVnQrZk1KTDFRbU95cFNySHlmMG9R?= =?utf-8?B?Nk5jdzgvL1p3TXZ3ZHh1MTJUVEVDb2pHbTVqRVVZT2xhYnlBMGVxRnp2TklS?= =?utf-8?B?M1RIS3VyUFlKeEl6d2xKVi9VQzd0YUtxY1RLcTR4eStnR3U0N3k1OFNLZzNT?= =?utf-8?B?aTJITC9xYWdZRDBqTWRWcW1kY0kyV1hhT3dQT2gyeHlRVjVsNWQxL0d6SGZK?= =?utf-8?B?bW5UMHc2RjJOUk43YjhRM2dZOU8rOTdMcktKM1JBQVRySHNTT2gvWHpDazd6?= =?utf-8?B?UGRSK1FJYTBFRTlnblJTM21FQllxQU5vemIzR1F3eCt5UFUwWllXSEJrRDdz?= =?utf-8?B?ZUVybjhla252OHZOUjBZRSt5cnFaa0JBVlJDQ0doN0diV3FTMXhOVGJCeTNI?= =?utf-8?B?YjMycXpEOFlzbFlJVW82NElMWXpXVTJlUCt1MlUzOVRuNUh2WlZFUkNEdGRu?= =?utf-8?B?SmxEY216ZmhhR2d0azBDdmhKQnk1dERZSlRQL2dSOU02aC9KQ0Y1SzhGRDJU?= =?utf-8?B?L0UxL20zaHZEY1VaTnJPVGpaUStlQnM2WFBqVFo3enBwT3NkKzlrSVo3Rmhl?= =?utf-8?B?ZzdFanNCME9QZ3JlZ0krTllML3NCa1lveVB5YWZCWHArbmZ3NXFlSzhaQUNk?= =?utf-8?B?QmJTaDEvQlQ1dDU3QlZvMFh4MDl0K0JBZHAyZnl5RTZuYkR0WFlyT3FmVmM4?= =?utf-8?B?MmhxRmhJVDYwVHpwSGxXK1FUQWhWdWtMYjVyL0kvME8zTVo3S1Z5VlkxTW9t?= =?utf-8?B?US9od21WbHlGdjZDQW4xSnVMam94ZTFlRlR4YXhLSE1WYUZadmZXKy9zNDJo?= =?utf-8?B?dnQwNVFCaDIva2ZtYTZnQ09hRnQxcEdsZjZLSWJxaXZoWko5RFZsblZmbVRM?= =?utf-8?B?KzJxU21xcElZc2RGdlRkU2FuSXUrTDNQRFFKbmtzUDVteDU2NC9QLzVrcXBk?= =?utf-8?B?Q1k1UnNyc0xwSDBqQnB0Yy9UM2xHNFlsR0VJWkppa2FtRlpac1pqcTAwVSt3?= =?utf-8?B?N1g4OHhyTjIrSkI4NnlUalZIQ0xYdlk3bFhIek1ic2xqcE1PdUZqbXY2WXpK?= =?utf-8?B?ZUl4U3NPZGplek1lUGtsL1NMM2dtcHpYSUJFeThzZE10anFqR2lkTWtLVkoz?= =?utf-8?B?c3VJeFQ3elkyemg3b21WaEEyckV2a0w2Y2NHOWNYdWlER2lXNzQ4QmJ3TFps?= =?utf-8?B?K280eFZpTVVrQ29rZ2pUSDFPM1ZEVmpFVHFOeEUyQlZhTXM3VmJZZG9OcDNI?= =?utf-8?B?MEIrQWRWRjg2cFBxMzlTSGt3WnBEQVBQS045S1kxZWtrcDNCdHlOb0dTanJ4?= =?utf-8?B?RGFqTXNxVjFmdTVpN1A2VStpZ05TWjJhYnV4ekRXQTcxS05hbVhibzZBQkdF?= =?utf-8?B?MGVUVTZFS2hueDhadkdubVl0QjZzdEdsbU42c2duMzYwTkZ4T0xmZStxTmRp?= =?utf-8?B?TjR0d1JSaGh6OG9vUmp6UklyVFNWdTM1ZGNNa2MranZhZ2x3UVh2REhJS3po?= =?utf-8?B?a1JQK2VCWFQ2U0ZpVVE4WVYyUkJmd2p4ZHY1OExBb0FCSUduQmJsOWhaSHJG?= =?utf-8?B?V2JBSXRwTHZpYXhBVllRaW9nWXcrcEpEWUkvWTcxcjVEVTJvYTliakhJZjNC?= =?utf-8?B?eWJSVDROYTh0Ui9ZamN2c2VUMkxJSzdOc0ZCOE5jVEZLVy9SdkQ5VHJNRjFM?= =?utf-8?B?UWRsSTRhNzk2WHkySTBReHBIYzQyaFhBY2luOXdJMVFzNVo2YlRacWxweVpq?= =?utf-8?B?dTJMblk5VkR5b3BzSldBaFhLTmkwMnQxVytPbnFKdmxxdzlNQis4VktCTG1w?= =?utf-8?B?S2dOLzFpbEdwTm5jdHdDT2ppY2ZrSjJMMS9ZTm5jR2tmWEt5ZERZSU1hOEFN?= =?utf-8?B?OFZCYmlodkJxbkgwQ2NhTDRqNE9ZZ0ZjMnJRQTZKUmJvQlJET05objN2Mklh?= =?utf-8?B?Sk5hek4rZWtwb0VqYlAxaE9ROFd6NDkyaUFEcWlZV0FlSEhMallmVXBNR1E0?= =?utf-8?B?bkJWRVZLZmdzUzRiRHAzRm44eE5xUzE0M1BrVXZqMmdHVzUrOW9TRG5iRFQ0?= =?utf-8?B?UTF2SGVCNXdtZGh3UDNna05EQ0Fqai93VFhyekJ2Z1M2cDlVMXF5cmQvYzA1?= =?utf-8?B?b0N5dGpXUGFTTEQzcC9nTFMrdHJWRkxuU2xUUGNBbGtoYWNzdERIdz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: a6603e59-4c38-4bc7-6fd7-08defde27429 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:18.7427 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: IeGfWNwOZ837SR554l18lYkNwx5/gjTeYgY7/GjszmXraVXNQbaKqtkOVEIjQHHQK+Yu+akrCGGfvevMD6ZMmw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB7056 Currently registers work for all untyped I/O regions, which is not ideal. It allows registers defined for device A to work for another device B and there is no safeguarding at all. All users of the `register!` macro know what type it will be operating on, and that type is consistent across the driver. Therefore, add a `base` parameter to `register!`. Currently this parameter is unused in the generated code; it will be used when all users of `register!` is converted to gain the parameter. Signed-off-by: Gary Guo --- rust/kernel/io.rs | 4 ++++ rust/kernel/io/register.rs | 51 +++++++++++++++++++++++++++++++++++++++---= ---- rust/macros/io/register.rs | 13 +++++++++++- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index ea072c098b13..84dd876b3407 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -916,6 +916,8 @@ fn try_write(self, location: L, value: T) -> Resu= lt /// }; /// /// register! { + /// base: Region; + /// /// VERSION(u32) @ 0x100 { /// 15:8 major; /// 7:0 minor; @@ -1058,6 +1060,8 @@ fn write(self, location: L, value: T) /// }; /// /// register! { + /// base: Region<0x1000>; + /// /// VERSION(u32) @ 0x100 { /// 15:8 major; /// 7:0 minor; diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 45d2e73a92e7..49a5fe069e47 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -13,9 +13,14 @@ //! # Simple example //! //! ```no_run -//! use kernel::io::register; +//! use kernel::io::{ +//! register, +//! Region, +//! }; //! //! register! { +//! base: Region<0x1000>; +//! //! /// Basic information about the chip. //! pub BOOT_0(u32) @ 0x00000100 { //! /// Vendor ID. @@ -55,11 +60,14 @@ //! register, //! Io, //! IoLoc, +//! Region, //! }, //! num::Bounded, //! }; -//! # use kernel::io::{Mmio, Region}; +//! # use kernel::io::Mmio; //! # register! { +//! # base: Region<0x1000>; +//! # //! # pub BOOT_0(u32) @ 0x00000100 { //! # 15:8 vendor_id; //! # 7:4 major_revision; @@ -429,11 +437,14 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// io::{ /// register, /// Io, +/// Region, /// }, /// }; -/// # use kernel::io::{Mmio, Region}; +/// # use kernel::io::Mmio; /// /// register! { +/// base: Region<0x1000>; +/// /// FIXED_REG(u32) @ 0x100 { /// 15:8 high_byte; /// 7:0 low_byte; @@ -464,9 +475,14 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// the context: /// /// ```no_run -/// use kernel::io::register; +/// use kernel::io::{ +/// register, +/// Region, +/// }; /// /// register! { +/// base: Region<0x1000>; +/// /// /// Scratch register. /// pub SCRATCH(u32) @ 0x00000200 { /// 31:0 value; @@ -516,6 +532,7 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// /// ```ignore /// register! { +/// ... /// pub RELATIVE_REG(u32) @ Base + 0x80 { /// ... /// } @@ -542,9 +559,10 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// WithBase, /// }, /// Io, +/// Region, /// }, /// }; -/// # use kernel::io::{Mmio, Region}; +/// # use kernel::io::Mmio; /// /// // Type used to identify the base. /// pub struct CpuCtlBase; @@ -563,6 +581,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// /// // This makes `CPU_CTL` accessible from all implementors of `RegisterB= ase`. /// register! { +/// base: Region<0x1000>; +/// /// /// CPU core control. /// pub CPU_CTL(u32) @ CpuCtlBase + 0x10 { /// 0:0 start; @@ -579,6 +599,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// /// // Aliases can also be defined for relative register. /// register! { +/// base: Region<0x1000>; +/// /// /// Alias to CPU core control. /// pub CPU_CTL_ALIAS(u32) =3D> CpuCtlBase + CPU_CTL { /// /// Start the aliased CPU core. @@ -621,15 +643,18 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// register, /// register::Array, /// Io, +/// Region, /// }, /// }; -/// # use kernel::io::{Mmio, Region}; +/// # use kernel::io::Mmio; /// # fn get_scratch_idx() -> usize { /// # 0x15 /// # } /// /// // Array of 64 consecutive registers with the same layout starting at = offset `0x80`. /// register! { +/// base: Region<0x1000>; +/// /// /// Scratch registers. /// pub SCRATCH(u32)[64] @ 0x00000080 { /// 31:0 value; @@ -655,6 +680,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// // Alias to a specific register in an array. /// // Here `SCRATCH[8]` is used to convey the firmware exit code. /// register! { +/// base: Region<0x1000>; +/// /// /// Firmware exit status code. /// pub FIRMWARE_STATUS(u32) =3D> SCRATCH[8] { /// 7:0 status; @@ -667,6 +694,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// // Here, each of the 16 registers of the array is separated by 8 bytes= , meaning that the /// // registers of the two declarations below are interleaved. /// register! { +/// base: Region<0x1000>; +/// /// /// Scratch registers bank 0. /// pub SCRATCH_INTERLEAVED_0(u32)[16, stride =3D 8] @ 0x000000c0 { /// 31:0 value; @@ -688,6 +717,7 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// /// ```ignore /// register! { +/// ... /// pub RELATIVE_REGISTER_ARRAY(u8)[10, stride =3D 4] @ Base + 0x100 { /// ... /// } @@ -707,9 +737,10 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// WithBase, /// }, /// Io, +/// Region, /// }, /// }; -/// # use kernel::io::{Mmio, Region}; +/// # use kernel::io::Mmio; /// # fn get_scratch_idx() -> usize { /// # 0x15 /// # } @@ -731,6 +762,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// /// // 64 per-cpu scratch registers, arranged as a contiguous array. /// register! { +/// base: Region<0x1000>; +/// /// /// Per-CPU scratch registers. /// pub CPU_SCRATCH(u32)[64] @ CpuCtlBase + 0x00000080 { /// 31:0 value; @@ -758,6 +791,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// /// // Alias to `SCRATCH[8]` used to convey the firmware exit code. /// register! { +/// base: Region<0x1000>; +/// /// /// Per-CPU firmware exit status code. /// pub CPU_FIRMWARE_STATUS(u32) =3D> CpuCtlBase + CPU_SCRATCH[8] { /// 7:0 status; @@ -768,6 +803,8 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// // Here, each of the 16 registers of the array is separated by 8 bytes= , meaning that the /// // registers of the two declarations below are interleaved. /// register! { +/// base: Region<0x1000>; +/// /// /// Scratch registers bank 0. /// pub CPU_SCRATCH_INTERLEAVED_0(u32)[16, stride =3D 8] @ CpuCtlBase = + 0x00000d00 { /// 31:0 value; diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index 8af12caa964b..2fb48e1be82d 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -27,6 +27,7 @@ }; =20 mod kw { + syn::custom_keyword!(base); syn::custom_keyword!(stride); } =20 @@ -139,16 +140,26 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Resul= t { } =20 pub(crate) struct RegDef { + base: Option, regs: Vec, } =20 impl Parse for RegDef { fn parse(input: syn::parse::ParseStream<'_>) -> Result { + let base =3D if input.peek(kw::base) { + let _: kw::base =3D input.parse()?; + let _: Token![:] =3D input.parse()?; + let base =3D input.parse()?; + let _: Token![;] =3D input.parse()?; + Some(base) + } else { + None + }; let mut regs =3D Vec::new(); while !input.is_empty() { regs.push(input.parse()?); } - Ok(RegDef { regs }) + Ok(RegDef { base, regs }) } } =20 --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021087.outbound.protection.outlook.com [52.101.95.87]) (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 1C70445D5E8; Wed, 19 Aug 2026 11:10:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.87 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137834; cv=fail; b=nQHJspifU7BqwJRpeNQudWZ7RWSL5WJh327a6H61yBMn6zP6UoYh5ccjlUwKblq0MDET++5FidiouWlkzruKt5SBhD2+i0lS33SuBJDiJaa0cWOqGil0hxE+aQA7ZzrsCq7oVsZmhLa3GQ/N/j4UNQS45pNJ4/HHt9Gq/H+SR78= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137834; c=relaxed/simple; bh=EA8nt8Iv5DnadzaZ1L833fTrj6susiTu+zZOLANPB2A=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=qmcafWXZAdfjk8MkIgfRru0xdT3cpIy9NJsVkQAr7VhmzLpxXlfpIkK2syFXaJnjTdDNvtpgI8JmDZrrAnZVArrWLpnzFf/E+5hgj/dToDR7zjhNw9KFnPg9p5UDcJGngxFnPX8jBKtLnT05Q/FRiBazTtVRTZZKAoLeUas5A6U= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=D/vlFjbg; arc=fail smtp.client-ip=52.101.95.87 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="D/vlFjbg" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Vx7IIfosOm+s60SPvu5v/hUovVbU8s+miUbjGMs18Cx0+tjEz+iuT0bNbtyMxIL1RqYZN73RmkWgjMa+RwlUt5B2W0vm9Lx+2BxD1953G3FBsV4bD9meaus3HAAXiFkYXrQtozPZaxiXKgCqNV5OA/WEbfDZc6NYlnrAlo5dKb6ccZJYwTXrgYsXPEkkXsBTVe0BXG0MNIvEKV/8FBSLzy44i+1BQaV/E6IYOKZFHd3Z5IroY7RDPEh3TWmJquIN0FuME2w8eam4q0Eq/GTysADu5abgUDrBFIRcmqonbsRzIx9f/LolI8GYSkuslKhRjH3ognFW1nTwb20eN5piPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Hb082skm67h44ihoTj0EfK5v+N6cUhum6FfNDFPKiGo=; b=RdfrXEXzbVNNyl6geTDFUM0BbTGnsnrEtSzLzrnAHJ3W95aatpd9Gml0KWhiF5Jfj6kpalRGoJMREF8OG0YRudqP2TrqGHtxCUyoE3m0dGLGIGNRVdC46bqhOeUOyQD/cxmXqy6UElVyFmdm4vos4sYCfoP8fSaXSe0Y07UjD+qyrjF+TVNqr6I7M68hkNaO4iD/ZkYwPKkg2k/GRFRXfqs5ozIYbGuyQigrdwZILiyU9aIoaHAY2Vw/DLHpgfxHaLt0FtGyTUyiFfEUcNHHRyXnfMLkclxkQIByJrQ8N78ALddr+SUxMpB1ApbnPkrmPmjptMd1pWQpxqXLiP4Dyg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Hb082skm67h44ihoTj0EfK5v+N6cUhum6FfNDFPKiGo=; b=D/vlFjbgquGHAa2pkz1YLMdB3R4fxQYcdTRYeBX2jyomtSAYkuyFFjegEj724vgq83BzRbFVxdof9SQSZ+aBdlG1W25u3CeMtTcJCh6DUkvArQd4Bah0Zlk6TvnGfnujyWTjdBQohxV2QBmjQjyVWd/ZTNw40PwrNwPJxiyj6BI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB7056.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:200::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:19 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:19 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:15 +0100 Subject: [PATCH v3 07/16] gpu: nova-core: specify base type for registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-7-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=8925; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=EA8nt8Iv5DnadzaZ1L833fTrj6susiTu+zZOLANPB2A=; b=YznlK0ObFWYzJ8n9slKdL9huS5iGINAwRO5Id2ZHomIFVJ6OKPGKASHHTW5Mg3fb+jxI+cO0v Ep1TBlQXRlaAA2WZGE1sD/tLFnGewjM+cOhZCycCghFzELuRpMjdBtj X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB7056:EE_ X-MS-Office365-Filtering-Correlation-Id: 9ea6ada8-1398-4d5f-4cf9-08defde27488 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|10070799003|1800799024|7416014|366016|23010399003|10067099003|56012099006|22082099003|18002099003|921020; X-Microsoft-Antispam-Message-Info: V1J9RhJ/XkWh9Muact+97+H2j5ABneLsTeh+AuwqyL0AKYVVbn4yVoGuFwcyVfZk4npMPbglZe4EwDeVirurnH+yt7iLdzRArVvKUgezVOLeOsuGmC7lydQNePY/rGsx/HgWE2vlCHWvgS81ra2kFjNQJPqVsGTAMP94l19Pp3ROt5LJf35o+hCzel29XVQJ9pzxfMCqcL4uw+fOcajWPqB3IuRn17b2Mboez6lPOa1DBo3or6LYripH7bgku2mmyfoNxEIMmzLr3Gtpnid+Eh5j5WqFMTB3QLR6XKIHAy3Kos/I2KEdR35XK9qTJDAoHkMoLY9Xs5+ttA4CHT6LQbRg/XDbMO57tZIqxq2b52n3bQiMt0MzN3KPC8nJBPrQR5cxsPRQQqAdQh9f06Eyv3e5O82S6ud4/uzZfOIoLi31zqw6CpWehHl5OwjDSnUcv3plCQcyUBDxq5MQjTyKKceUDVgfyS7x36UgqT0hXeZ5URjW1qNcJJVXKGRSbSMcOMBT8FchrzLXSLFBKby2gel/Zhg//JQFpQDxHcl2Xdv5o5qH46IwlRTm1VdEqdzShmZm8nyQNu4Mw6323HgOoExkBLHV6qtuLF/9nZ+2hc7rnYQoc4US61tUKwOxEtN1MySnUeI0PdB+SIWT+fmR2r4yvGjU1yXLSsNztoJikq9j/dw5JkCs8ToHKOjfLwyb6z/UIyyYvG+TTLuRgEc8wQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(10070799003)(1800799024)(7416014)(366016)(23010399003)(10067099003)(56012099006)(22082099003)(18002099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?R0F0dmhRZXN4eWN5MTNpUkJtQlpOanlEMlR2OXd3alhrdUpsT3BObVJ3RnlC?= =?utf-8?B?dGxiTWhQbG9VTWdYeWZnODJ5cWlCTlMxMjFWSmRGY0dKRTAyMkFFc3dhemNP?= =?utf-8?B?NEVUTng5U0Fic2VGQkpqWUtiTlQ5cjVVcU1DdlZNUDVpOU5paEtTNnFDVkpt?= =?utf-8?B?c0RZeVA5YlFia1pEeHZHbnZEMllVWGs2WkxFWlBUT05MTXZqTHRMc3RrTW5S?= =?utf-8?B?b0JZSWY5S1I3YlRxNGVCYmdQMDNzWXc4VC9qTHRmeTU1ZkZTZy9NNDJyclFa?= =?utf-8?B?K0Q1Vm1ORlRvbVNxTmdwMGtSYTVtSkNQRFNmZGtGUFhUOUhmT0hWQmZGSUJQ?= =?utf-8?B?aTNVaXRydVN2UnVHRjNrRHNmNU16UGFPSjdXK2pWeldTK1JJd2NvTm1lUzY5?= =?utf-8?B?VTlyditydEkxVVN0bmJGcFpvQXRmUFQ3cFFTR0NwZ2xxazZEV1NVWUFocU91?= =?utf-8?B?Ukkwd2V4T015WDJlSjZZblN0bU02ZVR1LzhHSVo4YW8zY0oyNVY4M0k5bGE1?= =?utf-8?B?N0MrN0FwWVV1cjRMZHl4LzRuZmN1YXJ5NE5tYXFFNS8vZmhkdlpCY2poeUM2?= =?utf-8?B?Y2MxWGtBczd0ampURzZwaXExRVl5a0dOem9pekFGZG5GcmFTV0Z5WDlhbFhj?= =?utf-8?B?YkVlWGdYeGtTRlBvTlJidWJlVWY1a245RVB1eCt6NVNwNTJOb29tU2pFOWU4?= =?utf-8?B?NzgwUmdZMHFUWDFqWWFPRGdRTmk5Z0dyUXdtQ1lsNEtCdXFPaGJXVzhvbWpE?= =?utf-8?B?ZlUwYXlZRGIrVkVLQjZTa1ZQWC9taVkrL0VrbFpKdy9hREJQN1Q0OXUrb3dE?= =?utf-8?B?NERCeVVITjdlLytXM0xtcGtNMjJZeDdlR3YzSjU1Nkl5NzllYmlXSzFHdUZ6?= =?utf-8?B?UWtnL24ydGVjOEtYYTk1MkU3bkpwK0pHUGI5WnYrNXh1WW9OSThacEZrbi9t?= =?utf-8?B?R3Nncm5mMW5CL0VTbG1zNzV0Umh6OEJOR1ZkQ0V4Q1NPSkdPR0VuVnV5dTVW?= =?utf-8?B?dzYwS3VuLzhIQ2hETjBnR1ZObFZYQVRESEZQL3hGWUhTTk1UYURVZ3NTOTVp?= =?utf-8?B?UUxvdE1NSnc3Mk9WOUdhdUp2VG1BNEtkYTdML3hWR2VINGhTYzQwczJjZm1L?= =?utf-8?B?bDU4Z3lWY2pDMVQ1ZXlaQ1N2QW9TRENsZ3g1VkM1Yk9oVXF6Z0RHQmhqUEll?= =?utf-8?B?YWFNc1I1REd4R0lZRURWSXhtL2ZDWkg3WnlWT3FwcUZ6Zkd6Wk9KV0llL2l1?= =?utf-8?B?VG5SbklkRG11blJYekY0c0dSd2M0VysrdEovdlZaQ3ZieEJ1djJVelBvZWRZ?= =?utf-8?B?MDZybStuNVRpRFNFTnVRaE54Y1RGSFNEYko0REcycU9Na2JobVJvNTFRMzYw?= =?utf-8?B?ZmtxZHpMUk1zWGpkd2IvWlc0NFlYWmdhSjFoMmVJYmlCb0p5aXdzekpKaExZ?= =?utf-8?B?aEdSNGhZL1VTeTMyZEF4NG5oYkNLWjRQN3pCQzBVQUtaaUxsWnp4SFB1Vkl2?= =?utf-8?B?L3BTVXBvSDgrTHB6Y0hLTEsvRE1TclBKZjBwekF5bGFLRVR5RmFlUnNvSEts?= =?utf-8?B?OUlXSjRIYkNxU3BUSVhwb0hJaGlMVEtVTnc4UkxRYk1mZHVna2hnMVdwZHcy?= =?utf-8?B?WFhTS3dCT29MTDRmay9IZVpjUjZzVnJ3b0xONGxlbDNPKzlRamd0MlVQUmtM?= =?utf-8?B?M0VJWThGRXVjVUNldEdGdzJMTnZRUzZmMWhra3g1VDB3Z0I0S0tNV3RsZmtD?= =?utf-8?B?UjhGZUJJaUJKWklpZThCSkJQZzkwNDM1azJpMm1vemlmSk5hQ3RQQjlQa1FI?= =?utf-8?B?SnNYb01GV1lYMTBLOEtzWVIyMzQyRGtsa21XT2xZUC80YlU4MWxTVHZ4aVY5?= =?utf-8?B?aFJ2QloyN0R4MnJDdnJHc1ZTV3U4Nm5wTnZ3R1JTd0djTkVpaXhrZG1sdzZB?= =?utf-8?B?VFlNYk9lOWY5eVVtdW5lb1hVTDVzYmVkYkREQzFZUmNISzVTRjJGZTFORk4x?= =?utf-8?B?N01Pbk1PU09nQzdiWDV5QWpqY05KdVJhMlhGQ0JRdUc4RzAxN2k4RHZ5SElB?= =?utf-8?B?NnNJWFEwWFNOSlJUVno2N1J3a0N5MVorN1VPWXVZc3A1NGxQeDV5ejVrY1ZK?= =?utf-8?B?WWpycHRFcTFjcm1yZFRJbmYxZWhTdzhtQ3lacG5EdUZkZUo5c1JRMy9FYzU0?= =?utf-8?B?RjRjVkZqem1nRW9ES2JBcDhVaVViMHNsZGFCNnhzYVh1V0pFOTNiUmFTWkVG?= =?utf-8?B?UXBOTnVwWk5mVE43b2ZxMjhRbjUyektjaTM1UGlaWEdXZUowZHl0TWlvTEcx?= =?utf-8?B?MTQ5RnBscHB3K0FObGpiZjZiRy9nbXVhQ2tQQ29oQ2tTRDJHVmZHQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 9ea6ada8-1398-4d5f-4cf9-08defde27488 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:19.3466 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: uCPdp72HehAt5EjxJMcnSSzWbjt3/rRZbfoU90PGHJgNRsS+KevZtGcLrS2ffcQLvHT7rMkmZPME+HDzLLWQVA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB7056 All registers use the same base type, which is `::Target`. Thus add the base parameter to `register!` invocation. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- drivers/gpu/nova-core/driver.rs | 1 + drivers/gpu/nova-core/fb/regs.rs | 12 ++++++++++++ drivers/gpu/nova-core/gsp/regs.rs | 9 ++++++++- drivers/gpu/nova-core/regs.rs | 37 +++++++++++++++++++++++++++++++++++= +- drivers/gpu/nova-core/vbios.rs | 11 ++++++++++- 5 files changed, 67 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index bbd93959e0b2..cf3534dd47d4 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -37,6 +37,7 @@ pub(crate) struct NovaCore<'bound> { const BAR0_SIZE: usize =3D SZ_16M; =20 pub(crate) type Bar0<'a> =3D &'a pci::Bar<'a, BAR0_SIZE>; +pub(crate) type NovaRegisters =3D kernel::io::Region; =20 kernel::pci_device_table!( PCI_TABLE, diff --git a/drivers/gpu/nova-core/fb/regs.rs b/drivers/gpu/nova-core/fb/re= gs.rs index 95adbe124a30..c27582e376e2 100644 --- a/drivers/gpu/nova-core/fb/regs.rs +++ b/drivers/gpu/nova-core/fb/regs.rs @@ -5,9 +5,13 @@ sizes::SizeConstants, // }; =20 +use crate::driver::NovaRegisters; + // PDISP =20 register! { + base: NovaRegisters; + pub(super) NV_PDISP_VGA_WORKSPACE_BASE(u32) @ 0x00625f04 { /// VGA workspace base address divided by 0x10000. 31:8 addr; @@ -30,6 +34,8 @@ pub(super) fn vga_workspace_addr(self) -> Option { // PFB =20 register! { + base: NovaRegisters; + /// Low bits of the physical system memory address used by the GPU to = perform sysmembar /// operations (see [`crate::fb::SysmemFlush`]). pub(super) NV_PFB_NISO_FLUSH_SYSMEM_ADDR(u32) @ 0x00100c10 { @@ -65,6 +71,8 @@ pub(super) fn vga_workspace_addr(self) -> Option { pub(super) struct Hshub0Base(()); =20 register! { + base: NovaRegisters; + // GB10x sysmem flush registers, relative to the HSHUB0 base. GB10x ro= utes sysmembar // through a primary and an EG (egress) pair that must both be program= med to the same // address. Hardware ignores bits 7:0 of each LO register. The boot pa= th uses a fixed @@ -87,6 +95,8 @@ pub(super) fn vga_workspace_addr(self) -> Option { } =20 register! { + base: NovaRegisters; + // GB20x FBHUB0 sysmem flush registers. Unlike the older // NV_PFB_NISO_FLUSH_SYSMEM_ADDR registers, which encode the address w= ith an // 8-bit right-shift, these take the raw address split into lower and = upper @@ -101,6 +111,8 @@ pub(super) fn vga_workspace_addr(self) -> Option { } =20 register! { + base: NovaRegisters; + /// Low bits of the physical system memory address used by the GPU to = perform /// sysmembar operations on Hopper. /// diff --git a/drivers/gpu/nova-core/gsp/regs.rs b/drivers/gpu/nova-core/gsp/= regs.rs index 9a48aa87e7fb..3c410d65e8e4 100644 --- a/drivers/gpu/nova-core/gsp/regs.rs +++ b/drivers/gpu/nova-core/gsp/regs.rs @@ -2,11 +2,16 @@ =20 use kernel::io::register; =20 -use crate::regs::NV_PBUS_SW_SCRATCH; +use crate::{ + driver::NovaRegisters, + regs::NV_PBUS_SW_SCRATCH, // +}; =20 // PGSP =20 register! { + base: NovaRegisters; + pub(super) NV_PGSP_QUEUE_HEAD(u32) @ 0x00110c00 { 31:0 address; } @@ -15,6 +20,8 @@ // PBUS =20 register! { + base: NovaRegisters; + /// Scratch register 0xe used as FRTS firmware error code. pub(super) NV_PBUS_SW_SCRATCH_0E_FRTS_ERR(u32) =3D> NV_PBUS_SW_SCRATCH= [0xe] { 31:16 frts_err_code; diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index caeef4d85874..1af073f3861f 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -13,7 +13,10 @@ }; =20 use crate::{ - driver::Bar0, + driver::{ + Bar0, + NovaRegisters, // + }, falcon::{ DmaTrfCmdSize, FalconCoreRev, @@ -37,6 +40,8 @@ // PMC =20 register! { + base: NovaRegisters; + /// Basic revision information about the GPU. pub(crate) NV_PMC_BOOT_0(u32) @ 0x00000000 { /// Lower bits of the architecture. @@ -108,6 +113,8 @@ fn fmt(&self, f: &mut kernel::fmt::Formatter<'_>) -> ke= rnel::fmt::Result { // PBUS =20 register! { + base: NovaRegisters; + pub(crate) NV_PBUS_SW_SCRATCH(u32)[64] @ 0x00001400 {} } =20 @@ -121,6 +128,8 @@ fn fmt(&self, f: &mut kernel::fmt::Formatter<'_>) -> ke= rnel::fmt::Result { // number. =20 register! { + base: NovaRegisters; + /// Boot Sequence Interface (BSI) register used to determine /// if GSP reload/resume has completed during the boot process. pub(crate) NV_PGC6_BSI_SECURE_SCRATCH_14(u32) @ 0x001180f8 { @@ -175,6 +184,8 @@ pub(crate) fn usable_fb_size(self) -> u64 { pub(crate) const NV_FUSE_OPT_FPF_SIZE: usize =3D 16; =20 register! { + base: NovaRegisters; + pub(crate) NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_S= IZE] @ 0x00824100 { 15:0 data =3D> u16; } @@ -191,6 +202,8 @@ pub(crate) fn usable_fb_size(self) -> u64 { // PFALCON =20 register! { + base: NovaRegisters; + pub(crate) NV_PFALCON_FALCON_IRQSCLR(u32) @ PFalconBase + 0x00000004 { 6:6 swgen0 =3D> bool; 4:4 halt =3D> bool; @@ -392,6 +405,8 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { /* PFALCON2 */ =20 register! { + base: NovaRegisters; + pub(crate) NV_PFALCON2_FALCON_MOD_SEL(u32) @ PFalcon2Base + 0x00000180= { 7:0 algo ?=3D> FalconModSelAlgo; } @@ -414,6 +429,8 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { // PRISCV =20 register! { + base: NovaRegisters; + /// RISC-V status register for debug (Turing and GA100 only). /// Reflects current RISC-V core status. pub(crate) NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS(u32) @ PFalcon2Bas= e + 0x00000240 { @@ -439,6 +456,8 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { // These registers manage falcon EMEM communication queues. =20 register! { + base: NovaRegisters; + pub(crate) NV_PFSP_QUEUE_HEAD(u32)[8] @ 0x008f2c00 { 31:0 address =3D> u32; } @@ -462,9 +481,13 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { pub(crate) mod gm107 { use kernel::io::register; =20 + use crate::driver::NovaRegisters; + // FUSE =20 register! { + base: NovaRegisters; + pub(crate) NV_FUSE_STATUS_OPT_DISPLAY(u32) @ 0x00021c04 { 0:0 display_disabled =3D> bool; } @@ -474,9 +497,13 @@ pub(crate) mod gm107 { pub(crate) mod ga100 { use kernel::io::register; =20 + use crate::driver::NovaRegisters; + // FUSE =20 register! { + base: NovaRegisters; + pub(crate) NV_FUSE_STATUS_OPT_DISPLAY(u32) @ 0x00820c04 { 0:0 display_disabled =3D> bool; } @@ -488,9 +515,13 @@ pub(crate) mod ga100 { pub(crate) mod gh100 { use kernel::io::register; =20 + use crate::driver::NovaRegisters; + // PTHERM =20 register! { + base: NovaRegisters; + pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x000200bc { 31:0 data; } @@ -505,9 +536,13 @@ pub(crate) mod gh100 { pub(crate) mod gb202 { use kernel::io::register; =20 + use crate::driver::NovaRegisters; + // PTHERM =20 register! { + base: NovaRegisters; + pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x00ad00bc { 31:0 data; } diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs index c03650ee5226..9c214b9f4dd9 100644 --- a/drivers/gpu/nova-core/vbios.rs +++ b/drivers/gpu/nova-core/vbios.rs @@ -16,7 +16,10 @@ }; =20 use crate::{ - driver::Bar0, + driver::{ + Bar0, + NovaRegisters, // + }, firmware::{ fwsec::Bcrt30Rsa3kSignature, FalconUCodeDesc, @@ -92,12 +95,16 @@ impl<'a> VbiosIterator<'a> { fn rom_offset(dev: &device::Device, bar0: Bar0<'_>) -> Result { // IFR Header in VBIOS. register! { + base: NovaRegisters; + NV_PBUS_IFR_FMT_FIXED0(u32) @ 0x300000 { 31:0 signature; } } =20 register! { + base: NovaRegisters; + NV_PBUS_IFR_FMT_FIXED1(u32) @ 0x300004 { 30:16 fixed_data_size; 15:8 version =3D> u8; @@ -105,6 +112,8 @@ fn rom_offset(dev: &device::Device, bar0: Bar0<'_>) -> = Result { } =20 register! { + base: NovaRegisters; + NV_PBUS_IFR_FMT_FIXED2(u32) @ 0x300008 { 19:0 total_data_size; } --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021087.outbound.protection.outlook.com [52.101.95.87]) (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 6FEE7469841; Wed, 19 Aug 2026 11:10:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.87 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137842; cv=fail; b=tMkI3daoUTbggIL/hCZ+ohx1h8Nq8xGsyLYqwvsVF2MBfB0mPM5bGQNZxne/2SAsOIIRdz2Sv7/sYI8hxqWxEKLQIO8uPDcN6BKZHdXr5wYSC1j7qUbar5wwB6YEM7ra9tpXAc4chcidJvJx+rNshytlSA7N+PzuJjZg732cBVo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137842; c=relaxed/simple; bh=nTJ7wZSeeUArV1c5w8DwZwK2ut/RdnBTX0czYVxRigA=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=jyfmI0OStBEdhiCAFtl3R+rPKVPW7WHxsgZhT2+eOVr3qHJnR8U4j8jkzMFL5vmp8zNA9w2tCFAYstA8Q/fEfR7t6+Qsj86326a8UTh4yiPWxW19pCMZEDOWnT6litOb9Dy8fs35jdc+a5kaNmLLbuZyl8fdgRzECRiJXQkZPzE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=zvpxA9sC; arc=fail smtp.client-ip=52.101.95.87 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="zvpxA9sC" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=O0K5pQ19n7Uh/1PmJuPdLBbXFMSmffiNGdeeknvqhusaRKuf/smCugNtNHBWdOas/YVDLpyh0GOFgsbUTxNOcEvRc8ePdnFDqd0YBlzAGjUfDZoZomV/RShsfiEmR+Wy0X8MX5/NTWZvvFacqn7cqVB9QKWAEhnfbD9lGNKZDxhtJb55vH7WkASaYITrrBVp/PpwB91NzHTRoNlicMh1XxCY8MnhwbrnNpzU5+ndJ736cApBbMMulwdi7zJOv9Xfs7P4VHroQ282bWQ2426+ZYIUnczkdnDgwiL6ednBlIt3APy2Py7va9gspFfsjLWM2zQ1ehg+ngZ8zZSshC5LkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=NvWLye6q3T6iJdVLSyDKt2fXUAcrrEInZPcP41AR6Mo=; b=NixWIX7Nm9aqhcCEz542utUtXB1Q21hHWs1qNg6Dk+PL72v2Z+hXFrTmel7iy19NIz6g8gC1lBx7aRQtDVsCA0YKTLUmemIZ9u2tq/3RYVfGu8xr+ek6QHOsD+JIj6n5tRa4jr2aW/EDxdpOEKDOb+Hnb53rpoTf590Q9hokpdAPdY5GUyE9zqNN9T37+/jGcFk8feK3lA+74Dw6Uz6sLhLQAaDlWUhkHrEDanbMGHa74GSapji6yQxKkoFXkYi8ojWDkhWD5sE16mkerGnWGXwfJPbTeknrlp6OsJmPckDSQ0CJMTOjKn37em/H0qeY4xGDoEh77l3KVlSNAsAMbw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NvWLye6q3T6iJdVLSyDKt2fXUAcrrEInZPcP41AR6Mo=; b=zvpxA9sCxLzCkYsIhf1AQxN6ia409dYWtmnvjY/2bYovRPeSs0Ryeze+Q0XuBRzCxEHGiaW9byigYXPKLgqmx0NSHBvYwCCwM6gOrmireUn1fpqKFQgFUPmQA6vNb/fCP9FoxLeSY+F1eRJpZj0CmVJLuQwY3QdswO+RqpuqrFk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB7056.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:200::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:20 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:20 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:16 +0100 Subject: [PATCH v3 08/16] drm/tyr: specify base type for registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-8-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=7409; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=nTJ7wZSeeUArV1c5w8DwZwK2ut/RdnBTX0czYVxRigA=; b=iJK1ONYarEIyTIJLbZ224SMSZb3cRTCKvsikDgCHO7OgTY03Xm0ZSO4SPaQjhGTpHFylYvRXW IKeWmbq0VqqBHD0866ZE1nW5yIPU7rZQZUg5hC0x4Qwj3CHeISkI1gr X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB7056:EE_ X-MS-Office365-Filtering-Correlation-Id: 71b98cf0-6105-4319-1a19-08defde274e6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|10070799003|1800799024|7416014|366016|23010399003|10067099003|56012099006|6133799003|3023799007|22082099003|18002099003|921020; X-Microsoft-Antispam-Message-Info: OSuNz6ieTZElrKtj3J9Oo0wy2ehTJP+75yjXhw0Rtr7qdjgEYhTXV7KnLB3pYXyoUeEr6rmqqhsKnS0X4PWdmfPcz1eNIM8Tiho+yDVRBv3twBraYB6WUFomvB8MrMxyhB6cJ01C7jf/CFquX0vglcpGelE31X1TMlNYb0ppRf+H9vyktyIgHz2n3Qgf8b9Mz/5QgmTBOKKu8ccZOOEEXT6zKn6ngbLtwOIbUz5kJcsnAjM/nhhKM29uJX37cNVNjH3AZppJw0B4/9LJSA+/hcTpD/LMiwG9PkMWrmiwEXLhPXaxfxcb/99+pYgYBJMOaXlRhuP8dLV82Yny54G924QA53DsONJA1uU1E8dlGRBXFsLBOAWLJhrnqM/+fvy/kh4C5EL9gW2QsuyTnfN9QqnbRYO2spfj64oQm4L37PqkvdcaarMni5q3vBmhZNYdQhd98fDVMqbk6vJXs4YG0nB3JLFEt7jQaL4bOWX0xJ7qJBUXtzEPOfIdiELllk5GRk6pPCfW1TDEFY3PwO57J8sSK249ZKJ990qrPKT65Ip45lSGIIEerm3al9d7+Poz77xSDrJoNPQZL1AnBPWdOU5rsPLbdn80gTio6aiYNTLJs2ZFojz+NkoWGaNCIoLy56V5ngfRRH24PJi06EURpLIfnlhxDGp0aGz4MZw2or1YzwP+Pe8ngjfOJJ+cYKAIemt3MygxTavry2uUyKFMYQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(10070799003)(1800799024)(7416014)(366016)(23010399003)(10067099003)(56012099006)(6133799003)(3023799007)(22082099003)(18002099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?YUJZSmdCNmZEN2Vxb0tjMk1WUllGUC9WTmhMNmllUEVaelptcmREN2VEd2xL?= =?utf-8?B?NXZMZng1UmFlbk4vNWpPcHd2VFdKK1hURHVsWGFpUkx4RmJXSjJFb2tXb1Jv?= =?utf-8?B?U1JpQUtWOGwrdm1PRStWOTAvQTFWR3huVXNCbDlzWStnMWxjOTVKMnJGUGZr?= =?utf-8?B?UUdMTktuUVdkVWxmMDZ1QTV5MGJCNDB2amcxYldoT25sV1VTVkNxaWlXdjNr?= =?utf-8?B?RFp4TU1vRHpFbmxnWWZZa25yM25RUVhpWmxQSDJiczRmTkN2bWplMTR1RGxy?= =?utf-8?B?QVkrQ2hRYk9jeEVYY0VIeGd0WHpWRWpVdzRBODdGdS9EemVLUmwyTUFsMDZv?= =?utf-8?B?UnVIdlVSOGpIU1YvQzg0T1ZzVno2Wk45UUNEbTlYZ0ZzeUNDc0dQQWRsdzdl?= =?utf-8?B?MkUwSUwxL3ZYYUxvSGJjU3ZvSDNwREdUWE0zQTI2QWZhV3hRVnRGeURna3ZG?= =?utf-8?B?bWdCMmZXQUVEeVo2amZHMy85NWNtUkY0cnNuV0ZkcHAwYXNuTTZwby9FQXZ1?= =?utf-8?B?emZxMmpuQ0x3b3RvMm1HOHIvUXNEZktKcE5yaHRuWUphOHR1SUEvNy9OcEFa?= =?utf-8?B?Y2tMNmhpaVFPcEt3dm9KWUdyd0RiNys0MnU2c05BdGR0S0lNMHdkZU1HeTVL?= =?utf-8?B?S0pYQjk0czJsYmFIY2JNT3Vhc04wcHlpai9Mc3BrcXpWMHdhM3REZEFUd1oy?= =?utf-8?B?eUM4NFdwWi9WVlpnK1loTzdJMWJEYlZUL2xpaFFiUitIaW1PQXlweHpacjda?= =?utf-8?B?ckVpSndrZFE5NmkrdmtudEJrbzJkZGNLblltc2ZNK1p2Rld3bW1EbldMQitP?= =?utf-8?B?S3QzbHZhUms3b21tVys0K0xYdksxOWZDSHNDUEdmeStUN2pQNEpZNFY5eTlN?= =?utf-8?B?QmNGb0pTMDNjVVpmNVRIRXh3eFQvdTUyc01Ba1kwZE1oK0ZScU9QOFFkUWJN?= =?utf-8?B?TkR2VURDbkYvVFlxM0NVTDV6OVFSVVlHK3NpWThrc3lkS3FNQmtTNzRRR3Mx?= =?utf-8?B?TU1pdlc4NS95cjM4TllCYy9Wc0x0VWp1VUxoa01qZnI4bk5tSTlmM3ZESHY0?= =?utf-8?B?N1F3MkpmUkRYZkEyZ3Rnb2VOb0VsaTZuVE0xSkpqa2F6Q2Faem52Yng2SC9Q?= =?utf-8?B?N0NiOHpKNWhMTUlXOUpQVGpGMHh6WkVyZHFMb1BJcU1PZ09JU3ovdmFDRnpi?= =?utf-8?B?YmFNQ1VnSEJLYjN3eXhRQmlIQkJadytsZ2Y3TFVRU1p1S2FkV21TTjdtU29i?= =?utf-8?B?L2RFUVlGR04yWmp2SnFhR0hrc1l5Tkl2eXQ2YWJTQjhHUlVPRWt3TU83bjFT?= =?utf-8?B?V2dqOFE5eDNkUytJNlNZazJHdC9BTnBOOVg4ZC9qTTRjY2RYaXV6TFJBZWxj?= =?utf-8?B?Z1g4dktpd1YySml0b3U3RGZic2djZmIrN0J4MkEyTGg0dnhZbzJjbFVIU0JO?= =?utf-8?B?MHk0am1GR0ZzYiswc1lxWUhpV3l4di96dmRhVmtBVEtFTHloVkZGU2QrbUQ0?= =?utf-8?B?RFJCc2FBN0hpR1BHNWRoWHZjcmE1S0p0RUM4d2hkUGxDd2wrUWU0ck4ybWx3?= =?utf-8?B?c0VwcXgzcE01bFBXU1l2c1NMMkd3Vm1CTDlMVzd2K2llYUhEZDVaOEdWR1M0?= =?utf-8?B?VkJ6Ni9UMjNLQnU0TDNRa3ptQzlOVGtTZmZYM1VBOVQ0RjZpVWwzS3FhajhJ?= =?utf-8?B?YnNBUU5nZmxDeG9GZUhLWkxLZHVIVHphR1JnY1dNRDE0RWJTQ0dmN0JLNjNU?= =?utf-8?B?T0x6K0ZjOHY0SUtUTDE5WnlVdUU4ZEJ0QkZPZks4RVU4RHVtbnpDaDVvcWsr?= =?utf-8?B?djVDRlFic2hPeDVqMStGbmZBLzkxaEcwUWtQYUEwSWJITWg1WldORjMrTDVO?= =?utf-8?B?S2Y3M2RMWHhEbGlFY2pOOFlOSEFsWmZXYWhCS3ZaTjBwcEZuV0dlTEpKVm8w?= =?utf-8?B?L2JsT241TXNaRUp4U1ZSU0djeWE2UjBXQmlEcG1lVzJaZWMzVllYWWpsNjNy?= =?utf-8?B?dlpnRXdkSGNIVGZjcitQRUpGQlY2clJMdkdyblB6VnpRNkVtQnNXeXozaHdl?= =?utf-8?B?cHV4Z1VvK21hWVpxcE9zVi90MnpqOUM2dVIwUUVSV295OXVUWkRNSk1aQkJ5?= =?utf-8?B?UkRXYmZzL0N1YW5RSm5qSWFQcVFWSk0zM2hEUkJUT0tjZTAzelZwc0JzcFFp?= =?utf-8?B?QnJOb2ZvQTQ5M1Z3U0tlZFZpWjB2d2hERWNyQXpBbElwWkFBQmdLK3FOVjRF?= =?utf-8?B?M0pDQXpaM2RhQ3FJOVpuVGNodHg4V2hoSGdyRVNoOEVIT05janFWSFhhNDRO?= =?utf-8?B?cGF5L3ZCMGVQb1M4S2Q1bVAxTmVMNmxhYnNsNEVSMzlZUU5MeDRnQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 71b98cf0-6105-4319-1a19-08defde274e6 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:20.0270 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: SzsWuObU/rSmpqeN9bmqRpclvhJnQf5bYYS9Q0Qw4J+QotwPIlBGJVOrKcPRCOdw8TV9NazD4/6Zd+m7a268jA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB7056 All registers use the same base type, which is `::Target`. Thus add the base parameter to `register!` invocation. Signed-off-by: Gary Guo --- drivers/gpu/drm/tyr/driver.rs | 1 + drivers/gpu/drm/tyr/fw.rs | 5 ++++- drivers/gpu/drm/tyr/regs.rs | 45 +++++++++++++++++++++++++++++++++++++++= +++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs index bfb0ba19caff..730b84e37a54 100644 --- a/drivers/gpu/drm/tyr/driver.rs +++ b/drivers/gpu/drm/tyr/driver.rs @@ -46,6 +46,7 @@ }; =20 pub(crate) type IoMem<'a> =3D kernel::io::mem::IoMem<'a, SZ_2M>; +pub(crate) type TyrRegisters =3D kernel::io::Region; =20 pub(crate) struct TyrDrmDriver; =20 diff --git a/drivers/gpu/drm/tyr/fw.rs b/drivers/gpu/drm/tyr/fw.rs index 47d25c901bd0..7edb5eff1707 100644 --- a/drivers/gpu/drm/tyr/fw.rs +++ b/drivers/gpu/drm/tyr/fw.rs @@ -39,7 +39,8 @@ use crate::{ driver::{ IoMem, - TyrDrmDevice, // + TyrDrmDevice, + TyrRegisters, // }, fw::parser::{ FwParser, @@ -101,6 +102,8 @@ fn from(value: CacheMode) -> Self { } =20 register! { + base: TyrRegisters; + #[allow(non_upper_case_globals)] pub(super) SectionFlags(u32) @ 0x0 { 0:0 read =3D> bool; diff --git a/drivers/gpu/drm/tyr/regs.rs b/drivers/gpu/drm/tyr/regs.rs index a62724378ced..0c419c4e1186 100644 --- a/drivers/gpu/drm/tyr/regs.rs +++ b/drivers/gpu/drm/tyr/regs.rs @@ -57,7 +57,11 @@ pub(crate) mod gpu_control { uapi, // }; =20 + use crate::driver::TyrRegisters; + register! { + base: TyrRegisters; + /// GPU identification register. pub(crate) GPU_ID(u32) @ 0x0 { /// Status of the GPU release. @@ -315,6 +319,8 @@ fn from(mode: FlushMode) -> Self { } =20 register! { + base: TyrRegisters; + /// GPU command register. /// /// Use the constructor methods to create commands: @@ -380,6 +386,8 @@ pub(crate) fn clear_fault() -> Self { } =20 register! { + base: TyrRegisters; + /// GPU status register. Read only. pub(crate) GPU_STATUS(u32) @ 0x34 { /// GPU active, a 1-bit boolean flag. @@ -463,6 +471,8 @@ fn from(access: AccessType) -> Self { } =20 register! { + base: TyrRegisters; + /// GPU fault status register. Read only. pub(crate) GPU_FAULTSTATUS(u32) @ 0x3c { /// Exception type. @@ -768,6 +778,8 @@ fn from(mode: CoherencyMode) -> Self { } =20 register! { + base: TyrRegisters; + /// Coherency enable. An index of which coherency protocols should= be used. /// This register only selects the protocol for coherency messages= on the /// interconnect. This is not to enable or disable coherency contr= olled by MMU. @@ -808,6 +820,8 @@ fn from(mode: McuControlMode) -> Self { } =20 register! { + base: TyrRegisters; + /// MCU control. pub(crate) MCU_CONTROL(u32) @ 0x700 { /// Request MCU state change. @@ -849,6 +863,8 @@ fn from(status: McuStatus) -> Self { } =20 register! { + base: TyrRegisters; + /// MCU status. Read only. pub(crate) MCU_STATUS(u32) @ 0x704 { /// Read current state of MCU. @@ -862,7 +878,11 @@ fn from(status: McuStatus) -> Self { pub(crate) mod job_control { use kernel::register; =20 + use crate::driver::TyrRegisters; + register! { + base: TyrRegisters; + /// Raw status of job interrupts. /// /// Write to this register to trigger these interrupts. @@ -912,7 +932,11 @@ pub(crate) mod job_control { pub(crate) mod mmu_control { use kernel::register; =20 + use crate::driver::TyrRegisters; + register! { + base: TyrRegisters; + /// IRQ sources raw status. /// /// This register contains the raw unmasked interrupt sources for = MMU status and exception @@ -966,9 +990,10 @@ pub(crate) mod mmu_as_control { prelude::*, register, // }; - use pin_init::Zeroable; =20 + use crate::driver::TyrRegisters; + /// Maximum number of hardware address space slots. /// The actual number of slots available is usually lower. pub(crate) const MAX_AS: usize =3D 16; @@ -977,6 +1002,8 @@ pub(crate) mod mmu_as_control { const STRIDE: usize =3D 0x40; =20 register! { + base: TyrRegisters; + /// Translation table base address. A 64-bit pointer. /// /// This field contains the address of the top level of a tran= slation table structure. @@ -1104,6 +1131,8 @@ fn from(val: MemoryType) -> Self { } =20 register! { + base: TyrRegisters; + /// Stage 1 memory attributes (8-bit bitfield). /// /// This is not an actual register, but a bitfield definition = used by the MEMATTR @@ -1137,6 +1166,8 @@ fn from(val: MMU_MEMATTR_STAGE1) -> Self { } =20 register! { + base: TyrRegisters; + /// Memory attributes. /// /// Each address space can configure up to 8 different memory = attribute profiles. @@ -1292,6 +1323,8 @@ pub(crate) fn from_mair(mair: u64) -> Self { } =20 register! { + base: TyrRegisters; + /// Lock region address for each address space. pub(crate) LOCKADDR(u64)[MAX_AS, stride =3D STRIDE] @ 0x2410 { /// Lock region size. @@ -1353,6 +1386,8 @@ fn from(cmd: MmuCommand) -> Self { } =20 register! { + base: TyrRegisters; + /// MMU command register for each address space. Write only. pub(crate) COMMAND(u32)[MAX_AS, stride =3D STRIDE] @ 0x2418 { 7:0 command ?=3D> MmuCommand; @@ -1480,6 +1515,8 @@ fn from(access: MmuAccessType) -> Self { } =20 register! { + base: TyrRegisters; + /// Fault status register for each address space. Read only. pub(crate) FAULTSTATUS(u32)[MAX_AS, stride =3D STRIDE] @ 0x241= c { /// Exception type. @@ -1705,6 +1742,8 @@ fn from(sh: PtwShareability) -> Self { } =20 register! { + base: TyrRegisters; + /// Translation configuration and control. pub(crate) TRANSCFG(u64)[MAX_AS, stride =3D STRIDE] @ 0x2430 { /// Address space mode. @@ -1760,6 +1799,8 @@ fn from(sh: PtwShareability) -> Self { pub(crate) mod doorbell_block { use kernel::register; =20 + use crate::driver::TyrRegisters; + /// Number of doorbells available. pub(crate) const NUM_DOORBELLS: usize =3D 64; =20 @@ -1770,6 +1811,8 @@ pub(crate) mod doorbell_block { const STRIDE: usize =3D 0x10000; =20 register! { + base: TyrRegisters; + /// Doorbell request register. Write-only. pub(crate) DOORBELL(u32)[NUM_DOORBELLS, stride =3D STRIDE] @ 0x800= 00 { /// Doorbell set. Writing 1 triggers the doorbell. --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU010.outbound.protection.outlook.com (mail-ukwestazon11022139.outbound.protection.outlook.com [52.101.101.139]) (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 E2A8045D5C2; Wed, 19 Aug 2026 11:10:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.101.139 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137830; cv=fail; b=KkE8/xGV+cBX5xCpGk2Bp/+UM6M9nv2Mmfl5ugC/EnbbTVG4Ral5BFVEI3gyRH5QuYFdvO0cmJILySbCgZRkzLLL7LGt5INxbYUnVqoLNmCNklVniR8e7DC9TzsP9yu++qmrYVT0pcRAJjBgi0fQ/osrf4QyZK2WDB/osW24D/k= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137830; c=relaxed/simple; bh=4IYGZYY5yfpiRR/pq59TMlwC0IwSy825+cZG4DHMQFA=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=XrrQdeTZtqTwhuyVkXMWB7+7xNpacJZqU2dliq7BX61/WPVy3tds/BMwBr3CZ6PZN2XrBoOp9FK2U1HSwPRXJsif9GlTk7RefFEEf2p6KMNhfQWsn1I9nb4oIGYgWZoDXBw2ya/2vbbbZEAwPRoBh81t14mjNBiAnWkmiUKXb/o= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=ix9eYWNL; arc=fail smtp.client-ip=52.101.101.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="ix9eYWNL" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=qjNiQHh5kl5OjNVI3264Fhv1p9Fh4+Qra7RM7q/vCHrgPAAgoRMhQblvbIsYT4M3mZV51pb7qYyKwu6zl7k4URXV4PLVgDZk8hGV0BOIElrgh8y6eQDkFcwcg8z2hOyYr+d/Hc8j1psgWRTcHH36ZGINqvOWy3xleNf375GM74ERIgXqyPWzeUv3V+zOQGHPy2oref+khCOwCXA88e2UsyLu94yW3EZB01Ms3B5FTnVMMFe8+xZ9otO7G3NVdQyrSkjVr5WBAPH1KXDVsLx9XEiLQh3dj5J1Iwptpf73IAYxd6hULVVdg9HcvHaTHfEHSLxnxf0A6H8MEHcrlH+naA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=A4E8hmqb30t8gQ5gAenzaXPjowRjYQsuGIN7wA5UX+s=; b=X0RwiHeDiKEDyqRXi8yj05JhqLVsQ5sLMIQnnt30PG0EJixkkTjJ50YHm1+idckarbF2uM1tHa+wEbkqgeL3n26IKdQBm1z77plKWK8eX0/SkybVjtYdAfAoG45F3BCZ5mXM+9zNGTDDG5ntCRuIVacKKXkAkll9uQyMr5LWM5MZOrkAspFcgMp8pTcmjza/N4IQ5zXRJ+KMe3sfRmSCRMmKDkK1yXyRnW9O2irwKRjjRARy1/AXJ0koFV6OEKVwkXmO59sC/2UU85gm/oZWVO9VsXx0yPxZfJ3hybRiBSF0Je6bIN9luGjOkZCi/pvG+tihVdkrEGhJohJHJUbO6Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=A4E8hmqb30t8gQ5gAenzaXPjowRjYQsuGIN7wA5UX+s=; b=ix9eYWNLpGD1/+XA2DpYlJZTT9h8WYs1j/nJRLk2QZrDjFE2AV12qyQpKK+5EeTH3dDzZpSWsG2EBPXFPqwSBmdDXSfqGeF/kQMowM4BJFXjZ96bwlT9AqfgGoiYiGXIBs/gyqAiWNnqbA11XFJqOwNu5D+JsJrnduV2LzsjSa0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:20 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:20 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:17 +0100 Subject: [PATCH v3 09/16] samples: rust: pci: specify base type for registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-9-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=939; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=4IYGZYY5yfpiRR/pq59TMlwC0IwSy825+cZG4DHMQFA=; b=SuQ4v2I6hN4e3V6lBsu61hpxoWKLl/Hb0QrxJ4ZCTh8jWsH4ZFin09GKn84MPBzlScqppVD35 0p5QctW0c+zBy+DVtINeENhBGtsESZ/BtAEPps5a+FU5i2VcU0vSA4g X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 0a7741ad-0b0c-4d0e-c617-08defde27574 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|6133799003|56012099006|10067099003|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: uCTvdj5S4C8Vqee3xncLkZ+sIEMpdlUBk2wvQL0HTXc3DskcEFDwohLBtvbw7EPNhWcSokYnJ6iG1ZRuf4LucDbCed0ssKAl7zy7NIG+zvnH5hNFa4+VHkGMzZLEeXs3gRNcKwx2ZHt88/fmh89pgQslDzUnCOydZ5PLL5DpnWbcmDe1NfGFb2BTSGxXsWekJQmTbACBzmGGiKs1AS6UEKSis1C4rYxyVpgxPDJM7E66duFwoxVD3Bb72j04/7qBf9aKSVANKPTHXaTXMgOy3nQYewKu+oTkBXUBnPmVHRP/tGNhZ9NWME7PB5w3f+z8HkG9uVfxl7kJ18QkugbwhqfuPM74piOLmdUM6bRrVA8L7a1YBdfTt3W7e/q8f3997GjkiynI9DXfxFxPTTMj5nish3G4WZPRlpWhZ9IWvx9+FYKxsw+SL/6aiH/H0Zu26gOxxyQxx0zYr7GUrtWQBLsDWmKi0cLr6g3GvPLqCumcgZmIdUG797YdwRLRNUj4Rr4Ew5TEY7EWdEt1AYDTBtwVTDyAs1fGeNWZ3Ar0anGPb4YE0d8vVvKQhx8VFXtDj0+jQ+8fAjIR201Ft0n0yvKBpgbVgSJRCmtkRMqaiuK5xXxJng//6xuNjv9oB6qtyH2p/VPzE7in+Y7VcXW5brKMiCzNvhj2n/GyqhTYJKjnuDLbc0hPrD27mg2/GJvmWP8ZJryVlAqmkYwS5FS8bw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(6133799003)(56012099006)(10067099003)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?OVd2M1ZGRnZKMmY2eWZlWjJqTDVxdzR4aFV1dDBZTnA3NmhzaDZpWDZRY3NE?= =?utf-8?B?SndaeUtldVk1Nm1ZL1N2dUJEajVlM3NyOXp2eEZvSFFwK3ovTWhuV3hoYWFm?= =?utf-8?B?UU4wZXM3ekhzY2Z4OVp3blNVS1hRaWw2TnBzWll5VzRiNnFNcVVoRmU2cmxt?= =?utf-8?B?TGVDb1FtcVZRNjg0WUdPWkFPNzBwWGdzTVNaeUZtQjR2RDE1THVxWm1LZHdv?= =?utf-8?B?UWhFb0NsUlQ1b010aitQZGVkRnhSQVk4TElYT2xPbHBza1lYYjRybi9TMTYy?= =?utf-8?B?T3pQaXBMQ0YwUFBRbWRLTlZpMWd4TTFnYlJVcVpWOGZuOS9TeFBSQldta1pl?= =?utf-8?B?TlF5aVUrZmp0K2tQSnhuZ0xGR21yVDRvZWVyODRIeVRDZ1BLMngvdFEwYVIv?= =?utf-8?B?YjIwT0lUMWE5T0ZYVkw2S080R0djbWZmMElzUzlvUUV2RmxKYmFJeVJCWUho?= =?utf-8?B?WUpTQUtoVWNiUnIxSDZnaGZ5ZElGaHRjNmpJWmxoYmthSk54Rjl2azNLSStz?= =?utf-8?B?cEp5clNvK216dHAyK2lVNVVjS3psZXovRk43bFp2NEVmUG52Qm5NM3ZHeVVz?= =?utf-8?B?VHZnVGRsc2UrK25OMDFyNk82RmpNV1JJY2g2OENDRDByM01Ud2pBS3ZIR2hU?= =?utf-8?B?QzhRWTNNQ3FhbC9SMWlZeW9mNFhGTFJDS2dRVlV2dS9KUUVybkNuRHZVWk9v?= =?utf-8?B?emFLaXkzSFBRODk2S0tkcitKMFFUZkhBQ1ZyUGpSY1Vjb1VQaXdSbDVjSWVs?= =?utf-8?B?SXFBRFFjYUNFK2QveWRHNmpDWTJzajI3L3dMV0NwLzl2OVg3eGxFVWFLTU5n?= =?utf-8?B?RDZHQTRFb216YjF5S3h4b016eEFrRUEzYjBxeEdwbE1DM3ZJVHVRMDEyRk96?= =?utf-8?B?UUJhTG4vQ0hFUDBmejlTTGthTkl5VXRFN0FhUTlkLzViSExqWEdqK0NLOVZK?= =?utf-8?B?WDcyc0ZFaUtMR0RFM1IrVis4alBiQlVkRDgvUUFaQ1FNTjk5cmJnZnhFVXZD?= =?utf-8?B?ZHBiQ1J3WGpxL1FvUUZxVHBNTVZuQ3p5UHd0UkhxdWNHVnJJU3Nvb05uWm5X?= =?utf-8?B?OEZ2TWFHNnRGVE9IY3pjTUVudnNpSHI3bkY1SjVOWkhSUzhyb0JYZVdsbU9V?= =?utf-8?B?bEdQRittYkpnY0g2WDMyZHVCai82MDZnNHkxNFg4aDdna0xzSEhzY0lmS3pW?= =?utf-8?B?V1ZmWG5lU0FyN2FQTWlRUlZVaEtGRXBpWUhiTmM2cFlXWkhWeVZLYXRqdWE0?= =?utf-8?B?bFBXMFVXc01mbE5DT01UUHJWd25VQUpSM2hqekxnQUFRRmZscS8wUTJRcU9X?= =?utf-8?B?UFRlQi95U21qNERrUk9JMm9KTTJYcFJJbm1hTDdKVFJpUFRINDZrdnd4RlJB?= =?utf-8?B?VUx5N29SYXgwYU1CR1hORW0rbVV1MmRpalg3dHZhYXBYVGxvRFEvVklNQ0lC?= =?utf-8?B?T2FtRlJZcS95eTdDOTFSSFlVSXFmSno0WGgwRHhJMGJuYnloNnpKdDJZUy9T?= =?utf-8?B?T3BNVHB6ZUgrYjJwbWZoMXBRN3c4Si9ObzRoMVZEN3c0dWk3QWsySDBKalZN?= =?utf-8?B?ZzEzYXZVVkFMRmRpS0dxcUdGRThOSmdaOEJ6MUUrOE5EdUZiUVZROWdjZlg2?= =?utf-8?B?dWxoUWx5MXExNHhGMGtnYURlL3p2Yk9nNDVydkdybER6SHExSDVnaFA2YWZr?= =?utf-8?B?cXZqL2hWSHdkdVRVOWdFcW1uMkxEbTZRaHg0MmhOSG5jSWhtWmtYMjgxT2ln?= =?utf-8?B?aWdoS3BvZzF6TzRTYzZ6Q3RSaTR0aTRFR01kOEdkalcvcmlNTDFFeWdkc0ZU?= =?utf-8?B?S2x2ZWpOeFo5K1F6QUR6Umo3VS9MVGZrR2FLN0xLeUhQT0ltaTJaTktOVjky?= =?utf-8?B?TUliVzBrQ1RUS3kvcHE1SFRSWmo5Zzgwc2NSbU00bHQrK3RBVzFyNTdzM2Q4?= =?utf-8?B?YkRpQ216TE9IMzE2b1VMUm9RYnFuNllseVFCYzdRVlJZQ0l5bUUvZUdSdmdQ?= =?utf-8?B?cERFWSsvSnMyK2NNeE1XR2I1YVBQa0R0L2ROUzd2Smc2a3EvVWlPeXlYOCtC?= =?utf-8?B?aHB3aHR5WUtTZGVjbWVVckhzZUVBQ2trWWFnYkZmdEJzOU9kQi8zWGNxOGlK?= =?utf-8?B?SlpXU0Z3QXZjOWVHdUl0ZS81SXM4eWtZaUw5eGlQOU1WRnlBcTFLUGZqbzNr?= =?utf-8?B?aFQ2YlcwRVRCaCtjYUhrVGdXTU16QzBsYjdOQ1kwcGlOVU9PU21YUFpPckRl?= =?utf-8?B?SFRCYlQ5RDJwbzlTWXBBdEh1SjYrbDBkN0tIT3ZJNXFBWFZWcWF1ZktLKy9i?= =?utf-8?B?R3lwMXpraUduMWkxcDg1OWJSRUtvTnNIaGM0YlJjVGFKRXBYQ2Q1dz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 0a7741ad-0b0c-4d0e-c617-08defde27574 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:20.8932 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: T2IsmLjpTNTpeLkxOhJm1PAsM3oIbWN0Xu1gDfE3Ybyr30zdMIk2XfN7muEgQVE9k2Fxhr/+vJwpJ3PVpAFS2A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 The `register!` macro is going to require explicit base type, specify it for both `register!` usages in PCI sample driver. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- samples/rust/rust_driver_pci.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 2282191e6292..13b035a95756 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -23,6 +23,8 @@ mod regs { use super::*; =20 register! { + base: kernel::io::Region; + pub(super) TEST(u8) @ 0x0 { 7:0 index =3D> TestIndex; } @@ -102,6 +104,8 @@ fn config_space(pdev: &pci::Device) { =20 // Some PCI configuration space registers. register! { + base: pci::Normal; + VENDOR_ID(u16) @ 0x0 { 15:0 vendor_id; } --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU010.outbound.protection.outlook.com (mail-ukwestazon11022139.outbound.protection.outlook.com [52.101.101.139]) (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 3A71F4582F5; Wed, 19 Aug 2026 11:10:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.101.139 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137827; cv=fail; b=HTgEnDI4GEGOD/RVc86gncergIZPsPCUhgGpDcBAy6fYp53ewk0jO25Ayo4nLoC/D7MVHPtEpZpKWRL5Z0/UTlcYrRFshccMl+5LQl5KLYh66LmfeTVPev0dEQC4St25Z0T7983JNg2n7SWghKDYCNqckAe0Qiu2tkUWfhiKHuI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137827; c=relaxed/simple; bh=fNklDIbUzqKSWVEec0SWn3DPw8OYEFfR6ffLgTCMyYU=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=KkK0q9vK8u640fFcN89p5kB5goxu0xAd8w/LJcVKxmGiVbjD5a1FT1BkDOcJCCsNS7F9Rxqpg1IhxV6v79kwNadEMtcVR2Da+56XAmDFCrhAZGPCEeX10je2ZPs+x7TbT/pG2zSGxrAXF83lEwAxVR/OSX5YGl84s0O4paMXozA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=WONRkcjY; arc=fail smtp.client-ip=52.101.101.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="WONRkcjY" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=wVpNd674T498BF3qwmvBrflbOns4B0l1EShDa4gULoAmzFNNn7wM6FfVjw2f7M0zjVNEAmT/EqjRQvWOFcWZjWfCyB8c8HNJCq0A54bZ0pHAYxDTBYmXUdhvR5fEbLUbUYdTn46mluA442GhfqMMtgmGRtyTaz+TEpTVP1QTQgQIn4EkYg+zq/sAu8/Uvy3JrrqJnKjkCl8jGSDdx54VkDyHuCBUPcSUGHz2sJOPCA6/sVBd2uMocRjW16XYXfvk8wfHKJetx9Yi0zE4+MkO1yf3yviHZnAL/eED6rqi0LHyjRy6SLw4G+sEWOHTZmax1JyoKX9xI/dsCnMrM1LhOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=VJJU6M0wRwT05SIiqR0kX7QMTa06jMPQLqD4QL3HvJg=; b=oNRv18YeMW7siwNKFnRV1Z8+p4d5RqDGVmgtOTJy31Nbi9yGY0LaBMko3mlY0hZWUZh7dnOUus/3hBgk1jVVLscWB97g70b2t1VKKPK9vaaEYJJOhBQq1/x8bkfTcgSCd0ADc0nHcZHIBp3lX9r1NdL1dLAW7N7ftdIy2KQkUFwHgG3p3SwfP5bYwKIv+i8/oEWVMLH+cke6/bwmkiVtEya1fgrAjNhymFoa5TH94LmalWlQxmKXQEp6vuWn6PmZhySMvD5d+YJWLCtDvxLRrxBI3GgjCTfF+b+izgNtZdfnaV+nqvhtsZh3e6k1a/YALzkZng+rmC/CgBIhWiVaKQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=VJJU6M0wRwT05SIiqR0kX7QMTa06jMPQLqD4QL3HvJg=; b=WONRkcjYGLWE9gSeF2o45pCrOYUkL+AZq1lRZvLWhvZn9MmwDT0wKMueZaB5x0681nsieL2le1iDsNYa4Wt9u3x/3Ldvy7xLQce+wBaq9d3XZbVypdRi4lcbkS65Z2TM7uH7sKIOULTu7SoZBtMgVeFlRSG8PFdgMhHWUIJfSB4= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:21 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:21 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:18 +0100 Subject: [PATCH v3 10/16] rust: io: register: make register have a typed base Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-10-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=9303; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=fNklDIbUzqKSWVEec0SWn3DPw8OYEFfR6ffLgTCMyYU=; b=fz5cHTSBS+Nb0xG7qnnrNoT1YMOMcJ0YOBm+VpAMcu2+rxaa7HCaGyIxKzuKy8hwn/feyiw7r upAMWWLxwz1CA+GvBpRWy0Gel3Y3vti70p69GKJbeCnROHSUVHSuQjW X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 5449a54b-9e34-4407-9980-08defde275d5 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|3023799007|56012099006|10067099003|5023799004|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: fujDrFXF/IMBBFjQnUVc6SN0c46MRdswste1XSt8I4pb0QKVYav+jDCGVt8sFyfQW+yriNAo37ZCLGVwr1qA0xP2bOCTEqnE82dbrxsXRAHLfPSEf4nv8kd/2NXztL2nDRHezg5riu9ZbavDP6IoRxlZsN9yc5j/XL3EQtS1kgVebM/6MaTkL+JKVCZVC2oeI94eiopa6yX1I4hWQgHnCJbHWluU5t9Ardn0WANHS1fmyLvw5xMXhPJ79a1bM+J74avHPPJVqQhFClfbpANW0lu05MSUHJj2YBXCj8tvmqaRYngdwAdrykJ//kAlV/a+hUbHe3ToakyyaFDupl5q8otWNWifPbaXdf5o0Dauw4LUGnQIJhpWPyWcOdkaVcJpgi3mGYM+G7ImmFE1hddyCgDwoCWKlJcYWoMBnqzI84gDUpU7Agyliz79KMhf7uq/CNV6SHwaa3wCCE9FrcAifb635jOEUt7fZtTPCdOozEGhn6Z/FZiL3gSYjDZrltHzTZ85zE5ZDP0IiRUgDo19JltlUww1D3Po3S2dI4J7bTjxRi7z4REm9vta6PJYWYBG2wSDMuoSjW3oKmWWJIbs7NAvk3lNoh5qTzFpLlO440d0FzsKyjFzE23MoKNIzpXkHgrkZDHCNmJFIFa0jgmq+DS4d/Dyu6QKRTpVBXfyAwxNx8WDxQICIqSCQWB02OukQHtdkWEEvkHirUgOkWzozQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(3023799007)(56012099006)(10067099003)(5023799004)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dEJTY1pScHJ4ZzEyNkNDem9pcG1XVXB4MHo5Ukt6UG1RdXVvYjNEdm9WWjl5?= =?utf-8?B?dFdUckNzaWdhbjZDS1dTQ3l0UE1EOFVaYlA4MEVrQ1ZiNFRkdFl2dXhkcmV0?= =?utf-8?B?cTcrQjh3ZXlzUUVZT1VTYk5LMG02d1NuZFV3aDVNWkNKZ3dMQnhHZDJYRWVv?= =?utf-8?B?czRyUTVoc1JCU3BINVBoSjRFNmNVMW1lMnlCMzhIYW9DdyszRGRVUzd2a1Ax?= =?utf-8?B?ZlM5QkV0U012OFN4ZUt2MHJvbVdETFBpREpJVUdnSmd1eldJclByTnBkRXVC?= =?utf-8?B?eWdleVJLc3VaVWZmS0hSQkxTR1RISy85aW12MzVzdlJFaGQ4VGkyUENRUHBW?= =?utf-8?B?VG5GelIrS01sNGFhcEhwaWJheDNFTW5DM0hjNVcwUzZyODFiS3Z3UmFSNytX?= =?utf-8?B?NER0VzhHWDZydmphU2tWOFNqcXVvdmdDYkhuQXVuMEVXY1UvTGs2eHBYWTBl?= =?utf-8?B?ckxLVmwrZnd5RnB6VmxDVUQ0Z0twaHpGYVl5bkJZMkJDNjlOai9panYxeXgw?= =?utf-8?B?bS9iS0JqVGNwM1N2NEJEZHM0VXFWaHdldTBaSFQ4aG5GcmR3UmdCZVhNSmxZ?= =?utf-8?B?T1p2aFJxKzNFRmpZckhtOFZseHhOVVZXWElwZGJFUENid2hjYzcxZVNDQk5P?= =?utf-8?B?WTNSa3JHNVAzRzkrOElrTkJ5b2ZsL3h2ZG5OaDdnZDNwYUozWDhPMWtXejRB?= =?utf-8?B?bzJZSlQwVS9EYVBzWS9IN2dHWWxzclZhc3ovVjBKMXhYa1hwL1B3NlBQd1Zy?= =?utf-8?B?b1Jsck9tOHgrUXZvSmRWTkQvZ1VYMHEzUGFhbjRxTllFUE1hOUtDRzZVaVMz?= =?utf-8?B?QUJHcERoVnFnbkZRTm5QdnROQWdocXMvOThzVXJGb1pSeEFTL0hVQXZnS0t5?= =?utf-8?B?dDdsUHNneXdsaHlScExsRTdNejBFdjVMYU1BVmUxMHMzQjdOME1nY01nSWpJ?= =?utf-8?B?Y1V4TVdPNXNSZjN1YU9FeVVSK2ZQaU9zY2lvZ0xveG5tZU9BK2w0c0RxZTZq?= =?utf-8?B?ZkpWMXpLdkhlTFllSEZRUTJVR0hNcW9kdTlBU085Ym5hUUhQZmdITXJuWlht?= =?utf-8?B?VDZkMFhlWGcvLzZqTXhsOUV4eWRhN2FRYW8xcE4wekh6d1d6ZzBUdXRqb09i?= =?utf-8?B?LzNlWi9ET2tGVkU2TjR5TDdLa2JxVFArUEtsOWVVa1NTakxTZGMxLzFMY1ha?= =?utf-8?B?dTIzMFJhaExmTXFCcUNYcGo2OW44djViRjlycEZEL0YreUxuYXVzWFFyV3VR?= =?utf-8?B?eU9LQ1FzYWxJYW1Nc1hSNGw5OFdtTmVpYk9LUmVPOVZubkY5d2hVbm0rMGNk?= =?utf-8?B?TG1zMHFtZ3ZHVEdyRWIya2J5YnJNa1BYZVR0QStyR1NVZFJPdVYxQ1ZwbVp2?= =?utf-8?B?eEtrUGYwTHZFSlJBSW1qcitwcUg1ckRLUWRFU1ZPbHB5Yk8wQmhLZk1RUkhD?= =?utf-8?B?WGxXT0VRZnB3aS9RVjN2VjdRUlp2aVJFZnFwV0UzbVlwWFFWaCtVYzhPS3VM?= =?utf-8?B?OHVudDQwWVpkc2dET01YalEyam1rVTVmZW1XQUgvMGZTeFlKWCtDeVFYWkJ5?= =?utf-8?B?RmphYkR6Z3doYWVsOHRVOHVBN1VVUzMyenVVQXphRU9GVXQ4NThtR05uRFFn?= =?utf-8?B?OUN3c1dvVUEvQ3lWWTdLVEJlWDVNSjFrOEdhMDRHZjhxZnMzc1FLaUx3c3oz?= =?utf-8?B?UWg4VjVoU0xSNnlXaGYxQk5lTnhncmIzQ04rM3dGUk8zS2tHaS9mSzJUNi9Q?= =?utf-8?B?eVB6UHJYb1VGVUJsb0RqR0ttdnAzaEs0dUdYRm1XYmFsaGZ3bGFObWVzYWEv?= =?utf-8?B?Vmc5QVNWWEMrMnp3RTROVTFoSGtWbVdFZE80Tlo4N0FmeHBSdC9DYWpTWVhH?= =?utf-8?B?TUVidGI2VXZLdmdnUnIyVjZPT3BuK2tUUTF0L1Y2VG1qeEVyUnVub2x2ZmFv?= =?utf-8?B?UTNjanczUUFCdllJdlUvQWt4SlR4bjJIbHFGUXBqWHg4TXh6WE4vaTNqYkxr?= =?utf-8?B?bmh6QkZXV0ZHc1pYMkFGaDhRUThlR21xVmlUOU1sY0loY0lic1NaemhRelpQ?= =?utf-8?B?SHVvdVVtd0gxUnJlTmprQWhxaExpUE1RM2pocGRuL0w0VlhtYnRQanBzRkxr?= =?utf-8?B?Z2ZhcXIvNzlhVFJsckpsZ0Y2eWRsQy9SbXl3RW85L1ViZEYvOU1ZaHQxNnRw?= =?utf-8?B?eWpjUjE2UmFGOHZrOTVOTTdaTWxFSWJJdEpzWVpwbGUzeVlCYmtNclVYT2o2?= =?utf-8?B?RXZDWDA0MHhHWGtNZUtSeGRURGpIM3BpZ2pObE9qQ0dmc1ZleVlIY2prOE9h?= =?utf-8?B?Z0NXTUlPSXZSd3I1YmhwVkNGWThxS0JDcVRrdnE4VkZiQ0VSZHFZUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 5449a54b-9e34-4407-9980-08defde275d5 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:21.5684 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: yLCZiKsxnpBW+2JZFYo6NUGMPMk7D3XXXK8hMNs6aYdrzVtsBTrllPLq1S8RswV02hznOkLVI+tIV6YSECWQAQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 Previously `register!` defined registers can be used on any untyped I/O regions. With all users specifying their desired register type now, propagate the specified type and restrict I/O access only when type matches. Also, add an `io_project!` example which is enabled by this change. Signed-off-by: Gary Guo --- rust/kernel/io.rs | 13 +++++++++++ rust/kernel/io/register.rs | 55 ++++++++++++++++++++++++++++++++----------= ---- rust/macros/io/register.rs | 34 ++++++++++++++-------------- 3 files changed, 68 insertions(+), 34 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 84dd876b3407..4542187d6b91 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -1692,21 +1692,34 @@ pub fn project_loc(self, location: L) -> ::View<' /// The syntax is of form `io_project!(io, proj)` where `io` is an express= ion to a type that /// implements [`Io`] and `proj` is a [projection specification](kernel::p= tr::project!). /// +/// `io_project!` can also project to subview of registers defined with [`= register!`] macro. +/// Register projection has syntax `io_project!(io, try: REGISTER)` for fa= llible projection and +/// `io_project!(io, build: REGISTER)` for infallible projection. +/// /// # Examples /// /// ``` /// use kernel::io::{ /// io_project, +/// register, /// Mmio, /// }; /// #[repr(C)] /// struct MyStruct { field: u32, } /// +/// register! { +/// base: MyStruct; +/// FIELD(u32) @ 0 { +/// 31:0 val; +/// } +/// } +/// /// # fn test(mmio: Mmio<'_, [MyStruct]>) -> Result { /// // let mmio: Mmio<[MyStruct]>; /// let field: Mmio<'_, u32> =3D io_project!(mmio, [try: 1].field); /// let whole: Mmio<'_, MyStruct> =3D io_project!(mmio, [try: 2]); /// let nested: Mmio<'_, u32> =3D io_project!(whole, .field); +/// let reg: Mmio<'_, FIELD> =3D io_project!(whole, build: FIELD); /// # Ok::<(), Error>(()) } /// ``` #[macro_export] diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 49a5fe069e47..f622057f7346 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -121,10 +121,11 @@ io::IoLoc, // }; =20 -use super::Region; - /// Trait implemented by all registers. pub trait Register: Sized { + /// Base type for this register. + type Base: ?Sized; + /// Start offset of the register. /// /// The interpretation of this offset depends on the type of the regis= ter. @@ -136,9 +137,9 @@ pub trait FixedRegister: Register {} =20 /// Allows `()` to be used as the `location` parameter of [`Io::write`](su= per::Io::write) when /// passing a [`FixedRegister`] value. -impl IoLoc, T> for () +impl IoLoc for () where - T: FixedRegister, + T: FixedRegister, { #[inline(always)] fn offset(self) -> usize { @@ -148,9 +149,9 @@ fn offset(self) -> usize { =20 /// A [`FixedRegister`] carries its location in its type. Thus `FixedRegis= ter` values can be used /// as an [`IoLoc`]. -impl IoLoc, T> for T +impl IoLoc for T where - T: FixedRegister, + T: FixedRegister, { #[inline(always)] fn offset(self) -> usize { @@ -171,9 +172,9 @@ pub const fn new() -> Self { } } =20 -impl IoLoc, T> for FixedRegisterLoc +impl IoLoc for FixedRegisterLoc where - T: FixedRegister, + T: FixedRegister, { #[inline(always)] fn offset(self) -> usize { @@ -240,9 +241,9 @@ const fn offset(self) -> usize { } } =20 -impl IoLoc, T> for RelativeRegisterL= oc +impl IoLoc for RelativeRegisterLoc<= T, B> where - T: RelativeRegister, + T: RelativeRegister, B: RegisterBase + ?Sized, { #[inline(always)] @@ -282,9 +283,9 @@ pub fn try_new(idx: usize) -> Option { } } =20 -impl IoLoc, T> for RegisterArrayLoc +impl IoLoc for RegisterArrayLoc where - T: RegisterArray, + T: RegisterArray, { #[inline(always)] fn offset(self) -> usize { @@ -367,9 +368,9 @@ pub fn try_at(self, idx: usize) -> Option> { } } =20 -impl IoLoc, T> for RelativeRegisterA= rrayLoc +impl IoLoc for RelativeRegisterArra= yLoc where - T: RelativeRegisterArray, + T: RelativeRegisterArray, B: RegisterBase + ?Sized, { #[inline(always)] @@ -393,9 +394,9 @@ pub trait LocatedRegister { fn into_io_op(self) -> (Self::Location, Self::Value); } =20 -impl LocatedRegister> for T +impl LocatedRegister for T where - T: FixedRegister, + T: FixedRegister, { type Location =3D FixedRegisterLoc; type Value =3D T; @@ -406,6 +407,28 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { } } =20 +/// Helper function for register alias implementation. +/// +/// This is used to enforce base matching. Only called during const eval. +#[doc(hidden)] +#[inline(always)] +pub const fn alias_offset>() = -> usize { + Alias::OFFSET +} + +/// Helper function for register element alias implementation. +/// +/// This is used to enforce base matching and provide bounds checking. Onl= y called during const +/// eval. +#[doc(hidden)] +#[inline(always)] +pub const fn element_alias_offset>( + idx: usize, +) -> usize { + build_assert!(idx < Alias::SIZE); + Alias::OFFSET + idx * Alias::STRIDE +} + /// Defines a dedicated type for a register, including getter and setter m= ethods for its fields and /// methods to read and write it from an [`Io`](kernel::io::Io) region. /// diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index 2fb48e1be82d..cb02e850b23f 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -140,21 +140,23 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Resul= t { } =20 pub(crate) struct RegDef { - base: Option, + base: Type, regs: Vec, } =20 impl Parse for RegDef { fn parse(input: syn::parse::ParseStream<'_>) -> Result { - let base =3D if input.peek(kw::base) { - let _: kw::base =3D input.parse()?; - let _: Token![:] =3D input.parse()?; - let base =3D input.parse()?; - let _: Token![;] =3D input.parse()?; - Some(base) - } else { - None - }; + if !input.peek(kw::base) { + Err(input.error( + "a base type needs to be specified for `register!` invocat= ion with `base: ty;`", + ))?; + } + + let _: kw::base =3D input.parse()?; + let _: Token![:] =3D input.parse()?; + let base =3D input.parse()?; + let _: Token![;] =3D input.parse()?; + let mut regs =3D Vec::new(); while !input.is_empty() { regs.push(input.parse()?); @@ -166,6 +168,7 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Result<= Self> { pub(crate) fn register(def: RegDef) -> Result { let mut outputs =3D TokenStream::new(); =20 + let base =3D &def.base; for reg in def.regs { let Reg { attrs, @@ -186,18 +189,12 @@ pub(crate) fn register(def: RegDef) -> Result { RegOffset::Fixed { offset } =3D> quote!(#offset), RegOffset::Alias { alias } =3D> { quote_spanned!(alias.span().resolved_at(span) =3D> - <#alias as ::kernel::io::register::Register>::OFFSET + ::kernel::io::register::alias_offset::<#base, #alias>() ) } RegOffset::ElementAlias { alias, idx } =3D> { - outputs.extend(quote_spanned!(idx.span().resolved_at(span)= =3D> - ::kernel::build_assert::static_assert!( - #idx < <#alias as ::kernel::io::register::Register= Array>::SIZE - ); - )); quote_spanned!(alias.span().resolved_at(span) =3D> - <#alias as ::kernel::io::register::Register>::OFFSET - + #idx * <#alias as ::kernel::io::register::Regist= erArray>::STRIDE + ::kernel::io::register::element_alias_offset::<#base, = #alias>(#idx) ) } }; @@ -211,6 +208,7 @@ pub(crate) fn register(def: RegDef) -> Result { ); =20 impl ::kernel::io::register::Register for #name { + type Base =3D #base; const OFFSET: usize =3D #offset; } )); --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU010.outbound.protection.outlook.com (mail-ukwestazon11022139.outbound.protection.outlook.com [52.101.101.139]) (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 5AA534562A2; Wed, 19 Aug 2026 11:10:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.101.139 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137842; cv=fail; b=DM4VatMsOeYyz45BOkl63/qk8QSOYHyU4nONuvGY/z/jZrwMUkHxua+pVn44TswMg/qcsGpwC+F/sPBGtgn70kbnw2kVTfCIhtkL8FeBYsYgaqmuMOtOsuaHWOgH4J3FMEMjTfK0L17OzxbGu/1spJaIKeqiW0YsQfeN0NJ9JFY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137842; c=relaxed/simple; bh=XZXD/efaS++QVM6lm/YgbjK0rEbg9/iNkZsP4HPrYQY=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=SqjyMttwR+5PZu/Vh+B8r40mzQNIDeLA5W02wO+Let07fMAhQAfFNA/iHvtONSJHEcgSCuB2ZgGCInLZXW5NHB2Ezw0FK+nqO5lrFbqztEHTPrNqMnsUwM4eJuQbMPdSrSh6N+9NRFtATPTq3qOWIQCi/eaxgDDih5/CRBmEgYU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=0SQQ+eQV; arc=fail smtp.client-ip=52.101.101.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="0SQQ+eQV" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=uXmXHF3fA3pOBhKQXT4mcv/xohJlPnCcEd0DfDq1voA57RcrdGFha+2wTaM6Sijizj9JKB7t8tKUNBH8CU19OonNeGDD+F6bp0Ybgf+NY8fQymU+cMjoqNT7OxtVvIdJQNzQFBy+lhkqG4tN6g02cIMYrLxWWzhjk5k05QglYvZgf4dBoXPu2sYUI6VIsLRhJ0lCvRrFFKHD5PgI/kVXCwdFb2JcwOz1PV8STYJsAxuyun4XKludChuOjAb13hXDgvl0j/M9s3MESCFraLB/CR0wtMjlNdrmDzFjvm7jxou+okjF5uanABeGRlwuaQ8dvxQy75kNtTKg6LyAUW2NDA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=XoGBtLeyYpMRN8b0+FC2+3BnjwjhBmSrKnHZb9pNeIs=; b=PmVuYSOJ3/tOb/DzhCrjSQh4cBaEN3VTfX6kHSC1AiVHY0zyglV93h80B4Nb+ERsVAvRSHyAHX36SP/nuHOZ0IYBLm7uhNVHejHBewGMp1LgCxkbyiMZdT6v9MjZRbowrJRJi5rz6EClUSIgEXO0SbLk9bwZJLKhwonTyoBjxe27Ti0w426geqhLqqDDzzRmxKNTJ+nrLRNphWsCElXPQwm9odD06qnzvLrEBO0obMl6zLZEwkI1bSeAKYtFvTWsa2OZ6Vcy/3kXNa7gOBp4w4KNK7bJfHJnzEIH6LeY+AvcTv9NMj6pD5JgRwq71yD2aYiCWRjL5e/SMjSRZfckZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XoGBtLeyYpMRN8b0+FC2+3BnjwjhBmSrKnHZb9pNeIs=; b=0SQQ+eQVYWaEzkQ968/be86yo6Jq4OLQoG7wnDjwaIkKy06PzKPgv0kj0laILNQQM1vmwOhdCW1z7IC+FiTABd1T9JVxhSHs4SKfrokMkMs+VF+jZf4jrn1M2I6OcQonT9sgMr9UWIGuzi3LR3Kjm3fpWTw6wnK0Lxqa3bMYH5M= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:22 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:22 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:19 +0100 Subject: [PATCH v3 11/16] rust: io: register: support fixed offset register without bitfield Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-11-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=7936; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=XZXD/efaS++QVM6lm/YgbjK0rEbg9/iNkZsP4HPrYQY=; b=ur0fPdU8p3BnmNPXsndl5MO9oGBW0Gena+AAZAI/J1q6UGj6Eh7+X7L7ff3RkUAKvgU59F237 RD4fBpsGZblBXflBm8HrW8bm+Vku1x0S6ks/ogFvSQUfv5kD8S7Jp7q X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 41e5692c-237d-4110-17bf-08defde2763b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|3023799007|56012099006|10067099003|5023799004|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: uFarUEpxD//1x7tvvGkm+9otvhS09UUPPpQjNw6NbAZ6ijuwGifIpLPUVUz8dNG1oXqInu4dTO9ReLAmCxIqsFX3DqqzYHkl+pbsrkDQlydYZJY0XsUVxfiFNpN3+vUL/JJm7zCm5FHOjfyQqsI/7uuEofMDzhEq8gpKbYgBweK6/iiJ0g/cfkZ9U5fsbQZJGtYztLegELAIbfozM0fdVNQbDtISLwi7UaOm6gdiV+T+B8mPfKBYNnwKHqjnjNSLfGHM3PK4qt6h8/Bdx8A4OFwmrKyEnCrmxGl8VJUgzMW/CieM+2WxcxDuFkclOaSvTkdf+aMFe+DUDYH5hvXJ2guqL+RxQMCXlY1sYtTkW6QTHt3fkHQNNpq2eOrXjcOzQKBM1RS4IQMFv0JtY5yr5lu4mJUj3xOptO+0xthec6lkpJx/xjtbxV5arMSBcdcTxi3d5s5I9uykX8r6w0TA6fM9709Z7YUHedvdZBFbybkLQ7iPt9GwOi5ffIaKJUhGMyFpBCSxDpT7NI9yX6fKbIp55Hd/1CB5gfD1jfHuNQgXjJd3rvjOnbRS4hj47y22gTuddD65efmY4ylT/qiUyjIlwdjdtju6kDQ8b5U2bN+YcjjxC1WGS1+xJ4aNxkB1IuWzHk/JeSoSbALDHEV3HoYtknEZ7AY1Tl0im2CDF7S68VoYSKHl9G0iBmVyE029NxJK6wvMagETqu9wS6Sfxg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(3023799007)(56012099006)(10067099003)(5023799004)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?UVBiN1VMR3lTOEJ5Ry9GUUxIc2dkWW1VckxyRkQ0eTZ3NHk1UUlZcitMbjRW?= =?utf-8?B?WU9UVmxqbzRwUnlXOE5ITUw3MWFiblVSY3F4T1cwcDJtOUxHc3dPY2g2dlZ3?= =?utf-8?B?Ti9NQnozZGdlWXNrejJzbXA3SGJabmxwWGJLK01laEEzNVhsNnZrdVZHMjlv?= =?utf-8?B?YUxGdjMwUmY0WlkvMHhrbGZKVmhyTXFFeHZnOHpQdjFseFdvMEtqWTFJazRE?= =?utf-8?B?V0Vnd0FsWE5xZEdZVkY5K0dNTFBFbDc4WTFIdmlJZHBjM01meU44VGU1Tyto?= =?utf-8?B?L3ZJWjkxc002UW5uS2Vkd0dvOWdsK08yYU9rZ2t0VVlrNnhrL1VBK2EraDlp?= =?utf-8?B?alpvQkREYkk2ZUk5SnZ4cVltZSswc0VJbXArdGpWSG5nYm9TOE1WdVA5R0c0?= =?utf-8?B?TmorOVpCVWZOQjFsRU12cXBtQ2R1L1l3TG5ZQ3ppVStjUmNVZlJzbzdITWQ1?= =?utf-8?B?ZFB3QVFLblU0WTAzdG1lSU4ranJtMlVtRnVUdThpOVZJdjBEa2p0N0tGZnZt?= =?utf-8?B?MTZESDNtMEVGb09sNExlT1NKb1NyTXZHN0ZmTnNEMmphTU1MQ3BuRUVlUFkv?= =?utf-8?B?VngyQVRtQ1VPSENLZ3lxQlVKOGRpUzBmcUJ5cDFEZ3BDRktiRHJLblVxcWtt?= =?utf-8?B?QTJBNG1vdXlmUHBBZXBESk02WWxXd29vQ1BHaWpXc2xmVm9VVUdmN3Ryd093?= =?utf-8?B?ZW4vbG5WR0lWK1pPZEFmRVNFQW9uK3VpRnlnTlc4ZkluWDdmMnZkZGRZSFZL?= =?utf-8?B?aHpFQ3MxNGdITDlwWUdpOUwwdm9zVGpOM2RjNmYxSmc1ejlPUWdYWk1rRmNs?= =?utf-8?B?UEFqNVpwN1h5WVhtb0ZjN1lFNFY3NHgzZ0xXWUhGMU1NR0JUaWtGeXZzVUFJ?= =?utf-8?B?bW5KTlRIakR3YWU0K0JkQVhtTHRJakduS3JUK1ozMTJTTCtDNHZGTi9mR1p3?= =?utf-8?B?TWJVckxNZVJnV3VZZk1VMnRDaXNaNXJwRzVIbGRXdEcySlk1VEVEakFxczcx?= =?utf-8?B?VWJPbHlnSm10djNvNVNXMldNRDJPaHNpRmJ3c0lhU0NIejN1KzNUSjc4VnF3?= =?utf-8?B?cDkrVFA0R3lSb2ZvQkxxZmZHL1NGS2o0a2RZOEFKUXBMbjk3RWRoTWYydjkv?= =?utf-8?B?bWczN1U2TVVsM25VTG9wVUlXYkdsZVVKOTBYZ21FQmNWemUzYzg4MithQXY0?= =?utf-8?B?YVFyQTdlUHdDdHk1NVNMV1dCTGh4SGVnUkhSTE9xMUVLL2g1THBkR0dKRUJQ?= =?utf-8?B?bWdKV2JRZUF3QUVLZFlWWWN0UitqYzk2SElYQ0Q4cEhXcUdTV1dONDQzd3R4?= =?utf-8?B?bEZybWtDRjF3R1NVQURLdTk5ajFWUHZwWjF3VXB1SGUvYnR2WUhZWFMrL1l6?= =?utf-8?B?UVZCdm9uY21paUJTY0JqOFpuR3hZL254K3g2ME8rbmFrUmp1UURuMW9Qd0tw?= =?utf-8?B?N1FybHBtbjh1OXJQMG4yUituMW9pWmRYWkh2S29oejJQOUlPZyswUFU0aU5H?= =?utf-8?B?MklCWlZHYW9JQ2NCNUh3bEF2OGJBR3RZU2w3bDdSK1lqRHZMMUFqd1hac29i?= =?utf-8?B?c25YdGcwR2VVSllzeTFlWk1XcldtM0paVDY3ZVBTc3NLbHBoSGE2Kzd3SUwy?= =?utf-8?B?QkgwbXhZZTJoclBuQUZCSis3Y3FoSW85anRXN0dUZDl3b1QyeVQ3MkQ5WkhS?= =?utf-8?B?cWcyUnJ6VkFwSHFWQjBMbXN5am1SL25NTVZ1cGJINU1IK2FGT3p0WEZoTWY4?= =?utf-8?B?UjNaRG9Gb2ovSFRFUXlTSUhtU3pDdmJaK2R4K0czZ0dmMUNZOXZCTDBXQng1?= =?utf-8?B?bHU5SmZ5VDRaaU1RTUpHWmdmRjZ2Zy83R3NKTTVCSjYyR2QxOG5iSzN5dTJP?= =?utf-8?B?QWdFTk91dnJIMkR0VEJYWWx1WGVncXhpekJWampjeU1XaUdVblE0bis4eXdR?= =?utf-8?B?VmI3d3lna2s4YVFualczWkRUM3k3SGhKeUpMZ284dm5OUyszSzBEeUpLVTd3?= =?utf-8?B?WVdmTW00VlZSRjFHNFRNTTdFci9qWEhvbEpjclB0aHVqQ092VHk5bHBiRWtO?= =?utf-8?B?dnZiTDFVeWFseHZTdmE0Z2hxOEZzTEZURkI3cmFHaVpYeWlua2VhazB5NWxN?= =?utf-8?B?bEI2UVV2ZVV6YWN5bTEzL08xS0RGMlF6d0R5TWpnS2FXbzZFTGlzUEhyL0Fl?= =?utf-8?B?QnBFaDlubkFKc0h3SlZ1TSsyYWhXZ3hBMGNHMEZXMFpkTmFuZ21vYU5vS0hP?= =?utf-8?B?d3NHU2ZMVHNxa3YvRStlZXFCNlpQUGlEWXdzWHQ0eHNxT3dqQ0dHOGRuNGxn?= =?utf-8?B?S1pIZE9hODhBR09kU2NKcGpMYm9YL3FvcTVsR0Jkb1ZTOGJPVmRvZz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 41e5692c-237d-4110-17bf-08defde2763b X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:22.1941 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: m36TOpOdljU0rs8epwg/D3aCivo7x9OBp/HJ57rSA9Tc+hvktcBMPXe0z0oXnWfVUWPIQx4iQ/PshWWH34atqA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 Add a rule to allow creating `IoLoc` in `register!()` using an existing type and not create a bitfield. Add an example to demonstrate this for FIFO registers. This rule is also going to be used to create subregions for registers; the example of doing so will be added later when relative registers are removed. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io/register.rs | 30 ++++++++++++++++ rust/macros/io/register.rs | 86 +++++++++++++++++++++++++++++++-----------= ---- 2 files changed, 89 insertions(+), 27 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index f622057f7346..63c054162e54 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -182,6 +182,23 @@ fn offset(self) -> usize { } } =20 +#[doc(hidden)] +pub struct OffsetLoc(usize, PhantomData<(T, Base)>); + +impl OffsetLoc { + #[inline] + pub const fn new(offset: usize) -> Self { + Self(offset, PhantomData) + } +} + +impl IoLoc for OffsetLoc { + #[inline(always)] + fn offset(self) -> usize { + self.0 + } +} + /// Trait providing a base address to be added to the offset of a relative= register to obtain /// its actual offset. /// @@ -521,6 +538,19 @@ pub const fn element_alias_offset; +/// +/// /// UART RX register. +/// pub UART_RX: u8 @ 0x100; +/// } +/// ``` +/// /// ## Relative registers /// /// Relative registers can be instantiated several times at a relative off= set of a group of bases. diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index cb02e850b23f..0b4e0d1903dd 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -14,9 +14,11 @@ bracketed, parenthesized, parse::Parse, + parse_quote, spanned::Spanned, token, Attribute, + Error, Expr, Ident, Path, @@ -49,11 +51,11 @@ struct Reg { attrs: Vec, vis: Visibility, name: Ident, - storage: Type, + ty: Type, array: Option, relative_base: Option, offset: RegOffset, - bitfield_args: Group, + bitfield: Option<(Type, Group)>, } =20 impl Parse for Reg { @@ -61,11 +63,23 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Result<= Self> { let attrs =3D input.call(Attribute::parse_outer)?; let vis =3D input.parse()?; let name =3D input.parse()?; - let storage =3D { + + let lh =3D input.lookahead1(); + let mut bitfield_storage =3D None; + let ty =3D if lh.peek(Token![:]) { + let _: Token![:] =3D input.parse()?; + input.parse()? + } else if lh.peek(token::Paren) { let content; parenthesized!(content in input); - content.parse()? + bitfield_storage =3D Some(content.parse()?); + + // For bitfields, bitfield macro will generate a type with the= same name as `name`. + parse_quote!(#name) + } else { + Err(lh.error())? }; + let array =3D if input.peek(token::Bracket) { let content; bracketed!(content in input); @@ -119,22 +133,28 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Resul= t { Err(lh.error())? }; =20 - let lh =3D input.lookahead1(); - let bitfield_args =3D if lh.peek(token::Brace) { - input.parse()? + let bitfield =3D if let Some(storage) =3D bitfield_storage { + let lh =3D input.lookahead1(); + let args =3D if lh.peek(token::Brace) { + input.parse()? + } else { + Err(lh.error())? + }; + Some((storage, args)) } else { - Err(lh.error())? + let _: Token![;] =3D input.parse()?; + None }; =20 Ok(Self { attrs, vis, name, - storage, + ty, array, relative_base, offset, - bitfield_args, + bitfield, }) } } @@ -174,11 +194,11 @@ pub(crate) fn register(def: RegDef) -> Result { attrs, vis, name, - storage, + ty, array, relative_base, offset, - bitfield_args, + bitfield, } =3D reg; =20 // Use register name's span for generated code, so error messages = (if any) can point to it @@ -199,21 +219,33 @@ pub(crate) fn register(def: RegDef) -> Result { } }; =20 - outputs.extend(quote_spanned!(span =3D> - ::kernel::bitfield!( - // `#[allow(non_camel_case_types)]` is added since registe= r names typically use - // `SCREAMING_CASE`. - #[allow(non_camel_case_types)] - #(#attrs)* #vis struct #name(#storage) #bitfield_args - ); - - impl ::kernel::io::register::Register for #name { - type Base =3D #base; - const OFFSET: usize =3D #offset; - } - )); + if let Some((storage, args)) =3D &bitfield { + outputs.extend(quote_spanned!(span =3D> + ::kernel::bitfield!( + // `#[allow(non_camel_case_types)]` is added since reg= ister names typically use + // `SCREAMING_CASE`. + #[allow(non_camel_case_types)] + #(#attrs)* #vis struct #name(#storage) #args + ); + + impl ::kernel::io::register::Register for #name { + type Base =3D #base; + const OFFSET: usize =3D #offset; + } + )); + } =20 match array { + None if bitfield.is_none() && relative_base.is_none() =3D> out= puts.extend(quote!( + #(#attrs)* #vis const #name: ::kernel::io::register::Offse= tLoc<#base, #ty> =3D + ::kernel::io::register::OffsetLoc::new(#offset); + )), + + _ if bitfield.is_none() =3D> Err(Error::new_spanned( + ty, + "defining without bitfield is not yet supported for this t= ype of register", + ))?, + None =3D> match relative_base { None =3D> outputs.extend(quote_spanned!(span =3D> impl ::kernel::io::register::FixedRegister for #name {} @@ -235,12 +267,12 @@ impl ::kernel::io::register::RelativeRegister for #na= me {} let stride =3D if let Some(stride) =3D &def.stride { outputs.extend(quote_spanned!(stride.span().resolved_a= t(span) =3D> ::kernel::build_assert::static_assert!( - ::core::mem::size_of::<#storage>() <=3D #stride + ::core::mem::size_of::<#ty>() <=3D #stride ); )); quote!(#stride) } else { - quote_spanned!(span =3D> ::core::mem::size_of::<#stora= ge>()) + quote_spanned!(span =3D> ::core::mem::size_of::<#ty>()) }; =20 outputs.extend(quote_spanned!(span =3D> --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from LO3P265CU004.outbound.protection.outlook.com (mail-uksouthazon11020099.outbound.protection.outlook.com [52.101.196.99]) (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 0FF514582F6; Wed, 19 Aug 2026 11:10:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.196.99 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137848; cv=fail; b=GXGYTKMVIpcw9OUDWIVP58eWSOnMnM0lc0UOucV7f12ecQ6ai3xvstIi+kszOYr++ARX7rRIrwJt+/rP6A6YRGb3CGifR7iSOfc4fT3wi5D6L5jx/99iywwi/wK8f6c8/B1Rvj4VRa02ynuUemTERPjIHLwB9k7tqujW8IhuW6M= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137848; c=relaxed/simple; bh=D0QIW3gLEGUq1PEvmPOkulzpq9vZOkliiKGcHUHy1vU=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=YrjFlRbznMSTzpeFSdOvw0LJk+VvV3mZpLWNQgFmSoRUWF77dT9ZK9KW1A8E6Nt/GI1YMPj9Ln/qbKAJD0txbC7nRps19DNfs5iUisOwkkvhpaJX2Y8mtAC5Ftamh1ONnNB7dD/GRTMSRCT6JStCyLRg2yd0guZtHmkqLzKep+U= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=w9Xr3+W+; arc=fail smtp.client-ip=52.101.196.99 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="w9Xr3+W+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kejM6kDwOA+oSBXrE4PfgMHMdn67ZHwR7Gn1777zuukKpPeNxh6c+SErftq5TY9RaRVG5W5yJAT+pL9hZowDv1zQvvYCs/u89mw6d9rpfrE9g2VwSlE1fIRKE60HWStfz2JqLOwv6gLCo5tD8KZRXY39FMNKWBU464kzGde+QOvpHlvcbT20gdlbWgc3NdYhDvOU/Nq6fRV8yKj3JBVn7NkbuGMO1sBZ9+IGzu/lSaO0c+/JHMA4eoIN38mzOrVAs4pz7fYlEe0Ku6OX783vulXrzgChiynkqnBh45SSk5LVgEadRqqk+0q7jvgVfC4VXrn3v1/DMbaHrhKeK1PZEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=EWBvJAcWXsTgFfXCWTRUaKpplLBkVQaS1dnrCqa/yfE=; b=sXYOLtFCVddMunL5gsOFp7oolNM5uiQhwm7dk78A4JfqT5LggSTAMXAvIrxfHdhkOralajp0+Iq3m75SOPVj0K3B312Gp2NrTYKjpsAAV4xFXZPUFaUzekdcCT3GKtWvF66ZMIG2fujirhjsDoKmynV7cVCfK/lsktNX7xqINohFO9hsIz9NoZU8VTT3fPZttja+iJWBxiPc8dx7Zt1mrJ4nKtyOGQkQ7HJddY5qpOZEaZtplUCINnBAY+FIAdRJ8Nj4j6oi3zX2TOinjdh0xiafOT5feeznuDj2sk40SVaPD611TkPP2Gm6ED0h9fwf2neCuYB4JEhSG0nWd3KuUQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=EWBvJAcWXsTgFfXCWTRUaKpplLBkVQaS1dnrCqa/yfE=; b=w9Xr3+W+AqQwK8hMO0zPfDZUOfNEo783pC5aC2y+dTaJ9RbVybyEE6HsHBSK158ZWGtA7J3ZQZhlDcyI0Qee9sfB/UXPs9mFjdg/FrFWUOldBBbiaJme+kps7iObUcnWk9Qam6S43jWEURldeJdOj565VE8m45niqjWBHnHqL/Q= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:23 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:23 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:20 +0100 Subject: [PATCH v3 12/16] gpu: nova-core: use projection for PFALCON and PFALCON2 registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-12-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=44579; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=D0QIW3gLEGUq1PEvmPOkulzpq9vZOkliiKGcHUHy1vU=; b=QT12oPLuA3Yzws/aAunhjNwrRjt2WU/eIq5CUq0a9pTcO+oHgcMJ2alFMFbu/twtiamdEblFw j1/UC44PYESDZhKWQY9dYd5q8S+XY97oCHpAo+ePSbZJ08/KcKHNZMK X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 494e9595-6c3b-4152-6316-08defde276a9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|6133799003|3023799007|56012099006|10067099003|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: 8l8tW0kSKP5hhevUSrYqwj4OMuD/t6+nZKNrNiPadUemurSp33G1y+vp+7pM8BZZZtSMc1FZR2GiBO+J7r/yBZYsHPzrGwWnhsWVLNqxlxOJC/vK2EZNwFYAS7rBU4+Vtda6Z7TtjMiA7h/eEgsQLhehrbguPHdheHwVtk36Lz+WyjQogwN7k8dHZWtzYLyxWlukY9UMFUGBLX0NPQ82XzK9wlvqaqXpMlGuR3Br5CBuw89T5sQoigPmhMzTv4R/N2AoVOfSe+bW9uMfcmLE4/doq3CawKHkhApBNWSQ9jNtnBYoQXsXxLv7GhtYK+CJbdhKknXd0QNLW2fCjLETS6zlg6/jcfdc4s5qsWjNDqX3sLCiPkt5muk2RRODguq4xGL7P3HFvxYstzLXmN65jChL8lRL/CkiQuWqCASnjkHl7ZPbSjTvxzQSh/e0XtmQ0Y6ePcTs0QXX3KJ9X1ESaoxCtumat5C0DI0U2rCLGnU6ZTwHpIabQVrbtx51K3uM6rcNqP4Lm5pBQdO20f9XTFmq0ksmAhJGoF2cuaPiAKaITPR3ZCJrDxxGDyDdciIFi6yhuOXHeUt9fl/iJS6d0DcQxEg1vAeImz/+PLlpGiVczm1flveU4JUJV7Skq33gIRuVlGr1wbh3QWsU+RXWTZvMDu3awV8a1c8J3MTQPlF6sOZby0MC0HwebALXli0kuWuqsdpXSSY8tSX8xrBGig== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(6133799003)(3023799007)(56012099006)(10067099003)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dUJaR1duT3Zlc1l2V0kxNDhkckRSUnlMWjEwWkwvbUhqZDE3OUh1aTVteHRo?= =?utf-8?B?aUdWOFRVamtuRVJpVVN2NGNUL01GWXFRYTNjOWNWRkhndTlEL1NrRENOMTZs?= =?utf-8?B?Q1BhcEVzRFdhK2RrRUZlRnJWQkk5RXV2MWJRWk5GM2xYU3kvUnIrNm1xZXUv?= =?utf-8?B?WUoxVC9ycFNiZTZkZUptQXFHUGlocjV4L1FYUkVvOUdhaFpCTk9ZdnBXYWhM?= =?utf-8?B?TFFXWmp1S1BQZG9zMTNaczFEMG40NGpRRzEwVnNoQ1pXTXZ2Wm05TTg3WCsw?= =?utf-8?B?L29EeWpXak1ieGZwbkJlek5PZGZMVFR4U3dCTFVabEhWdFRlTGZ1QkZKTUM1?= =?utf-8?B?cGhVeTBpYm85NENTbS96dVI5a1NlNWE4VkNPb2Y3U0pjZGV4N1JhVzlVOHFO?= =?utf-8?B?TW1jU1JCYUJLa0ZMSHFRUWJ3N1NldGlNWkF2bkJYN0kvZUNWTUwyamFMOFJy?= =?utf-8?B?MHJvbDVmWWVROW0zbmRKSHgrWjRDcGJvWEZ6UUQycUt4UW55K0VMZ2IvSjVQ?= =?utf-8?B?bGdhRUJ6clBsTks2a0lJQ00zMDR4TVdnY256VTY5WXJrbWU1SlNnMi9zdDlC?= =?utf-8?B?Y243WFNFSlVmNys5NjlHdGtNcXdiYmxpWnhyd3RpWVdYYXphektNNWt4NHJ5?= =?utf-8?B?a29IU2d4MFhHTmtxT29DdXBtZndpSWtPbjZoeVJ6c3k3aTd4RHpXMWdkUWNn?= =?utf-8?B?N0JPdGhOQlNQRlJlOE5qT3JOUWZYK0FiRmtBdVR3a2hDai9mY2J1UmoyQXVM?= =?utf-8?B?ajN3eitZcTJyY3B6cFphM1hRVnNZcWxiS2J1WitpRzdUK3MwZU92b3YyamE0?= =?utf-8?B?K0h2eUZSMWF6Z3dhSVVyZW9xenlPUEszYTVOT1FZbkJsc3M3MEhEclVQUTNi?= =?utf-8?B?Z3pFbXhBd3lFYWpoenhpeWZwUXMweTB6M2NMUWxGM2hJbUdnUEhXR3NCWVpV?= =?utf-8?B?N1d0cFUxMDJMQXFVSmdlY2o4L2FpalpBelk5cDNSYkFYUDhnWVNleUZ2SzFw?= =?utf-8?B?NW5HK2VpbzV0N2JiUEwyZUNFRElZMWRqOFZ3bDNqK1JUQk43NS9Jak9xMXVi?= =?utf-8?B?dFFscmJ4NUVsZTVPTHdjbnkyOGdqcFlxOEdXSE1VUUN4Tjk2bHRhS014bkds?= =?utf-8?B?Q0ovdklqdlUvd0wrSVB5ZmFmRnZhSHdwZ0RmRmduNEZtT21qb1prdHc0SlNC?= =?utf-8?B?YmpNV1QxTEhKeGtiZDdYUGNEZUV5dGQ3V1BlRnpKRGlLTjdNcitVRDVhZ2F2?= =?utf-8?B?amJqblNvbitHSUI2aHdBRkFlbURCRlNTU3lDb0ZtSWpzMmkwOStCZzc1Mks0?= =?utf-8?B?NXRzelJjOTV6b1p3K3J3Wk8vaDA5NnZHbE91Ujg5eG5pSFhubmhLRStPdGhs?= =?utf-8?B?OWFJZkRtMVlHZnhEVmc5ZnU5MHhrZFE2WWlPQVYrdkgwMmdwamxYSEpoNWEx?= =?utf-8?B?RGFmeTA3K3A3MTZiRDBFdGllK1hDc1psUzNXVUZIdFBPRmNpM0h6aGtjVUpa?= =?utf-8?B?QkkyclN5ajltcG4waVZ2cGFsWEFVVnNGYXRjVmwxVThCTHJFR0xzR09vbGxO?= =?utf-8?B?bmFCQWI1VnljbkVOK0N1dVczMkYrSkZxc0oyeWxVZ2wzVmltaG9xM0VaNmNp?= =?utf-8?B?cVlVKzlFTDNVcjJUSWlGdVExTTQ5Z0tiWEtmY2Y4anZjNHE4M1NFbkI3bi8x?= =?utf-8?B?VzBHNVhQZmxhNWJjeW1TVDRZKzZXb2JmemVpVVk5aE9WZ1pBdUVpTDdwVlBU?= =?utf-8?B?dVRzZXhQYkc5anl4azdZeXFFSWtxZlhPYTJKcVpnREx5OTNPZHlkQzByNHg0?= =?utf-8?B?cnpNTGhsTEZPZUdVNkxMVENoT2JkbW5NNXFJMGRzOGRlcG8rVFhFelI3emJ6?= =?utf-8?B?VVVhQytKR09lenExUjMwSkJ1djhpRU5KMzdDN3dLY2VpUzFaZ3dRaW1PbWtT?= =?utf-8?B?TU9YeGRuM1FUWFM1aTFTK2ZTUVppUVZRNS9TVGhBTi81cDQ0MnhJWUc5d1RK?= =?utf-8?B?VG42ZmthQkdaOFlGRmJIbHlYNzE1UGhYVnA0b2VtMHZxYzZHL1gzV053Yit2?= =?utf-8?B?UDVKOWVGRkRCelgyMFdtWEVlRmhQR1E4djVYVFdGbW9TRzFCMDJHbjI0NmZu?= =?utf-8?B?bkFMN1o2SnpGL3pCR2RFcGxaR3BYeUlqYWFCTUdCVFpvYk1vMUJ1MEp2aG5l?= =?utf-8?B?TUtVUnd6bGJ2aDBFc0p0NmJBakxYNG1ZS2d2SzcyZ1p6ODVLRmk0UGVXajJZ?= =?utf-8?B?MXFRemh5dS9YSVZZVS9QdXpyRU9mSEpMRmEwR3l4NEczcW9paGN3dU5VUGRj?= =?utf-8?B?V0JNUWtySlNqMlVHajZTazJFSmtOckZSdWUwb3drb2hDQnBaLzQ4Zz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 494e9595-6c3b-4152-6316-08defde276a9 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:22.9821 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 6G+zbuD2RMZu1HVNrNdkpStZSGXcEYATurnqvWq1ZJX8COW/W2AtzKEw4SCzUom0zwvfPr/KpmHPIrAojVZJnw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 Add fixed size region types `PFalconRegisters` and `PFalcon2Registers` and update PFALCON and PFALCON2 registers to be fixed register on them and not relative registers on `NovaRegisters`. Update `Falcon` struct to store projected views when constructing and access with `self.pfalcon` and `self.pfalcon2`. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- drivers/gpu/nova-core/falcon.rs | 157 +++++++++--------= ---- drivers/gpu/nova-core/falcon/fsp.rs | 63 +++++---- drivers/gpu/nova-core/falcon/gsp.rs | 51 ++++--- drivers/gpu/nova-core/falcon/hal/ga102.rs | 62 ++++---- drivers/gpu/nova-core/falcon/hal/tu102.rs | 9 +- drivers/gpu/nova-core/falcon/sec2.rs | 37 +++-- drivers/gpu/nova-core/firmware/fwsec/bootloader.rs | 18 +-- drivers/gpu/nova-core/gsp/hal/tu102.rs | 7 +- drivers/gpu/nova-core/regs.rs | 92 ++++++------ 9 files changed, 238 insertions(+), 258 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon= .rs index 65cb12d26e2b..119d305e2ea3 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -14,13 +14,12 @@ io::{ io_project, poll::read_poll_timeout, - register::{ - RegisterBase, - WithBase, // - }, + register::Array, Io, + Mmio, // }, prelude::*, + sizes::SZ_4K, time::Delta, }; =20 @@ -165,18 +164,22 @@ pub(crate) enum FalconFbifMemType with From> { } } =20 -/// Type used to represent the `PFALCON` registers address base for a give= n falcon engine. -pub(crate) struct PFalconBase(()); +/// Type used to represent the `PFALCON` registers. +#[repr(align(4))] +#[derive(FromBytes, IntoBytes)] +pub(crate) struct PFalconRegisters([u8; SZ_4K]); =20 -/// Type used to represent the `PFALCON2` registers address base for a giv= en falcon engine. -pub(crate) struct PFalcon2Base(()); +/// Type used to represent the `PFALCON2` registers. +#[repr(align(4))] +#[derive(FromBytes, IntoBytes)] +pub(crate) struct PFalcon2Registers([u8; SZ_4K]); =20 /// Trait defining the parameters of a given Falcon engine. /// /// Each engine provides one base for `PFALCON` and `PFALCON2` registers. -pub(crate) trait FalconEngine: - Send + Sync + RegisterBase + RegisterBase += Sized -{ +pub(crate) trait FalconEngine: Send + Sync + Sized { + fn pfalcon(io: Bar0<'_>) -> Mmio<'_, PFalconRegisters>; + fn pfalcon2(io: Bar0<'_>) -> Mmio<'_, PFalcon2Registers>; } =20 /// Represents a portion of the firmware to be loaded into a particular me= mory (e.g. IMEM or DMEM) @@ -358,6 +361,8 @@ pub(crate) struct Falcon<'a, E: FalconEngine> { hal: KBox>, dev: &'a device::Device, bar: Bar0<'a>, + pub(crate) pfalcon: Mmio<'a, PFalconRegisters>, + pfalcon2: Mmio<'a, PFalcon2Registers>, } =20 impl<'a, E: FalconEngine + 'static> Falcon<'a, E> { @@ -371,19 +376,19 @@ pub(crate) fn new( hal: hal::falcon_hal(chipset)?, dev, bar, + pfalcon: E::pfalcon(bar), + pfalcon2: E::pfalcon2(bar), }) } =20 /// Resets DMA-related registers. pub(crate) fn dma_reset(&self) { - self.bar.update(regs::NV_PFALCON_FBIF_CTL::of::(), |v| { + self.pfalcon.update(regs::NV_PFALCON_FBIF_CTL, |v| { v.with_allow_phys_no_ctx(true) }); =20 - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_DMACTL::zeroed(), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_DMACTL::zeroed()); } =20 /// Reset the controller, select the falcon core, and wait for memory = scrubbing to complete. @@ -392,10 +397,9 @@ pub(crate) fn reset(&self) -> Result { self.hal.select_core(self)?; self.hal.reset_wait_mem_scrubbing(self)?; =20 - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_RM::from(self.bar.read(regs::NV_PMC_BO= OT_0).into_raw()), - ); + self.pfalcon.write_reg(regs::NV_PFALCON_FALCON_RM::from( + self.bar.read(regs::NV_PMC_BOOT_0).into_raw(), + )); =20 Ok(()) } @@ -413,8 +417,8 @@ fn pio_wr_imem_slice(&self, load_offsets: FalconPioImem= LoadTarget<'_>) -> Result return Err(EINVAL); } =20 - self.bar.write( - WithBase::of::().at(Self::PIO_PORT), + self.pfalcon.write( + Array::at(Self::PIO_PORT), regs::NV_PFALCON_FALCON_IMEMC::zeroed() .with_secure(load_offsets.secure) .with_aincw(true) @@ -424,14 +428,14 @@ fn pio_wr_imem_slice(&self, load_offsets: FalconPioIm= emLoadTarget<'_>) -> Result for (n, block) in load_offsets.data.chunks(MEM_BLOCK_ALIGNMENT).en= umerate() { let n =3D u16::try_from(n)?; let tag: u16 =3D load_offsets.start_tag.checked_add(n).ok_or(E= RANGE)?; - self.bar.write( - WithBase::of::().at(Self::PIO_PORT), + self.pfalcon.write( + Array::at(Self::PIO_PORT), regs::NV_PFALCON_FALCON_IMEMT::zeroed().with_tag(tag), ); for word in block.chunks_exact(4) { let w =3D [word[0], word[1], word[2], word[3]]; - self.bar.write( - WithBase::of::().at(Self::PIO_PORT), + self.pfalcon.write( + Array::at(Self::PIO_PORT), regs::NV_PFALCON_FALCON_IMEMD::zeroed().with_data(u32:= :from_le_bytes(w)), ); } @@ -450,8 +454,8 @@ fn pio_wr_dmem_slice(&self, load_offsets: FalconPioDmem= LoadTarget<'_>) -> Result return Err(EINVAL); } =20 - self.bar.write( - WithBase::of::().at(Self::PIO_PORT), + self.pfalcon.write( + Array::at(Self::PIO_PORT), regs::NV_PFALCON_FALCON_DMEMC::zeroed() .with_aincw(true) .with_offs(load_offsets.dst_start), @@ -459,8 +463,8 @@ fn pio_wr_dmem_slice(&self, load_offsets: FalconPioDmem= LoadTarget<'_>) -> Result =20 for word in load_offsets.data.chunks_exact(4) { let w =3D [word[0], word[1], word[2], word[3]]; - self.bar.write( - WithBase::of::().at(Self::PIO_PORT), + self.pfalcon.write( + Array::at(Self::PIO_PORT), regs::NV_PFALCON_FALCON_DMEMD::zeroed().with_data(u32::fro= m_le_bytes(w)), ); } @@ -473,14 +477,12 @@ pub(crate) fn pio_load + FalconPioLoadable>( &self, fw: &F, ) -> Result { - self.bar.update(regs::NV_PFALCON_FBIF_CTL::of::(), |v| { + self.pfalcon.update(regs::NV_PFALCON_FBIF_CTL, |v| { v.with_allow_phys_no_ctx(true) }); =20 - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_DMACTL::zeroed(), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_DMACTL::zeroed()); =20 if let Some(imem_ns) =3D fw.imem_ns_load_params() { self.pio_wr_imem_slice(imem_ns)?; @@ -492,10 +494,8 @@ pub(crate) fn pio_load= + FalconPioLoadable>( =20 self.hal.program_brom(self, &fw.brom_params()); =20 - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_a= ddr()), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_valu= e(fw.boot_addr())); =20 Ok(()) } @@ -547,16 +547,13 @@ fn dma_wr( =20 // Set up the base source DMA address. =20 - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_DMATRFBASE::zeroed().with_base( + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_DMATRFBASE::zeroed().with_b= ase( // CAST: `as u32` is used on purpose since we do want to s= trip the upper bits, // which will be written to `NV_PFALCON_FALCON_DMATRFBASE1= `. (dma_address >> 8) as u32, - ), - ); - self.bar.write( - WithBase::of::(), + )); + self.pfalcon.write_reg( regs::NV_PFALCON_FALCON_DMATRFBASE1::zeroed().try_with_base(dm= a_address >> 40)?, ); =20 @@ -566,23 +563,21 @@ fn dma_wr( =20 for pos in (0..num_transfers).map(|i| i * DMA_LEN) { // Perform a transfer of size `DMA_LEN`. - self.bar.write( - WithBase::of::(), + self.pfalcon.write_reg( regs::NV_PFALCON_FALCON_DMATRFMOFFS::zeroed() .try_with_offs(load_offsets.dst_start + pos)?, ); - self.bar.write( - WithBase::of::(), + self.pfalcon.write_reg( regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed().with_offs(s= rc_start + pos), ); =20 - self.bar.write(WithBase::of::(), cmd); + self.pfalcon.write_reg(cmd); =20 // Wait for the transfer to complete. // TIMEOUT: arbitrarily large value, no DMA transfer to the fa= lcon's small memories // should ever take that long. read_poll_timeout( - || Ok(self.bar.read(regs::NV_PFALCON_FALCON_DMATRFCMD::of:= :())), + || Ok(self.pfalcon.read(regs::NV_PFALCON_FALCON_DMATRFCMD)= ), |r| r.idle(), Delta::ZERO, Delta::from_secs(2), @@ -614,8 +609,8 @@ fn dma_load + FalconDma= Loadable>(&self, fw: &F) -> }; =20 self.dma_reset(); - self.bar - .update(regs::NV_PFALCON_FBIF_TRANSCFG::of::().at(0), |v| { + self.pfalcon + .update(regs::NV_PFALCON_FBIF_TRANSCFG::at(0), |v| { v.with_target(FalconFbifTarget::CoherentSysmem) .with_mem_type(FalconFbifMemType::Physical) }); @@ -626,10 +621,8 @@ fn dma_load + FalconDm= aLoadable>(&self, fw: &F) -> self.hal.program_brom(self, &fw.brom_params()); =20 // Set `BootVec` to start of non-secure code. - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_a= ddr()), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_valu= e(fw.boot_addr())); =20 Ok(()) } @@ -638,7 +631,7 @@ fn dma_load + FalconDma= Loadable>(&self, fw: &F) -> pub(crate) fn wait_till_halted(&self) -> Result<()> { // TIMEOUT: arbitrarily large value, firmwares should complete in = less than 2 seconds. read_poll_timeout( - || Ok(self.bar.read(regs::NV_PFALCON_FALCON_CPUCTL::of::())= ), + || Ok(self.pfalcon.read(regs::NV_PFALCON_FALCON_CPUCTL)), |r| r.halted(), Delta::ZERO, Delta::from_secs(2), @@ -649,19 +642,13 @@ pub(crate) fn wait_till_halted(&self) -> Result<()> { =20 /// Start the falcon CPU. pub(crate) fn start(&self) -> Result<()> { - match self - .bar - .read(regs::NV_PFALCON_FALCON_CPUCTL::of::()) - .alias_en() - { - true =3D> self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed().with_startc= pu(true), - ), - false =3D> self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_CPUCTL::zeroed().with_startcpu(tru= e), - ), + match self.pfalcon.read(regs::NV_PFALCON_FALCON_CPUCTL).alias_en()= { + true =3D> self + .pfalcon + .write_reg(regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed().= with_startcpu(true)), + false =3D> self + .pfalcon + .write_reg(regs::NV_PFALCON_FALCON_CPUCTL::zeroed().with_s= tartcpu(true)), } =20 Ok(()) @@ -670,32 +657,24 @@ pub(crate) fn start(&self) -> Result<()> { /// Writes values to the mailbox registers if provided. pub(crate) fn write_mailboxes(&self, mbox0: Option, mbox1: Option= ) { if let Some(mbox0) =3D mbox0 { - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_MAILBOX0::zeroed().with_value(mbox= 0), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_MAILBOX0::zeroed().with= _value(mbox0)); } =20 if let Some(mbox1) =3D mbox1 { - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_MAILBOX1::zeroed().with_value(mbox= 1), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_MAILBOX1::zeroed().with= _value(mbox1)); } } =20 /// Reads the value from `mbox0` register. pub(crate) fn read_mailbox0(&self) -> u32 { - self.bar - .read(regs::NV_PFALCON_FALCON_MAILBOX0::of::()) - .value() + self.pfalcon.read(regs::NV_PFALCON_FALCON_MAILBOX0).value() } =20 /// Reads the value from `mbox1` register. pub(crate) fn read_mailbox1(&self) -> u32 { - self.bar - .read(regs::NV_PFALCON_FALCON_MAILBOX1::of::()) - .value() + self.pfalcon.read(regs::NV_PFALCON_FALCON_MAILBOX1).value() } =20 /// Reads values from both mailbox registers. @@ -760,9 +739,7 @@ pub(crate) fn load + Fa= lconDmaLoadable>(&self, fw: =20 /// Write the application version to the OS register. pub(crate) fn write_os_version(&self, app_version: u32) { - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_OS::zeroed().with_value(app_version), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_OS::zeroed().with_value(app= _version)); } } diff --git a/drivers/gpu/nova-core/falcon/fsp.rs b/drivers/gpu/nova-core/fa= lcon/fsp.rs index 0437180b8829..85f9c8c5d60e 100644 --- a/drivers/gpu/nova-core/falcon/fsp.rs +++ b/drivers/gpu/nova-core/falcon/fsp.rs @@ -8,13 +8,12 @@ =20 use kernel::{ io::{ + io_project, poll::read_poll_timeout, - register::{ - Array, - RegisterBase, - WithBase, // - }, - Io, // + register, + register::Array, + Io, + Mmio, // }, prelude::*, sizes::SZ_1K, @@ -22,11 +21,13 @@ }; =20 use crate::{ + driver::{ + Bar0, + NovaRegisters, // + }, falcon::{ Falcon, - FalconEngine, - PFalcon2Base, - PFalconBase, // + FalconEngine, // }, num, regs, // @@ -41,15 +42,24 @@ /// Type specifying the `Fsp` falcon engine. Cannot be instantiated. pub(crate) struct Fsp(()); =20 -impl RegisterBase for Fsp { - const BASE: usize =3D 0x8f2000; -} +register! { + base: NovaRegisters; =20 -impl RegisterBase for Fsp { - const BASE: usize =3D 0x8f3000; + PFALCON: super::PFalconRegisters @ 0x8f2000; + PFALCON2: super::PFalcon2Registers @ 0x8f3000; } =20 -impl FalconEngine for Fsp {} +impl FalconEngine for Fsp { + #[inline] + fn pfalcon(io: Bar0<'_>) -> Mmio<'_, super::PFalconRegisters> { + io_project!(io, build: PFALCON) + } + + #[inline] + fn pfalcon2(io: Bar0<'_>) -> Mmio<'_, super::PFalcon2Registers> { + io_project!(io, build: PFALCON2) + } +} =20 impl<'a> Falcon<'a, Fsp> { /// Writes `data` to FSP external memory at offset `0`. @@ -62,19 +72,15 @@ fn write_emem(&mut self, data: &[u8]) -> Result { } =20 // Begin a write burst at offset `0`, auto-incrementing on each wr= ite. - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincw(true), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincw(= true)); =20 for chunk in data.chunks_exact(4) { let value =3D u32::from_le_bytes([chunk[0], chunk[1], chunk[2]= , chunk[3]]); =20 // Write the next 32-bit `value`; hardware advances the offset. - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_EMEMD::zeroed().with_data(value), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_EMEMD::zeroed().with_da= ta(value)); } =20 Ok(()) @@ -90,17 +96,12 @@ fn read_emem(&mut self, data: &mut [u8]) -> Result { } =20 // Begin a read burst at offset `0`, auto-incrementing on each rea= d. - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincr(true), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincr(= true)); =20 for chunk in data.chunks_exact_mut(4) { // Read the next 32-bit word; hardware advances the offset. - let value =3D self - .bar - .read(regs::NV_PFALCON_FALCON_EMEMD::of::()) - .data(); + let value =3D self.pfalcon.read(regs::NV_PFALCON_FALCON_EMEMD)= .data(); chunk.copy_from_slice(&value.to_le_bytes()); } =20 diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/fa= lcon/gsp.rs index ae32f401aeb0..4c96ae325fda 100644 --- a/drivers/gpu/nova-core/falcon/gsp.rs +++ b/drivers/gpu/nova-core/falcon/gsp.rs @@ -2,23 +2,24 @@ =20 use kernel::{ io::{ + io_project, poll::read_poll_timeout, - register::{ - RegisterBase, - WithBase, // - }, + register, Io, + Mmio, // }, prelude::*, time::Delta, // }; =20 use crate::{ + driver::{ + Bar0, + NovaRegisters, // + }, falcon::{ Falcon, - FalconEngine, - PFalcon2Base, - PFalconBase, // + FalconEngine, // }, regs, }; @@ -26,24 +27,31 @@ /// Type specifying the `Gsp` falcon engine. Cannot be instantiated. pub(crate) struct Gsp(()); =20 -impl RegisterBase for Gsp { - const BASE: usize =3D 0x00110000; -} +register! { + base: NovaRegisters; =20 -impl RegisterBase for Gsp { - const BASE: usize =3D 0x00111000; + PFALCON: super::PFalconRegisters @ 0x00110000; + PFALCON2: super::PFalcon2Registers @ 0x00111000; } =20 -impl FalconEngine for Gsp {} +impl FalconEngine for Gsp { + #[inline] + fn pfalcon(io: Bar0<'_>) -> Mmio<'_, super::PFalconRegisters> { + io_project!(io, build: PFALCON) + } + + #[inline] + fn pfalcon2(io: Bar0<'_>) -> Mmio<'_, super::PFalcon2Registers> { + io_project!(io, build: PFALCON2) + } +} =20 impl<'a> Falcon<'a, Gsp> { /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to /// allow GSP to signal CPU for processing new messages in message que= ue. pub(crate) fn clear_swgen0_intr(&self) { - self.bar.write( - WithBase::of::(), - regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swgen0(true), - ); + self.pfalcon + .write_reg(regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swge= n0(true)); } =20 /// Checks if GSP reload/resume has completed during the boot process. @@ -59,8 +67,8 @@ pub(crate) fn check_reload_completed(&self, timeout: Delt= a) -> Result { =20 /// Returns whether the RISC-V branch privilege lockdown bit is set. pub(crate) fn riscv_branch_privilege_lockdown(&self) -> bool { - self.bar - .read(regs::NV_PFALCON_FALCON_HWCFG2::of::()) + self.pfalcon + .read(regs::NV_PFALCON_FALCON_HWCFG2) .riscv_br_priv_lockdown() } =20 @@ -71,10 +79,7 @@ pub(crate) fn priv_target_mask_released(&self) -> bool { const LOCKED_PATTERN: u32 =3D 0xbadf_4100; const LOCKED_MASK: u32 =3D 0xffff_ff00; =20 - let hwcfg2 =3D self - .bar - .read(regs::NV_PFALCON_FALCON_HWCFG2::of::()) - .into_raw(); + let hwcfg2 =3D self.pfalcon.read(regs::NV_PFALCON_FALCON_HWCFG2).i= nto_raw(); =20 hwcfg2 !=3D 0 && (hwcfg2 & LOCKED_MASK) !=3D LOCKED_PATTERN } diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-c= ore/falcon/hal/ga102.rs index 7600ee07ca2e..7880c145f8f7 100644 --- a/drivers/gpu/nova-core/falcon/hal/ga102.rs +++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs @@ -6,11 +6,9 @@ device, io::{ poll::read_poll_timeout, - register::{ - Array, - WithBase, // - }, - Io, // + register::Array, + Io, + Mmio, // }, prelude::*, time::Delta, // @@ -24,6 +22,7 @@ FalconBromParams, FalconEngine, FalconModSelAlgo, + PFalcon2Registers, PeregrineCoreSelect, // }, regs, @@ -31,17 +30,16 @@ =20 use super::FalconHal; =20 -fn select_core_ga102(bar: Bar0<'_>) -> Result { - let bcr_ctrl =3D bar.read(regs::NV_PRISCV_RISCV_BCR_CTRL::of::()); +fn select_core_ga102(pfalcon2: Mmio<'_, PFalcon2Registers>) -> Result { + let bcr_ctrl =3D pfalcon2.read(regs::NV_PRISCV_RISCV_BCR_CTRL); if bcr_ctrl.core_select() !=3D PeregrineCoreSelect::Falcon { - bar.write( - WithBase::of::(), + pfalcon2.write_reg( regs::NV_PRISCV_RISCV_BCR_CTRL::zeroed().with_core_select(Pere= grineCoreSelect::Falcon), ); =20 // TIMEOUT: falcon core should take less than 10ms to report being= enabled. read_poll_timeout( - || Ok(bar.read(regs::NV_PRISCV_RISCV_BCR_CTRL::of::())), + || Ok(pfalcon2.read(regs::NV_PRISCV_RISCV_BCR_CTRL)), |r| r.valid(), Delta::ZERO, Delta::from_millis(10), @@ -86,24 +84,23 @@ fn signature_reg_fuse_version_ga102( Ok(u16::BITS - reg_fuse_version.leading_zeros()) } =20 -fn program_brom_ga102(bar: Bar0<'_>, params: &FalconBromP= arams) { - bar.write( - WithBase::of::().at(0), +fn program_brom_ga102( + pfalcon2: Mmio<'_, PFalcon2Registers>, + params: &FalconBromParams, +) { + pfalcon2.write( + Array::at(0), regs::NV_PFALCON2_FALCON_BROM_PARAADDR::zeroed().with_value(params= .pkc_data_offset), ); - bar.write( - WithBase::of::(), + pfalcon2.write_reg( regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::zeroed() .with_value(u32::from(params.engine_id_mask)), ); - bar.write( - WithBase::of::(), + pfalcon2.write_reg( regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::zeroed().with_ucode_i= d(params.ucode_id), ); - bar.write( - WithBase::of::(), - regs::NV_PFALCON2_FALCON_MOD_SEL::zeroed().with_algo(FalconModSelA= lgo::Rsa3k), - ); + pfalcon2 + .write_reg(regs::NV_PFALCON2_FALCON_MOD_SEL::zeroed().with_algo(Fa= lconModSelAlgo::Rsa3k)); } =20 pub(super) struct Ga102(PhantomData); @@ -116,7 +113,7 @@ pub(super) fn new() -> Self { =20 impl FalconHal for Ga102 { fn select_core(&self, falcon: &Falcon<'_, E>) -> Result { - select_core_ga102::(falcon.bar) + select_core_ga102(falcon.pfalcon2) } =20 fn signature_reg_fuse_version( @@ -129,27 +126,24 @@ fn signature_reg_fuse_version( } =20 fn program_brom(&self, falcon: &Falcon<'_, E>, params: &FalconBromPara= ms) { - program_brom_ga102::(falcon.bar, params); + program_brom_ga102(falcon.pfalcon2, params); } =20 fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool { falcon - .bar - .read(regs::NV_PRISCV_RISCV_CPUCTL::of::()) + .pfalcon2 + .read(regs::NV_PRISCV_RISCV_CPUCTL) .active_stat() } =20 fn is_riscv_halted(&self, falcon: &Falcon<'_, E>) -> Result { - Ok(falcon - .bar - .read(regs::NV_PRISCV_RISCV_CPUCTL::of::()) - .halted()) + Ok(falcon.pfalcon2.read(regs::NV_PRISCV_RISCV_CPUCTL).halted()) } =20 fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result { // TIMEOUT: memory scrubbing should complete in less than 20ms. read_poll_timeout( - || Ok(falcon.bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::(= ))), + || Ok(falcon.pfalcon.read(regs::NV_PFALCON_FALCON_HWCFG2)), |r| r.mem_scrubbing_done(), Delta::ZERO, Delta::from_millis(20), @@ -158,20 +152,18 @@ fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_= , E>) -> Result { } =20 fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result { - let bar =3D falcon.bar; - - let _ =3D bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::()); + let _ =3D falcon.pfalcon.read(regs::NV_PFALCON_FALCON_HWCFG2); =20 // According to OpenRM's `kflcnPreResetWait_GA102` documentation, = HW sometimes does not set // RESET_READY so a non-failing timeout is used. let _ =3D read_poll_timeout( - || Ok(bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::())), + || Ok(falcon.pfalcon.read(regs::NV_PFALCON_FALCON_HWCFG2)), |r| r.reset_ready(), Delta::ZERO, Delta::from_micros(150), ); =20 - regs::NV_PFALCON_FALCON_ENGINE::reset_engine::(bar); + regs::NV_PFALCON_FALCON_ENGINE::reset_engine(falcon.pfalcon); self.reset_wait_mem_scrubbing(falcon)?; =20 Ok(()) diff --git a/drivers/gpu/nova-core/falcon/hal/tu102.rs b/drivers/gpu/nova-c= ore/falcon/hal/tu102.rs index 5291598fedf7..7fc6e83c2566 100644 --- a/drivers/gpu/nova-core/falcon/hal/tu102.rs +++ b/drivers/gpu/nova-core/falcon/hal/tu102.rs @@ -5,7 +5,6 @@ use kernel::{ io::{ poll::read_poll_timeout, - register::WithBase, Io, // }, prelude::*, @@ -50,8 +49,8 @@ fn program_brom(&self, _falcon: &Falcon<'_, E>, _params: = &FalconBromParams) {} =20 fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool { falcon - .bar - .read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::of::(= )) + .pfalcon2 + .read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS) .active_stat() } =20 @@ -62,7 +61,7 @@ fn is_riscv_halted(&self, _falcon: &Falcon<'_, E>) -> Res= ult { fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result { // TIMEOUT: memory scrubbing should complete in less than 10ms. read_poll_timeout( - || Ok(falcon.bar.read(regs::NV_PFALCON_FALCON_DMACTL::of::(= ))), + || Ok(falcon.pfalcon.read(regs::NV_PFALCON_FALCON_DMACTL)), |r| r.mem_scrubbing_done(), Delta::ZERO, Delta::from_millis(10), @@ -71,7 +70,7 @@ fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>= ) -> Result { } =20 fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result { - regs::NV_PFALCON_FALCON_ENGINE::reset_engine::(falcon.bar); + regs::NV_PFALCON_FALCON_ENGINE::reset_engine(falcon.pfalcon); self.reset_wait_mem_scrubbing(falcon)?; =20 Ok(()) diff --git a/drivers/gpu/nova-core/falcon/sec2.rs b/drivers/gpu/nova-core/f= alcon/sec2.rs index 91ec7d49c1f5..6648a397d38a 100644 --- a/drivers/gpu/nova-core/falcon/sec2.rs +++ b/drivers/gpu/nova-core/falcon/sec2.rs @@ -1,22 +1,37 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::io::register::RegisterBase; +use kernel::io::{ + io_project, + register, + Mmio, // +}; =20 -use crate::falcon::{ - FalconEngine, - PFalcon2Base, - PFalconBase, // +use crate::{ + driver::{ + Bar0, + NovaRegisters, // + }, + falcon::FalconEngine, // }; =20 /// Type specifying the `Sec2` falcon engine. Cannot be instantiated. pub(crate) struct Sec2(()); =20 -impl RegisterBase for Sec2 { - const BASE: usize =3D 0x00840000; -} +register! { + base: NovaRegisters; =20 -impl RegisterBase for Sec2 { - const BASE: usize =3D 0x00841000; + PFALCON: super::PFalconRegisters @ 0x00840000; + PFALCON2: super::PFalcon2Registers @ 0x00841000; } =20 -impl FalconEngine for Sec2 {} +impl FalconEngine for Sec2 { + #[inline] + fn pfalcon(io: Bar0<'_>) -> Mmio<'_, super::PFalconRegisters> { + io_project!(io, build: PFALCON) + } + + #[inline] + fn pfalcon2(io: Bar0<'_>) -> Mmio<'_, super::PFalcon2Registers> { + io_project!(io, build: PFALCON2) + } +} diff --git a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs b/drivers/g= pu/nova-core/firmware/fwsec/bootloader.rs index ec4d92317a93..02a36fd59902 100644 --- a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs +++ b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs @@ -12,7 +12,10 @@ Device, // }, dma::Coherent, - io::{register::WithBase, Io}, + io::{ + register::Array, + Io, // + }, prelude::*, ptr::{ Alignable, @@ -23,7 +26,6 @@ }; =20 use crate::{ - driver::Bar0, falcon::{ self, gsp::Gsp, @@ -235,12 +237,7 @@ pub(crate) fn new( /// /// The bootloader will load the FWSEC firmware and then execute it. T= his function returns /// after FWSEC has reached completion. - pub(crate) fn run( - &self, - dev: &Device, - falcon: &Falcon<'_, Gsp>, - bar: Bar0<'_>, - ) -> Result<()> { + pub(crate) fn run(&self, dev: &Device, falcon: &Falcon<= '_, Gsp>) -> Result<()> { // Reset falcon, load the firmware, and run it. falcon .reset() @@ -250,9 +247,8 @@ pub(crate) fn run( .inspect_err(|e| dev_err!(dev, "Failed to load FWSEC firmware:= {:?}\n", e))?; =20 // Configure DMA index for the bootloader to fetch the FWSEC firmw= are from system memory. - bar.update( - regs::NV_PFALCON_FBIF_TRANSCFG::of::() - .try_at(usize::from_safe_cast(self.dmem_desc.ctx_dma)) + falcon.pfalcon.update( + regs::NV_PFALCON_FBIF_TRANSCFG::try_at(usize::from_safe_cast(s= elf.dmem_desc.ctx_dma)) .ok_or(EINVAL)?, |v| { v.with_target(FalconFbifTarget::CoherentSysmem) diff --git a/drivers/gpu/nova-core/gsp/hal/tu102.rs b/drivers/gpu/nova-core= /gsp/hal/tu102.rs index a5c0ca355493..d2ef35080689 100644 --- a/drivers/gpu/nova-core/gsp/hal/tu102.rs +++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs @@ -62,12 +62,11 @@ impl FwsecUnloadFirmware { fn run( &self, dev: &device::Device, - bar: Bar0<'_>, gsp_falcon: &Falcon<'_, GspEngine>, ) -> Result { match self { Self::WithoutBl(fw) =3D> fw.run(dev, gsp_falcon), - Self::WithBl(fw) =3D> fw.run(dev, gsp_falcon, bar), + Self::WithBl(fw) =3D> fw.run(dev, gsp_falcon), } } } @@ -88,7 +87,7 @@ fn run(&self, ctx: &mut GspBootContext<'_, '_>) -> Result= { // Log errors but keep going if it fails. let fwsec_sb_res =3D self .fwsec_sb - .run(dev, bar, ctx.gsp_falcon) + .run(dev, ctx.gsp_falcon) .inspect_err(|e| dev_err!(dev, "FWSEC-SB failed to run: {:?}\n= ", e)); =20 // Remove WPR2 region if set. @@ -168,7 +167,7 @@ fn run_fwsec_frts( if self.needs_fwsec_bootloader { let fwsec_frts_bl =3D FwsecFirmwareWithBl::new(fwsec_frts, dev= , chipset)?; // Load and run the bootloader, which will load FWSEC-FRTS and= run it. - fwsec_frts_bl.run(dev, falcon, bar)?; + fwsec_frts_bl.run(dev, falcon)?; } else { // Load and run FWSEC-FRTS directly. fwsec_frts.run(dev, falcon)?; diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index 1af073f3861f..90ac8dac5349 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -4,8 +4,8 @@ use kernel::{ io::{ register, - register::WithBase, - Io, // + Io, + Mmio, // }, prelude::*, sizes::SizeConstants, @@ -13,22 +13,18 @@ }; =20 use crate::{ - driver::{ - Bar0, - NovaRegisters, // - }, + driver::NovaRegisters, falcon::{ DmaTrfCmdSize, FalconCoreRev, FalconCoreRevSubversion, - FalconEngine, FalconFbifMemType, FalconFbifTarget, FalconMem, FalconModSelAlgo, FalconSecurityModel, - PFalcon2Base, - PFalconBase, + PFalcon2Registers, + PFalconRegisters, PeregrineCoreSelect, // }, gpu::{ @@ -202,32 +198,32 @@ pub(crate) fn usable_fb_size(self) -> u64 { // PFALCON =20 register! { - base: NovaRegisters; + base: PFalconRegisters; =20 - pub(crate) NV_PFALCON_FALCON_IRQSCLR(u32) @ PFalconBase + 0x00000004 { + pub(crate) NV_PFALCON_FALCON_IRQSCLR(u32) @ 0x00000004 { 6:6 swgen0 =3D> bool; 4:4 halt =3D> bool; } =20 - pub(crate) NV_PFALCON_FALCON_MAILBOX0(u32) @ PFalconBase + 0x00000040 { + pub(crate) NV_PFALCON_FALCON_MAILBOX0(u32) @ 0x00000040 { 31:0 value =3D> u32; } =20 - pub(crate) NV_PFALCON_FALCON_MAILBOX1(u32) @ PFalconBase + 0x00000044 { + pub(crate) NV_PFALCON_FALCON_MAILBOX1(u32) @ 0x00000044 { 31:0 value =3D> u32; } =20 /// Used to store version information about the firmware running /// on the Falcon processor. - pub(crate) NV_PFALCON_FALCON_OS(u32) @ PFalconBase + 0x00000080 { + pub(crate) NV_PFALCON_FALCON_OS(u32) @ 0x00000080 { 31:0 value =3D> u32; } =20 - pub(crate) NV_PFALCON_FALCON_RM(u32) @ PFalconBase + 0x00000084 { + pub(crate) NV_PFALCON_FALCON_RM(u32) @ 0x00000084 { 31:0 value =3D> u32; } =20 - pub(crate) NV_PFALCON_FALCON_HWCFG2(u32) @ PFalconBase + 0x000000f4 { + pub(crate) NV_PFALCON_FALCON_HWCFG2(u32) @ 0x000000f4 { /// Signal indicating that reset is completed (GA102+). 31:31 reset_ready =3D> bool; /// RISC-V branch privilege lockdown bit. @@ -237,17 +233,17 @@ pub(crate) fn usable_fb_size(self) -> u64 { 10:10 riscv =3D> bool; } =20 - pub(crate) NV_PFALCON_FALCON_CPUCTL(u32) @ PFalconBase + 0x00000100 { + pub(crate) NV_PFALCON_FALCON_CPUCTL(u32) @ 0x00000100 { 6:6 alias_en =3D> bool; 4:4 halted =3D> bool; 1:1 startcpu =3D> bool; } =20 - pub(crate) NV_PFALCON_FALCON_BOOTVEC(u32) @ PFalconBase + 0x00000104 { + pub(crate) NV_PFALCON_FALCON_BOOTVEC(u32) @ 0x00000104 { 31:0 value =3D> u32; } =20 - pub(crate) NV_PFALCON_FALCON_DMACTL(u32) @ PFalconBase + 0x0000010c { + pub(crate) NV_PFALCON_FALCON_DMACTL(u32) @ 0x0000010c { 7:7 secure_stat =3D> bool; 6:3 dmaq_num; 2:2 imem_scrubbing =3D> bool; @@ -255,15 +251,15 @@ pub(crate) fn usable_fb_size(self) -> u64 { 0:0 require_ctx =3D> bool; } =20 - pub(crate) NV_PFALCON_FALCON_DMATRFBASE(u32) @ PFalconBase + 0x0000011= 0 { + pub(crate) NV_PFALCON_FALCON_DMATRFBASE(u32) @ 0x00000110 { 31:0 base =3D> u32; } =20 - pub(crate) NV_PFALCON_FALCON_DMATRFMOFFS(u32) @ PFalconBase + 0x000001= 14 { + pub(crate) NV_PFALCON_FALCON_DMATRFMOFFS(u32) @ 0x00000114 { 23:0 offs; } =20 - pub(crate) NV_PFALCON_FALCON_DMATRFCMD(u32) @ PFalconBase + 0x00000118= { + pub(crate) NV_PFALCON_FALCON_DMATRFCMD(u32) @ 0x00000118 { 16:16 set_dmtag; 14:12 ctxdma; 10:8 size ?=3D> DmaTrfCmdSize; @@ -274,15 +270,15 @@ pub(crate) fn usable_fb_size(self) -> u64 { 0:0 full =3D> bool; } =20 - pub(crate) NV_PFALCON_FALCON_DMATRFFBOFFS(u32) @ PFalconBase + 0x00000= 11c { + pub(crate) NV_PFALCON_FALCON_DMATRFFBOFFS(u32) @ 0x0000011c { 31:0 offs =3D> u32; } =20 - pub(crate) NV_PFALCON_FALCON_DMATRFBASE1(u32) @ PFalconBase + 0x000001= 28 { + pub(crate) NV_PFALCON_FALCON_DMATRFBASE1(u32) @ 0x00000128 { 8:0 base; } =20 - pub(crate) NV_PFALCON_FALCON_HWCFG1(u32) @ PFalconBase + 0x0000012c { + pub(crate) NV_PFALCON_FALCON_HWCFG1(u32) @ 0x0000012c { /// Core revision subversion. 7:6 core_rev_subversion =3D> FalconCoreRevSubversion; /// Security model. @@ -291,12 +287,12 @@ pub(crate) fn usable_fb_size(self) -> u64 { 3:0 core_rev ?=3D> FalconCoreRev; } =20 - pub(crate) NV_PFALCON_FALCON_CPUCTL_ALIAS(u32) @ PFalconBase + 0x00000= 130 { + pub(crate) NV_PFALCON_FALCON_CPUCTL_ALIAS(u32) @ 0x00000130 { 1:1 startcpu =3D> bool; } =20 /// IMEM access control register. Up to 4 ports are available for IMEM= access. - pub(crate) NV_PFALCON_FALCON_IMEMC(u32)[4, stride =3D 16] @ PFalconBas= e + 0x00000180 { + pub(crate) NV_PFALCON_FALCON_IMEMC(u32)[4, stride =3D 16] @ 0x00000180= { /// Access secure IMEM. 28:28 secure =3D> bool; /// Auto-increment on write. @@ -307,17 +303,17 @@ pub(crate) fn usable_fb_size(self) -> u64 { =20 /// IMEM data register. Reading/writing this register accesses IMEM at= the address /// specified by the corresponding IMEMC register. - pub(crate) NV_PFALCON_FALCON_IMEMD(u32)[4, stride =3D 16] @ PFalconBas= e + 0x00000184 { + pub(crate) NV_PFALCON_FALCON_IMEMD(u32)[4, stride =3D 16] @ 0x00000184= { 31:0 data; } =20 /// IMEM tag register. Used to set the tag for the current IMEM block. - pub(crate) NV_PFALCON_FALCON_IMEMT(u32)[4, stride =3D 16] @ PFalconBas= e + 0x00000188 { + pub(crate) NV_PFALCON_FALCON_IMEMT(u32)[4, stride =3D 16] @ 0x00000188= { 15:0 tag; } =20 /// DMEM access control register. Up to 8 ports are available for DMEM= access. - pub(crate) NV_PFALCON_FALCON_DMEMC(u32)[8, stride =3D 8] @ PFalconBase= + 0x000001c0 { + pub(crate) NV_PFALCON_FALCON_DMEMC(u32)[8, stride =3D 8] @ 0x000001c0 { /// Auto-increment on write. 24:24 aincw =3D> bool; /// DMEM block and word offset. @@ -326,29 +322,29 @@ pub(crate) fn usable_fb_size(self) -> u64 { =20 /// DMEM data register. Reading/writing this register accesses DMEM at= the address /// specified by the corresponding DMEMC register. - pub(crate) NV_PFALCON_FALCON_DMEMD(u32)[8, stride =3D 8] @ PFalconBase= + 0x000001c4 { + pub(crate) NV_PFALCON_FALCON_DMEMD(u32)[8, stride =3D 8] @ 0x000001c4 { 31:0 data; } =20 /// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGI= NE` depending on the /// falcon instance. - pub(crate) NV_PFALCON_FALCON_ENGINE(u32) @ PFalconBase + 0x000003c0 { + pub(crate) NV_PFALCON_FALCON_ENGINE(u32) @ 0x000003c0 { 0:0 reset =3D> bool; } =20 - pub(crate) NV_PFALCON_FBIF_TRANSCFG(u32)[8] @ PFalconBase + 0x00000600= { + pub(crate) NV_PFALCON_FBIF_TRANSCFG(u32)[8] @ 0x00000600 { 2:2 mem_type =3D> FalconFbifMemType; 1:0 target ?=3D> FalconFbifTarget; } =20 - pub(crate) NV_PFALCON_FBIF_CTL(u32) @ PFalconBase + 0x00000624 { + pub(crate) NV_PFALCON_FBIF_CTL(u32) @ 0x00000624 { 7:7 allow_phys_no_ctx =3D> bool; } =20 // Falcon EMEM PIO registers (used by FSP on Hopper/Blackwell). // These provide the falcon external memory communication interface. =20 - pub(crate) NV_PFALCON_FALCON_EMEMC(u32) @ PFalconBase + 0x00000ac0 { + pub(crate) NV_PFALCON_FALCON_EMEMC(u32) @ 0x00000ac0 { /// EMEM byte offset (4-byte aligned) within the block. 7:2 offs; /// EMEM block to access. @@ -359,7 +355,7 @@ pub(crate) fn usable_fb_size(self) -> u64 { 25:25 aincr =3D> bool; } =20 - pub(crate) NV_PFALCON_FALCON_EMEMD(u32) @ PFalconBase + 0x00000ac4 { + pub(crate) NV_PFALCON_FALCON_EMEMD(u32) @ 0x00000ac4 { 31:0 data =3D> u32; } } @@ -385,13 +381,13 @@ pub(crate) fn with_falcon_mem(self, mem: FalconMem) -= > Self { =20 impl NV_PFALCON_FALCON_ENGINE { /// Resets the falcon - pub(crate) fn reset_engine(bar: Bar0<'_>) { - bar.update(Self::of::(), |r| r.with_reset(true)); + pub(crate) fn reset_engine(pfalcon: Mmio<'_, PFalconRegisters>) { + pfalcon.update(NV_PFALCON_FALCON_ENGINE, |r| r.with_reset(true)); =20 // TIMEOUT: falcon engine should not take more than 10us to reset. time::delay::fsleep(time::Delta::from_micros(10)); =20 - bar.update(Self::of::(), |r| r.with_reset(false)); + pfalcon.update(NV_PFALCON_FALCON_ENGINE, |r| r.with_reset(false)); } } =20 @@ -405,23 +401,23 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { /* PFALCON2 */ =20 register! { - base: NovaRegisters; + base: PFalcon2Registers; =20 - pub(crate) NV_PFALCON2_FALCON_MOD_SEL(u32) @ PFalcon2Base + 0x00000180= { + pub(crate) NV_PFALCON2_FALCON_MOD_SEL(u32) @ 0x00000180 { 7:0 algo ?=3D> FalconModSelAlgo; } =20 - pub(crate) NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID(u32) @ PFalcon2Base += 0x00000198 { + pub(crate) NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID(u32) @ 0x00000198 { 7:0 ucode_id =3D> u8; } =20 - pub(crate) NV_PFALCON2_FALCON_BROM_ENGIDMASK(u32) @ PFalcon2Base + 0x0= 000019c { + pub(crate) NV_PFALCON2_FALCON_BROM_ENGIDMASK(u32) @ 0x0000019c { 31:0 value =3D> u32; } =20 /// OpenRM defines this as a register array, but doesn't specify its s= ize and only uses its /// first element. Be conservative until we know the actual size or ne= ed to use more registers. - pub(crate) NV_PFALCON2_FALCON_BROM_PARAADDR(u32)[1] @ PFalcon2Base + 0= x00000210 { + pub(crate) NV_PFALCON2_FALCON_BROM_PARAADDR(u32)[1] @ 0x00000210 { 31:0 value =3D> u32; } } @@ -429,23 +425,23 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { // PRISCV =20 register! { - base: NovaRegisters; + base: PFalcon2Registers; =20 /// RISC-V status register for debug (Turing and GA100 only). /// Reflects current RISC-V core status. - pub(crate) NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS(u32) @ PFalcon2Bas= e + 0x00000240 { + pub(crate) NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS(u32) @ 0x00000240 { /// RISC-V core active/inactive status. 0:0 active_stat =3D> bool; } =20 /// GA102 and later. - pub(crate) NV_PRISCV_RISCV_CPUCTL(u32) @ PFalcon2Base + 0x00000388 { + pub(crate) NV_PRISCV_RISCV_CPUCTL(u32) @ 0x00000388 { 7:7 active_stat =3D> bool; 4:4 halted =3D> bool; } =20 /// GA102 and later. - pub(crate) NV_PRISCV_RISCV_BCR_CTRL(u32) @ PFalcon2Base + 0x00000668 { + pub(crate) NV_PRISCV_RISCV_BCR_CTRL(u32) @ 0x00000668 { 8:8 br_fetch =3D> bool; 4:4 core_select =3D> PeregrineCoreSelect; 0:0 valid =3D> bool; --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU010.outbound.protection.outlook.com (mail-ukwestazon11022139.outbound.protection.outlook.com [52.101.101.139]) (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 A679145DF4E; Wed, 19 Aug 2026 11:10:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.101.139 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137845; cv=fail; b=hje+ALQ2P0EZCn8d+mpyy+yJod71xOtKAth24iHV02PRYEoIgG8NwcgBArIVR03pSd2x4nEQJCc0s6ZTE2LPm+4yDDY0LCVCGxVEw55s/DZhQeodkUtMVYbpeMvsgxXHCt2HP2uijS1SInlPXtGDfnRXBYoAfJC0xmjg1+avKco= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137845; c=relaxed/simple; bh=UcdRmVpzRIL5d6EXe2nVU7lPrMffwe962tEbCQsnEq8=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=WAQHMXPSq4Vw+MLH5R11Iq9yf4jPDBGUX9nSZ86lA4kWsINvi0npEfKy40BFHUZrthmEzBfqNJO7aZymDFqkGAqDm+8DdzWB5Vh/eghtUw7+WUE6p74T+bKY1UFu7osk1c361a9ZHuuBWXPWZJxCGLNv2TTWLnJWtEiS5s3twrY= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=Ha9JBVjA; arc=fail smtp.client-ip=52.101.101.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="Ha9JBVjA" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=jALZFgFobHgWgmHM33DuosQEs0P/RISZuniyYGKSPmU6dFFh3n3CjD/rlxh2+HM6sn/tEXWKWBN1gpdgp2qUGIUm65+bChoF8o4ALnZoUhgTegKOzQNcwbWphsMI8IQ11z9G3rqwD5btRHWKuVm6z83G+acAdvbIJSFaYpTvShWqRk3VVY1x6KozltbjdNbzigh4aKTprCjlhnVAwTaPS4fzTkkELtCOpsGq4RmZ162ixdOL6BEaZ6TeLTAelnXpu57Ctzw+D3cdiFemObCOlamBAO35aRO6+/WbOgAvKKyxnKwIe0FDtZnFjV8Ld5fGTO9LAkPp7Aro9/wrIauTyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=v0B9J7EtjFFOfqpNapB2NAxL9XvD5dlbr2Cpc+w+7pc=; b=IzZtI40MBD7I1LsT/1jzzQfXfw4dQJhN/7xONzvQEzuveE1KqnEc5aSn33c4qGKP0KRxSpfj87fPvgFmEBYFNH8WYjBiRtL7X2DjlpN4bFkZ5ig8T9Oex2yGw9uoKl8tAWtzPzBDeGjPHLpKhJQV4iBcmqeYHqIHSAd/cMO19I0mDZ7UdXuwK0FHhahzsrj5QyGecVaQ2Mp39IkwSA6uX2fSkiVeS/9Fh4sucFbmtueVFpo7vMANTlZBdJyTjGRJPDcHhSDHhVqjl81Hb24V1LTaW8977Y7xh7Q6stS/jbxYAc8pIr35QLA/6Ut7yFuBZobzaqHHB2PRkarsb9fcQA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=v0B9J7EtjFFOfqpNapB2NAxL9XvD5dlbr2Cpc+w+7pc=; b=Ha9JBVjAn2WNErgFAOlunk/CaUtzEwlNbhES8ijrxytpX3mXNOuL8sGBm+y34hSiTMPJt1H6L92cfdaymyXlru0BZNEPQevke2X1W/BMDypyeti26rvCdVAxq2JQ/hxroS6JFvN6H65O5S/yPZvtuyQ1PUjkZ4rTimlgBXTL5G8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:23 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:23 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:21 +0100 Subject: [PATCH v3 13/16] gpu: nova-core: convert hshub0 from relative register to projection Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-13-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=6702; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=UcdRmVpzRIL5d6EXe2nVU7lPrMffwe962tEbCQsnEq8=; b=dEHU3s9Bt6dbAAcjdnsSRiJ5FhuX3fnSoI4gjo0CkeMrfeY575uC6sAMCFXwhAsAlnr4eFJ+b nhmPxD3opaCCho/D0u6kZQr+RhiaEdoSVTGHjkcVW+oLdmjMCuuPiBA X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: c894bf8a-4e06-4420-1d5d-08defde27716 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|6133799003|56012099006|10067099003|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: zbZMLvH2x/Qpe2XcHcVoNiduVTlci05kpOg7cnTMMg6sDlK6ooMdiwlz8hQzC0WRMNhlqucXE4SMjI2w0ePy4K86kwLfMzQK46RNPv3ipSE/2qgOQ2Ezxvc08mjMp2plC3pd0EyGTNtGTnbMwKmsD8Gm41Ij9wkExKo8U0DGVzoUacWysKzzBzJJNSRO1mbBPDpi+TIbs1YTJSQNkaWZkir9ez6N45Of87CiW6XTgFaKrA5QaQcOGC83UYg7uoou1ITf/O0EGSV1+Dst482cXKq1cBD51zUQ1ocut+HbP4VW2wad7Wh6WYwY3XiOhvXQnLgp8TJPimD9a/t2baoelj2Yec7kCU3fpDMDrFs8mQYW0fd6E4Sy/x4Cp1V85SLOQ87PZ4Z5nMCvkql1hVoIejZSZaerB5e1qPbJ7RciTwKm6VLqn9C+y5Eqgagevq11WiydYd/ZA4LlJPQVbhITtio5WPiLmWSx/Yeiu069O4f6F/zG39omltxuidEHh73exy9E4dEGk45LhcGcsvCcwGGgIyPsRRgLAKgctLf3eW5s42v5uD7ZX1so0YCIcGmYrWs1UwQ5784xOhyIvJ/WCDpoK61YsM1D5t0JwjcI8wRomitdMaLSirbldE0QDIflpIMLGAJxqGnD+szlQ4HCU5/a0DcrQrgiyi6ArK4ZPbE74KVXGsm7PG+LUOyO66AJet+1F+8VZPAIryjkBd8wVA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(6133799003)(56012099006)(10067099003)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?STh4LzlsWUNzdndOdFlJZm1NMUJaMHJ1bnErcDlHMHVSTWNIdXd5VmF2cmE0?= =?utf-8?B?T2xaMDdYVWw2Y2xUNFBGM0ltRlhRSkRrMDNkQ0Vzbys3UVY2TWEvM0kxSExq?= =?utf-8?B?VGxoUndvWC93T1V2VUZBWVBmL280ZC84WExseUNQbGtIblRucEZ1VW16cGc5?= =?utf-8?B?WVU1QnppaFJ3cm16R1JLbVZsNFdNbUJINEJ0OGtCTmdXdEo1ZXZFbUIwWi9R?= =?utf-8?B?QXFWL1hUV0syZHlXUFJycU1RejNQa0RDWDAxUGFWeU5SSGJIcmlQSmo4QnZp?= =?utf-8?B?MU1WdlpCNDlsTXdaSUZaYWpicmwxajd4TlVkTHR1LzJZNjdXWUlZWGxDcDNU?= =?utf-8?B?WUxMeTRtNVkzaWc0clFMRklWZmk1cGZQNTBweUViT1ZmbzVCRkhIazJ0cDVo?= =?utf-8?B?QWZkUHpKM2gwd3NaSTkrZ3Zyb1VpMCtKKy8xYmphV0RObUlRanlMdnJhbUVk?= =?utf-8?B?S09BcjBvOVMwZlpiRk90ZldnT1YvNTI4ZW5Cczh6dXJxcGt0QVdtQ3R5ZmtP?= =?utf-8?B?ZHA0VVc1eit5TzVwU0RWUkFQb0dCRitJcjk4c1lHT012OW1OaGo0ZEVFMHBx?= =?utf-8?B?OVpaK2xza3Z2aXlIMEs3Ri9GalFKTzg5NVRiUy9JTUFHZkticm1BbmxNWjNR?= =?utf-8?B?em8xTGNZUk9YYldBQlI0RGFxYWNwMjNJZjFUbDU0SnAxYWNiWk9KeGtmdVNP?= =?utf-8?B?M1hDeEpSL2l4cWRzb3dMNWtOYVcyWm14WU9xbC9oWGcwNlhXVCs1aXV2QTBK?= =?utf-8?B?S1h5Q3k2V3dDNU9oMkFCV1k2b25Hd0RYUXVOdE5hSlU1alpEYnFPSlVBUVk1?= =?utf-8?B?bWU4UnllL0V5d2cva2RJaElCanZUR2hjVlZjM3hBK1d5WTE3L1lldVVzckhJ?= =?utf-8?B?SjhVdGx4R3NoenkwZENRSU5kNXp5R2ZoY0hEVWEvNGNCemFJdmxzU0J3cWFx?= =?utf-8?B?dGdYMmsrQnNYQXJVOW9nZXVVcjB4RDY4QVdqUFN1ZU91cHl0THZrejBRNlh0?= =?utf-8?B?NHluMWJMQXJadnA3MC9QN2pnYzVINEhiZnZ3QkdOWUxKdnQ2NFVmbWNhU0E3?= =?utf-8?B?S2FVS1FUTXZpNUpqZU1VaGEvVnRkQnNHL2tMaVQ2ZHZJQXdMeU5EdmdxaUdj?= =?utf-8?B?UitPUWt1cjkxbDVPSGRnMmZuQkJnOXFZSDROMXU2OW43ajlRU0FROUZpNTVw?= =?utf-8?B?bWNNbDAvWHhKOCt6WVlUbnRLVXd6WllIOXpWTVpwQjBaYUJ5SVlabUhhRXZX?= =?utf-8?B?ZlZ1VDFEdXZsbms0Ky91a0NZSGFXS2JiZjZucUpoR1dFcVNmRFRDZXNlYXlu?= =?utf-8?B?bHladDRhRlhOTWZSNHdiaWhqQ044c0NtU3lIclQrL280cnYyT3ZVek5odmti?= =?utf-8?B?bTZKKzVSdGJZNENrTUMxbXdKcEluQmExNUVua0NNRmdrOXNGakRMUS9mZmVo?= =?utf-8?B?RTdUUG0xZDBIZnRSNkV5UW9ZbU05SHRidmhTVDZQckxCMHMwNlBzZXZkck1m?= =?utf-8?B?TnFWYk9kanVoVXFSVDJWaUoveWZMcVA0Rk9wVFEvcnJJbktqanh2bTBHaFhz?= =?utf-8?B?aEtZR25YbkdPb1V1MHNHOXpRV3hoaTdjK0Z3ay9nckFVQ1FsWitMS09uVDQz?= =?utf-8?B?RTVLTjNnVGNNVTVnR2FJcTVqQWkySFlEbnM0ZndncW50TURCQ1JrWndEaExi?= =?utf-8?B?R0p1TlRJRnBsaVZUTUdMZ3Q2d1pRdFJWc0M4RTBpWStCbEVBcjZzeitYWWFa?= =?utf-8?B?ZnkzT3VZRDNTTnhjamVoZ01sOXBvdUFpQlRSWVNyRktSVElmUGY4bzcreTcx?= =?utf-8?B?SENRZFlSWEwyaFFINy9RbTl4Y0IvbXhLbC9wNWtGUmhpK1F1TGxRZGR5Q0F2?= =?utf-8?B?dU0zdXpER2Q2dTB5NlBhYTloY2NGWTE2VnBtRHh0NzRkbHF2Sit4Z2ZmUHl6?= =?utf-8?B?Y1BVRlMrcE5QWEw3VnZLcmRzbXRzOU5zSkkzWWxFV0o0UGYrcFlab2VKMEFO?= =?utf-8?B?RkNQeGpvekNROGxrdHgyRW90WElvMnNwNFFBMnBCMFZob2UxRVBQOVIwRUZZ?= =?utf-8?B?S2dRcnpTSVNUbmw2T1hhYk9WMzhVb1ZsQStxVU44RldkS3IvYmpRWDNpakJO?= =?utf-8?B?ZUR2U2Y5aDdONUdmUG9GYzJOK0pzeERoT3BNQXRBSkJTTC96czZ2eG41dmU5?= =?utf-8?B?MWtkM0JFSXNhYWppK05jTHNzOUc3a21qK0RFVlZNRTdYNkRiN1Q0NGNaejlL?= =?utf-8?B?a2R2ZEMydzlWOXZCcXN2cThKanI4d2Z0VFhtQmNwK3pMd3dRdHBoMzFHMko2?= =?utf-8?B?RVZOYllRT1hYSzkrNFVUQ29QTG1iMmpWMEgzNEE1R1RkbmhQT29Tdz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: c894bf8a-4e06-4420-1d5d-08defde27716 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:23.6915 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Y6kUVRAgYnAEDAdGZx5dkSCF/L0CQ4zd2rPMNMx/4rU2zxgyTD4Ql83sjLriW8C+7F+k/v9Kttbc+GapPweHVA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 Similar to the PFALCON and PFALCON2 conversion, the hshub0 relative access can also be achieved cleanly with projection and a new base. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- drivers/gpu/nova-core/fb/hal/gb100.rs | 59 +++++++++++++++++--------------= ---- drivers/gpu/nova-core/fb/regs.rs | 19 ++++++----- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/nova-core/fb/hal/gb100.rs b/drivers/gpu/nova-core/= fb/hal/gb100.rs index d9e4d62ae632..9fa094939600 100644 --- a/drivers/gpu/nova-core/fb/hal/gb100.rs +++ b/drivers/gpu/nova-core/fb/hal/gb100.rs @@ -5,11 +5,10 @@ =20 use kernel::{ io::{ - register::{ - RegisterBase, - WithBase, // - }, - Io, // + io_project, + register, + Io, + Mmio, // }, num::Bounded, prelude::*, @@ -21,7 +20,10 @@ }; =20 use crate::{ - driver::Bar0, + driver::{ + Bar0, + NovaRegisters, // + }, fb::{ hal::FbHal, regs, // @@ -31,17 +33,26 @@ =20 struct Gb100; =20 -impl RegisterBase for Gb100 { - const BASE: usize =3D 0x0087_0000; +register! { + base: NovaRegisters; + + HSHUB0: regs::Hshub0Registers @ 0x0087_0000; +} + +#[inline] +fn hshub0(bar: Bar0<'_>) -> Mmio<'_, regs::Hshub0Registers> { + io_project!(bar, build: HSHUB0) } =20 -fn read_sysmem_flush_page_gb100(bar: Bar0<'_>) -> u64 { +fn read_sysmem_flush_page_gb100(hshub0: Mmio<'_, regs::Hshub0Registers>) -= > u64 { let lo =3D u64::from( - bar.read(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::= ()) + hshub0 + .read(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO) .adr(), ); let hi =3D u64::from( - bar.read(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::= ()) + hshub0 + .read(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI) .adr(), ); =20 @@ -52,7 +63,7 @@ fn read_sysmem_flush_page_gb100(bar: Bar0<'_>) -> u64 { /// /// Both the primary and EG (egress) register pairs must be programmed to = the same address, /// as required by hardware. -fn write_sysmem_flush_page_gb100(bar: Bar0<'_>, addr: Bounded) { +fn write_sysmem_flush_page_gb100(hshub0: Mmio<'_, regs::Hshub0Registers>, = addr: Bounded) { // CAST: lower 32 bits. Hardware ignores bits 7:0. let addr_lo =3D *addr as u32; let addr_hi =3D addr.shr::<32, 20>().cast::(); @@ -60,24 +71,12 @@ fn write_sysmem_flush_page_gb100(bar: Bar0<'_>, addr: B= ounded) { // Write HI first. The hardware will trigger the flush on the LO write. =20 // Primary HSHUB pair. - bar.write( - regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::(), - regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed().with_adr(ad= dr_hi), - ); - bar.write( - regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::(), - regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed().with_adr(ad= dr_lo), - ); + hshub0.write_reg(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed(= ).with_adr(addr_hi)); + hshub0.write_reg(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed(= ).with_adr(addr_lo)); =20 // EG (egress) pair -- must match the primary pair. - bar.write( - regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI::of::(), - regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed().with_adr= (addr_hi), - ); - bar.write( - regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO::of::(), - regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed().with_adr= (addr_lo), - ); + hshub0.write_reg(regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI::zero= ed().with_adr(addr_hi)); + hshub0.write_reg(regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO::zero= ed().with_adr(addr_lo)); } =20 // This PMU reservation size is r570-specific. @@ -88,13 +87,13 @@ pub(super) const fn pmu_reserved_size_gb100() -> u32 { =20 impl FbHal for Gb100 { fn read_sysmem_flush_page(&self, bar: Bar0<'_>) -> u64 { - read_sysmem_flush_page_gb100(bar) + read_sysmem_flush_page_gb100(hshub0(bar)) } =20 fn write_sysmem_flush_page(&self, bar: Bar0<'_>, addr: u64) -> Result { let addr =3D Bounded::::try_new(addr).ok_or(EINVAL)?; =20 - write_sysmem_flush_page_gb100(bar, addr); + write_sysmem_flush_page_gb100(hshub0(bar), addr); =20 Ok(()) } diff --git a/drivers/gpu/nova-core/fb/regs.rs b/drivers/gpu/nova-core/fb/re= gs.rs index c27582e376e2..584488a3e012 100644 --- a/drivers/gpu/nova-core/fb/regs.rs +++ b/drivers/gpu/nova-core/fb/regs.rs @@ -2,7 +2,8 @@ =20 use kernel::{ io::register, - sizes::SizeConstants, // + prelude::*, + sizes::{SizeConstants, SZ_4K}, // }; =20 use crate::driver::NovaRegisters; @@ -65,31 +66,33 @@ pub(super) fn vga_workspace_addr(self) -> Option { } } =20 -/// Base of the GB10x HSHUB0 register window (`NV_HSHUB0_PRIV_BASE` in Ope= n RM). +/// The GB10x HSHUB0 register window (Base defined as `NV_HSHUB0_PRIV_BASE= ` in Open RM). /// /// The base is provided by the GB10x framebuffer HAL. -pub(super) struct Hshub0Base(()); +#[repr(align(4))] +#[derive(FromBytes, IntoBytes)] +pub(super) struct Hshub0Registers([u8; SZ_4K]); =20 register! { - base: NovaRegisters; + base: Hshub0Registers; =20 // GB10x sysmem flush registers, relative to the HSHUB0 base. GB10x ro= utes sysmembar // through a primary and an EG (egress) pair that must both be program= med to the same // address. Hardware ignores bits 7:0 of each LO register. The boot pa= th uses a fixed // HSHUB0 base, so the multiple runtime-discovered HSHUB bases are not= needed here. - pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + = 0x00000e50 { + pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x00000e50 { 31:0 adr =3D> u32; } =20 - pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + = 0x00000e54 { + pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00000e54 { 19:0 adr; } =20 - pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base= + 0x000006c0 { + pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x000006c0= { 31:0 adr =3D> u32; } =20 - pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base= + 0x000006c4 { + pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x000006c4= { 19:0 adr; } } --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU010.outbound.protection.outlook.com (mail-ukwestazon11022139.outbound.protection.outlook.com [52.101.101.139]) (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 DE65445D5E2; Wed, 19 Aug 2026 11:10:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.101.139 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137849; cv=fail; b=SLewNp/jXyDIz6kXRy24lK5HnxTydcfSvu+QzwyxRoUaxBUlOfXV3vpuIjn1sPD9iu1eTWTdXhizMdmmtHswi0U6X65yHDfS4YVmn9lW0bWXyWw2vHgn3x9d2NMHhKesLQlPskZpsUSzLUwfmwqLwyT7kRE0OWiQd4ZTGEnXCDE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137849; c=relaxed/simple; bh=QK1le1HxUqoKzvsVPNYCGxqAhC5hdY3awRRalC47ao0=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=KLX51MpQhavSXEFqKoGxvYJ+nFNYVbXfYteICOpouM3EqOokr4BaINS9yBkHFe0iYX9GBc84ohz3xAiqa/n5LTtNWffJ2EJ8XkLhzfz2LuLuorFiCPoGPaZCTa5n5G5PUpeXBNJHH2Iw+WHK6PwpiQyY38VFNYj/AVO5diCotsQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=jZKmDysG; arc=fail smtp.client-ip=52.101.101.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="jZKmDysG" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=yLc7kSVnTP2grDC0xzucO+lTVa1zTdqY8CSpWXlkMRCnguhKtEQbeZR/eCPiPaPmM+XReM/XA7lzKcjBb2wauiqKDxKWJD0Co06vLy5GALG8XW7PxgpARCJeETma1TkClq2zwzHeVIrxkW1dYnyQF2az5/l4kfcLw8ycFviuMOIPOMxHwrcqBSp7E+n9X1SELsv/xZJu74yG8o6RiggksUhP4VwQH7xMCDjvzHSABl2Scy3eO7CicM7Sr6lJzebYeKyhCjqyodtY7MmXhwy96HjfxVB7Uh2sjZZZ2E7hZTBAewRuBT7hU21/XmECv7m5ryDClD8sIybz4+mZFC/aeg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=wUCf+rqxAxDjIcVyRzQlNpOG4zfjfpD6Ogu4pqNvK8g=; b=q+ACbnQu4e3bD84lQ/w3oHi4aEIgkc4O0UAlSDuOfwoonDd6WU16Asxg//V1yb/nCOeYG4iW2jreYjWA4e1ylBRft6b9LPW/DtFKZp8wlj5cs5H3FKZb9FM760NqMri5oRatTbKqZAfqyCAKKiQK0RWzkK7CGtSyXD2BnE7Mr6lwFrS9dz78T8JOrdnyvuzC/2sDnUCLfdjKckw2LOuYXq+JeIgAHZk0KvMXTiuqBSqfHM7ZMdr0ejB/tpeCeCeZqAVwWdsk86SNTG3yE1mRlsawqKHah1PFUwA9I6RopHDcazzg2d9/uFrPsZdQbyUjy5w8sI+eTVksV3JoHGfAtg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wUCf+rqxAxDjIcVyRzQlNpOG4zfjfpD6Ogu4pqNvK8g=; b=jZKmDysGlVKrIVCzkcZB3JLImqjMgAg4QHSy5LvSL6hsPvyp6ynjSBOiEFgIRNxQpfTgztkf38MuPmziHYEEnG3NPzkN7vr+oHhm1M5431rZmyDJiBVIJz/KUEz3iTpQjqQiMbpbD3DBnspu/bglOJQ7lu9DQ/wuL5odfQ2lp88= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:24 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:24 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:22 +0100 Subject: [PATCH v3 14/16] rust: io: register: remove relative registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-14-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=21901; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=QK1le1HxUqoKzvsVPNYCGxqAhC5hdY3awRRalC47ao0=; b=g6ZPyqRlXvoDdNlqEf642fIU6sfs0xOuFxOCLyJh3O3lUZMV8otXleyp9uDcP8txeGffRaMUl GPLtPXE2V/qC1E2kUMLaMHzICXVR+wE9JS0Y/Tq77EPToJF40lLMUwB X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 17ae7c6f-076a-4057-1024-08defde27789 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|3023799007|56012099006|10067099003|5023799004|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: C2k08hOt7nEEYSZRoONKW2/Z76ZWAlmHBBXNiNJ4LRg8nYB9qc/acYk5VhV/tyePodm7Ze9uZyN8KcfqFBQ8Qk9929qaIYOVS4XWOSd55dt8RL5Fze8KEL3dJ6R9lloQGq/ueKhNlXIKUPyI3m1oDX+g0riwVh+bg9GFcG2QyqrV2bHzMK7WQpsG92xwjaoV1/28W0dZzWCb7Uk61FKwlTft/Mw7qYaMJYuFnT0MXR9ZSg4QalQD0VMPScQCQDb5jMGNjxTjd7mkmNICOHImGA/x+xUcjd0W+iwZWrqvWtLSnnxdj6vzVVQVXgZ7nTCKGDOyx9ynR4VQCbXLAv1IJ0uwrsAGf80mR1052A/P3kMCaPAnGQOgk3pvzMPFptMpRli8zRFGXijD3T1lFotAWdE4qBjr7yB6CCfVBtKtBM1UhgI6tajdvF1Mwa2c4fCqxezfEBYtMnbITo6tWioSnATkstuEJ8qfKrd+4novo2XZOyVqpkYRgoHArUYlNJ11whInsbvVn6PgzY5milAtQsx56ziK4FkY/FxUhv8sjSL4Tu3XgOe3EarEPmHpO28JCdkDF9qdiXH389VyjbVJEL8YgPFm4HuAV7jtymP/wlK4+ibimJ2Sg3hjOnFPK3YJP49eZ/ckN33LhsPbwJEuHtOYJbF72lXiSZKOl8Tgma1w73V3RsNL4q2kCgD9GHZR/JfoYnBMWhm2PZZBTJOdJA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(3023799007)(56012099006)(10067099003)(5023799004)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?MEI5WXBpUGFmQ2tMbW1vT1RNSXNyams5VEo4V20zY0RHb1hRU3FEK3dMdU1G?= =?utf-8?B?ZjIya1JteTZTUGRGOU5TbWNvWk40YzFmbFB5WnhUdlljUm10YWYvTk5rWTgv?= =?utf-8?B?bTFJMWdDelNBTS8wZTNXR29PbzdyTzNjbWUzSENWa3FQS2piRlpYeGhTcTMx?= =?utf-8?B?KzdPNmpPdmlKVEZEOG5paUl0Y0JkZk1ZdkZaRWRZUHVmUnNGMEt6N01zQUo0?= =?utf-8?B?dktrNFJmaU9JUmxnMGJkR3JCL05JVDRweE5iRk8vVERNWVFINStoWVVJNWNG?= =?utf-8?B?Y2Y3NEl4c2tnMVpmdWVlVll2OUdSekVtVUxuaG1pK285QnRFVFh3SmVuS0Fu?= =?utf-8?B?a0pld1I1UGFBb3djMGNnYXZONDg2VGJYUUNFRUhNSzRpMHJ4aDEvNkFKc1Zt?= =?utf-8?B?YlI2bWtjTW42alRpNS9OZ1dFY1J6b08wdnhySXZqMUhrOFhkNTJaVUFUaWJl?= =?utf-8?B?eTFBVzYrN0pHQk9KcmY5MDBJVGdXenc2UTVhcVB5WjBkYnJrRVBWNDJZaU00?= =?utf-8?B?SVJ2aEpkYStSM1VKVWwwNGhNMENwUFlUcUdjYmxmRkRnK20rNVI3N0JMOGxv?= =?utf-8?B?ZHNrSWgrNEl1SFJEVzJqQVNJd1ByWHZLcjNjTFRZN0hxV2J2RkN2WXFrZ1BX?= =?utf-8?B?Y3BoYi81UEJXdTUyR1l6Z1J1ZHMzVy8rUFdBSEd6ejFXVHRMQUdtV2VmVFhp?= =?utf-8?B?SnMxY2pqUWk2bldPNGp1M0tSNE5UMmlXSi94MHV4Q2xwUEZPSkpJSC9uekxY?= =?utf-8?B?cjJ6NlVqdEh1QXorOTRBQkpiSHJlNnNWT0R0NmkxOGQwM2loM1RSSXJYMzAz?= =?utf-8?B?Rkk4OW9VVlVpOWY1ZG9FUkEyZk1SK3FYMXFCV3BOZk0zd3lDcjZ0TEhhaDJI?= =?utf-8?B?UUdXMEJ2QVIwNVFobUdIQmlZWmttVHBsT29qaGEzcll2TkEveDdYeGZ5Uy9M?= =?utf-8?B?V1UwVXFBb21jcVJNUE5GcmFHOXhvMC9NQy9IdXcwbm11ZTFjR2hzQ2M3M3d4?= =?utf-8?B?TlJHcFUrMjFxTm1ZQjFOSEhaZ0tXTUlteWg4NEhSMFVhTmRpeE5lVXZtdUVu?= =?utf-8?B?RXVHOXYwTWN2NWxrYjdDV1V6cHpDYk5tTmRSckI5OUVGdWpFMzYyZU1JRnAr?= =?utf-8?B?RG1lZWRLbHVBZlV4cm5DMUxoSlNxOHlHTTBzSUNrejM5QXNlQ2o4QXh6RXhq?= =?utf-8?B?WmU4Y21oNlAxb01JRnlwSVhWOG14T0UzaERaUGZIMWxZRmlMQzdsVFZ0dzF4?= =?utf-8?B?VFQ3Yjl5K3VUR2cyU0M0a216TDJyWVlMZUVueEFqTVZUU0dHbEo4Kzd2Z3Rm?= =?utf-8?B?V1duN1FLNHU2Q2JmeUxxd2hyT21GMnVWK0RlZTBKaVc4SnF3TFRGU1BJZ1I4?= =?utf-8?B?eGphTXRnZVV2amxBWlcxamZyWDZwN1RGK3MvVkgwcUtzSFJnczNFTWxybyt6?= =?utf-8?B?elZPSmZsTWIxMWJ0QWlmTGZwb1AzNnhnMTR2Zklzcm9HUzN0QzdGQlVvOHhq?= =?utf-8?B?LzFtbU9sa3RiZTBNNUpVMkt5Qm11THpuZFluVVdMTTNVMUpFeUY4S2k3SDFj?= =?utf-8?B?ZVpBSnF3cUpETnZHSkpzbTJVMzVURnR2VmNlMkFUSlVKY2UyM1NzVkhkMEto?= =?utf-8?B?WmI4R0pZQ042YTUzWmV1OVNaMnZIY0Y3U1JaWmhWdWJ4c2N2REVaK011bzRK?= =?utf-8?B?ZXBwVXZZdW1JdWpETzZ5TEFaV3RPeVY1bVc4MmZMY3dkME9JSmVrNlcvZFBM?= =?utf-8?B?ajVUL1c0bGk1NjhVZEhXMkdOK1lHSVJOM2oxOUpRaEVRWmFrNVJ6cmlDMXhZ?= =?utf-8?B?aHlOOGZxa3IzeG1ZR3EyQk1uM0NEeEFXVEtlb1ZtVjY5dytqeWVnemNqZ0I5?= =?utf-8?B?NWJBclJJTGxtdkZYQmRWWFNHMHFlaENwQjJZM1V3ejh5SWkzTVNsazJIZHBj?= =?utf-8?B?TVVxR21tcUxZY3JKWUtSWVh3dUpuRHlBZ01NMGo0aE1HcFVOTEl5ZDVCb3Qz?= =?utf-8?B?VG1zS1dwbmNudlZ1c2x4UDRHNzFIY0pVSkh3VEpoTTVLUTA5TDVXSUx5Y3Jk?= =?utf-8?B?NXhqQkt0YThrTTgyR3FlOHcydGVHN0NDTDJsU1lmK2daeVVrbW45RlBidi9B?= =?utf-8?B?OUNCSmpkamNsWTdKQVptUTNIYTJGVi9KaVMvTGN6d1lvMmZCQmp4UTU4MHls?= =?utf-8?B?ZE5qZHhoZTBwNXVxUzduR0pWdEIvMjQ4RmIzRUp0UURQeHltQXpoM0FVYUJo?= =?utf-8?B?YU9CRko5aDJ0UkdYUDIzWlpScWF2aXh0b1RBempEK3F1ZmFEZzJERlY2Q0dt?= =?utf-8?B?YkM4eHJzTWIyL3BTMTFUcUtrYkYxZDY3QUtnV3B6WU1ZREV1OE81QT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 17ae7c6f-076a-4057-1024-08defde27789 X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:24.4299 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 01QyJbumDIFk7wicpn1ODJvocG2vQE6dRsTi8hZ4cGg/xy+dmb7Ggh0DPZGzGaYxSvv3gZnuaQY1ZC8X7u7jYw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 Relative registers can be better served by projection to subregion instead of ad-hoc handling in register macro. Projection composes better (e.g. it natively allows relative registers of relative registers without needing additional support). Remove relative register support, and update the documentation to demonstrate how projection and subregions can be used to achieve this instead. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io/register.rs | 388 ++++++-----------------------------------= ---- rust/macros/io/register.rs | 52 ++---- 2 files changed, 61 insertions(+), 379 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 63c054162e54..4d4afd3ae94a 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -8,7 +8,7 @@ //! //! Note: most of the items in this module are public so they can be refer= enced by the macro, but //! most are not to be used directly by users. Outside of the `register!` = macro itself, the only -//! items you might want to import from this module are [`WithBase`] and [= `Array`]. +//! item you might want to import from this module is [`Array`]. //! //! # Simple example //! @@ -199,76 +199,6 @@ fn offset(self) -> usize { } } =20 -/// Trait providing a base address to be added to the offset of a relative= register to obtain -/// its actual offset. -/// -/// The `T` generic argument is used to distinguish which base to use, in = case a type provides -/// several bases. It is given to the `register!` macro to restrict the us= e of the register to -/// implementors of this particular variant. -pub trait RegisterBase { - /// Base address to which register offsets are added. - const BASE: usize; -} - -/// Trait implemented by all registers that are relative to a base. -pub trait WithBase { - /// Family of bases applicable to this register. - type BaseFamily; - - /// Returns the absolute location of this type when using `B` as its b= ase. - #[inline(always)] - fn of>() -> RelativeRegisterLoc - where - Self: Register, - { - RelativeRegisterLoc::new() - } -} - -/// Trait implemented by relative registers. -pub trait RelativeRegister: Register + WithBase {} - -/// Location of a relative register. -/// -/// This can either be an immediately accessible regular [`RelativeRegiste= r`], or a -/// [`RelativeRegisterArray`] that needs one additional resolution through -/// [`RelativeRegisterLoc::at`]. -pub struct RelativeRegisterLoc(PhantomData, Pha= ntomData); - -impl RelativeRegisterLoc -where - T: Register + WithBase, - B: RegisterBase + ?Sized, -{ - /// Returns the location of a relative register or register array. - #[inline(always)] - // We do not implement `Default` so we can be const. - #[expect(clippy::new_without_default)] - pub const fn new() -> Self { - Self(PhantomData, PhantomData) - } - - // Returns the absolute offset of the relative register using base `B`. - // - // This is implemented as a private const method so it can be reused b= y the [`IoLoc`] - // implementations of both [`RelativeRegisterLoc`] and [`RelativeRegis= terArrayLoc`]. - #[inline] - const fn offset(self) -> usize { - B::BASE + T::OFFSET - } -} - -impl IoLoc for RelativeRegisterLoc<= T, B> -where - T: RelativeRegister, - B: RegisterBase + ?Sized, -{ - #[inline(always)] - fn offset(self) -> usize { - RelativeRegisterLoc::offset(self) - } -} - /// Trait implemented by arrays of registers. pub trait RegisterArray: Register { /// Number of elements in the registers array. @@ -331,71 +261,6 @@ fn try_at(idx: usize) -> Option> } } =20 -/// Trait implemented by arrays of relative registers. -pub trait RelativeRegisterArray: RegisterArray + WithBase {} - -/// Location of a relative array register. -pub struct RelativeRegisterArrayLoc< - T: RelativeRegisterArray, - B: RegisterBase + ?Sized, ->(RelativeRegisterLoc, usize); - -impl RelativeRegisterArrayLoc -where - T: RelativeRegisterArray, - B: RegisterBase + ?Sized, -{ - /// Returns the location of register `T` from the base `B` at index `i= dx`, with build-time - /// validation. - #[inline(always)] - pub fn new(idx: usize) -> Self { - build_assert!(idx < T::SIZE); - - Self(RelativeRegisterLoc::new(), idx) - } - - /// Attempts to return the location of register `T` from the base `B` = at index `idx`, with - /// runtime validation. - #[inline(always)] - pub fn try_new(idx: usize) -> Option { - if idx < T::SIZE { - Some(Self(RelativeRegisterLoc::new(), idx)) - } else { - None - } - } -} - -/// Methods exclusive to [`RelativeRegisterLoc`]s created with a [`Relativ= eRegisterArray`]. -impl RelativeRegisterLoc -where - T: RelativeRegisterArray, - B: RegisterBase + ?Sized, -{ - /// Returns the location of the register at position `idx`, with build= -time validation. - #[inline(always)] - pub fn at(self, idx: usize) -> RelativeRegisterArrayLoc { - RelativeRegisterArrayLoc::new(idx) - } - - /// Returns the location of the register at position `idx`, with runti= me validation. - #[inline(always)] - pub fn try_at(self, idx: usize) -> Option> { - RelativeRegisterArrayLoc::try_new(idx) - } -} - -impl IoLoc for RelativeRegisterArra= yLoc -where - T: RelativeRegisterArray, - B: RegisterBase + ?Sized, -{ - #[inline(always)] - fn offset(self) -> usize { - self.0.offset() + self.1 * T::STRIDE - } -} - /// Trait implemented by items that contain both a register value and the = absolute I/O location at /// which to write it. /// @@ -452,8 +317,7 @@ pub const fn element_alias_offset+------------CPU0-------------+ -/// | | -/// 0x110--->+-----------------------------+ -/// | CPU_CTL | -/// +-----------------------------+ -/// | ... | -/// | | -/// | | -/// 0x200--->+------------CPU1-------------+ -/// | | -/// 0x210--->+-----------------------------+ -/// | CPU_CTL | -/// +-----------------------------+ -/// | ... | -/// +-----------------------------+ -/// ``` -/// -/// `CPU0` and `CPU1` both have a `CPU_CTL` register that starts at offset= `0x10` of their I/O -/// space segment. Since both instances of `CPU_CTL` share the same layout= , we don't want to define -/// them twice and would prefer a way to select which one to use from a si= ngle definition. -/// -/// This can be done using the `Base + Offset` syntax when specifying the = register's address: -/// -/// ```ignore -/// register! { -/// ... -/// pub RELATIVE_REG(u32) @ Base + 0x80 { -/// ... -/// } -/// } -/// ``` -/// -/// This creates a register with an offset of `0x80` from a given base. -/// -/// `Base` is an arbitrary type (typically a ZST) to be used as a generic = parameter of the -/// [`RegisterBase`] trait to provide the base as a constant, i.e. each ty= pe providing a base for -/// this register needs to implement `RegisterBase`. -/// -/// The location of relative registers can be built using the [`WithBase::= of`] method to specify -/// its base. All relative registers implement [`WithBase`]. -/// -/// Here is the above layout translated into code: -/// -/// ```no_run -/// use kernel::{ -/// io::{ -/// register, -/// register::{ -/// RegisterBase, -/// WithBase, -/// }, -/// Io, -/// Region, -/// }, -/// }; -/// # use kernel::io::Mmio; -/// -/// // Type used to identify the base. -/// pub struct CpuCtlBase; -/// -/// // ZST describing `CPU0`. -/// struct Cpu0; -/// impl RegisterBase for Cpu0 { -/// const BASE: usize =3D 0x100; -/// } -/// -/// // ZST describing `CPU1`. -/// struct Cpu1; -/// impl RegisterBase for Cpu1 { -/// const BASE: usize =3D 0x200; -/// } -/// -/// // This makes `CPU_CTL` accessible from all implementors of `RegisterB= ase`. -/// register! { -/// base: Region<0x1000>; -/// -/// /// CPU core control. -/// pub CPU_CTL(u32) @ CpuCtlBase + 0x10 { -/// 0:0 start; -/// } -/// } -/// -/// # fn test(io: Mmio<'_, Region<0x1000>>) { -/// // Read the status of `Cpu0`. -/// let cpu0_started =3D io.read(CPU_CTL::of::()); -/// -/// // Stop `Cpu0`. -/// io.write(WithBase::of::(), CPU_CTL::zeroed()); -/// # } -/// -/// // Aliases can also be defined for relative register. -/// register! { -/// base: Region<0x1000>; -/// -/// /// Alias to CPU core control. -/// pub CPU_CTL_ALIAS(u32) =3D> CpuCtlBase + CPU_CTL { -/// /// Start the aliased CPU core. -/// 1:1 alias_start; -/// } -/// } -/// -/// # fn test2(io: Mmio<'_, Region<0x1000>>) { -/// // Start the aliased `CPU0`, leaving its other fields untouched. -/// io.update(CPU_CTL_ALIAS::of::(), |r| r.with_alias_start(true)); -/// # } -/// ``` -/// /// ## Arrays of registers /// /// Some I/O areas contain consecutive registers that share the same field= layout. These areas can @@ -763,115 +511,83 @@ pub const fn element_alias_offset+------------CPU0-------------+ +/// | | +/// 0x110--->+-----------------------------+ +/// | CPU_CTL | +/// +-----------------------------+ +/// | ... | +/// | | +/// | | +/// 0x200--->+------------CPU1-------------+ +/// | | +/// 0x210--->+-----------------------------+ +/// | CPU_CTL | +/// +-----------------------------+ +/// | ... | +/// +-----------------------------+ /// ``` /// -/// Like relative registers, they implement the [`WithBase`] trait. Howeve= r the return value of -/// [`WithBase::of`] cannot be used directly as a location and must be fur= ther specified using the -/// [`at`](RelativeRegisterLoc::at) method. +/// `CPU0` and `CPU1` both have a `CPU_CTL` register that starts at offset= `0x10` of their I/O +/// space segment. Since both instances of `CPU_CTL` share the same layout= , we don't want to define +/// them twice and would prefer a way to select which one to use from a si= ngle definition. +/// +/// This can be done define a new type for the subregion, and then define = registers that use the new +/// type as the base: /// /// ```no_run /// use kernel::{ /// io::{ +/// io_project, /// register, -/// register::{ -/// RegisterBase, -/// WithBase, -/// }, /// Io, /// Region, /// }, /// }; /// # use kernel::io::Mmio; -/// # fn get_scratch_idx() -> usize { -/// # 0x15 -/// # } -/// -/// // Type used as parameter of `RegisterBase` to specify the base. -/// pub struct CpuCtlBase; /// -/// // ZST describing `CPU0`. -/// struct Cpu0; -/// impl RegisterBase for Cpu0 { -/// const BASE: usize =3D 0x100; -/// } +/// // Subregion type. Make sure it has adequate size and alignment. +/// #[repr(align(4))] +/// #[derive(FromBytes, IntoBytes)] +/// pub struct CpuCtl([u8; 0x100]); /// -/// // ZST describing `CPU1`. -/// struct Cpu1; -/// impl RegisterBase for Cpu1 { -/// const BASE: usize =3D 0x200; -/// } -/// -/// // 64 per-cpu scratch registers, arranged as a contiguous array. /// register! { /// base: Region<0x1000>; /// -/// /// Per-CPU scratch registers. -/// pub CPU_SCRATCH(u32)[64] @ CpuCtlBase + 0x00000080 { -/// 31:0 value; -/// } +/// // Subregions can just be defined like normal registers. +/// CPU0: CpuCtl @ 0x100; +/// CPU1: CpuCtl @ 0x200; /// } /// -/// # fn test(io: Mmio<'_, Region<0x1000>>) -> Result<(), Error> { -/// // Read scratch register 0 of CPU0. -/// let scratch =3D io.read(CPU_SCRATCH::of::().at(0)); -/// -/// // Write the retrieved value into scratch register 15 of CPU1. -/// io.write(WithBase::of::().at(15), scratch); -/// -/// // This won't build. -/// // let cpu0_scratch_128 =3D io.read(CPU_SCRATCH::of::().at(128))= .value(); -/// -/// // Runtime-obtained array index. -/// let scratch_idx =3D get_scratch_idx(); -/// // Access on a runtime index returns an error if it is out-of-bounds. -/// let cpu0_scratch =3D io.read( -/// CPU_SCRATCH::of::().try_at(scratch_idx).ok_or(EINVAL)? -/// ).value(); -/// # Ok(()) -/// # } -/// -/// // Alias to `SCRATCH[8]` used to convey the firmware exit code. +/// // Then you can define new registers on the subregion. /// register! { -/// base: Region<0x1000>; +/// base: CpuCtl; /// -/// /// Per-CPU firmware exit status code. -/// pub CPU_FIRMWARE_STATUS(u32) =3D> CpuCtlBase + CPU_SCRATCH[8] { -/// 7:0 status; +/// /// CPU core control. +/// pub CPU_CTL(u32) @ 0x10 { +/// 0:0 start; /// } /// } /// -/// // Non-contiguous relative register arrays can be defined by adding a = stride parameter. -/// // Here, each of the 16 registers of the array is separated by 8 bytes= , meaning that the -/// // registers of the two declarations below are interleaved. -/// register! { -/// base: Region<0x1000>; -/// -/// /// Scratch registers bank 0. -/// pub CPU_SCRATCH_INTERLEAVED_0(u32)[16, stride =3D 8] @ CpuCtlBase = + 0x00000d00 { -/// 31:0 value; -/// } -/// -/// /// Scratch registers bank 1. -/// pub CPU_SCRATCH_INTERLEAVED_1(u32)[16, stride =3D 8] @ CpuCtlBase = + 0x00000d04 { -/// 31:0 value; -/// } -/// } +/// # fn test(io: Mmio<'_, Region<0x1000>>) { +/// // Read the status of `Cpu0`. +/// let cpu0_started =3D io_project!(io, build: CPU0).read(CPU_CTL); /// -/// # fn test2(io: Mmio<'_, Region<0x1000>>) -> Result<(), Error> { -/// let cpu0_status =3D io.read(CPU_FIRMWARE_STATUS::of::()).status(= ); -/// # Ok(()) +/// // Stop `Cpu0`. +/// io_project!(io, build: CPU0).write_reg(CPU_CTL::zeroed()); /// # } /// ``` #[macro_export] diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index 0b4e0d1903dd..757ea8094f61 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -53,7 +53,6 @@ struct Reg { name: Ident, ty: Type, array: Option, - relative_base: Option, offset: RegOffset, bitfield: Option<(Type, Group)>, } @@ -98,26 +97,15 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Result<= Self> { }; =20 let lh =3D input.lookahead1(); - let mut relative_base =3D None; let offset =3D if lh.peek(Token![@]) { let _: Token![@] =3D input.parse()?; =20 - if input.peek(Ident) { - relative_base =3D Some(input.parse()?); - let _: Token![+] =3D input.parse()?; - } - RegOffset::Fixed { offset: input.parse()?, } } else if lh.peek(Token![=3D>]) { let _: Token![=3D>] =3D input.parse()?; - let mut alias: Path =3D input.parse()?; - if input.peek(Token![+]) { - let _: Token![+] =3D input.parse()?; - relative_base =3D Some(alias); - alias =3D input.parse()?; - } + let alias: Path =3D input.parse()?; =20 if input.peek(token::Bracket) { let content; @@ -152,7 +140,6 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Result<= Self> { name, ty, array, - relative_base, offset, bitfield, }) @@ -196,7 +183,6 @@ pub(crate) fn register(def: RegDef) -> Result { name, ty, array, - relative_base, offset, bitfield, } =3D reg; @@ -236,7 +222,7 @@ impl ::kernel::io::register::Register for #name { } =20 match array { - None if bitfield.is_none() && relative_base.is_none() =3D> out= puts.extend(quote!( + None if bitfield.is_none() =3D> outputs.extend(quote!( #(#attrs)* #vis const #name: ::kernel::io::register::Offse= tLoc<#base, #ty> =3D ::kernel::io::register::OffsetLoc::new(#offset); )), @@ -246,21 +232,12 @@ impl ::kernel::io::register::Register for #name { "defining without bitfield is not yet supported for this t= ype of register", ))?, =20 - None =3D> match relative_base { - None =3D> outputs.extend(quote_spanned!(span =3D> - impl ::kernel::io::register::FixedRegister for #name {} - - #(#attrs)* #vis const #name: ::kernel::io::register::F= ixedRegisterLoc<#name> =3D - ::kernel::io::register::FixedRegisterLoc::<#name>:= :new(); - )), - Some(relative_base) =3D> outputs.extend(quote_spanned!(spa= n =3D> - impl ::kernel::io::register::WithBase for #name { - type BaseFamily =3D #relative_base; - } + None =3D> outputs.extend(quote_spanned!(span =3D> + impl ::kernel::io::register::FixedRegister for #name {} =20 - impl ::kernel::io::register::RelativeRegister for #nam= e {} - )), - }, + #(#attrs)* #vis const #name: ::kernel::io::register::Fixed= RegisterLoc<#name> =3D + ::kernel::io::register::FixedRegisterLoc::<#name>::new= (); + )), =20 Some(def) =3D> { let size =3D &def.size; @@ -276,24 +253,13 @@ impl ::kernel::io::register::RelativeRegister for #na= me {} }; =20 outputs.extend(quote_spanned!(span =3D> + impl ::kernel::io::register::Array for #name {} + impl ::kernel::io::register::RegisterArray for #name { const SIZE: usize =3D #size; const STRIDE: usize =3D #stride; } )); - - match relative_base { - None =3D> outputs.extend(quote_spanned!(span =3D> - impl ::kernel::io::register::Array for #name {} - )), - Some(relative_base) =3D> outputs.extend(quote_spanned!= (span =3D> - impl ::kernel::io::register::WithBase for #name { - type BaseFamily =3D #relative_base; - } - - impl ::kernel::io::register::RelativeRegisterArray= for #name {} - )), - } } }; } --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from LO3P265CU004.outbound.protection.outlook.com (mail-uksouthazon11020099.outbound.protection.outlook.com [52.101.196.99]) (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 6C61C46C830; Wed, 19 Aug 2026 11:10:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.196.99 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137850; cv=fail; b=hA8xhLmaohyRvdYSTWoAkqqGXXKS7ABtDsvcwRjJQpF4ps8pfSOKJmd5U+bZhHBWiGBaGqShYYTmwTrJykCQ+BQd0E8q70Z8F35Kp+oz61DWLyliGO28LXlsqSyKk2jlQnCC+1xuIKMUSvmuvURhostyN05A5IsT5U7798+f3DY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137850; c=relaxed/simple; bh=hhnaSlzSE2Z66uVV7DHhQmy4tSqv+1IXM+RJzzv/+x4=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=eB/ywofy7edLes81k2lztax2RdpMRq8P4m/Msua+2MrWjvDe+6UyAYXDGqCRio75zBk0sB4Djjlryoh+ZUVXsCHS/cD1JsGQVLI5HDfPLGrqhm6zyO7+M5iIlJY9dB/IDjtJNH9/ZwCAvkJu7uW2FWVR/YpQMkxu6gD1mQmNkck= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=burTnuKU; arc=fail smtp.client-ip=52.101.196.99 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="burTnuKU" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kKJrwIBEFT7GC2FOP+PBlkEhN+GIS2t4tjoabe6ZC6casporA7v60uWwu80aVB34RhjljAIxr8FaV0Z1kEvq4mb48z6xn6lrvUlQt89xiR5p24e57Gohksv5ckMwmkXCBijjsEIuvPBbTq/YnKJQ+5NjLxBKkMBonPHv3W6Kiz+xs4uOixcCvnthp2EhbtaDKqsJuDZTqhlnKkYc2PvHrgB6wZ6mbZXLcG/U0aEBg6vOAEfAzRkaJaDW4sSD3P34AjKkIC4BimkuDV+swjqjU/yHZlOuIUtwJnKldVPJRHryDlZ2Li5tdJ2SE5+LAtOzorn0VwCO4O+Wj9nQGpN9Pg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=2aTEr+ItVCLi14N3Bau2Rhv3A5PUSmeEBSOimB/TVzo=; b=FDBzE0zltj2qzZjCkl9hVyTrKpVoADAmpO+2EkiFlXyiwg3sF5MWCZBkHoTxdYFOqZUR+UWaOrmCUiMGGtrmrl6lmJZ+Gna23D0+Qj1WIEDsibbmeBKw5B/xoNeTm3BF19yHf7tYVodjMbUj0UY+SfZRF6XsgfaA4yGVYknwl1sEL23mjeBahos3kmI/0NDYiWUjhFiPx5E4/BHJ8wSnCun+rcVZK8A2UtMGWqJwdcEYfbCGYO0sjRXEWbUOGD800xai/j2X3feEKJQwv7iISQhHjlgK9QCcerfg6A2bPBoUtC7zUgNLE92tbBaXMV8PlxayiaGS5EJ+ma5X+lJWZQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2aTEr+ItVCLi14N3Bau2Rhv3A5PUSmeEBSOimB/TVzo=; b=burTnuKUxooqrVQY+kspi5l7Wo1nnFzPaUqXpzXBERMWCemWuBhOp8rr9K6PMjNxqPhTjC0IlIPlnVgri0muPxFuzxh3bsw+ax9NPIqv/6lUnr0SpWjl4tz9IFy23lnBw3yPnfXjU7cmQiIHCyrdzlXauIzT3Rv/qBprGlv1Kng= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:25 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:25 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:23 +0100 Subject: [PATCH v3 15/16] rust: io: register: remove `Register` trait and cleanup macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-15-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=4365; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=hhnaSlzSE2Z66uVV7DHhQmy4tSqv+1IXM+RJzzv/+x4=; b=ty935MJoWB2ycq7iW0ju+qYmJ8uTOkIeEb7xq5bwQYxGX/i6Jn7EIikrRAOUhA+DWSlwyplIc ibqJ5bkX87XBmgSNhpjF7cRHoI1rD146oCnLtME2D4L4tEnUzI00Rmv X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 47a2a8e5-44d6-45ab-9c41-08defde277fe X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|3023799007|56012099006|10067099003|5023799004|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: FZq3y4EN2flwnNc8Oj7HRb9hmPmuL7DCGnXmNRqXxwoLBHG4miakt87c4YzDwQwNZ7352KoUXlibD+X4HJ+f5WQYtsdir2k0Yj1sCg2Oku0ET5cJVgbTWDhWB+9i3napyC3Z+7XFiAn+wtj6sLwlyi6RclL3DGBtFHqTMXHvoQJ8ui4a2KBTXJQcorr71VPB+4JNUhIH0qzQ282W9nXLtWSfzqmkwd9Udfabbre61vHgYhLtWXd/KzpPYCzeTolv5f6M4uZAd70zaa+/I6ox49W202lNvUqnF8FWLLpPSdt4rcxZoNbtbO+CEjZpfDPYS+M0BG5mtDn3oZmbm0P3aW5IBepT+EpWCTJ9y0l+tUUlc/SIKhfgu9lBW2DPnKr8d533ybLZ20QvUz8CTFpCH36aXwPXf0OLw+qpylAmMi23rLTO4P3u4U+WqpaJdWAC5ltXm08Swc1mNdlF9YwdpjUEfOAQTcsCIryqV3LvGhFw3uQJOAjsgs+jkOWAJ/rog6bbDS6Eal52pPsj0u+pT5jO6phfxMuspLo12gTmPVFZ49Ei0xP8SiZyDUCOETWPFYt0YZGmMtoy/5aTMkzh8lniSsmBn63XR72aViQx1j3Xx6qsjgSWRVSZ9ZTFBIzo9oBEBYIbBF6fHMrsUZD531Wg2vLRl4mDHYrVXw9hie1WBA6Tofol5HoDngu60hjEmGIlqUBGAti36AYbGnqBDw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(3023799007)(56012099006)(10067099003)(5023799004)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?VVJ2V3c5MXRaRjN1UkVISXdwSlQ5WUdJYS9WMWJ0enZOUUZRSUtQcDRjZ1NR?= =?utf-8?B?UGlCYTQxamdCTk8reXZmVXNMVUtXNEdjVFpxL2I4bHlVR3Y0L0xkRXRaeldX?= =?utf-8?B?by83bmpkQVJBRmIvV3FyY0drQkI1YVNmRHZwOU1IbE1jYTJiYi9qOXFGMjh2?= =?utf-8?B?ZTJSaUVLTFpXUDVzcWcrb2pOR2dMaTF3bzBqam9WUi93eW9Ydk5HVnpjMGRr?= =?utf-8?B?WlZicm9jVUJHQ0dNNDJvMmpSU1RqdjdxcWNDelJNSnptNm0xSHB5OTVVSjk3?= =?utf-8?B?bjBmRVFuWnYwWmtFSDhTMm85UkV6ZUdGVmJMaXl6S2lUSkxsTlNHdVh3dTZa?= =?utf-8?B?eWdWTnNXTmwrOXAxY2xYMlpNZ0hRYWV6UXpNZzdobUVhR0ZzRmFEU1g2eHUv?= =?utf-8?B?UG81RmZ5VzhQeDdpcC9yd0ZMQ3BOeXIvbW51QjdsaGROZVErNlJKdXNqeWJC?= =?utf-8?B?WmNhdDEwdEhmVFNvTjFMc3Jab2N6NnpNRk1qODRMYU5kM2FUZHFwU2RsazNP?= =?utf-8?B?YkY4M3Ztc3pzYTBBMUNnSXNkMGkwNThxUE9UakVKN3RwL0MzSzRlMnM1Y1ZK?= =?utf-8?B?TXJNb1FzU29mVmhlVjVXKzYxa1FTNlp6UHVEK253OTI1RTRVbDhCVldLSEFv?= =?utf-8?B?RHVxWlA2S2pMekM5TEZUVUR4di9LNHBINGhyMzlmSm9wODdiTk1ZR2NUaVpE?= =?utf-8?B?SjQ1N1Ftc0ZJRE92S0h5WXkvK0RKZmNSSFBPYThWdFQrUHpPSGROcUVwbklO?= =?utf-8?B?Q0c5c1diM1BCK1F0bmI5OHNzSnVsQW1mdjZRVVFZQnY4Y0JMbkZxMXZaSFZG?= =?utf-8?B?cWFxTkw3ME9sdEJHNEl4OFNLbTl5ak9ybGxwaDBvc2N5dk52LzZFeHVBMmsw?= =?utf-8?B?N3NXYXY5dllzdVQ2dXluSmhzaGlLVUl0OHFwVkQ3MnFRWW9lRXAzOWgwVmEv?= =?utf-8?B?b2Y1UXFiRU5ZTVIrdXFnS1Z2akd1QVVtdytaVVI4a3ZWaVBrTEt2QzlTMm5p?= =?utf-8?B?bmxVVmZ4azM4MGc0NDdHNm92VjdTQXN4d2NHWDdSeW9Fa3hFUkNDTmFheXpX?= =?utf-8?B?OGxneEQ3Z2F6ZHZvTklkUkV3MnFZRklTQU10eDV3SVFVK3BDOVJMeWNwckJ0?= =?utf-8?B?Rml5N0xKalZUQ0NZZUdkZDc3VS9hb1YrcEdJSHBsSFhOTmxodEdqYXdrS2xF?= =?utf-8?B?VEpnSk4zaGZqVDhYbS84ZDY5ZXF2VzdlMVhPZ1NubWhCc3NSZk1BeDM3Tk9N?= =?utf-8?B?SDJTWTZXS3VaSGhYTEdQeW52cUdXdmQ3TEQxMyswa2pEN0FBeEtVWkVWbTJz?= =?utf-8?B?c2dHcm83ZmJzY3lYS1dLNldwUVM3NEF0cVJqeFlMdERycjdxdFh2RlNkeEh3?= =?utf-8?B?TkpNOFdpc21nWThETkRjSXZ2bGZvZDhac0o5OEU2Vks5eVgxNWlGbXpzSGxk?= =?utf-8?B?WU90SjlMZzVMQ1hmT0d5ZzNJUEFBTkpZUlpuSjFFRkZwWjBOZUxSTkpuYWp6?= =?utf-8?B?NmwrUFZ1VSt1alhnU25BcmlhTlc2YUhSd1lBeGhDNlF4VkNyWFN2RXlPWGRC?= =?utf-8?B?RmRGcXJnL1pYTkJOUXEvMVFpdy9DZDZiRWVEbkZEYTdqbEJmTkt4bDZpNkpl?= =?utf-8?B?Zm41SVpZNm41aGFQL2FmZ1ZBSEFDaDg4WStqK3hnRGZzMXRJREZrdTJPclp3?= =?utf-8?B?akxrV0pyOHVBZkR2ZlY2S1BDOHU2R1NBc2pxOFUwdTgzL1FTSlE0OEZHYnEr?= =?utf-8?B?aGFscFFMZWN6L211eWtPSTFDaVZFZ0dBNUQ4eUh2RHY2T094c0pBbHVyNGcw?= =?utf-8?B?bWFXYUowVTZ1OFkxMEhlZWZkaFJ4dzFyWEJMb2hVcG1DR2daMTdGWFU1RXdt?= =?utf-8?B?VVZNTkhNMkdST3Y4UGUrRVhKcUE5TWRBWjlHR3JhNC9uekpnRitOVjhVOEhB?= =?utf-8?B?TVBsd0loNVZEejlzYjdNV1ZKc2hkKzNmeUlJbUlmVE5oUnhObVZLb21oTzFB?= =?utf-8?B?TEFBMU9Wbm02aTdhNGtTSy9Cd1VweGkyUHIvNnJxcnlHMHlidmFUQVFNRitR?= =?utf-8?B?V2ZLYThZSHR2SUlJbkJ4YmJic00vR0dGaUV2N3VQdjJxZUJ3R0xQTGx4ckxi?= =?utf-8?B?clBoTnltTGZkNVJ6cTcyaVZrODdaQkZOU0JZaXBiakdLVUNrZHFlYWs3ZW1X?= =?utf-8?B?b3F6b2trQlJhc0lOUXRwY2JDV1lxNW9tY0dIUGlZYWVTdTJNY1FnL1QybTlC?= =?utf-8?B?S1U1bGwwMmVTZ281S2ZWc3ptQ1FJblFoanZtWk4wNmlObytPb092Y0lJRkNn?= =?utf-8?B?L0ZQQk1QTGRjenVHZXJlSlVycUo3cHFUcTdWcUVtMEtpY1NxSjBXUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 47a2a8e5-44d6-45ab-9c41-08defde277fe X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:25.1557 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: eg0+/RzXjvWXiAEiaiG96AoDBJoEVenhH653q5xkgN6GQH1Jrw8WfThLZlCyiORr0sH8mUtBzNIJMDY00yXnpA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 With the removal of relative registers, there are only two type of registers left, fixed register and register arrays. There is not much benefit in having a common super trait for them anymore, thus remove it, and cleanup the macro rules associated with it. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io/register.rs | 22 +++++++++++++--------- rust/macros/io/register.rs | 12 ++++++------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 4d4afd3ae94a..6aeee6c0a5f2 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -121,8 +121,8 @@ io::IoLoc, // }; =20 -/// Trait implemented by all registers. -pub trait Register: Sized { +/// Trait implemented by registers with a fixed offset. +pub trait FixedRegister: Sized { /// Base type for this register. type Base: ?Sized; =20 @@ -132,9 +132,6 @@ pub trait Register: Sized { const OFFSET: usize; } =20 -/// Trait implemented by registers with a fixed offset. -pub trait FixedRegister: Register {} - /// Allows `()` to be used as the `location` parameter of [`Io::write`](su= per::Io::write) when /// passing a [`FixedRegister`] value. impl IoLoc for () @@ -200,7 +197,14 @@ fn offset(self) -> usize { } =20 /// Trait implemented by arrays of registers. -pub trait RegisterArray: Register { +pub trait RegisterArray: Sized { + /// Base type for this register. + type Base: ?Sized; + + /// Start offset of the register. + /// + /// The interpretation of this offset depends on the type of the regis= ter. + const OFFSET: usize; /// Number of elements in the registers array. const SIZE: usize; /// Number of bytes between the start of elements in the registers arr= ay. @@ -266,8 +270,8 @@ fn try_at(idx: usize) -> Option> /// /// Implementors can be used with [`Io::write_reg`](super::Io::write_reg). pub trait LocatedRegister { - /// Register value to write. - type Value: Register; + /// Value to write. + type Value; /// Full location information at which to write the value. type Location: IoLoc; =20 @@ -294,7 +298,7 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// This is used to enforce base matching. Only called during const eval. #[doc(hidden)] #[inline(always)] -pub const fn alias_offset>() = -> usize { +pub const fn alias_offset>() -> usize { Alias::OFFSET } =20 diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index 757ea8094f61..e0bba6b71ebc 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -213,11 +213,6 @@ pub(crate) fn register(def: RegDef) -> Result { #[allow(non_camel_case_types)] #(#attrs)* #vis struct #name(#storage) #args ); - - impl ::kernel::io::register::Register for #name { - type Base =3D #base; - const OFFSET: usize =3D #offset; - } )); } =20 @@ -233,7 +228,10 @@ impl ::kernel::io::register::Register for #name { ))?, =20 None =3D> outputs.extend(quote_spanned!(span =3D> - impl ::kernel::io::register::FixedRegister for #name {} + impl ::kernel::io::register::FixedRegister for #name { + type Base =3D #base; + const OFFSET: usize =3D #offset; + } =20 #(#attrs)* #vis const #name: ::kernel::io::register::Fixed= RegisterLoc<#name> =3D ::kernel::io::register::FixedRegisterLoc::<#name>::new= (); @@ -256,6 +254,8 @@ impl ::kernel::io::register::FixedRegister for #name {} impl ::kernel::io::register::Array for #name {} =20 impl ::kernel::io::register::RegisterArray for #name { + type Base =3D #base; + const OFFSET: usize =3D #offset; const SIZE: usize =3D #size; const STRIDE: usize =3D #stride; } --=20 2.54.0 From nobody Mon Sep 28 18:36:45 2026 Received: from CWXP265CU010.outbound.protection.outlook.com (mail-ukwestazon11022139.outbound.protection.outlook.com [52.101.101.139]) (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 1D6A245DF47; Wed, 19 Aug 2026 11:10:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.101.139 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137853; cv=fail; b=prT3The2roAi7PI3VfWc2g4+cMfa6YwKN7vM6niPIBbIwC1m59DTgjit2jlD0SemDJSZl3lxR+OtigzfdfmLjwwmHd6/if4paRlSXheCuYuinWjUnS8Aj6wHwZPG+bZWpF9togSkkvqd/6OAGO+D5TGygJn0WuKGAsmLLxIZnfQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787137853; c=relaxed/simple; bh=JMrzYCCzURp2mz3dTp7Fxw7Ib+5Gt81QM3FwMsopjK4=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=BMk2Fanbxxhn1Z33DsBi+d76k0GBhE/rCwypOoDZkf6I/kyh8+zFV0KH/JfQzZeAZBGRAQvBOJRYqqzZU6WJOstcGKWfEXFErVp90ROj34X3MvNyS9iDb1E1UR88ji9353Cm7TeWcJoZjvofAVwU9qzIN4i2tyJwzSEh/ZinjBE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net; spf=pass smtp.mailfrom=garyguo.net; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b=eocrs4hn; arc=fail smtp.client-ip=52.101.101.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=garyguo.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=garyguo.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net header.b="eocrs4hn" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=hmhB0O7o1NIylugBeSueNiuwsBQvIoPNnXPagzDufk7iYXXtkb5Rb0PdZO8Tn8FWvk+ZS2woGRxykDtOGUAVTw3bmArEJt6uNJTwUaRX/UmZjbBtTGlyea9/+APwLOzdWj9yNAhtDD5GsqbERgAYSD8T/nXPOAaEMsqQMqUYGs7YKE/hSJ7fG5yEDiJQhJqxafRQudbzNB1hKxezxjYqf2zKrlp9sHpxyqhJTNgYm3Abd4W90HTowxwiNf5Nj9YzJu8J9xw0shybDr+kxPufrn1aMM0pqHGUL/L58K12MPMqpy/xkWuB2ABrILLX63jWBmhDrfqwGks4LqjCd2ge7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=J/y5I1JBTn6cmjbdLd7/BOmMMYAM3FlzpiOMsdJE9Eg=; b=Qi/lM59zyNrG4uFd494S6yQ0xcKpfFMi5m7GipEfrrIMMLDZuMKjzMN/7Am75wb2bWTbjddDq9+kgAHOfGvSTwO7e1ybnl6lgZC8DI+wXDk2DKrK0jht8/brNroeoeOjuQ2uDJa5/Zas1uTp4cXV4357Pv6sqV4Dn7IYiAcZHyrOyvpIg1sNkHGP7PtBKdLfzN0JcyShWvSIwaHq5AuFYdpMHIyiX4N/UTRQX8gtuutfEcvvBpDm3yAfk9ESeYdhdq5+bVsZdN44N2VS+ag6zBUtLNP44E1qinvdwkDqsP3rQMRoKi2g0kqSUPzdOiTph78p0S4MQEigJTY3sgF1lA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net; dkim=pass header.d=garyguo.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=J/y5I1JBTn6cmjbdLd7/BOmMMYAM3FlzpiOMsdJE9Eg=; b=eocrs4hnKNZQzg6mLC3WNTPeBJ9UZpXItNqr1QGHwFF5Nc6iY3ipToPFC42UcQcF98Y0NPf/BmDJr61qZbWmABrHG5mE0Jjdf2Ojjc1/QBA/uA0QlYuRzEJvieb24Y5Hdkz/SrRFBFpcnGOtqlsECtXpwHSv9Ydn0cXFLq7fbo0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) by CWLP265MB5113.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:15d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.339.8; Wed, 19 Aug 2026 11:10:27 +0000 Received: from LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1]) by LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM ([fe80::f60b:1537:68d7:4fc1%4]) with mapi id 15.21.0339.007; Wed, 19 Aug 2026 11:10:25 +0000 From: Gary Guo Date: Wed, 19 Aug 2026 12:09:24 +0100 Subject: [PATCH v3 16/16] rust: io: register: unify handling of register with/without bitfields Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260819-typed_register-v3-16-3699a75fadf1@garyguo.net> References: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> In-Reply-To: <20260819-typed_register-v3-0-3699a75fadf1@garyguo.net> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , David Airlie , Simona Vetter , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= Cc: driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, Gary Guo X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787137814; l=10173; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=JMrzYCCzURp2mz3dTp7Fxw7Ib+5Gt81QM3FwMsopjK4=; b=pqJluX9sMEzCSANY3xkiBtFpNAby1zhrilrfh5JfAP/o8nmF4UMjX25iIArKURmUNlbUZf/dg sUaiXunFBF5ACtRQJ46FOtHkDB9EXKr+YmruaPCMpWGdUzmKYw4HT9t X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0096.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:191::11) To LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4ab::19) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: LOAP265MB8560:EE_|CWLP265MB5113:EE_ X-MS-Office365-Filtering-Correlation-Id: 8d317c98-fab6-459c-1bd6-08defde2785f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|376014|10070799003|366016|7416014|23010399003|921020|6133799003|3023799007|56012099006|10067099003|5023799004|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: DXMcvezXgi2ZQMaY6cHFkij4CglYzakXaLCZ9CPDJfxbxR1c/8H/zuzaork9wUkaJtcb4js9szw6gQFD0LkQykTSWTzO5hiSrAiMp1nZEiLVsazXRdgmzBkYYzDFdPgpl5dGKLQQWpqfR2Xpg6yfRv1ioCx9hXkmVlWluKpYZZJ3cEg1uuoiEjVY+tbqSZTUl4eABizx+y9rpi6zOHeORzXqW/J2bB/ok0+mhJSfc28iabKD01irMUsOd8dvNAW5YI7hM3afOVGWRlidG17+TngyzVnJCnrKLKdNAHUwUnRiyLs8PU5gQIV+gstNb4qVoZ82iF+ui6POdUyOIEg+urp406vZ3EzqZW3N49kKS+85WYl58EYgwBMKqFSNd1bnjETToYD3LC1Im3MhUargfV0fnsQcvBazhw+UZgYBSxqweWVlQTD551jX4Y0j93BVo4L2LNdG1ThGM35kdL4Y30VaDcuYz7IPZ8MyMLEPfQ/qynMK5iL4/23w3DwmOU+tR8zfl5RMPU89DsRJ/UDuHbTZVSt0RWmQ46FayGzlqdQ6Dr2HIhs9aIHBPJEPUuMUbsb7UuRZf8jLAs+bOWT8ypOKJmEGEGwohOMS8Rb4evAbs6IyC/rV5ytwYA80UnKGJ4zvXdmQkuv+1w0jgdltu0pCkvl7AVQobjr1GL072jElEsT4B0McxdaU0SqLTWrNACln+DWck2lv/NDKodAhzQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(10070799003)(366016)(7416014)(23010399003)(921020)(6133799003)(3023799007)(56012099006)(10067099003)(5023799004)(18002099003)(22082099003);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?ZGphOHdZbXRZc1lvNWJ5amFFQUNiMHY0STFWVXR4ZEdpV2hvdjRhRkZ0bjV3?= =?utf-8?B?R0dLOVhVZTI5bzVFa1JHUjd0cGFvTno2TDlybDR3NmZrRUJIcHpIOWJITk1q?= =?utf-8?B?QWQ5MUNGLzRuSWM1ZFpaU01vK1UweXBsdFViMFdYdHRzRklwTnRLUzZ6bjNa?= =?utf-8?B?ZkNZYXRZMEFIZy9SdDNVV2U5Q1E3aXpNN3ppei9yQlp1ZVAwV2Y5OHRqUXI1?= =?utf-8?B?WlJla1B6N0x6d2FReUI0K0xJa3VKVTd2eVJVUVBVMUp5Um9lTnJnc0FFUjZH?= =?utf-8?B?NUVDc0Iva3dpQ09GUzVSYWJ4MUpJK0RwOWNJaFpLOG55dFRuYVQ5c1ZmY2hC?= =?utf-8?B?U1ZuTGxxR05PNndjOTRBeUs0ZXRBdmc1NkYvTm1lVFRlODZBTkR4bmxpVEZ3?= =?utf-8?B?dTVITmo2QXVrVXZTSm84Qzg5NWJtQTZYeGpDNGxRWnlha3BqRFZSQTY5SWVU?= =?utf-8?B?VDlGREc1U1RHdGh5bkRzMVJtdTUvUFpJNCtTNjkzSUlFWHhRQm9iY1h5aVpz?= =?utf-8?B?VyszTkxSTGRzdVdHeGZxdnpnNjJsbWd6bk9za2liNkdwR3l3anFlaEp5eXpM?= =?utf-8?B?ek52S2piVDJqSUEvcnVPT2lpKzNuNlVrZDZVRkFjdFJ4Q2RxZHVVR2szSEZh?= =?utf-8?B?MEZac2VVb3VYS2xoN3JpUHZPYzNVRlFMM2ZXVXA3bnBxVTNWWDJHb0hWTWJq?= =?utf-8?B?RzBtNkVrb1FOQ1hTbnpHTDVLbnJyL1g1OEdlcjFuM2YzODVUVlFibnZSY2tR?= =?utf-8?B?L08rQTJuU0FqamRVM2UxbklFRXhVWTRFbEtZcDBWYXp2WDdMSmRqRDJXdE9O?= =?utf-8?B?Q0JjSTgydnduQUYwY3lSRk9tQ25iMzlkemRNbG5NRjh3OTByamovWWw1akpO?= =?utf-8?B?a1lINkVFc1JMOURRWDJ6QXJyV2RuZXFtR2xkT1k3NUR0T0lxVEdaTTZ0Zmlp?= =?utf-8?B?a3JoNHhJR3JYSDhncDhQN0laRXhXRzM4S0QrNVpYMWdTem05ODJNRUtPMmFN?= =?utf-8?B?Z1BIaVdna2k2emtmSWVyUmxsQ0ZqUlJXOXpIRW9mKysyTFhqZGZwYzVtaFlK?= =?utf-8?B?TFN4RnJGdHlXUXJMNUJVRys5TjFiZCtxdmp6aVlFR3VybzdGVG93WjRXVk1Y?= =?utf-8?B?K0hZSDMrMGw4Tk1CZHhSRURCaVJocWl1eE9GaHhXc3VBMVhQclhSYzVXWTZE?= =?utf-8?B?cUdDSzRCbWpzVU1aTzFuY2pXV1JyS0w0N0pVR2FoYVF5RUlUK2lvdmN4ZFpi?= =?utf-8?B?WHlwbVdpTUlxbU11bE9SVEw0c1NMNjJQQ3g2dSs3WUZuNlREa2QzOXhIaVVx?= =?utf-8?B?SmYzbnU2MjZRR2ttRlA2UlJCV3ozM0JlL1FrZy9XTXovZUpwUzl2Z05hek9J?= =?utf-8?B?OStITk01VjRLQkxxTUlsN3U4QlJYcUN2NVpuOVRnYXdxcW1vbU1LMGloZUhM?= =?utf-8?B?SFBRQUF2WjFueEl0L0xraC9JZjlrNkQyQ1VSR2V5RHFEQlV2bFQ1eEhaVHAw?= =?utf-8?B?T082ZGJkQWhWTEZ1aDc1T1BFb1htS2NpRXpaUXJDOFpQSHBrZVBJQStTcDdP?= =?utf-8?B?MmptQUdGaTFQemxld1o3ZEhwWm5HMUpMUmVxU0NHMXA4V044ZXMrWlJmbWk1?= =?utf-8?B?OEJ2UFpJKzFGK3RJQk5uS2pXWjdYR05kQS9yN1Z3SWdIcFpjU29DMEhXTWRM?= =?utf-8?B?Q1pQcDRUNFhSNXFOeWZ0WDJCTmQ4d3RsYjJIc2NMQkRGaGJxc1owOVdzQ2lU?= =?utf-8?B?cnFQSXBUTmZQbjNDbkV4SkFSVmtaaVphSjVzeXNFWGFFTitzRytsWS9lb0VD?= =?utf-8?B?NjJwQjloaWphN0pUS1hGOEpFSFVYWkxaS0xqbjlkZVh0ZzZGb3ZvOW1aakZs?= =?utf-8?B?bUNUeWhHa29kZ2pGeFpsMFIvcE5pWUp5OExlOGhmSnVOOGNQQ01qMzBhYmk4?= =?utf-8?B?ajgyaHN5TFp3bUpBM3pOZnFVTnMyMFBkUzQyeTlvMDlicjhBTEpyeS9vNE5V?= =?utf-8?B?Yk9oOGp2YThLSDlSeHVXbDIvSDVvNWwzZVFFVXNvR1c1QjF3SVlEelNUNzl5?= =?utf-8?B?blNQYjl6VnhxbkZqbm43UEhITmFkYTNYSXZxS0FDU3RyemNHY3JDUEE2cVhq?= =?utf-8?B?bGdkUUFUTW9YeWlFeW9yaFYvWDVGRzBYSGNNdDVURVU3QnVCRVlrTEthSlY4?= =?utf-8?B?QkNJTzhpMWJ0OVhSS29qd0xjWGtmWXFESmZCQ2VFenNTL09nakFPRlBNVk5O?= =?utf-8?B?NDdNK2hFYVZiRTI4Nkh5M2hzMnE4MHBEcUdYbGNENElwRVpOV1NGSWk2SWRz?= =?utf-8?B?NnBROGJqUWFvb3RBbk5FaDU3am1VaDdQbWFhY3VoMUFJQysvSlBLQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 8d317c98-fab6-459c-1bd6-08defde2785f X-MS-Exchange-CrossTenant-AuthSource: LOAP265MB8560.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Aug 2026 11:10:25.8196 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: bbc898ad-b10f-4e10-8552-d9377b823d45 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: nk/dOWO8R0gdjlpH5HUb1WLiqhBmYZ+IuDCs2OzH+UhzNfLaj+VEkP6rGjqu8nryZ3f+k+rvblgHcrxciv3F7Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB5113 Move the `FixedRegister` to be a property of register to become a property of type. Name the new trait `FixedIoLoc` indicating if I/O location of a type is unique for a specific base. Thus, bitfields become just a special case of this (where type is unique because we're generating it in the register macro), and expose feature to registers without inline bitfield definition with the `#[unique]` attribute. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io/register.rs | 110 ++++++++++++++++++++---------------------= ---- rust/macros/io/register.rs | 58 +++++++++++++++--------- 2 files changed, 85 insertions(+), 83 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 6aeee6c0a5f2..6d4ffe6e7b5f 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -121,61 +121,15 @@ io::IoLoc, // }; =20 -/// Trait implemented by registers with a fixed offset. -pub trait FixedRegister: Sized { - /// Base type for this register. - type Base: ?Sized; - - /// Start offset of the register. - /// - /// The interpretation of this offset depends on the type of the regis= ter. - const OFFSET: usize; -} - /// Allows `()` to be used as the `location` parameter of [`Io::write`](su= per::Io::write) when -/// passing a [`FixedRegister`] value. +/// passing a [`FixedIoLoc`] value. impl IoLoc for () where - T: FixedRegister, -{ - #[inline(always)] - fn offset(self) -> usize { - T::OFFSET - } -} - -/// A [`FixedRegister`] carries its location in its type. Thus `FixedRegis= ter` values can be used -/// as an [`IoLoc`]. -impl IoLoc for T -where - T: FixedRegister, -{ - #[inline(always)] - fn offset(self) -> usize { - T::OFFSET - } -} - -/// Location of a fixed register. -pub struct FixedRegisterLoc(PhantomData); - -impl FixedRegisterLoc { - /// Returns the location of `T`. - #[inline(always)] - // We do not implement `Default` so we can be const. - #[expect(clippy::new_without_default)] - pub const fn new() -> Self { - Self(PhantomData) - } -} - -impl IoLoc for FixedRegisterLoc -where - T: FixedRegister, + T: FixedIoLoc, { #[inline(always)] fn offset(self) -> usize { - T::OFFSET + T::LOCATION.offset() } } =20 @@ -187,6 +141,11 @@ impl OffsetLoc { pub const fn new(offset: usize) -> Self { Self(offset, PhantomData) } + + #[inline] + pub const fn const_offset(self) -> usize { + self.0 + } } =20 impl IoLoc for OffsetLoc { @@ -265,6 +224,17 @@ fn try_at(idx: usize) -> Option> } } =20 +/// Trait implemented by types that indicate there is a fixed I/O location= for this given type. +/// +/// Implementors can be used with [`Io::write_reg`](super::Io::write_reg). +pub trait FixedIoLoc: Sized { + /// Type of [`FixedIoLoc::location`]. + type Location: IoLoc; + + /// Location of this type within given base. + const LOCATION: Self::Location; +} + /// Trait implemented by items that contain both a register value and the = absolute I/O location at /// which to write it. /// @@ -282,26 +252,17 @@ pub trait LocatedRegister { =20 impl LocatedRegister for T where - T: FixedRegister, + T: FixedIoLoc, { - type Location =3D FixedRegisterLoc; + type Location =3D T::Location; type Value =3D T; =20 #[inline(always)] - fn into_io_op(self) -> (FixedRegisterLoc, T) { - (FixedRegisterLoc::new(), self) + fn into_io_op(self) -> (T::Location, T) { + (T::LOCATION, self) } } =20 -/// Helper function for register alias implementation. -/// -/// This is used to enforce base matching. Only called during const eval. -#[doc(hidden)] -#[inline(always)] -pub const fn alias_offset>() -> usize { - Alias::OFFSET -} - /// Helper function for register element alias implementation. /// /// This is used to enforce base matching and provide bounds checking. Onl= y called during const @@ -419,6 +380,31 @@ pub const fn element_alias_offset; +/// +/// pub RESET: #[unique] Reset @ 0x100; +/// } +/// +/// # fn test(mmio: Mmio<'_, Region<0x1000>>) { +/// // let mmio: Mmio<'_, Region<0x1000>>; +/// mmio.write_reg(Reset::zeroed().with_const_reset::<1>()); +/// # } +/// ``` +/// /// ## Arrays of registers /// /// Some I/O areas contain consecutive registers that share the same field= layout. These areas can diff --git a/rust/macros/io/register.rs b/rust/macros/io/register.rs index e0bba6b71ebc..84be1a593959 100644 --- a/rust/macros/io/register.rs +++ b/rust/macros/io/register.rs @@ -51,6 +51,7 @@ struct Reg { attrs: Vec, vis: Visibility, name: Ident, + unique: bool, ty: Type, array: Option, offset: RegOffset, @@ -65,16 +66,26 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Result<= Self> { =20 let lh =3D input.lookahead1(); let mut bitfield_storage =3D None; - let ty =3D if lh.peek(Token![:]) { + let (unique, ty) =3D if lh.peek(Token![:]) { let _: Token![:] =3D input.parse()?; - input.parse()? + + let mut attrs =3D input.call(Attribute::parse_outer)?; + let unique =3D attrs + .extract_if(.., |attr| attr.path().is_ident("unique")) + .count() + !=3D 0; + if !attrs.is_empty() { + Err(Error::new_spanned(&attrs[0], "unexpected attributes")= )? + } + + (unique, input.parse()?) } else if lh.peek(token::Paren) { let content; parenthesized!(content in input); bitfield_storage =3D Some(content.parse()?); =20 // For bitfields, bitfield macro will generate a type with the= same name as `name`. - parse_quote!(#name) + (true, parse_quote!(#name)) } else { Err(lh.error())? }; @@ -138,6 +149,7 @@ fn parse(input: syn::parse::ParseStream<'_>) -> Result<= Self> { attrs, vis, name, + unique, ty, array, offset, @@ -181,6 +193,7 @@ pub(crate) fn register(def: RegDef) -> Result { attrs, vis, name, + unique, ty, array, offset, @@ -195,7 +208,7 @@ pub(crate) fn register(def: RegDef) -> Result { RegOffset::Fixed { offset } =3D> quote!(#offset), RegOffset::Alias { alias } =3D> { quote_spanned!(alias.span().resolved_at(span) =3D> - ::kernel::io::register::alias_offset::<#base, #alias>() + ::kernel::io::register::OffsetLoc::<#base, _>::const_o= ffset(#alias) ) } RegOffset::ElementAlias { alias, idx } =3D> { @@ -217,27 +230,30 @@ pub(crate) fn register(def: RegDef) -> Result { } =20 match array { - None if bitfield.is_none() =3D> outputs.extend(quote!( - #(#attrs)* #vis const #name: ::kernel::io::register::Offse= tLoc<#base, #ty> =3D - ::kernel::io::register::OffsetLoc::new(#offset); - )), - - _ if bitfield.is_none() =3D> Err(Error::new_spanned( - ty, - "defining without bitfield is not yet supported for this t= ype of register", - ))?, - - None =3D> outputs.extend(quote_spanned!(span =3D> - impl ::kernel::io::register::FixedRegister for #name { - type Base =3D #base; - const OFFSET: usize =3D #offset; + None =3D> { + if unique { + outputs.extend(quote!( + impl ::kernel::io::register::FixedIoLoc<#base> for= #ty { + type Location =3D ::kernel::io::register::Offs= etLoc<#base, #ty>; + const LOCATION: Self::Location =3D #name; + } + )) } =20 - #(#attrs)* #vis const #name: ::kernel::io::register::Fixed= RegisterLoc<#name> =3D - ::kernel::io::register::FixedRegisterLoc::<#name>::new= (); - )), + outputs.extend(quote_spanned!(span =3D> + #(#attrs)* #vis const #name: ::kernel::io::register::O= ffsetLoc<#base, #ty> =3D + ::kernel::io::register::OffsetLoc::new(#offset); + )); + } =20 Some(def) =3D> { + if !unique { + Err(Error::new_spanned( + &ty, + "defining without bitfield is not yet supported fo= r this type of register", + ))? + } + let size =3D &def.size; let stride =3D if let Some(stride) =3D &def.stride { outputs.extend(quote_spanned!(stride.span().resolved_a= t(span) =3D> --=20 2.54.0