From nobody Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021138.outbound.protection.outlook.com [52.101.100.138]) (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 D2F543F12EF; Wed, 5 Aug 2026 16:37:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.138 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947825; cv=fail; b=a9WdIgeuXm/hsIY3P4gtkqdTto5N53hsT1mS5Ha8vETZm2AgF6AcV5AMyRydepNTeMajcegQaW5t9vawd2pP3bAoitCcrKlk0LwCAk1FhhLRNVzCqbzLAcD5LkVKAigiE3YnzCqj3d2YOwlQG9mwaW/wY4RwNOZic2TDb04xzWY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947825; c=relaxed/simple; bh=o9NP3KChQiiuJi1QX3sJ7C+sxJNUC14IZemxkEQI+tE=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=FgCdPdgyzGGnue4TXSHgkWuCDBX8PtZw7jwa255Z2sreYQ8CimsUcN35QZ+HXQ/74I7H/rXdIt4eRZHwR3Ds2we1RLENxGRVWQgqYz2Bx4DAK+OgmncR/QZv/1WpyqlAS6NmFoaY2sNi+ekjaBnGqR5sQMn2iKo+SWEMwzR9pIE= 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=gi7hOpYg; arc=fail smtp.client-ip=52.101.100.138 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="gi7hOpYg" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=t18cnuhC0wIAiLB+gkWXOLP0Mi3uWdtWokXdgzFwDFvfW7koXpMS7FsdvO8R5aLE/qGbNIELpK5Nwta7OyNjmJmVbXVrMl8MmRj+leSn79tkM4/LDRI/fvHyyP4p/+cJyi8/duuI5B0/P8+K0xLLwkOsDLEkUEbhMMwkFFA31X9Nklx1PPYkfhQ4w/1VTMurgsR4vASNiqzVyjuEuO30dP3Twkt3Em5l55aFym0cSTaWotBdLfHfZWbAdLcZe2i0nclLoFA3QYub80oPbnLoxf/XPirRixSeiBLrf8PWI/D2haXItA+3nVMpiVqjP6UQBGJea9JBXk9fd9mb9sYXBg== 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=d8OQ7ZBrw0of9g3HlhJ/tG/nL4mq7cL7aN4guX+dW9k=; b=dGZKsKb+Y1bBSsGVBkFCnX5rkHKUFQhAOj2/ulTk35Iol6T2M5IB0kJ3U0TbHMqLWwcr8KL0jlR/AsB4L6LY7kA7lyTR7ujQCTUqdYAAVPpaVHbXRcsS0W+PabknDPX0XKYwHIhs6XlJucNxWTsQ3CBAKDk+VWNAvkKWqiEPM4e6PZuiv7jqekFTG+7Rn9Mdpy1t294hDKxHdxowtDk24cxgGKuMteg2DdjPJWto3MCoKsZZZ7zCN+0N/YFea9L9q3bVDiPt5QeKmYsgfc2PJNr5jNpc5I4Xo2s+rC5b/OpGhJBtNMAxsjmLMiVhEpY+BZT9og2JI11yGpVGcfR8BA== 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=d8OQ7ZBrw0of9g3HlhJ/tG/nL4mq7cL7aN4guX+dW9k=; b=gi7hOpYgdwjMN/2S8aqSQquJQXAr4oqOPZdhq/J45CVom678CFjtPp5Xo1EbGEKa+X/EYgXYwKR9sSMsSLMroBHyXTU8AvXSjfcSxTHZsd8kzcm+eb8N0dRMmT9f2XHVBDeHQfOXnSmlTT/6fTXLZ3ouHfnL5bIPwlq8x3neziA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:00 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:00 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:44 +0100 Subject: [PATCH v2 01/16] rust: io: add static `cast()` method for views Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-1-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=1983; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=o9NP3KChQiiuJi1QX3sJ7C+sxJNUC14IZemxkEQI+tE=; b=Y9PkUbJayNfxosKzmqJ6X77HKBe9iumC0tPSdx2YmBMhDdke89n1toW4uBDid5n7dd3/ROQFf PRt6SuZupqWCFcmnnoTFjnW6saMjrlIISm3b8mUz/+/EPeyUDWQa5XL X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: f10805a9-3732-4fc8-ba03-08def30fc5bf X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|6133799003|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: ITjJ+jFpHKnua7K7h47B2fuzAV7o9YGoU8aUi8qXE9Z3QMA78qQI4E70QTA95+qQIN+bOxgB6nqnWxpMESCA6aK/xH3ikAC8NceP+N3mz4khG8u5OQwymjLiAianavdklXHqrMK0SyGbKyinXZP/0LUEuhvrCSJILaTI3DAwUSasxnP9VscIGlayksSIOJWbe0e/jAoeEb5DVxcDcAOjCguXB+Imm/SQZTqp8a8XILJJYU88IJS0EVCiNPPQtGwN+dVUJTktwCOfeOrgRXx/uad8XmA+YCtuH149Emo4P5PaFOnBbJeXzN4jBG0g9p7JRyj4fHRdZjK3InNSiUrGT41znVLXZyIEMqlhOc3BFfSbT98y/SjX2HAjnhURabgtJx5WKrLCROXfdhhPj7vHRU6VD1Av2g5+y4OXXnYR0mlSwPDi1/NZC7XhBLmb2rW8pW5NVBzh5O8pD/0XRdZbafANkayv8r9dqqd7cxLV7Ia+NHgRIaJHzElXEfC4oZzLLC6hWPLBVs8B05Mx0F2Loq/am4c6fDbDt7WYaISi0vrFVcbpDz02GkK9dS5qvj3s1hVu7umpoNDl/yzehC60uPte9HadmXX0Rpy8UnwzGx31gUSOkoNksobDHXzrPmIckcSvsWrteKHdAkzbDXA+S9e7p8Sd2IGexjyYTHMiTNVsOIEIPmcryWZr3mpQZvTPLxju1/fQf0xfrWmBV1ZaUA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(6133799003)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?RXk5emlJZWRlV2ExdTFOWmFLeDc3WTdoM0U0RmEra0tOVUcvWENiaUhLYUU1?= =?utf-8?B?WFhzU3RmVFlpR1lRMEFlU2MyeXduR09qSlRTUGdncGhRdXJOWWZYbXFtOTkw?= =?utf-8?B?a3Nwb3huZVVzSVE3Y0ZrYldWTnpsRWlDS0l3Mm5MdmN2ZHQ0alBQODVPUWR1?= =?utf-8?B?QjNSUmdqRkp0R2NTREtyTVBMeHJKc3dmbUdLeFdlbjNKaVd2N3RBb21HaldH?= =?utf-8?B?MHBuRkNpc0RIMlZKWmk0OWE0VXowY01LRmRvK3crcmZHcU4ySU5mYkNYdllJ?= =?utf-8?B?akpsdjIwRE5NUVczbnUwMVVaVTlsbHFwazIwUHVoZW5kK3p0cmljSkFueFdX?= =?utf-8?B?RVdSVHh1dTRkcnYvUXl5bVc5RGs5NzI3TE10K1BIQWIwWElVRytQRDl4Z3Rh?= =?utf-8?B?TmFIWTIyYXFyK1R1WmpSeDR4TUlaRHVHZlgyMkxkV21MNHQ2QkdZMm1IQ1FW?= =?utf-8?B?d1kzcGd1RXhTcnNkZCtBKzNoL3ZjTXVaeUJMbmx0SEJuYVFlYmFZaUUrYTho?= =?utf-8?B?YVlFQkVNc3JQMC9VQk9HVDRJV0tDUitxTzFMUlg5bW4weWFkT2w5QjFuQS9G?= =?utf-8?B?aFNoVjRadDFibzVoRzNWNDkzYXNNaGFGelJkbWxGa3NsSVlUZ21hejNPeXpp?= =?utf-8?B?Ti9WYmJoUDFycmJlaThqNGxqMS9GV3poWnVpUnloOE1kYmpRbzdpRjI1endI?= =?utf-8?B?ejJHbFlZTkJUUFZybzc3SUtKeHJuUjJSNFVQajNUcmduRDZ3OFdVUHlCUmRy?= =?utf-8?B?RDJHV1REOVg5Tmc3dmlXSmxsa0hPWjA4cWphVERpczRXOVNIYk5yQ1VFVmxu?= =?utf-8?B?WXN6VUY0d2VKNkZSaXdDeUxHdjlSUTFzYUdWZHJzUXBxZE1OUEwyd1NEdDcr?= =?utf-8?B?SWs0UFl4U0FEYjZHeGlDZndCSEZtM3BzWWVZZlF4cEVkdnJoQmZFOEZBVTRt?= =?utf-8?B?eERPbm16bUNTT3czbmdCNzA5SGJmbGVBRTFxcEdVbHZ4djFBRjZJWUNNeGEw?= =?utf-8?B?MExQT2ZxUEo3djNzeTBGbHRWOGVhYVpEei9oelRTWFVYdHhiRTlDempzKzhL?= =?utf-8?B?eXRyaXZkLzVianppL1dPRVZ6Ui91N3hLUzlWdThUNmI5aG5zTVdZeHZmNGhQ?= =?utf-8?B?S3llY21RakE2bFBBME0zYnRncGk0bEdRMkdlbFRaWjZaV01HcVNLQ3RiQ21p?= =?utf-8?B?SHRGWXlCcG1EclgzMnR0WW5kZ2NQTDFpKzBKY0phRzRXREtFTlpkU0VwbXpD?= =?utf-8?B?UVQ3ZzlIaTVCMWVLQVVQb3k5cTM1MnFYYUlmSlpRZFQyVExPTkQrSkovT3kx?= =?utf-8?B?YUREaVJCY3BPUGgrcU95akxtbS94QmVnZE5HM0c0WEpKQ3RPajdHNDlHaUdS?= =?utf-8?B?M0l5U05qT2VoMmw5Vi9tUjNqLzVxUENpMU94VDYvZS9qdFJhUnIyUWw3a0N4?= =?utf-8?B?LzI5ZGNwZTM4aDNoV21yOXkvUUQvZmNMeFZSd1ZpZ1R1aER4S0pkSThXTC9W?= =?utf-8?B?bzJ2SEZIVFV2RVBvejd3MUcwT1l2THhaWTlLcENqOGZrS0g3N2ZWVU5LbldQ?= =?utf-8?B?UDh4MTlKMUJxN25wYVhlTUtuZzluTHc4aDhFUDd1TzViaE1zb1dhalhYdG90?= =?utf-8?B?QXJ3czdZMk8zcXgvZTZRQVJ2QnFIZ1hsZTNvUDh3QVVTSHltZk1qdWNBd3cz?= =?utf-8?B?MUlDdFQzWFlnaEErWU5PYVM1UXh1emZ2Q1VzbTBDSm1pZTZpdVovcEFwYkhl?= =?utf-8?B?NU9wQ0dxNU8rU05QZzBmTEZKSyt6cWhlaU9WbksrN25TUGRMamdqTml2VHBp?= =?utf-8?B?Nm1FVGl2ZC9TMlk2VmtNNTdlbm94ZkRhYmFNendVSnE0dkI2WG1xemR4Rkpj?= =?utf-8?B?K05xZ2ZtQjZ4Zmd6UmQ3VDBNZjdOcGVqWW8xSkczNjRITWhzWHJmQ0RYeCt0?= =?utf-8?B?RTE5Q2pNRFUxS2dRNEl1cFlyZjhWUzN4ejNuSWc5UTUxa0lUZ1d5ZWZDZWtG?= =?utf-8?B?MHgyWjFFRGxxTDNIb1pOSnJaRGpJWWJ5Z3ZudHVXK2hsNEM0Y1JxWjRnM29l?= =?utf-8?B?cGtRdUp0QnBsUDNJVW1BbmtoQUxHMkdxNXRoSnJsN2p6NVR2QVlBRitDM1JC?= =?utf-8?B?OWc3dnhJdTliRXpEV09zRHdOZjR2L0dqYlpCUHZLOTRGeFhYZW5LMFpBQ0Ra?= =?utf-8?B?NDlKUm5hMlppZkxQZk5LTWFybTVvc1A1a3NzL3MrdUNRd1JBN2d6ZTBFcnVX?= =?utf-8?B?aEF5R0pLTVZZUzIzTVRtUVF5TWxyaFFLZUc3NHI0WXVKZDhPdEEwd2JHdnJv?= =?utf-8?B?TWxidUZaZFRIYTArVXhxdGI1SFY4Q2FZdUhGTFdlZHdQMW5nWHhNZz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: f10805a9-3732-4fc8-ba03-08def30fc5bf X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:00.1889 (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: 06dmyMOBJ4f5dyBayBbBYdRoVJ4BHKlmjNdFiOv9YQb50mYiVwYpg4qLyF/ONQ7sTl8+946EqluBLoph1Jl2cw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 Add a compile-time checked variant of `try_cast()` using the minimum size and alignment information. Signed-off-by: Gary Guo --- rust/kernel/io.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index a38c20ba3d23..adfc555de7d0 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -436,6 +436,45 @@ fn is_empty(self) -> bool self.len() =3D=3D 0 } =20 + /// Convert into a different typed I/O view. + /// + /// The target type must be known (statically) to be of the same or sm= aller size to current + /// type, and the current view is properly aligned for the target type. + /// + /// # Examples + /// + /// ```no_run + /// use kernel::io::{ + /// io_project, + /// Mmio, + /// Io, + /// Region, + /// }; + /// #[derive(FromBytes, IntoBytes)] + /// #[repr(C)] + /// struct MyStruct { field: u32, } + /// + /// # fn test(mmio: &Mmio<'_, Region<0x1000>>) { + /// // let mmio: Mmio<'_, Region>; + /// let whole: Mmio<'_, MyStruct> =3D mmio.cast(); + /// # } + /// ``` + #[inline] + fn cast(self) -> ::View<'a, U> + where + Self::Target: FromBytes + IntoBytes, + U: FromBytes + IntoBytes, + { + let view =3D self.as_view(); + let ptr =3D Self::Backend::as_ptr(view); + + const_assert!(size_of::() <=3D Self::Target::MIN_SIZE); + const_assert!(align_of::() <=3D Self::Target::MIN_ALIGN.as_usiz= e()); + + // SAFETY: We have checked bounds and alignment, so this is a vali= d projection. + unsafe { Self::Backend::project_view(view, ptr.cast()) } + } + /// Try to convert into a different typed I/O view. /// /// A runtime check is performed to ensure that the target type is of = same or smaller size to --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021138.outbound.protection.outlook.com [52.101.100.138]) (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 C955E47CA73; Wed, 5 Aug 2026 16:37:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.138 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947830; cv=fail; b=sN33thdOdC9tGiUtfsWQoaG6lQ7WdWsfm+hFaq76UlLK0kcYgqTkuJSzpWjcICxoa9YjiGZRoV4mYdI7ShL6MDYXqDMPdcevRuG1j8Y3Ua+Qsv99OQikUd4IhwMQsOu8dn1ndx523o73CixcobkYo+2Tw8+8bYUsd3RbiYPa+Hw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947830; c=relaxed/simple; bh=4OTC0teSIM1xSp6kRfAuey2wjXPl4VEtk8eMLcGEVSI=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=AQzvshcM5VuHTqQ7u4FqCVATF9vMEteWCJG8R+kjtkpSWfKtg6ah4MQWOAYBfa9y4f4OlC9GanSydUHNZErXJOmJusyWBvVH7uWxwvrUpHVPw5yGLKq121z4pfYm7pWL6lGZaAIM2iIDDS05fjE089VQhSBFjKr8ZfdArY5LrkQ= 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=vtXyHGBe; arc=fail smtp.client-ip=52.101.100.138 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="vtXyHGBe" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=oxYMsCXLker6WrqsveulbrMcxcmU8rZty/WhSxvCbf/Ks3FcTPmHPeQ58p37zl7arJdkbA2Uq2nUDzVNu/sFfAn/25DJ60LHOY/MmnVQD4hKEwyGC35z2dkEwuavjZc2gpU+m7UnrXkcMJ0HbZXSbocjRwSfrxz46X6jmx92ox7JcbcfklwFu8d41Mb/8OIfwVMzz8uBkuA4x95DsI+iemde33+8n8EhqO+MqEX7RVHOIPTk8TcVXupG3f/IVT+ytjmE8X5Hp3UYbG+AcbBrsyuZ6M9gTqp+ny1Ah/N8LNZdz/E7ziOmbMga9E7QX8s2lLIE21DU53KSrDU4fAq0wQ== 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=foTm3n/NlJ0DNqvRWEZ6c59U9jEKFZU5e06FbdSgk9I=; b=b7dWKXxBAhROu6GChFLrxrefv+A+bOHq6lnl5OB4XctMBa9s6aA3Ixy+nhcxWYhR2Fcw47a/OG44yKHBeDavO92XdmGwUJcLH0gvhZo8bkLPGXPRtqX/qS/K8qKuXv/X/8Fj6oyG86yGLBvEXwW4sHU8ravb/TDXZK1nFkugHqTRygebtvhW6O5ydPeyEz4VMo3J/mZbipfm3a5Xgs4ZCpxnMvNG285R7Iy99YJjpN2r+s8IHkL+fJ4ddPW8PaNK72m6x0ibL6u41aG3lRn9oyO0BiNzDvZu85whiMfV/w9N5mJ9Cs2oJEv1z70RAZPnS4YjAydDdRbDUncN1NdZFg== 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=foTm3n/NlJ0DNqvRWEZ6c59U9jEKFZU5e06FbdSgk9I=; b=vtXyHGBeKbDLMb6uiLR7v2N0mC5gMp2NJzGRYOOF5tbEeMa20Wyi7Vvt32MyMREQAolkiAr3nnzd55i+kJh3MhXSsxsBT5SVdSu71SwZ7nqeXLTeSmQNpatIkgyWxSi+vK2AmmZEVQD06mZXljtXTx5NqbQwfe3sI1I+RO6dmYs= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:00 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:00 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:45 +0100 Subject: [PATCH v2 02/16] rust: io: add `IoRepr` trait Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-2-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=26792; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=4OTC0teSIM1xSp6kRfAuey2wjXPl4VEtk8eMLcGEVSI=; b=di0eyeAQVEUUwzDMlzQPN0hf2BmAo8iQ0fWE7vpJsFWJVu6deVUEEosHwo35rxZFHwB+749lI +Xe3Rjw/Hc6Bm6XN8M0A77jfKgFs8kFpRPayT1Uq/8U8Yg4weBJtY18 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: cbbdbf91-ca40-45fd-dfab-08def30fc61d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|6133799003|3023799007|22082099003|18002099003|5023799004|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: 4pAbdPVpZkSd1oRLYyMt1dwB7X5bO+HNTa/nXTgPMbj4bb2tw0OqGxL0JQGF5wv9wOl6hYVw3WOr3ms5Z0aRj3rXeFZcDTqd9YrRiTdsVCpBVcYlXK3XkjNh5qXSrG/L3SfwrfVnirBJ/BYGc7Iyh/Yw4nFoxC8RiIA3aiNJ8HGh2nFkEOY9RTB8EiiRtTXN11HSX0DPa9uzoEqs9wGuvOhxm99lyCzj6ZpAtC62dS4+p6t1TCvxGjP0alQnRyZ9gKw/lC02WbnIRZtCJjYDCNiWXrSc4z+mSqeWBOrUb9eeSqewIvSJhEeojO3aPPrOCGpL2c5pjFAtlZfEHmTlABsC+iK1cazqqNdfcI1AaSjKX6DCEqrE0y8ZFeHp21vR5QFmWv3Jl0ir7Ef2uxQRULjIpXgsfeVRF0VM9H00MplGyfjurLvIYTZYa/VTvOJM4s2Ay1hnLxEc0Tez+jFJpL98d4zfz9q+b++cRjjmr5cgXvJfbMpke3xbRNwl7KaG/tq6Y4HL73ez5kGONZ6KJFj0d9a1Ib6uKtmsHtxjAmiHfVaPFzu8GqM4yej1cjCPdAoT5wyOilYpdyFH+QLns1vU3JaE3JDZ9Lo4+Fb/58y3pIPnphleU4sds+2JSek/G18ZDhY2iG/9uboGrrHkBG60f/DpfXVn/6w8EdnEKRSo8I6uoe4zU0IEUH/nCErvWMd1FWhM12RpJBLg99FN/g== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(6133799003)(3023799007)(22082099003)(18002099003)(5023799004)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?U2h3cC9OeXR1ejVkZ2kzcGRkc3FPaFgrL1RrcVdXSXZJR09uaUpOL2hLam5Y?= =?utf-8?B?b0JodG9aSk9oeGEyb1dDOU1HODVJckV3aEYwZ21VdFU5NUlQRlI1ZkxEa3ox?= =?utf-8?B?dEp0ejVGZHQ4blQyQTIxYnBubnBoRnpiYnRLUFFvS09QcmNkWmtGaG5GZjhO?= =?utf-8?B?WjdZZjJlZkNBWEF6WUk2ZjArVm50c0svTjV1YkdqSnBmZEZYWXBmYUVzWGk4?= =?utf-8?B?WU8yY2VISGVRSW9qUGFFZXpOZzY4V3A2RDY5c0xZRllKNkRlZFNLSDF3V3da?= =?utf-8?B?QThtbldPZCt2dE5KdUlpczlJcUg4TkhjYmR4NmpmODg3RGgxcEc1V2pSNTJY?= =?utf-8?B?S0RrYmpXMTBGSnRQM3ltS0RvWG5ESmpoTmZ4Tmllcklyb05HNG9nRXU0RWpz?= =?utf-8?B?UXk0MHllSnkvb0pBWTB2R0E0MnY4SXI4MmNKK09GTEhEVGIzYiswbDhPVStq?= =?utf-8?B?WHVXUDdHcDFmQjAwZE5Ib2dTMElsZmhQSlE2VnpyWUpkZ1pMNW1seXVrYzlp?= =?utf-8?B?WE1Xc0kwTTJtVm5rNTdoWXFrUVFEbzNucXBEYVBQMjZwSm1IUXRIY2s3TVlm?= =?utf-8?B?V2dkQnlobkNTWXgrVUZyOVJZcHNlUExGcFJSWG9QdUhHS0JpOGVqTFpDdVRJ?= =?utf-8?B?cUE5N244TE9OUjVBdG4yN3hXRU1VbXRwN1dGclNuNGNkY3ZxeDlHM09jaEJj?= =?utf-8?B?a2lLMEI5WjZUQ3JzdnBmbm1BTDNlcldub0pVTzZuaFJ0dlRaYjZTWHNvanlk?= =?utf-8?B?QjhUYnVlOE14dnJERDM4SEEzbmZGOWY4M2FiRFY0dFI4enMyVG0vZXN3N1B5?= =?utf-8?B?NVN4eTlXR3BTdCtPMkVEOHVtVzA1RGdsNUFXeEFpNkhwUHhkQmRadDlKbWM0?= =?utf-8?B?N0gxbkY5S0p1MTdib1N6d3IvWWM4dHZ6N1d0bEI3dXYvSzJPS2MxM2JxdGs0?= =?utf-8?B?WVg1dzhVQjhnbVZDNWR3M0RXM00vWGNCR2lDQkY2ajMwclJhY0MwYW1pNHc4?= =?utf-8?B?WUlYaUtlSDYzNFFXYzVpNCsyRjZQSmFjcDFhTnhCanIwTFlLdW5lbjBoWVRy?= =?utf-8?B?SmYyNk1ZbDdteFRUYUFyczQvWGpFY25zVEwxM0FPc1NxeUMwdmJabWxxZyt0?= =?utf-8?B?MndxdytoOGtlMlB3WDQ3Zm1yNXVhNTdQQnlyRlp6UGkzL1c2M09jdDZ3S1JX?= =?utf-8?B?Z0R5S1B3a3lxMkhLaUlEWEpNMzBQSkhCR3ltVW81cmE3cm5ITm1QVXhxREJ2?= =?utf-8?B?Z3hGeWtmVzUwWEpnNlYrTFVIdVkyQ2c0dXgwWFhQZkgvVE1MUFcwY0ZITm5y?= =?utf-8?B?ZWFSQnczVitNQmhZbmEvQW1aeUxnZmpSalI5c3lJOEd3R2lKOTQ4S1lnd1ll?= =?utf-8?B?cGpKL2hnVjJoQjFBWUFlOGN2Z2ZDRHc4My9INGdmRGN0Nzl5bFpYTk5tWDhp?= =?utf-8?B?eFlRcWV5YU5NSmVSTmlNekpzeHpNNFd6Nm9wc0hXM3dRQ3lMODd2dXozYjFK?= =?utf-8?B?TUcyUFlIZWY0ZlNuOG8vb2lORDlFb0Q1bG0zTFlmaGV2U2s5Qmsrckl6Yzc2?= =?utf-8?B?QkcyT0d5Ty9iME9LdDV3eWVPWTY4V1JTU1dHODVVUmFBWHZsZkdTYzMrTE1W?= =?utf-8?B?T1JWTjJrRnNFdHhFV1lNWG0wdzI4YlBEdnBpbE5FcEFiNlJnVzZSRHArd2gz?= =?utf-8?B?TXB0NG5zdHZETmlsZEdvQmFXQkJKUzdLL2tOQjRSWmRNZmlPbWVXTzhrN0po?= =?utf-8?B?NjJwSHVOVXNaZG5abFlkdStid0lTT1FLQ2dGbStqS1RVWG1PaHQrN1AvRFpL?= =?utf-8?B?VEtkYjR2L3pOWnNzZ0IxQTQzdHRpRmZRVmhPME0vWEMxUEZOS2ZEdU9EVjlG?= =?utf-8?B?WVdJdy9XeEt5Q3ZQZk9yR096L1JjTURnbGJ0US8xdjhaMnM1UEFwTytQS0lF?= =?utf-8?B?Wld0UmJtKy9BSkNjNXM4VS93T1VCWnU4UlNZejMwWlhyODZJMGFQWEhEeTU5?= =?utf-8?B?SENnRkd4QzhNTXZTSThva0kxd0lGN084WUQ2allRbU9UeTIyZkdEYm9ZakhH?= =?utf-8?B?WlhSdDZsSzZGWmdVa0VXajNZWSs1T1NrR0lzK21ZT3RaYXhIMndHOE1CczFC?= =?utf-8?B?T0EwTWo5bkhETTdveEliUzdZUkFBTUZTM0c3M1dTZTllcDA1ZFNPdTFkVEkx?= =?utf-8?B?dGp0ZkZKVWVPdThFVzJ0blpSclRnVUhhbGJmUmFaemM2WDdBbVF4UGxRSVFN?= =?utf-8?B?TmRSWDk2TkxUVEptTFNvYkdjSTRUZnhSZVhwT2k5VUJhMjhtSFhIM1Jkckth?= =?utf-8?B?Z0NNVzJQZVRQVWtCazMyTDJ2VVlDZUtkblFIQkhUOGpIVFpsUllXQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: cbbdbf91-ca40-45fd-dfab-08def30fc61d X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:00.8290 (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: HsnIeBq3NyXiJYf6RA/OMUzuKnfHGnT9Pm5yxbupazR6tndNFeaqlfmgeqzETpA6IWBnisvX/mrvL2E7BpGpiA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 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 adding a `IoRepr` type to denote the underlying I/O type to use for a specific type. 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 --- rust/kernel/bitfield.rs | 5 ++ rust/kernel/io.rs | 203 ++++++++++++++++++++++++++++++++---------= ---- rust/kernel/io/register.rs | 59 +++++-------- 3 files changed, 170 insertions(+), 97 deletions(-) diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs index 35ede53f2b8e..4bc92c62da06 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,10 @@ fn from(val: $storage) -> $name { Self::from_raw(val) } } + + impl $crate::io::IoRepr for $name { + type Repr =3D $storage; + } }; =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 adfc555de7d0..71c6180ed745 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -276,6 +276,91 @@ pub trait IoCapable: IoBackend { fn io_write<'a>(view: Self::View<'a, T>, value: T); } =20 +/// Safe transmute that performs size check on monomorphization-time. +/// +/// Can be considered as generic version of [`zerocopy::transmute!`] macro= but using the unstable +/// `core::mem::transmute_neo` instead of [`core::mem::transmute`]. +#[inline(always)] // This is a no-op. +fn transmute_neo(val: Src) -> Dst { + const_assert!(size_of::() =3D=3D size_of::()); + + // SAFETY: `Src: IntoBytes` and `Dst: FromBytes` and we've checked siz= e is the same. + unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(val))= } +} + +/// Trait indicating the underlying primitive types to be used for I/O ope= rations. +/// +/// Implementing trait allows arbitrary types to be used for I/O operation= s, not just raw +/// primitives. +/// +/// The layout of the type and the underlying primitive must match; this i= s enforced via const +/// assertions when I/O methods are used, as the type system cannot repres= ent this. +/// [`IoRepr::from_repr`] and [`IoRepr::into_expr`] can be overridden for = conversions, however it +/// should be noted that they are only invoked on value read/write operati= ons and are not invoked +/// on byte operations such as [`Io::copy_read`]. +/// +/// # Examples +/// +/// ``` +/// # use kernel::io::*; +/// #[repr(transparent)] +/// #[derive(FromBytes, IntoBytes)] +/// pub struct MyNewType(u32); +/// +/// impl IoRepr for MyNewType { +/// type Repr =3D u32; +/// } +/// +/// #[repr(C)] +/// pub struct MyStruct { +/// raw: u32, +/// new_type: MyNewType, +/// } +/// +/// # fn test(mmio: Mmio<'_, MyStruct>) { +/// // let mmio: Mmio<'_, MyStruct>; +/// let val: u32 =3D io_read!(mmio, .raw); // Raw primitive read +/// io_write!(mmio, .raw, val); // Raw primitve write +/// let val: MyNewType =3D io_read!(mmio, .new_type); // Read via `IoRepr`. +/// io_write!(mmio, .new_type, val); // Write via `IoRepr`. +/// # } +/// ``` +pub trait IoRepr: FromBytes + IntoBytes + Sized { + /// The backing I/O capable type. + type Repr: FromBytes + IntoBytes; + + /// Convert from [`IoRepr::Repr`] to `Self`. + #[inline(always)] + fn from_repr(repr: Self::Repr) -> Self { + transmute_neo(repr) + } + + /// Convert from `Self` to [`IoRepr::Repr`]. + #[inline(always)] + fn into_repr(this: Self) -> Self::Repr { + transmute_neo(this) + } +} + +macro_rules! impl_io_repr { + ($($ty:ty =3D> $backing:ty,)*) =3D> { + $(impl IoRepr for $ty { + type Repr =3D $backing; + })* + }; +} + +impl_io_repr! { + u8 =3D> u8, + u16 =3D> u16, + u32 =3D> u32, + u64 =3D> u64, + i8 =3D> u8, + i16 =3D> u16, + i32 =3D> u32, + i64 =3D> u64, +} + /// Trait indicating that an I/O backend supports memory copy operations. pub trait IoCopyable: IoBackend { /// Copy contents of `view` to `buffer`. @@ -352,15 +437,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: +/// IoRepr` 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; } @@ -371,8 +453,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 @@ -536,10 +616,12 @@ fn try_cast(self) -> Result<::View<'a, U>> #[inline] fn read_val(self) -> Self::Target where - Self::Backend: IoCapable, - Self::Target: Sized, + Self::Target: IoRepr, + Self::Backend: IoCapable<::Repr>, { - Self::Backend::io_read(self.as_view()) + Self::Target::from_repr(Self::Backend::io_read( + self.as_view().cast::<::Repr>(), + )) } =20 /// Write a value to I/O. @@ -558,10 +640,13 @@ fn read_val(self) -> Self::Target #[inline] fn write_val(self, value: Self::Target) where - Self::Backend: IoCapable, - Self::Target: Sized, + Self::Target: IoRepr, + Self::Backend: IoCapable<::Repr>, { - Self::Backend::io_write(self.as_view(), value) + Self::Backend::io_write( + self.as_view().cast::<::Repr>(), + Self::Target::into_repr(value), + ) } =20 /// Copy-read from I/O memory. @@ -683,7 +768,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) @@ -693,7 +778,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) @@ -703,7 +788,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) @@ -713,7 +798,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) @@ -723,7 +808,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) @@ -733,7 +818,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) @@ -743,7 +828,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) @@ -753,7 +838,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) @@ -765,7 +850,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) @@ -777,7 +862,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) @@ -789,7 +874,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) @@ -801,7 +886,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) @@ -813,7 +898,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) @@ -825,7 +910,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) @@ -837,7 +922,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) @@ -849,7 +934,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) @@ -881,11 +966,12 @@ fn write64(self, value: u64, offset: usize) #[inline(always)] fn try_read(self, location: L) -> Result where + T: IoRepr, 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. @@ -914,12 +1000,12 @@ fn try_read(self, location: L) -> Result #[inline(always)] fn try_write(self, location: L, value: T) -> Result where + T: IoRepr, 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 @@ -958,9 +1044,10 @@ fn try_write(self, location: L, value: T) -> Re= sult #[inline(always)] fn try_write_reg(self, value: V) -> Result where + T: IoRepr, L: IoLoc, V: LocatedRegister, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { let (location, value) =3D value.into_io_op(); =20 @@ -992,16 +1079,13 @@ fn try_write_reg(self, value: V) -> Result #[inline(always)] fn try_update(self, location: L, f: F) -> Result where + T: IoRepr, 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 @@ -1029,11 +1113,12 @@ fn try_update(self, location: L, f: F) -> = Result #[inline(always)] fn read(self, location: L) -> T where + T: IoRepr, 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. @@ -1060,12 +1145,12 @@ fn read(self, location: L) -> T #[inline(always)] fn write(self, location: L, value: T) where + T: IoRepr, 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. @@ -1102,9 +1187,10 @@ fn write(self, location: L, value: T) #[inline(always)] fn write_reg(self, value: V) where + T: IoRepr, L: IoLoc, V: LocatedRegister, - Self::Backend: IoCapable, + Self::Backend: IoCapable<::Repr>, { let (location, value) =3D value.into_io_op(); =20 @@ -1136,14 +1222,13 @@ fn write_reg(self, value: V) #[inline(always)] fn update(self, location: L, f: F) where + T: IoRepr, 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 6cb07fc92cc3..d898b2b46d52 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 @@ -831,8 +816,8 @@ macro_rules! register { { $($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($storage)); + $crate::register!(@io_base $name @ $offset); + $crate::register!(@io_fixed $(#[$attr])* $vis $name); }; =20 // Creates an alias register of fixed offset register `alias` with its= own fields. @@ -842,10 +827,10 @@ macro_rules! register { ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!( - @io_base $name($storage) @ + @io_base $name @ <$alias as $crate::io::register::Register>::OFFSET ); - $crate::register!(@io_fixed $(#[$attr])* $vis $name($storage)); + $crate::register!(@io_fixed $(#[$attr])* $vis $name); }; =20 // Creates a register at a relative offset from a base address provide= r. @@ -854,8 +839,8 @@ macro_rules! register { { $($fields:tt)* } ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); - $crate::register!(@io_relative $vis $name($storage) @ $base); + $crate::register!(@io_base $name @ $offset); + $crate::register!(@io_relative $vis $name @ $base); }; =20 // Creates an alias register of relative offset register `alias` with = its own fields. @@ -865,9 +850,9 @@ macro_rules! register { ) =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 + @io_base $name @ <$alias as $crate::io::register::Register>::O= FFSET ); - $crate::register!(@io_relative $vis $name($storage) @ $base); + $crate::register!(@io_relative $vis $name @ $base); }; =20 // Creates an array of registers at a fixed offset of the MMIO space. @@ -878,8 +863,8 @@ macro_rules! register { $crate::build_assert::static_assert!(::core::mem::size_of::<$stora= ge>() <=3D $stride); =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); - $crate::register!(@io_array $vis $name($storage) [ $size, stride = =3D $stride ]); + $crate::register!(@io_base $name @ $offset); + $crate::register!(@io_array $vis $name [ $size, stride =3D $stride= ]); }; =20 // Shortcut for contiguous array of registers (stride =3D=3D size of e= lement). @@ -904,11 +889,11 @@ macro_rules! register { =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!( - @io_base $name($storage) @ + @io_base $name @ <$alias as $crate::io::register::Register>::OFFSET + $idx * <$alias as $crate::io::register::RegisterArray>::= STRIDE ); - $crate::register!(@io_fixed $(#[$attr])* $vis $name($storage)); + $crate::register!(@io_fixed $(#[$attr])* $vis $name); }; =20 // Creates an array of registers at a relative offset from a base addr= ess provider. @@ -920,9 +905,9 @@ macro_rules! register { $crate::build_assert::static_assert!(::core::mem::size_of::<$stora= ge>() <=3D $stride); =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name($storage) @ $offset); + $crate::register!(@io_base $name @ $offset); $crate::register!( - @io_relative_array $vis $name($storage) [ $size, stride =3D $s= tride ] @ $base + $offset + @io_relative_array $vis $name [ $size, stride =3D $stride ] @ = $base + $offset ); }; =20 @@ -949,11 +934,11 @@ macro_rules! register { =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!( - @io_base $name($storage) @ + @io_base $name @ <$alias as $crate::io::register::Register>::OFFSET + $idx * <$alias as $crate::io::register::RegisterArray>::ST= RIDE ); - $crate::register!(@io_relative $vis $name($storage) @ $base); + $crate::register!(@io_relative $vis $name @ $base); }; =20 // Generates the bitfield for the register. @@ -970,16 +955,14 @@ macro_rules! register { }; =20 // Implementations shared by all registers types. - (@io_base $name:ident($storage:ty) @ $offset:expr) =3D> { + (@io_base $name:ident @ $offset:expr) =3D> { impl $crate::io::register::Register for $name { - type Storage =3D $storage; - const OFFSET: usize =3D $offset; } }; =20 // Implementations of fixed registers. - (@io_fixed $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty)) =3D> { + (@io_fixed $(#[$attr:meta])* $vis:vis $name:ident) =3D> { impl $crate::io::register::FixedRegister for $name {} =20 $(#[$attr])* @@ -988,7 +971,7 @@ impl $crate::io::register::FixedRegister for $name {} }; =20 // Implementations of relative registers. - (@io_relative $vis:vis $name:ident ($storage:ty) @ $base:ident) =3D> { + (@io_relative $vis:vis $name:ident @ $base:ident) =3D> { impl $crate::io::register::WithBase for $name { type BaseFamily =3D $base; } @@ -997,7 +980,7 @@ impl $crate::io::register::RelativeRegister for $name {} }; =20 // Implementations of register arrays. - (@io_array $vis:vis $name:ident ($storage:ty) [ $size:expr, stride =3D= $stride:expr ]) =3D> { + (@io_array $vis:vis $name:ident [ $size:expr, stride =3D $stride:expr = ]) =3D> { impl $crate::io::register::Array for $name {} =20 impl $crate::io::register::RegisterArray for $name { @@ -1008,7 +991,7 @@ impl $crate::io::register::RegisterArray for $name { =20 // Implementations of relative array registers. ( - @io_relative_array $vis:vis $name:ident ($storage:ty) [ $size:expr= , stride =3D $stride:expr ] + @io_relative_array $vis:vis $name:ident [ $size:expr, stride =3D $= stride:expr ] @ $base:ident + $offset:literal ) =3D> { impl $crate::io::register::WithBase for $name { --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021138.outbound.protection.outlook.com [52.101.100.138]) (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 DE9A6483BC6; Wed, 5 Aug 2026 16:37:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.138 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947833; cv=fail; b=eTz5poDRHYI1kBeRtFSc/fljrZ3kJ3KrwwUpqULDQvwtrd2S5WL50zC1zI9VHnFAMhc8pfXkvPF1Rc6/XuMz709Dn48epqYTEWVBhtJdUc3NtIWS7LRP1P0It/LVSzLF6sQm/+dcsC2RTIf+01h4BH5Q+vDkwXXXniQh+9wkqyw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947833; c=relaxed/simple; bh=EbHCj1FMWHFtLfPDfgUWddDIprNCdd3K5CRvUw4dH70=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=JNc6Ig/0maGr38jSSHZBg27XWs9tEGC0i/ou//Bkbg3MTyyJktE+usMbY3L0EPJuJHrtopPjGMuF5a2UiaPA6Oh/bLE2VKVaoCgSy6o6j242UDNMi+/5ZfxxeASQm54VROXR6aDa8obv8nyROPA5QfcLiWtPHzZZnaP1TJ9HooI= 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=xYMmDxmp; arc=fail smtp.client-ip=52.101.100.138 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="xYMmDxmp" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=hNLLFruRpO8UwiviiRWdHIk+2QoUHA1j/lhgAm3ZZoBSz3d2XieCtrbW9/eNLwWo8k/Z1ojsl3BAUd374F9AuwktXx0yey1wEUbNo+G2NswD/L2T51EQ6cISWa+4UDQpbQhntbhHU+76WoDWyGu8UIwMySOjk/bJZ0gS/ykeicWRjvkQyNB7WFS35/MlnVZyAbythi7yY2fthyYo5F2uRly91S5B+UO90jEKB/kOvWflPEhVHvNCmxQQQvyr6Dp5r4uANIJpA2K1Zb+VWKrU5bWnuiSfIF8aQ2vCfB2aT+sj8T0C7Q+OW3mNXRXzSeFJrw+p7Cj5969MiiE5uz+a0Q== 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=dvS/jlP6DOy9hGWhegPfAalUb3KtPmZmYDbiK7fztyc=; b=p+azD5E9zTnBthCVJCadIYbL3u33dJw+vPOpJGd6LQlGAcquVxV5lYCC1Nzoc3Eo9KdU4EHnvm4XRzgAODUqBt59licwd7GT4pU9bh9rnPPRvyQ3i53uCdQpcCZvCWAyfz8H6Chkh5X1fmAeqkZUF+72ugHfpAa/WAyB2r95zQrA6K3deNLCQBqLcmpiWpzw3grsL5IONO2w25pTQjFDdPatMUQ2S3FrRIr0s9a+LY80qlpgCPqZ1rD4OHjTYWWJFOUWqB8BmUejs/kPlN8Kd4MuaYVF6gWY4AJ2smG2m3jpO19kvPVekGA5BALQwkA3ibtqo3bd+DnaX5QtouKyjQ== 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=dvS/jlP6DOy9hGWhegPfAalUb3KtPmZmYDbiK7fztyc=; b=xYMmDxmpRomyerujm7kq4Zn2yKkiad/2kZcwU60puprKD+NzaqujlLC2Qc+zc5fVLDCHG+yyIqwCgObyXl2MGXo+YiuVKfLlUHijATKXLF1kt+7czF7W0Ilxpq+YrKeZcTLQl3AwRROuGM1tpTlnHGtUlOM6ynZVox0A7XoPRo0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:01 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:01 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:46 +0100 Subject: [PATCH v2 03/16] rust: io: support register projections Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-3-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=5910; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=EbHCj1FMWHFtLfPDfgUWddDIprNCdd3K5CRvUw4dH70=; b=RfksNUMRUkPiRtC741WaSv6nfB39pbLnibHBEmepJAyKzyWTVAZMiV3M66GKSNlfwOOuB+rzF vV3A2AWwHYyABCpZz1kUtPrU7pJ+iQAXyb8fsC9nNcsOSdgJpWWBhH4 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: bd05853b-d950-4b58-b834-08def30fc682 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|6133799003|3023799007|22082099003|18002099003|5023799004|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: gxkp4bjHaZD44Wwc4eFrJPI713c6XlXzddkiF154kQdzoGrOLtBnzh3d4k2SAbckP9V4VOlWzt32pvudz+8XBIKh6BwYowURlfcS5gaOfAENBXxF0aitZK01B3GXwIeV43V3G3h+jAGkPPpEBg0u6yr4mwcW4kOgpAZR3VmES0q1ljBu3eb3CZU1U1MHiWaPan1Kux0WSkVed/WkkLKHRFhMJvFvekVrnshGIl1eijGkNsijR4myluH6Lnt2XvDxWF9JFbW9rqpNvoP/bEmaG06D4RPZkUo49h+CWUOutN0+OZm9zuV3nlapm/sjMxpOliseQ56ETqn78WeN9DI5Z4spm2J19MRoRcfBGuTkizVB/wpa6EJaEuLFhBGLUauHorEVOwb8Bl/Tqb2OELmaKZvgioW1gfaewRNajbFz5S88jO5xuCRT+LzBpBcEjV5j7IXD3VeFzWchSdH/u3rd0NJMam8r4vzL4hzXw5lf9d1OVfACTi38A/9UPcJ68+AtY3RWTN8ppC3BygipSJHumi2qaNGOfmmFAhyoBeJ35ZSlRRdkUQhO9xOaXsl0Qhovwvy5xbdYOZ0lBQateqa6HNDI/AlEhWqOZT5E3hK/4MobesirHiNz8hqGVf7Ji8aXQaQVWDYxf6Gv/m6a1WQWr6UBADfPKVMi2lGjGbSu7zYHPkqu5cvxPjpSGOuQiQ1Kr3/HFIoxg3fQdRWaY4MFrA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(6133799003)(3023799007)(22082099003)(18002099003)(5023799004)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?SWRJK0R6TXRnYnpROEVwODE5L2IwUlJPOFFzUmNPL2EvQlQ5VHdydmdTNmh5?= =?utf-8?B?Rk9LUXZRbHNsL0hWN3RpQjBsMnZpT25DY3lPUDJneXZlT2FITTk4cnBkZDR5?= =?utf-8?B?TUxzVzJ1aFBHaVpXZTdIek04QWlQQzk2ajhXMWhtakx0SEZmajU1TnFVdS9v?= =?utf-8?B?Y2QyOERZbmorekJrOTdjcmNmYTFQM1AvRlVIOWtNTGQwZWpjNDdqRnE2bHlo?= =?utf-8?B?YUNrN280b2k1czRrckpPNEp0UUhaYXJLSFk2dTF3amtwTDJ6ZktvUXFNMjlN?= =?utf-8?B?Tm9NcXBGd3dJSVF0c2hRN2FHdkhKcmtzdmhNTEs2L2czOUhrZmo4QmxXQ0Fk?= =?utf-8?B?RVY4ZXB3RHZmMm1neFZvd0E1MldHZUl3MG91b3hvWHB6WW53bGRHTTc3V1BB?= =?utf-8?B?QTBiZlpMbjhhWTNFVlgxS05YSWM2QU83eERSSEswMVpDa0REVUJvZXBVbWRz?= =?utf-8?B?NXZhT2d2M1pESlAvaXUvN1NaeEtnMFk3VFFPSXFGT2ZjaWtLR2tSNHdyZDZC?= =?utf-8?B?cTJyQXh3TkhDcE1aamlPVWhiZXFTeEFocUZQUEZVRlQxRE0wc1dCNWRESldM?= =?utf-8?B?OWFXYjgzQllUdnB6aDloMVRnbEVCcFZjcDk3OWljTkdRbENiZmc5MjV2L2RU?= =?utf-8?B?NE1xYWMrM2pENUJiSy9VTDJPZjVzUjd6N1ZVOGlXbmF0RWZtT0RXN1YzRWEz?= =?utf-8?B?ZmErRXlVS2VVaHRyQmRSUk5vNy95VUxBa2g0dmRLY0REYUMwSzM0dUhKZ2hs?= =?utf-8?B?Zk5ZdnhLTEM2elBNQmNqMld4dEFKZHdMZ2dFVWZNa1grRGhaS1VZM3ZHaUZ2?= =?utf-8?B?YWtoQmtuOG5TMlRTd0JDSEc2YmdLYnlPRFdZR3FKVVZRakJiUHZpdTJ3d2R1?= =?utf-8?B?M3FuSW9tWkd2RElCbnRnSmNYakNvT3N4azFWT0RYOXlkOEJzNkxCSHM3d1g4?= =?utf-8?B?Szdyd01abVB2TDF6dmVRMEVtRStqY2ZnMGN3akNINFZXMUx5ZklxMW9kaXNz?= =?utf-8?B?Z3dvNWYvb1RneTlvUjNGbVo5NHlYdE1sUlhCKy84cnIxNjc3UkFVbSs1Rjl6?= =?utf-8?B?bmRhaE41VlZaeGJWUXpkNm1uazltMUVicTRGc2ZzdWN0Tm9LUm9RM3lrZ0Fl?= =?utf-8?B?RlNBTnBVOFZVMTc1ZjNheWpVbHRyeHViQlcyUThyQTFLbzR6ZXFzZHVlNzFa?= =?utf-8?B?aXBvVjJnSVE1MUQvN2VRY2RJcUFiaHc2MG5sSUNvbHhGRGZPaG1lT3FiTHRM?= =?utf-8?B?M0JMM3I2U05hZjRTMW5YZWJFMUR2dUlPcW1SbjN2ODIwNkhONW1TZXNCNkdB?= =?utf-8?B?MjhpS2xxNXZObFFlL1lTNmlZUUx0c1kreEx0d0Y3TnQ0WlMzVXlMRXZLaTZU?= =?utf-8?B?NE5tRmZDSDdvOS9xVDVudVpuU0lVZHFMdW9zOEkwN0pmU2lORHF5OHVPcy9R?= =?utf-8?B?a25OeGxKWW5oUlAzeVZIaVRTUHRJdTZMc0RCeTEyR1FSNTlBdy9YbnBURDMw?= =?utf-8?B?ckJVLzRmQ3VTMHRTYUwxZk9QamdLdjJTMmRXdStRdFpkLzY3d1o4QzEwRm53?= =?utf-8?B?djBMbXNodzBYTlVKMDVlaUk1R1JCWHRHK0ViL21DR0xtZ1lWbjlPSGk0SG5j?= =?utf-8?B?TmVaTVZGUmVDQjdiV2Q4b3VQT045bk1tM0p4a2RmZ0c3K1NLTG5VeTVHd09F?= =?utf-8?B?NzdqRFZuM1ZYb2VQLzFLQW9ESTlnT0hXZHhZMDBqKzIxZ25IZElORml1bDd3?= =?utf-8?B?Slhhb25wblpTdEloZ3hJM2wrYnNUK2ZQaXZ1cjN3SCtnK2hOa0xTeVV3MGRu?= =?utf-8?B?MWNIR0tmYjVjVGxtb3FUckcwWFYvd2h0ak5ZaC8rRTJhKzVmZng4QUFycmFM?= =?utf-8?B?YWpmSjk1d1BtOVBTRDF2eEwxUUxYTzV2WWwvalBPMW15d0w5cnBtMlZoajFY?= =?utf-8?B?S0pVN01QUmdYb0pHT0JiNWtrc3pmUHh6ZXZ2ajgyQ2hBcjBwUlMxTncyN2k0?= =?utf-8?B?UHJMYXhJM3ZNWkVaRksxRVRkbUhoYjVMRU1idWZZZlNGY0tZV0FjZ2ZaSXJF?= =?utf-8?B?VU9iSmU3cG1BUG5mcjI5MGFORjhaYzNwOEJqRmN2blQ2U25vdUkzOVE3SEhF?= =?utf-8?B?ZkJUL3l3MEEzVTNET1k2Y2RJcjhhMXhLN01BNjVPYzNZS3Q2dFZ4TmpTQVo5?= =?utf-8?B?T2hFbnRzd1MyNklDaGY2d0RLcHZpcGtOUksyeG51S0FucDRmZytYTkNMS01O?= =?utf-8?B?czk2OXdzQzV6aEdLdGJPU1FteXJ0cU9yUXZFQXNVNjA1b3lTTXpPY2xOenpI?= =?utf-8?B?Z0o1OTEzSmhyeC9aNDQ3S2hMODd2eEp3L0NNT21nVWxpR2R1bnJHUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: bd05853b-d950-4b58-b834-08def30fc682 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:01.5037 (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: XpH8foBcvi1vJNPoOzOzIGeIv8XSY9HPlvu5ECR0UpN/S7A+EvDJxNnWXaK6LFl/h++i8QHk0b8fWqiTneE7pQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 `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 --- rust/kernel/io.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++-------= ---- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 71c6180ed745..ae18890866b6 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -295,7 +295,7 @@ fn transmute_neo(val: S= rc) -> Dst { /// /// The layout of the type and the underlying primitive must match; this i= s enforced via const /// assertions when I/O methods are used, as the type system cannot repres= ent this. -/// [`IoRepr::from_repr`] and [`IoRepr::into_expr`] can be overridden for = conversions, however it +/// [`IoRepr::from_repr`] and [`IoRepr::into_repr`] can be overridden for = conversions, however it /// should be noted that they are only invoked on value read/write operati= ons and are not invoked /// on byte operations such as [`Io::copy_read`]. /// @@ -970,8 +970,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. @@ -1004,8 +1003,7 @@ fn try_write(self, location: L, value: T) -> Re= sult 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 @@ -1084,7 +1082,7 @@ fn try_update(self, location: L, f: F) -> Re= sult 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(()) } @@ -1117,8 +1115,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. @@ -1149,8 +1146,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. @@ -1227,7 +1223,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())); } } @@ -1772,6 +1768,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. @@ -1799,6 +1814,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 _; @@ -1869,6 +1899,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 Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021089.outbound.protection.outlook.com [52.101.100.89]) (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 91F5D484237; Wed, 5 Aug 2026 16:37:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.89 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947834; cv=fail; b=kCrPWh4Sx4fzdTGvqrSYclPjNy+gfh1bdjwhvsbiyfzjed9xjA/DYe8PIsIlP15SfhhoVuqcIoS6X24oeNhxe/0PjE/H4OWeXhnmNcpHh6NaW3YfcZfCt1lfcI7jqL2E9ndJpyUBnzMikYLexwzwDjoVbrA1fMZQXLSQ+8OERx4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947834; c=relaxed/simple; bh=idjicAStg+Y9oU6UdrvmqeBvU6YtX/NtYE+YThryDYQ=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=ZVosBnBh+4zGje9pvFWRopExGXGE7VnKYcUtCxpELqCFYDG8j3neu6RcTmHAX3ddSJFDMpRe/dCL8NjwgMthqfeygKWzTiP46TcG77iX1fYqufOdqbHsFcxP2x07dHaqblePvu9UeNhxjx9YhuUZxnNydz17ve9lwNHBNwu98dA= 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=NE22Oo9L; arc=fail smtp.client-ip=52.101.100.89 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="NE22Oo9L" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=SDlFgLF+2szJNXWXBkK+JYoinmtdHWew8sN9Oe8kP2QaO4cV81f07zXDRaaVwIvPegbZZhN0xmjobJ2Fh8M9fxTLvLze3m1wYrrXfmKD1YDd8kdSuLwhRzHG0yEwPUIKhySKBlhi7OCPjC9zm2lnLZ34/zsRp7tJOK3yTFOVYQB3AoTAxajBMyr0qgE3TxEVIfO/3TBXO3CrXcYNaXD4F+B1UqRO1nTlFcSDQ0+x9X1LcRTHlp8T4+UiQPJyamp9yIYhH39wyztmM8JZ5dSlQiSH21j8LlXp4DLiOaD9WeFZzKDNw+6sisYMQbXY6hJHRWWvlPQh86NFpYZVctil7w== 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=BNvwP/Xugfdj3O3shHiVeDZgbFC/A34UbkPeubaGtFg=; b=OMCDAciogekUMSrslxRtZ9r2MWreiWKnbIXgL+OChM3mxDPLLluhK1fra/qWUW9oaJGNSAmpFLgapFyNucEXf4Ygi1O03fzNGx+z2znNjJCgJftkkwuktnl1h0Bz8EPm1krI/3YbPCXwc4KkG94Ogqt9iLGmDCs2rbIyMgMoGLyHfzj9YlZ+p5Zp4BzAoOyOLIRy87X0VEkP47JOU3K+L0XHhN0NHRreZkjo769zYjg70BSfonmIG77SnSzaUXQ7fBQ12WSz1wQJVmv0SmSn/C7yoIXj7PnZNEGRZ92byb7qrN0qbinCCTBJAwc7+xBWbDuRaRL+j+NiwGVd0kzYjw== 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=BNvwP/Xugfdj3O3shHiVeDZgbFC/A34UbkPeubaGtFg=; b=NE22Oo9LNxIV6XD7fqEj0JGmOQwTKo4xZfERObecG9JVtmb2x8Q2Qst7FbzGbpnQBYOoofFxBCrK8ICC/UDVsYd2ty1MNhIfdMMRAHYd666lSVVNWPTdJehKoYxRQjaSERMgplohd5hXxfm454ewVp53pLDjOMKuxXKq02lmJm8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:02 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:02 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:47 +0100 Subject: [PATCH v2 04/16] rust: io: register: handle one register at a time Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-4-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=8533; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=idjicAStg+Y9oU6UdrvmqeBvU6YtX/NtYE+YThryDYQ=; b=2QiYSZ0I6C+98AP7b4ImZvuiNTkl1KYxBokSiOY0UdKi5y+qtmXVaSEycNlJFcPso9fvO6SER yBMc+F24JeCBU+fx/JQV0fnP0SMVEWKPCJ925B08d6SurKs0mViJpEV X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: b4d0fa86-2e44-4388-1364-08def30fc724 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: IRTAqhvpvJ3YTfCQ35l8HKsZFLYkMydNJY7Iv6YAMs8HaKg74xAHxgZ4EhhCbnqoueI8NWB2vKGWfqpnCsCyU++cdHp4mMPDuomDlTc7aJtIT2IofRv8pX6PLMDTQS1ZYZQcsqA+pmN5LRMhbGuP+4zyry3xII7zbHyNe5dNbPnMeObUSI5p9kceQorzGYrkjqheYbOgPPLYi2fkK3RwHUhT2zt9z8nOXHJtnRg9qvQORKNtFTN2WZyZ6OaJ1O+ky9rVyLEaM9DzKSocR0k3etI3KTQAMZkPIK1KyOfr86DXCvuT7aAjKag/jrC7ZF1oYHq0Nik5cl5lDDRu//SeMZh72cOkiNC5JU6bf+gbr0V31ECEKZp2YXIOT9MQpicsM62wxzjcGiUhEP77DPZ6gV7Afi5sH/fbTaEYHgJaFn8lo6kv8FXDUmwOAMSe3SgrGVPH/Gd88QoCTJHKhS2E6KZl6BioKg3zNXZIMNdU2eNco+GU7v5CYeQQUfN/9IB4PjHV/k1i/e/1+btAa5oSb/kDuynBYJwoimkGetOzufloXfkG9FD2ZbcNoFDaD1YS6hwk7ISrHCtkcM/4fvxTLD4BE85WciSDJbxubV/1ivdbRsy59sqQI5V/1lFP9Zl9RAy/Hfl85ZmjcBe236VeVkRzZsH+8YQVzCy8qqWJJjFPahsvRz6F/CG5NSMkLw9o X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?SHZhZ2twK2Q4cEJ6ZEM2UHVMUllpdnlrVUx2NU4wZ0p2TEs0WCt2WmswdGJs?= =?utf-8?B?MW9oV3NRRmpkNWZTOGt5NTRFc1FRTWNJWTFEOE14bFRGWS95Rkl4VjhFZHJN?= =?utf-8?B?RDI5VXZtWFJGWDhMdjVOSHZrMWhPcVRZTjV6TEFsdEp6cXZONW8yYmZMVjlV?= =?utf-8?B?MmI5ZGlVUjkyM0R3dmdLbGdKSEVWWnhsVDRVVjRaSlJKRE5GL1k5RzFXcm0v?= =?utf-8?B?emdqdU5mWTBYbVVJRURqb1J5N3Q1UDVuNkt5WkF0eThYRWhyYmFDNEp0VEN0?= =?utf-8?B?bnBqc0c0bjZkaktCY01NclJqOStiVHl3Mlh3ZFBaMk1oWEtNVWRwQytNUWt0?= =?utf-8?B?YmhmOFR5eWRyclkrRlYyV2lMazdXMjUrQ1EySTAwdzZxT29McXIxN2dXWTFh?= =?utf-8?B?THJrRHYxMHB1dkdtdk9QbjlqWmVqNXlsWS9IeXBENzkyVnhsaDdtdXlWdUY2?= =?utf-8?B?Q0hkZUdxbUNoZHV1Y0JGcDJUanNHWnM3VjR0UTFZQTVhTDJwWUZJdWh1MFlY?= =?utf-8?B?dUVQd2JMUE9rMVdHaVAzdTRNTGQ2SlFrdjlNaVpSWmJwMUxRMjN5Y1JDTlp0?= =?utf-8?B?R1JtSnlLMndkaCtjM3ZNRTNKT0JjZlJCSkorNzk4eG55a045aXo2NjRTSnUr?= =?utf-8?B?YS9FSVc0SEREMUh6T1RWYTZaVkc3Q25BcHJrbWMrK013SjVjb3JvbXZiYllK?= =?utf-8?B?NHU4ajFxdmtWNGlTYXV4dm9wWXBSWHMyUG00T0tWUXVsRC9KaFJyWDZoQ1g2?= =?utf-8?B?dnRkTzltUk9hSWl1aXFhN2xzdjhZWTl3dnZhTE5sSVR6Z0JVSnFUb0FOMGJs?= =?utf-8?B?N0tUNXU3VzA1R1JiM3huQWlvenhVMlZ5SURWTlIyWk91Ym9aSVpVNUlFaG41?= =?utf-8?B?d1J5MGw2L2I0OW12U1U1N1VCUWpBalVCQnp2MXdKZWpvZ3lvcys1YVBMc3FR?= =?utf-8?B?a3FkbzJiUFRCbWE0bElkRkNwVVNOQUl5QUxmR2NJNDBNK2Z6TjZMRSs4SFBX?= =?utf-8?B?ZEw4LzNaSVBWT1FKYzZNZERianBYR0xMTStTNVFQTTMxWFpHc3diU214WU93?= =?utf-8?B?TUIzUUs3S2xSWVIxVmZ6MUZWMitTb0Q4YVV1di9GU2VqTm02NXRxQ1BYTFBW?= =?utf-8?B?OTgySGd6ODhiMEg3SGNHeVN3UjAyKys2Y3dMaC9tNElPdlNmQ2lLTW9PdXNj?= =?utf-8?B?YkdnaVpIWXdURXRoMnhYRTJ0YmdzcnJLektJS2Y1U1g5WHhMWXVTS3E2aDcy?= =?utf-8?B?ZWxGMXFGdFRtL1haOVZjTDdnS0I1V04xdWEvRmRNd0N0QUtTWVFBK0dyY1cx?= =?utf-8?B?ZThtZUNuV1hXenVFS1VvMjFKSURJM3c0SzgybDhLK2dMYnV1MStYbnZvelhC?= =?utf-8?B?cGM5WE85cjMvYTRRdmFWWGt3K1N5bWYzL3ZXYStTT2hYdngrbXErOS9xMTV0?= =?utf-8?B?VUxIQXZBUUl0bEdLUVV6c3RQd1RqQnpNWVozUUJYNWhJWlFUNXdreW9lUjM4?= =?utf-8?B?TWZYKzNwMEI4ZjI2cmdEcm1DMWY3cFMza3FVU2REamhHQzlna2xLRUp2N2N1?= =?utf-8?B?cnUwbmttMVpUclpmRzI5dVB4cWRtcmJRcDNrRmRhVWNWTXVrWG1IOE4xd0NP?= =?utf-8?B?Qmk5ZEZ5cERPZm9nYnRXUkpEUTkxL0txbkVFZDlkbkRMS0N4ajV6SERuam9J?= =?utf-8?B?WTFFMmV2b3RVNXczcm1OS3BLcko4MEpYNDB4RTNzbFBWUDdsSEVOQnNzWThI?= =?utf-8?B?YUZlbXcyT2N2bHB6L29JWXltRkFLcDltNjhCajBiTXpCZlBhQkJZVERjTnlh?= =?utf-8?B?Nmx5cXlNNXpGM0JTNE1RRGJJWnJWYTkzQ0xWUzdvUVZyVnJjUEI3ZFptUzdl?= =?utf-8?B?dVZnTk9qZGFWdzlNeTBVRkNqVEp1Vm41Nkg5dmVicDVKZlRSYzBXWWxlTGtL?= =?utf-8?B?S04zUnJnWDIxZzl4ZjloeWlDVmQydzNsR01jVWppVm90SkorQTVURjdpcXZY?= =?utf-8?B?VnRqdkN0RHJWMnBsbEFiNExIVk5TS2wxKzdxT3BzUXBnbE1xM0xpblZ6R25M?= =?utf-8?B?NjAxb0hUUTZCT2xzMFhGRE1yWnYveHpraEFGVmtzQ3JLZ1I3aklRZ2RxWUpk?= =?utf-8?B?VFd4RGpLTnRvclVRa2VUVjQ1VXRBYXRuclZMbnVSUlZyYVZPVVAvTXNKT3Bs?= =?utf-8?B?MVgrVjFIbUh5SlovUEtUMmQyTnhaeVNNdklhczFNemduZStSSURnU3RwcXJT?= =?utf-8?B?TStYc0cyYm55UGxmSHBhR0NjRzV3QndmWmYwdHV4dVR4UlRxb2l2MUtVY2ZF?= =?utf-8?B?SXZHWmVpL3RtZGtkb1paeit1c3F3cHFPQ2xRYUY3bjJyeUVYd1dUdz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: b4d0fa86-2e44-4388-1364-08def30fc724 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:02.5937 (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: uZKxww/1KAGJUgoCNcp0Ztkmwye0uVOjgewFznayuvfGnHsXZEfT612PS7RaWLbyHCtHABgTzQ1wjdQbvNhWEw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 It is easier to change rules in this form, as there is no need to define a single rule that can match all possible register definitions. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io/register.rs | 66 +++++++++++++++++++++++-------------------= ---- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index d898b2b46d52..91804c1ca117 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -786,44 +786,25 @@ 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. - ( - $( - $(#[$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. + () =3D> {}; =20 // Creates a register at a fixed offset of the MMIO space. ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $offse= t:literal + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $offset:lit= eral { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!(@io_base $name @ $offset); $crate::register!(@io_fixed $(#[$attr])* $vis $name); + $crate::register!($($rest)*); }; =20 // 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:ident + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $alias:i= dent { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!( @@ -831,57 +812,67 @@ macro_rules! register { <$alias as $crate::io::register::Register>::OFFSET ); $crate::register!(@io_fixed $(#[$attr])* $vis $name); + $crate::register!($($rest)*); }; =20 // 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 + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $base:ident= + $offset:literal { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!(@io_base $name @ $offset); $crate::register!(@io_relative $vis $name @ $base); + $crate::register!($($rest)*); }; =20 // 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 + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $base:id= ent + $alias:ident { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!( @io_base $name @ <$alias as $crate::io::register::Register>::O= FFSET ); $crate::register!(@io_relative $vis $name @ $base); + $crate::register!($($rest)*); }; =20 // Creates an array of registers at a fixed offset of the MMIO space. ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr, stride =3D $stride:expr ] @ $offset:literal { $(= $fields:tt)* } + $($rest:tt)* ) =3D> { $crate::build_assert::static_assert!(::core::mem::size_of::<$stora= ge>() <=3D $stride); =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!(@io_base $name @ $offset); $crate::register!(@io_array $vis $name [ $size, stride =3D $stride= ]); + $crate::register!($($rest)*); }; =20 // 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 + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr = ] @ $offset:literal { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::register!( $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] @ $offset { $($fields)* } ); + $crate::register!($($rest)*); }; =20 // 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:ident [ $idx:expr ] + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $alias:i= dent [ $idx:expr ] { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::build_assert::static_assert!( $idx < <$alias as $crate::io::register::RegisterArray>::SIZE @@ -894,13 +885,15 @@ macro_rules! register { + $idx * <$alias as $crate::io::register::RegisterArray>::= STRIDE ); $crate::register!(@io_fixed $(#[$attr])* $vis $name); + $crate::register!($($rest)*); }; =20 // Creates an array of registers at a relative offset from a base addr= ess provider. ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr, stride =3D $stride:expr ] @ $base:ident + $offset:literal { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::build_assert::static_assert!(::core::mem::size_of::<$stora= ge>() <=3D $stride); =20 @@ -909,24 +902,28 @@ macro_rules! register { $crate::register!( @io_relative_array $vis $name [ $size, stride =3D $stride ] @ = $base + $offset ); + $crate::register!($($rest)*); }; =20 // Shortcut for contiguous array of relative registers (stride =3D=3D = size of element). ( - @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:= expr ] + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr ] @ $base:ident + $offset:literal { $($fields:tt)* } + $($rest:tt)* ) =3D> { $crate::register!( $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] @ $base + $offset { $($fields)* } ); + $crate::register!($($rest)*); }; =20 // 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) + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)*= } + $($rest:tt)* ) =3D> { $crate::build_assert::static_assert!( $idx < <$alias as $crate::io::register::RegisterArray>::SIZE @@ -939,8 +936,11 @@ macro_rules! register { $idx * <$alias as $crate::io::register::RegisterArray>::ST= RIDE ); $crate::register!(@io_relative $vis $name @ $base); + $crate::register!($($rest)*); }; =20 + // All the rules below are private helpers. + // Generates the bitfield for the register. // // `#[allow(non_camel_case_types)]` is added since register names typi= cally use --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021089.outbound.protection.outlook.com [52.101.100.89]) (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 44E0A485509; Wed, 5 Aug 2026 16:37:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.89 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947838; cv=fail; b=qsvKY8QVOs3F0wNympT9X8Okz1p3pmY/evH1fqNas7kBhn9V48mugDs2A0E9GoVGJXxrxXXx8qf30KDVdcGd3k0wPmfk++Mfy+A+7/oLi2xzZVJ4M2xLE8cN7+Ymy1FAEWWQbKBl5L/pECn57fF/UwMfra40aRfuRdFZQcMS4SE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947838; c=relaxed/simple; bh=/Y4Qgsj/Y8MasF5B1mbDGsToiwgqsiI1N94mauL0kok=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=oqIvjFe28RqqZU+JZBt3DhLiwbHRhIhCgfTmK/Bc1lbsaLWuWgg5Zn6eStWTkv6Mr2AetppKfw+WFsRKvh0gjodWu3hN4bC0/AjXrG2TDPUhb7zTvV63LHmLSCGfDWc8hS4Uu20OvH4qOAN4Z5NUCQfhWeWnjA864SNT8Hfdzek= 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=tAR+fkpL; arc=fail smtp.client-ip=52.101.100.89 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="tAR+fkpL" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=IUw+IXHQEZAtNzfabTvQbhADVbMkmsE09CW8iqzuy5t+VGzk39v972F0J7dLqW5tXRwRQaBRXy7GwGkkP6nYK4pkrr/tqB4CcbapZvfyOYR2ItGTlJu5qmDSHSi2uziLx8zoJYnxg4FlDyrvTJ28f+uPow8f0ZyFG/lRC7KIh8693yi+YBfoqsyVkzEEl7KCb5quExtMpMCn8U0qU3ahIMkIuG99p3ngsMOnuUduas+mslbxJlM2Hg7/eX03An7DVXwsoMHwvWYGmHctRTXdHI9kDpCWs3gji3ZG+1YxRfjPW+TBhcKcSlbm1HZh9SIGyecnnWt26IiNBLoTUW73yg== 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=mpOgwqfwG2ALHBZLncL3EvBmfEKgtwaKyEwKgrS0t30=; b=bv67utsBcXV/hQ/MPpKWdBPXd3wjbWYCGhvKFkXA7t9gRHINPbAv+8c7lCpI3qcdyx6A1vDPYBgj4OC+iVRSqOkaVxpEhYPRSIIznUBx70BxITQFK2AEJcK0PEwaywerCerekMtctoZnDv2062WrkpedjzySm7xmrFd8x6RCQp2Cr9yhm6H7fxTSYTGWbGGgdPvRacXQNAWoheTt1eJ0L5isz07+tvxmqQsTIQ4iLPA5Ug/Q7BKkjgvkacAR9beiq1KPPWwJffsOg2azLR3m8TFfAUGNs3GburHq++FOhR4v3/7s0K1EIEiJnnasNRhxqZo3cfnvBTqyyVIteXiekQ== 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=mpOgwqfwG2ALHBZLncL3EvBmfEKgtwaKyEwKgrS0t30=; b=tAR+fkpLRyvxH/3bVKstorwXRukHGpuhFPniymr1HnRConsfUmsRqYz9AGE54e6WY/ENgefHOkMeJfrJoyMeYW9/0WGZeRM5jtgenSLfb4HW7hZO9elLmsJCIgZPK7fDIcLKvKWnBxD3PgwLIlMxea2lmLTcOYSvqYx/8JHkZQw= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:03 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:03 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:48 +0100 Subject: [PATCH v2 05/16] rust: io: register extract offset computation to helper rules Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-5-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=8026; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=/Y4Qgsj/Y8MasF5B1mbDGsToiwgqsiI1N94mauL0kok=; b=XmX+oOXv+MF84OhTi5qjVDM/+YZ/NIYICmMupYdyw9pnssh0KYk6Wgm+eQim9zPXcBK0nrmbX M1DUEEOc07TDfbFSWs9sJw3OictNrYyexwVWDXa6yK/Songml9lmbVA X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: e5d27585-ece3-4ef9-c431-08def30fc796 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: TR+audOBpEfV6wEAZumXtK4C40PrS49RxqQcFvvVudKwXwDQNo4VIlauOgx/sHIr/YQFhxwN7KlwEzJhSfxRkrLqK19JnIxDxLp6YCuRGnr1ACy9rwQ1QwQKUMmPi6HJtO6ngGQUcuVBE3lXDWj/VI8RrgeuDg6Q5HL21+GL7yyhyRxorZSdDtWh+tR8nJnThwzEAshK0niQmj/cPlxoIi8SYDUUVhgpWyLR8XPISrW1BOpuQsyup31rQdcPpTe6pAqqlPKcnR9tiPmW7Zg8wi54etphGNxBrBBTppgrS4TnbM29hW7gzF0l1nFeBaEUls0/ocpPFxi0uNMy+FtC0ZJqM09CLG9czx3PjjFfSDAqzyq6/265LoDNGDS2o6VQf+R31fbA/zNTRkYtIODWnVnFflEL1EtqDNLY9OaajvCXck5UBJKAIcrL2l2VME1Ixa/bwRoWJHF+7koswj5OxVjvuxlF7slRbuzU4Wtn+5HNumLljjc6m2RPz+XMDXv1aPnpG0OJ3D0UADMNIp6q/Iqm8n8d84lhRlB8rcnRlp9Aj+GCzHYz4P1kG2PJ4qD8c3w/2yMNbodvlR2HIoJ6apHCw3iyas1gBSYHjw/6zqPABW8pReeMG6vSzxFh7cjXcyr4UsspQkIbr4636W5rFF+ZygM/lwU8p4KmwAjgBkqiU0zq2qGDudGDSgQhwuIv+1A86YP7t1P4Tq0NvRgLqA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?Z3V1WmtOSDlkNGNGMVh4QStyN0VXTmE3Q2IwWHpkalFPeW9rNmRvRE1KaElW?= =?utf-8?B?dEJmOUpmTXhkZTl3N2JYQWloclNwOXNjQzVIbS9uL1dTcDFlejNmRmtIR0I1?= =?utf-8?B?SXJaaVdzRFRaQUdmL2NKQ3hPQlpnMHJVV2NxZ2FjQm1rNSszVWwyOEVtT3lM?= =?utf-8?B?VW1HYUNIS3k4cjZkQ0dxdUM4L3cwdytiOVFaVGhyQkhRVDZOWk1wU1lFTnNy?= =?utf-8?B?M2lpQjl2SStFYWMya09BOElKKy9hM3F4bndBb2hDVzBTNUFDUUN3aVRtTGl0?= =?utf-8?B?eWNQQ1hiUjQvOFp1U21wMzF3Qkhlb3gvZVdKUE83OU1XaFFFK3prTG1yTVhq?= =?utf-8?B?MmNJV1NOTXMzRnFFQmQzNC9BOXhmMjZxSitURlhQcW9SbC9GZUJ2RE1NWGgz?= =?utf-8?B?TjJxcEZVTjhxdExHbTJRTWIwTHRBZSs3SEtWVC9hWW02T3VGYXRodFRxVHdO?= =?utf-8?B?UGJ2MjJHd1N3K3QyWTJoSDIzOVRhUmVLTWwwWExubU0zQkJ6NWNOQ1kzK1d5?= =?utf-8?B?NEIwRDhCemkrd2crSUgxcHM3UWptbmNLWXN6emhENDFWMldSelo5VkREd2J5?= =?utf-8?B?dnR6Zjg2M1JscE1rS1J6Y3IwajcyMXp2UE9lQ215SHA5dy9TNFRtYXdNOWZ2?= =?utf-8?B?cGE5d05JUjZRSURQWDh1K2VZMkpER01WY2g2T1hFVWNGdzhobFpNc3daWkdo?= =?utf-8?B?Mlk0SjFEME0xN1ZyY3AzWXNkRzZKSGs3OXp5UEtLT0lUaEptWG1ocGZjQXM3?= =?utf-8?B?Y2FTYno2K2h6WTByc3p0OS9DVFVrSUtKYWFCTFFWTEE5cnNBTUVnRVk2YlNv?= =?utf-8?B?WDI0TjZWRGpxaWVidDc0K1VWRXVtTi9YUTA4MFJ0cXJrT0ZRL3RrNG02c0NE?= =?utf-8?B?UVFlSzdPbmVRZFJTMjRxV3ZKNmtJTU9QeHI5YzNoQXUydkhpL05HczNob05t?= =?utf-8?B?UURmZitIL0xEUkZjTmc0SXM2YjBQSmFndS9iMlN5aEtUdU5ueGFiYmJDa3lD?= =?utf-8?B?bjRNcWlZTkZFOGEranVpRjBiTVY1dyt5dDBGRlQ2Lzh1YjBsWTk4emFJK2V5?= =?utf-8?B?MG5FTGlOWkRraDBWQXZQSW1YaVhsQ1gvR1kwMTYwbVhNd1QwZ1czcitMRmd0?= =?utf-8?B?bXVQczRHZzVwUW9LUlptSUJIekNESUFNNGtLVUxVWm1YYWNzUUd5UW1McG52?= =?utf-8?B?VmN1UFRnNlg5enVGU3BIOVJHZXF5a2tDbnI1aHZUYk9oSTAwOFp6N3FWOHRF?= =?utf-8?B?aFNab3l0MmJwVExBZ29YZm9DRVR2dmhRdWNXSWZGNEZpUnFqb0wzUVZsVklT?= =?utf-8?B?SnZYYXRjZ2JYKzQvS3I0TjhFYU5NYmZWNnVZbmJlYWF4RkpzNVBiS1dIOUhl?= =?utf-8?B?b016TVpWelJiRTZCeFJDSmgrelRaNkZvb0Qvc2VodFB0U3RjWmFqWTJ5Um9U?= =?utf-8?B?VmE1UUhkdFNpNktEWExrWDlBenFUSE5GOFdXZGppSkhjYUN3YkY5Z0N1clY0?= =?utf-8?B?YmxXeGJKTU9jY0R6d3UwWWNQazlmM3F1WmR1SS9INWgvM3RBUEx5U2w4djN6?= =?utf-8?B?K3M5V3pWbHpCSU1CZU5iVml1ejk4V0VzdzJ5MHppUVRiZFdPYVpwRklaNGF5?= =?utf-8?B?UldDR1FtYm8vOEUwTlZNRmhKNWR1RjZ5aDJqT3JtUHFWUVJ4STRJVm5IbnJS?= =?utf-8?B?U1pUWDl4Rk5LclQ2aE9uN2ZTaXJHeG80R1pUTlRWUkdLZERiWWpqQ2c4V0VX?= =?utf-8?B?S3IvN24zMlNaek1kRS9hTnozTDBjSWxOMmlmTFIrL0x1OXdYV3pUc2VqMDU4?= =?utf-8?B?ejFkanVCd1AzeUxRbGpROC9IVDl5dWRSU3FERXVtcDB5QVB2NHZTcFhFcUU0?= =?utf-8?B?VGRhZHR1dEk2Y1JvT1U5bUJnSzZFalhoR2pOTzduei84azdFaTNIQk5LNC9q?= =?utf-8?B?dGV2NzdjdW01SGJIQ2pKU2hUTS9vZWVuVWhxaWEwdHlNMGFQQWlBcjh1aDZ3?= =?utf-8?B?dXZKZGlCanIwTGlVM21YWWFMYXBGRUczKzJaSkRpT0pXNFV6QzVmRHlXSkg1?= =?utf-8?B?QmlEcEx3TlZ2TSs1ZFp6Q0YwelcraXlSS3d0RVdOYm55WlpIaGRGenhJWE9X?= =?utf-8?B?L01jamFtd3BWb0VCdTN4WWZVRmNGc09iZHN4bXl4a0ZjKzAyNHR4Wm9UNEgz?= =?utf-8?B?eXJucTNBZGRMdHFaa2MrYkRrQkNvMGZCUTIvOG1Ydyt6dFZtZDhIbXlESTlB?= =?utf-8?B?Vm9qeGFmdDBTU3dxT2tJcXdibFU3NHpld1FiK0N3OFFvakFweS9oMlRCT0w5?= =?utf-8?B?KzZXenJTTmh4Z0RiUktYWE43YjFDcWJvbDc2ZGFmdVhvNENpeC9GUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: e5d27585-ece3-4ef9-c431-08def30fc796 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:03.2906 (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: a7lC8j2pqPv48dOWFUXZICjLYAm21XyYTh6MKy0VsW0y4HY8yAri7LJEHMrBZHTzAg/yr88xx6mv2Nuef8+80Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 Create a helper rule for register offset computation so there can be a single rule for fixed offset registers. Similarly, extract stride computation to helper rules. Signed-off-by: Gary Guo Reviewed-by: Alexandre Courbot --- rust/kernel/io/register.rs | 115 ++++++++++++++---------------------------= ---- 1 file changed, 36 insertions(+), 79 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 91804c1ca117..e4039e31b4e7 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -789,27 +789,19 @@ macro_rules! register { () =3D> {}; =20 // Creates a register at a fixed offset of the MMIO space. + // + // This handles all of the fixed offset `@ offset`, alias of register = `=3D> alias` and alias of + // register array element `=3D> alias[idx]` cases. ( - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $offset:lit= eral - { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name @ $offset); - $crate::register!(@io_fixed $(#[$attr])* $vis $name); - $crate::register!($($rest)*); - }; - - // Creates an alias register of fixed offset register `alias` with its= own fields. - ( - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $alias:i= dent - { $($fields:tt)* } + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + $(@ $offset:literal)? + $(=3D> $alias:path $([$alias_idx:expr])? )? + { $($fields:tt)* } $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name @ - <$alias as $crate::io::register::Register>::OFFSET + $crate::register!(@io_base $name + @ $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$al= ias_idx])?)?) ); $crate::register!(@io_fixed $(#[$attr])* $vis $name); $crate::register!($($rest)*); @@ -834,9 +826,7 @@ macro_rules! register { $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name @ <$alias as $crate::io::register::Register>::O= FFSET - ); + $crate::register!(@io_base $name @ $crate::register!(@offset =3D> = $alias)); $crate::register!(@io_relative $vis $name @ $base); $crate::register!($($rest)*); }; @@ -844,76 +834,28 @@ macro_rules! register { // Creates an array of registers at a fixed offset of the MMIO space. ( $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - [ $size:expr, stride =3D $stride:expr ] @ $offset:literal { $(= $fields:tt)* } + [ $size:expr $(, stride =3D $stride:expr)? ] @ $offset:literal= { $($fields:tt)* } $($rest: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 @ $offset); - $crate::register!(@io_array $vis $name [ $size, stride =3D $stride= ]); - $crate::register!($($rest)*); - }; - - // Shortcut for contiguous array of registers (stride =3D=3D size of e= lement). - ( - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr = ] @ $offset:literal - { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::register!( - $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] - @ $offset { $($fields)* } - ); - $crate::register!($($rest)*); - }; - - // Creates an alias of register `idx` of array of registers `alias` wi= th its own fields. - ( - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $alias:i= dent [ $idx:expr ] - { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::build_assert::static_assert!( - $idx < <$alias as $crate::io::register::RegisterArray>::SIZE + $crate::register!(@io_array $vis $name + [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] ); - - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name @ - <$alias as $crate::io::register::Register>::OFFSET - + $idx * <$alias as $crate::io::register::RegisterArray>::= STRIDE - ); - $crate::register!(@io_fixed $(#[$attr])* $vis $name); $crate::register!($($rest)*); }; =20 // Creates an array of registers at a relative offset from a base addr= ess provider. ( $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - [ $size:expr, stride =3D $stride:expr ] + [ $size:expr $(, stride =3D $stride:expr)? ] @ $base:ident + $offset:literal { $($fields:tt)* } $($rest: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 @ $offset); - $crate::register!( - @io_relative_array $vis $name [ $size, stride =3D $stride ] @ = $base + $offset - ); - $crate::register!($($rest)*); - }; - - // Shortcut for contiguous array of relative registers (stride =3D=3D = size of element). - ( - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr ] - @ $base:ident + $offset:literal { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::register!( - $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] - @ $base + $offset { $($fields)* } + $crate::register!(@io_relative_array $vis $name + [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] @ $base + $offset ); $crate::register!($($rest)*); }; @@ -930,11 +872,7 @@ macro_rules! register { ); =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!( - @io_base $name @ - <$alias as $crate::io::register::Register>::OFFSET + - $idx * <$alias as $crate::io::register::RegisterArray>::ST= RIDE - ); + $crate::register!(@io_base $name @ $crate::register!(@offset =3D> = $alias [$idx])); $crate::register!(@io_relative $vis $name @ $base); $crate::register!($($rest)*); }; @@ -954,6 +892,25 @@ macro_rules! register { ); }; =20 + // Offset computation helper rules. + (@offset @ $offset:expr) =3D> { $offset }; + (@offset =3D> $alias:path) =3D> { <$alias as $crate::io::register::Reg= ister>::OFFSET }; + (@offset =3D> $alias:path [$idx:expr]) =3D> {{ + $crate::build_assert::static_assert!( + $idx < <$alias as $crate::io::register::RegisterArray>::SIZE + ); + + <$alias as $crate::io::register::Register>::OFFSET + + $idx * <$alias as $crate::io::register::RegisterArray>::STRIDE + }}; + + // Stride computation helper rules. + (@stride $ty: ty, $stride: expr) =3D> {{ + $crate::build_assert::static_assert!(::core::mem::size_of::<$ty>()= <=3D $stride); + $stride + }}; + (@stride $ty: ty) =3D> { ::core::mem::size_of::<$ty>() }; + // Implementations shared by all registers types. (@io_base $name:ident @ $offset:expr) =3D> { impl $crate::io::register::Register for $name { --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021105.outbound.protection.outlook.com [52.101.95.105]) (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 485D0483BCB; Wed, 5 Aug 2026 16:37:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.105 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947839; cv=fail; b=DxNSIvy1cMYEI9sEU8HDioLKKhjJSPb31wuIgbDFGxBEeSTdKhmHac3w5BsXkpVjseYXenyWy65WK+BBRQ6PtvgrmcOdLfcZsSVrsmnuERr3KcdfQhlbdgsohpj0Tqtce/qLw24ZgWsm/2qmcD4BvZj5S/ij7aS3QkGuvxyRROY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947839; c=relaxed/simple; bh=kxYvMQ7UZOZnHvroydQaLwy3JkmA7ZZfobEsk/DeEdI=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=D5BlZSogzYvMOg7vsYR1H6CrLga4ql7uuA1TtKKCxK3d+UvRcQQN0Rk3N5Sb3PIbJx+TU0UhqQu3I8T27mrSNpkgBOn9JaP3+9ba1AGXhzmOi6d5JOWkmkfIodNIbYFLuLq4EfmaS5vQPuyhYlW7EG7Qw8ozdoeoP4DOPmA9xfo= 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=lL4mmeiy; arc=fail smtp.client-ip=52.101.95.105 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="lL4mmeiy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=b37Em66/r9CKCvS/X4ErsYROiMF0dZQiaK8XC5X71obO0QkdSUoS8kmhZ3JUWMRCK2F4rKSAIqjDn4wKw73A86/pLMBF57yqktg5yHHa4BbwDrpEN9ZXnMqW2jG+uh5cpN2qe0wimDZZbq526EbTyUVJus4lYJSsBeDLarcD8bjmRxbu7XU7QjE7XMGiSZvjz0YKzV1bs25YoQgXpU7Rt2kLc8I0JPMZECjm3zvPMKn1oOzaoGMKMNjnk5sTo7Eg7Y/BsPaltroOm/XVc0bKuj1+MxO/s2+4YxA/wG8PreVXS4Am2A4TDVDFO6APmairJkb1ogsd+l9LJKQKH4eS+A== 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=drUypYPRnv6ULrv9Li0qH+xITjQcHHHsahchsFzwJ5g=; b=PLRktzBdtQuVdV8t7rqLJW1mSMqf9vgHfHDwMWNUVa1K9TLMR5nhYRTvhWFB2EjzBq++oG4vcfGk69/EfoG/NGX+f+pgQ3yeBEEsPRq4nPRJXKQYpIGgLFU7Jx7vQwNxThDGoVKUVhkfhrIA3UCxjTD0m6w2OKZhwpeGKFeC4welpFJwaLcwfp+u/2Z+tJt8YR7cYZvOxMc6PKDkKJeyVNN8KCFXts566cM9GTZJqFYFpjLIPbKwjSvN1zQDgSrd/vN+wgRPcpMyqVeBYkx5bzT3OxRe2YDPieEZyZ76sY6Mn1qepUCbylQfJZQbpA68XoKt5/RbQOxEZPdR7P8gnw== 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=drUypYPRnv6ULrv9Li0qH+xITjQcHHHsahchsFzwJ5g=; b=lL4mmeiyA1ZPEF6pqnIAl0QAZykCB/rDxSjyRtRI/34Po4KFl1uZ4+ozxpqz8h39vGjZ95tCjgjlQkIg5r+vpNUMMLDZmeUSB8cJCkV9sLGwAEpeegLsivSZj2HV9+Va5dVX5bxZWUPpoa1xsvEyGBmz+7BgQ0kVXBI0SVqu3jA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:04 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:04 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:49 +0100 Subject: [PATCH v2 06/16] rust: io: register: allow explicit base type specification Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-6-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=12073; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=kxYvMQ7UZOZnHvroydQaLwy3JkmA7ZZfobEsk/DeEdI=; b=8NRAjr5Laeniyx3vJKy9sXSWAKXmHv8rczcyZmg8qx8uwWksLz8KYZzdDya/cfTjaTxYgTI89 fKc1PaXNiPvA/Dxjc/JdjDE4dyKG+xIgm+2n37xv5s3dgwImV4pXwjk X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: 6fd5c7fd-4239-4f98-0089-08def30fc7fa X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: cjHi1jMpqctHdMlBSj7HUNOMQfwVjoHQWK4EuEsX0ikf09PXjr+FhWVa0IHWhfWlwa4SWQeobILHOV9wqcqynFyRO0UyD1YkxEKKwE/V3ga/gd1P5HKGgsxcXE8l+fXGbNSMgTz8Cge0vfXieEE196sLTKqiLs1/6A+QLGcMRkOU+vcolDeQ7knr9NwJHsfBNlLAwK4tmiZ5VywKDJZcFRhF45CBQqTfXSbyg47I9hhusTFdp6KLncb2twmi1eyDurztL2Z6KhD6H9FCGzmKFOjzE2hQn9F/0Ni2Abo2XZ+yAtB9hmr5MATErmN2uRlsH4jccKwAkUATqpPV1jWCwUiYghVzDcarvDjZWMz32B6T/PEwyPVSLgqXhogUnnQutU/t9tYolPluMQ2IeF+70me5XvIY/YNhI6IjgQAJKqnfOKJhZa/9Q4ec+8Ed3OCjbmpn900NsaxS3lxO8fgBnxLKnMfF31FaWN0qV0A+utUQuj66rCOTLbZZYNTgc50VU+sAEmMvIUYY8BoJGdSO8iG2xWF6kGJLu3iLgwwMMIKhkGYleLURsVeVM9HHJ4KkS9B3WNM/H3yEjxNXK6OsfLnx94ES8ekNO98YpcUvxhHMYrHDEXKvxaCGRM3z6n8ebX4gTj4viMo1PswR4xRgD8G5dsijpmWgSyVt36wA9Nt5Y9pws+XDnklmHK7I1GwUnT59rlcD/ajRWqDl2w2mmw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?NjhYUjJBWmR1M1Nqcmc1VVNzbmszUUJDQnA4Yk50Y3M1VUN3RnlodTlWTzVo?= =?utf-8?B?WVYwRU50TXJWK0w0dVROSWRZdXc1amtqakh0dTczRnhtNi9Cem1ZZytkd3ZC?= =?utf-8?B?WDBJbWY2RDVRcjNCT3ZJQmhYazlPRjZIWDVZRmlHbnZHQTcwdUhJZDFGWnI4?= =?utf-8?B?OTVuOEpibzh5ZURqS0hxcmJ6aHh4b3Vjd2M0ZXM0ZkNtVnBEV2VVMW1UZjI3?= =?utf-8?B?QUhieGEzNnE5b21yZC85b0ZINVA3dGR2Nk9CeUJub2J6SEFtd29FWFRtRzhO?= =?utf-8?B?WUdYLzViWGhPaWRCbTlINHdDVUNJUkpJOUNUaU5MbnJBekxJQnZFNUYrK25W?= =?utf-8?B?YWNhbWgwaGRjSEpEelNCODFZY3N1bWNKK21PS3hmVnRXV0YzaUovdXArb1pq?= =?utf-8?B?ajc2Rm5sSzZBSEtyUzZrUWxjUmdJbGxFSG14dmFxOW1MdWZIdlRlVjJXNEZi?= =?utf-8?B?ZGExdHJPV2RZczVPU0R0MjlDVUZDd25OSU9kcCswdUtLOEtjcTJWRjZZdW5C?= =?utf-8?B?WWswcWtmaDlDdkc0OVVLT3VKWnJ2ek5UZ3oxWlFhcTVTdnE4U0Z2eFRZT05M?= =?utf-8?B?WkZ6SGt3RHpsejFqYUthRVFCbEgyTEdpdzB2aElXQXMvSUNpSWJocSt4Wi9C?= =?utf-8?B?SDZsbENWL1VienhabTRFaEM4RS9FMTE0akRDdnhMN1JHVTg0L2lMZXdWZGMw?= =?utf-8?B?K0hRNG5NMFVSRjRhSThEV1JaSk5DVHRoMVpIWmVVL1lEbXIwSElYQWlRbi9m?= =?utf-8?B?bkNhRlNZM0xEbmhmb2pqbnd1WWNwajF2M1JPQ0JQaEgvUWl6Y3JOVEJGL1ll?= =?utf-8?B?K2NlblV0WlNqUTdTbjZuTU1RTU1vMGYzZ3NRaUVqL09pUTB4L3Q2TVl2THIr?= =?utf-8?B?QlErRExTRnk0dERTTzJTeHdCS1BNYzg5MEl0YlBXRXRMZC9xTmcyZklaYmNQ?= =?utf-8?B?QkFGN20waWh1T3daWHNCODRYNTE0Q2t2VUNxdmpJcGtFQnR3dUZ2NTljb2Ja?= =?utf-8?B?b3NJZmk1NEh3LzNTMGFvUWh3aXpCSHNWZTRTaXh2cnhOVXozTXNBUS82OHEz?= =?utf-8?B?VzZ1Ulh2SXRYclJDNkdiTDhaOUxOZ29KV3R5WnNJYUZkbGFLbnJsQlNQY3NL?= =?utf-8?B?SzZZWHFCeVFaeHhRNWx2dGVSdmdjU2pQTFdXd1RsS21WTmNBKzdXajJjYzVY?= =?utf-8?B?TmwrSUU0cGZxaGZ0a0xpWFdydkdtMUZsOVgyUjladmxwbDVQazZ4Q0hzS2Z2?= =?utf-8?B?STRlT1ZlTU9vM3VrSi95eUFBL1l6aTZxU3lGclRDajVBQUxLc0RYaEk4ai9t?= =?utf-8?B?bU9wZUJ5Ti8zWkp4NEVpSGlwWisrTXF2U0lvSzR6eFNJT1lhMXh3TllkRC9h?= =?utf-8?B?SzFhcS8zekIvWG9ZalRHbjlzVDVzQ3lzcy9GSzFPM25vWWxSZS9Rd1d4c1hv?= =?utf-8?B?S00xenUxek42UW9zZ3ZmTjFJVDFIVHZFMmRSZTVrdVdEbFN5SUpodGlHWjlB?= =?utf-8?B?bUdCVlRrV3p1S1crWXJzWUZ1d1YrZS84Rmd2OGRjUnE0WkMzclpuVTA4T0Y5?= =?utf-8?B?dWhXSzdxZG0vRVJWdFRFcnFZM2lxK0doY3Z3SjdDbnM5NlBkOGNCZkNLWTY1?= =?utf-8?B?bVlsbi9KWXZ0d2FxbUJMbVlkaWdyQWpSZ1VNZGtaVEtQMEpnNGZ1Y1N6UUVW?= =?utf-8?B?Z1lBd1owTWJjdHJrUGlCaE9tdGMwRVFOaU5xT2gxeEdFaGxrTUN2Vm12NVIr?= =?utf-8?B?akJ6VThHNGlOVnNaL0ZtZFBZZmlsb1QvMzExQmpJTEVDVThpZU1sME40VHNi?= =?utf-8?B?cmR2dnhsODc4amxCRWM3MnpTRkh2RmtCY1VPS2xTcnlmRWJsUEpJemhoWGhL?= =?utf-8?B?Uk50cDlmdDlYOEgvMWxyU2pzRDdtU2VBbm1PaWg1dkZwMTBTRlhFZ0xaMloy?= =?utf-8?B?K1R1cUFhdjdNQWRibkZUY1czeDNFeE1mazArVTh0OUwwcFptYWxKNVdvOVhG?= =?utf-8?B?THk5dWN3Vy9STnU0ZTZ5Y2wwOXUvZ3FWYzFydElXL2wxQWErN0dCeXlubGhN?= =?utf-8?B?bXhPUDg1dzU0S3h3RS9XbEUvdUw5alJSemoxaDFlVTVUR29Da1BPYVgwNk5Y?= =?utf-8?B?aE1GMjNCVlNkUnBUK0tUeW4wdVo4UjR1WU1lRVVGZUxxU0IzVjJkUTRzdzZn?= =?utf-8?B?SEZtZUUrZmZzNmhyNnR6b3ZtVDN6NTFzd1AwYVBneUV5NW9DVEp5dS85WkxR?= =?utf-8?B?ZTJzcDdEQkN5V0l4bW5uTTZnQ0c3Nm9RTzJFaUZ1N1J1bS9YU1ZiYzBqVnJL?= =?utf-8?B?YnRxbHRnazYzaHF3aG1VSUVUcldncVNkemp0WDJHZHdtY2dadktYQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 6fd5c7fd-4239-4f98-0089-08def30fc7fa X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:03.9316 (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: MzWjXBrInUIOHq1aHzi6i52gjDuQA51zxklEjpE3/IEOyq31LTTUqWFZCbHvrpxdPOz8CgSPv+TIhQCTNA29cw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 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 | 84 ++++++++++++++++++++++++++++++++++++++----= ---- 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index ae18890866b6..d92e0b6adc99 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -1022,6 +1022,8 @@ fn try_write(self, location: L, value: T) -> Re= sult /// }; /// /// register! { + /// base: Region; + /// /// VERSION(u32) @ 0x100 { /// 15:8 major; /// 7:0 minor; @@ -1164,6 +1166,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 e4039e31b4e7..7dca2437b551 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; @@ -786,13 +823,19 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// ``` #[macro_export] macro_rules! register { - () =3D> {}; + (base: $reg_base:ty;) =3D> { + const _: () =3D { + #[allow(unused)] + type Base =3D $reg_base; + }; + }; =20 // Creates a register at a fixed offset of the MMIO space. // // This handles all of the fixed offset `@ offset`, alias of register = `=3D> alias` and alias of // register array element `=3D> alias[idx]` cases. ( + base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) $(@ $offset:literal)? $(=3D> $alias:path $([$alias_idx:expr])? )? @@ -804,11 +847,12 @@ macro_rules! register { @ $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$al= ias_idx])?)?) ); $crate::register!(@io_fixed $(#[$attr])* $vis $name); - $crate::register!($($rest)*); + $crate::register!(base: $reg_base; $($rest)*); }; =20 // Creates a register at a relative offset from a base address provide= r. ( + base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $base:ident= + $offset:literal { $($fields:tt)* } $($rest:tt)* @@ -816,11 +860,12 @@ macro_rules! register { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!(@io_base $name @ $offset); $crate::register!(@io_relative $vis $name @ $base); - $crate::register!($($rest)*); + $crate::register!(base: $reg_base; $($rest)*); }; =20 // Creates an alias register of relative offset register `alias` with = its own fields. ( + base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $base:id= ent + $alias:ident { $($fields:tt)* } $($rest:tt)* @@ -828,11 +873,12 @@ macro_rules! register { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!(@io_base $name @ $crate::register!(@offset =3D> = $alias)); $crate::register!(@io_relative $vis $name @ $base); - $crate::register!($($rest)*); + $crate::register!(base: $reg_base; $($rest)*); }; =20 // Creates an array of registers at a fixed offset of the MMIO space. ( + base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr $(, stride =3D $stride:expr)? ] @ $offset:literal= { $($fields:tt)* } $($rest:tt)* @@ -842,11 +888,12 @@ macro_rules! register { $crate::register!(@io_array $vis $name [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] ); - $crate::register!($($rest)*); + $crate::register!(base: $reg_base; $($rest)*); }; =20 // Creates an array of registers at a relative offset from a base addr= ess provider. ( + base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr $(, stride =3D $stride:expr)? ] @ $base:ident + $offset:literal { $($fields:tt)* } @@ -857,12 +904,13 @@ macro_rules! register { $crate::register!(@io_relative_array $vis $name [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] @ $base + $offset ); - $crate::register!($($rest)*); + $crate::register!(base: $reg_base; $($rest)*); }; =20 // Creates an alias of register `idx` of relative array of registers `= alias` with its own // fields. ( + base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)*= } $($rest:tt)* @@ -874,7 +922,7 @@ macro_rules! register { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); $crate::register!(@io_base $name @ $crate::register!(@offset =3D> = $alias [$idx])); $crate::register!(@io_relative $vis $name @ $base); - $crate::register!($($rest)*); + $crate::register!(base: $reg_base; $($rest)*); }; =20 // All the rules below are private helpers. @@ -962,4 +1010,12 @@ impl $crate::io::register::RegisterArray for $name { =20 impl $crate::io::register::RelativeRegisterArray for $name {} }; + + // Compatibility rule when base is not specified. + ($($rest:tt)*) =3D> { + $crate::register!( + base: $crate::io::Region; + $($rest)* + ); + } } --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021089.outbound.protection.outlook.com [52.101.100.89]) (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 A2D49483814; Wed, 5 Aug 2026 16:37:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.89 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947843; cv=fail; b=SeRre4KqMcduL93S3nqVL3Ae2iunZ3gPUU4MygPRHp/n/469zVj8I8lRb2d9LiCu3tsoSqUvf6hw8UHjBKrqnKahr2ElRhASkRlVt3H3fmkqDBnyoN/5lvHz+DXUCEOGRw0kT+eEfjLmqbN6m0dDr6BXfrpY/hFCx+JGT0fDink= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947843; c=relaxed/simple; bh=EA8nt8Iv5DnadzaZ1L833fTrj6susiTu+zZOLANPB2A=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=pyU70sbFo9zQMTGFLkXQIgEjgopTG219qMGbLkfhvoaWLEoffNSmORxPn6M2fgk45GaPuQap/iwAP6oOMDXauy8fOzIVjtgtRaeBo7XTNr8hUUtmdAR9Or+rLuCNrL9RURzN4rZs5O364zCfHfYWcgEd12UXRgnibcFRaCQv6ao= 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=e9RfLLx6; arc=fail smtp.client-ip=52.101.100.89 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="e9RfLLx6" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=tWOH1OovDOCe4Jw1N5WmwJsxZiNxNUwYITWnPDj+85LsI+IS8ck55dJKgJwPcDE8m4YU+qPT7xzv7x5vZp3jKwusSqRfUDVE1RC+8L7h0Igh3h1DPiKVu+rz1bKk03KXpSkUrojLv+3C3AVxluDguniZyifbaW63Rvv+2rSVN3YKhrfcFY5KvuvcgyXhXXvoB2RDEncjNYvrWi+cgS2xuzxw/6T8ByuUscLOwlSW7CUL0e+gA0PGevNp3m6aWlvxp4FNzEQwN2Vo3S3AmjOJs/3I9yGWJt8JO357MTBeAxdfcs7xVyTLfLNWGY93CfVCdIJguWRpzOF/M+AYX408FA== 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=emkmSzvt5u8J0D/+qqMnjmcJzUewTxDC8iy4Z8z4mO2NaMwhZJwQyLLzz/NgWf+BxyzdNkEXPVFFWngwO+OVaYvjfgGcDluC6P+K+pTV+va1yMFhC+IWLwk0TnjwbHisICwRWZ5k/lE2fnZsyO0swqd/VN2bVvDbK1wGyD7Iv/l3m2CM7ryVEOwTmHLLlrdNqu9EN+aYWGCmYie/6MLxmsgUhsyLwQAFgU4tVHkOkRtloI5gGiCiT7IyIAA06sQMkP/8ckc0QdngWRAk0D20ozCE/Ox3fhnkNpWcGQDqbSnxInUJS9W1CpIM8qGRyD9wr3fvz1/VCnutV3UejVtcVg== 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=e9RfLLx6ByGSxonF2xJMGPfLrpe6fNU+3ACxHFXjP1e+l5JgomfCj9qwPExlCClcmqoDUThvsgdp+q30Tcxja0yXIJ6FBS+8iIRzs7HMxttkN+CSmpcBPBmujkQSWAoDk/U8Z17IyEJEcOPCOX4HK4083XchI2TMopRZPTv3CqU= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:05 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:05 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:50 +0100 Subject: [PATCH v2 07/16] gpu: nova-core: specify base type for registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-7-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=8925; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=EA8nt8Iv5DnadzaZ1L833fTrj6susiTu+zZOLANPB2A=; b=0C81QwBvANKXq+syHcxgqJ0znDm/WtG/3mLtk7426pd8DGYy39xBJuH8OeCJqvs0JZdeNTH8o lut3Ew+kU5bDnr4zEncJI7jvJEgTgPa2AN4DzkcuAXSSv+sFbSQLT4f X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: bcd0faee-9a09-478a-5ca6-08def30fc854 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: fjfmJNXYsh7zv5zlHE8sltZEvUnOp0QfrO+md99PjhlSouoKxaRhLBdFFGq1b0F06OTDLJybcw0WtPYcFEGBrUFF1QgiQvhD/z8OKqnLiz06QOU0DvA4sOlB4lZRM7oxGxW1BQEZ750B7/IKVyQ5x2TW5MQ//shH8698bbmQ+x3Lb7Z02ghqFepSYo4OConn4e0M+jZ2QSSiczJDUGfgJVabKuRkP+OMabBPJkJg3n3BFyZ0FXdkdSCVLO/LrZVo6mTWcI5QnkGn65kP2ZyDlJ7Om43zQrZPnTgUKni1u9gCChtC/WLMqqGGMebgMF3um6OVH/WiJMtF5qmf4cSye4T/4BNVOT2nghZGQJxDZyRUI2drauDDpKRm3KTJfQ5VZhG0vGYmY/SrZ5HIjvaEAn70J67bxyI4l78+RQOuAwnYxQ+MDxSxNKaBr6sKQsd4V/ZXPBiuUsZQYVqH5E4DMInu6yyxFEeirWm8HAn2S00vErlCIaGJIqjJm6fTlkqmUyOyZbJNCnceiRBl/shvxkDx1FtYxBMafA1IYssvhRDd+82Jf0EBp+ytFKvkdXIGxKc0MHzfb8xJLa8HXrE6+Gz+oya9AmlnvpxVp42lITGLdGgjd5VgEa872JUS6dWpwluANC7v3MsidHMhchdHTnPx31eKTlJqTAQikfWllioVjbU6ogDu+iLjkqwkGmgdmuhoOEMibXH+wWLAjoNs7Q== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?ei9mRldsRjlxdU1FaFhPRXVPUkdXeTlFdm95OWhaQUZRa2NNYTZGZ0tYeC9Z?= =?utf-8?B?OHVaSnFEWWZVOGkwWE5JOFQzSEFmZXVWS2F0UlZ3VGVkOXNHOURxb1FPYXdZ?= =?utf-8?B?dEhzNklRT1EzY2NwendrZnp4dy9CT3didUl3dWFUQm9mQ1Fic2xlTGw1ZTBR?= =?utf-8?B?TDlyOHFUbVRzMGdPZm9ROGI4SERRNEZxdVlnUlo0d0k1b0pMODJmMG9jS0Nu?= =?utf-8?B?elVRVUJJbldMTUJiT0EwMUlOMEIyQzNLRVhQbWNFS1UwbmdLcktXT1lJcWlQ?= =?utf-8?B?T0FCUURUeDlMbFFZWE9uNXU3ajJuOXJYN1ZIMVMwdWd0QnZObkZaZUFiaWxY?= =?utf-8?B?dCtvKzJZV0VjQzNCT2FScUhGTkJSNVFXdnEzTWJjM0U0ZHFWWHQwOGVkTVp0?= =?utf-8?B?b1dDUEFLK0liQWhEVGYrRWR4UHdkTUc0MVR6NXgrN3BubDZIdVA4b2QwK2Q2?= =?utf-8?B?encrOTN4bEllTHRpUlV3WkloTW51L2lkM1lLRU1xa3VnUzhVSjFVNFk1MWYw?= =?utf-8?B?eGlkQnFCbzZOeUpqcDlJYWtjUHJ4eUhEdzRUNmQxM1Q5QnpKZS9ndVpwM2pL?= =?utf-8?B?UEQ5WldvQ0ZWVW5tOUF3bmVmdzhCVnVvdUhrZGlHa1orZXIveFhxQnhJdFZX?= =?utf-8?B?M0owTmhWKzNMdmpHT1RaSW5EaEFpS3d6VHJLVE45VEdTZHJkaEU3N3l6VFFE?= =?utf-8?B?ZzQ1anZOZWpTN0dGMzN1Y2M3cndyVTBxTDBFWDM2VnJ3UGZ6QS9xZldPRzN2?= =?utf-8?B?MGU1Qjkvb3A0YS9KbVFtTzczcStzbEtkVWdGMU5KNHJiak5ycjhJbk9XcHBY?= =?utf-8?B?bFRVdTlkTWVBODNNTXB1RysrcTVZS3pjSjRNU2ZIb0w4VEFBZ1hmQkNqajF5?= =?utf-8?B?QmlxekJpVDBSRnBvTk5tekpneFkwQXM3b2R2TGY3WlZNM1F5RHVFS2RWZHps?= =?utf-8?B?T0hTNGltZCtzaEJpU2dNaEh5WFhsZkFvTktERThHNUZjcExjTnFKVWN5ZHlk?= =?utf-8?B?UUI4VWdmR054WStVQ2M2STdTZ3g3QkxvcU5hUElKM0puVmZJV2gyYmNrbXdw?= =?utf-8?B?V0FZVTdCVVlvQVpuNmdxOU5zQjlQWWZIQmZZelVlbXZZakp6dkdCTGpKaWVX?= =?utf-8?B?M2RCUThjWTVadzgwQTBkc0l2K3NiVy9tYnNaYWQ4bUEvWEJtRGwwNXZ2RHpG?= =?utf-8?B?MFk2dFNtRVAyT0xXMld3WE90Ykd0NkFtZUo1RE1VU0cxTjZ2OFYrOVVIenMz?= =?utf-8?B?b2lKVjV2WmtGSEVPTmkweTdzQUhQd2dabE9iTUFKYjVNSXFIWFBLWmVacGls?= =?utf-8?B?VVFGSWFUd250dnFKaEkxTjB6WmY4Qk9nd0FuQVpxMnlXRDQxNndERHAzMnBI?= =?utf-8?B?M3lZdi9QbDZYeU1oc0NDVmxaY2ZMd3lna2JJc0c0LzhZa0dYcWhDMFVvMlh2?= =?utf-8?B?ejQ1ZlRoR09EN0d3R1dpcEw2Y2p4MFBnbmhwSVNIMlorSUVSdGZhZHVJSFRD?= =?utf-8?B?enl5ZVY1WnZsNXZ5cmtDK2FFeWEyNlEvYmVBZ1N4OUdWQ25XQjdFMUVmektX?= =?utf-8?B?S2ZaS2hBV2VSNTRvVldjeFBLejM2YlFPTy85SzM4WW1wZWJQTVpPZ1ZRUEth?= =?utf-8?B?Qmgva2w3ZE9WTWwyclU2dEh3MFQvR0RkUml5WHdIbVQwY1g5V0lwWU9OeE9v?= =?utf-8?B?bm1iTVh3dVFNbHZVNzViekFER09ObndJdGFvT2hwRkREOEdKVXc1ekZvMVhS?= =?utf-8?B?dENCVEd2dTlpenNOQ2JVVnk2UVZ5MWdxbVBFd29ncjFORHlJdFRsdjBhZUlB?= =?utf-8?B?dFV6QTgzcnd6ZzNTRGpnUldQOHM2bEpvVElNbnRERExjeWZlV3lMeHBENkRM?= =?utf-8?B?eXJ2dzc3Wm1aTm1yY1ExY05oMDRENG5vR21sOWhlcC9ydTA0N3E0TCtOclds?= =?utf-8?B?R051a25wTXY3MmpQQzhoOVVxQTVVZnZJL1NSUUdzb08vMERZS2RyK29YL3pN?= =?utf-8?B?aE1XL21sanFtRnhFbUx6SmZRcUdZamNzbnR5Q1RuajFUaisrSzZ4US9aeXAv?= =?utf-8?B?Y1lOS3hRcHJwc3NpK042eEJaVFlHM2xKQ2x1elFzbVZYdHNnOXBEb3VHM2NH?= =?utf-8?B?YW5GVkM2UE85RGl3aFVhcktiT3VJdWVDRnA0OTRGVmFoOFZtdTRzY0MrLzhB?= =?utf-8?B?a0dwQ2RuNWdOcjcxMkFvcUFDY092Q3Eyb3Ntbk10WkhMMVF2ckhvZ0pjY0Uw?= =?utf-8?B?ak9obi9rTEFoWVZ4M2lGU2FtS0kyai9lOVYzSk5HZ09JYUI2cnVtNHp6THJ1?= =?utf-8?B?QXFxd0xOeitlZkUrRFdHSXZVKzRBdys0cEcrN21XTFN0cERYd0Zudz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: bcd0faee-9a09-478a-5ca6-08def30fc854 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:04.5241 (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: 8AqGio3nByFOBONYRUmMQqmiKI91JC4awkJDH582ZXWVmTEhU/6TmfVvl2YDv/Y57Z8ZG7NQ1b4sYr6+cR0I5Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 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/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 Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021105.outbound.protection.outlook.com [52.101.95.105]) (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 E1D00488DA9; Wed, 5 Aug 2026 16:37:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.105 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947843; cv=fail; b=m26we13ematad5o4iRmmMASlWumjMQ1A2vKF0aLpuDvRVqQQkBEMQOnL72nM+Pwv5UjMPM2dFUX0eHd5BU92W/YgP5zhjmT1d83LtAKr5cLMoQoOTaeBowR1TKJmTbb2IP3vMFLqyT2TpTUC+PuT47kWCYA7ni3CFaAmr3N/GTg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947843; c=relaxed/simple; bh=mv3/sV5/3SVN383DdQp42etg9sPrNM13SS1QFVQvyEg=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=nnsH52CcYthD+DbyKKIVe2wmFR1dmpYklbri0lrnC+PD4PElmgThI0r9KXf3lEnYbYK20CT9yXYB+3SfMVke4oftmvDFz1Gqn880a828+lKJ3Nx9WXfswvDSGu1i9PkkLDKzwsGm/GiH1Q90PefkDpfZCNbPkM4wjmfDy6OFmKo= 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=IuOyVS+a; arc=fail smtp.client-ip=52.101.95.105 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="IuOyVS+a" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=U7xCs2a7WKcn1lhZrCYUCLhVmKYtuacDqFa9PmWQu4EV58tZibN/kfv68fdiBfoCV4VI2/DOngT/HDXnThTviKz8zoy5F8pJOfjDeSSARL+nGf5DLp6Sr9KXSpTiK9DEf00d2qU8W/VnCuc6myK4Fm2r2uNSF/Z7SlEbLEAIHmb6y+l9S/v+TR0LmzVFwx5hTU+EU4aZVdLpQfFywIEb1WPItEIsC4gpUUtANvtBXPD2Gvg+0Sv5aZ2g/pZyAQ4xnvfYuuZVj0NKdmSNZlCc6R7/n2ri0u8utNtp09TUM/ZwHeAy392mnNla8et9rDw0qWel/iL6VPPazlhoCivPUg== 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=w0Gb3VD/MXDl9xV8m/t5L6cOG17hk/zKGM1ulBtV3Rk=; b=XhImwpio7HAHEOJheCC4jE2M+0dzxPHo2kWuRxowKZg2hABl2t66fJS9Jl2z9zCM4Gwq6rrE06rnCEmpyLpWvkbh8wyrXJiDGgpNLmt+TR9p9oVJ3jJCtbTo60fSoeHLY6C8aD6SBcWhydKSRcq3ZsJ4y0OB6AkpxJwyeJepQvgv7lZvWNHuxo/N84qNaUoi3FxoOtLLFvtdlvS+b00hXMSOdywNzAZ4pR47caFCcbWxIQdawlelFsMVI6pCC1xYFOcRpRXuBuUVNegUe3NckOU9nqy8WDcZI2UibQyNzTIuNJOqBiidpOlde7XzdVPhkKclvN8Ire7wZQg0wG6NqA== 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=w0Gb3VD/MXDl9xV8m/t5L6cOG17hk/zKGM1ulBtV3Rk=; b=IuOyVS+a2TEv8htFRqVhimh9Tdlv5CyhzTgsSx8eryXzjX8pkHYk/5wQVOk+BkSufKgSam9xAX3kJCZUlRW7boFCPOegdbQ0vOjOAy+bAkFBsYZLJYvf4Lo6N8IV/oj8sny233ri9yHobJlxRVj1hfKQMD4q4+yybrufUM9PiB0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:05 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:05 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:51 +0100 Subject: [PATCH v2 08/16] drm/tyr: specify base type for registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-8-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=6459; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=mv3/sV5/3SVN383DdQp42etg9sPrNM13SS1QFVQvyEg=; b=U7GSEt07zAVbHdlqUYaMPys3WGaU9/7WO5AalGCictiUsg2ydgBhU9KVol28Xg0XRrf/dn9PQ KiTS3s5CgXJBfT6zApiyX8zCCnXRGymWEDyKYxIWvCv7iU/giiQ34XN X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: 48802ec9-0ecf-435d-a52e-08def30fc8af X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|6133799003|3023799007|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: THkJVPHqwDsN5Y6FvzKyOHMHte7y8JCO9bmUbW49J67lh/dSpcYpoyIthTKFNYeLGs35lgUZx5TaxCr58uNMa9/sPPPO0zSzL/ygjhLhiufpcQ1HqaPGs0uy2eVaYrAFUYSB75yHIsBevZEi/psHo2ILHkIrbmcJerZJQKMnSYm8wxBY2UXqcR2Gj2fJeGnE14yTEVC/2y7zqvdJgyYVJTqN6PC4sOinQho4Y4m/AbVLt/sTDdnuoALhm5oZifS8Zy02HZ6YIic39gYupAteS2b7fB4djVZzoYsOPS8z0AVITWXcR0wlMbNPk/HiTLEDiY0WgVjHmkHmqPP/3qJoIwwUkLP7k+9zzEX7EQotMQkWmH20JmXg9u1vkqNtvyXkIw6ZLBdxtcIsjWTSCkgnEq26fLZZsZSeoNg2T0RImGpOS8Vpm0wbLY3eagSpiqmKIl2ME7n0+f8yEiCo/zT+SoiKQLwyvsRGKVo6FsACTf/Y1dVJ2l+pYTYn53chpb9vFn2+6IqjHWESUrKcVIMt5JskKd+aD9/o4ZKr+rFENR8Cc9kLhtpFzuIpzgMST1hCTsuNI1kHn2qr0vP+PJY8X8ILxBYU9Tgu4crGcVuYAIqNNIFTvJp3QaVCoKKheiAxsgIuEA5VhaU51biXVJWjDXcKwxZFg/M6767D6VEH8pJO7v3/qtVlm59u5KPPCRBJG6OqFN5X3m8xwc76LUVKcw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(6133799003)(3023799007)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?Mi9kLzcxa1pWTzRiKzNmMktTTld5QnZpUXlKY1V5aDBWaFJORC8wd0xFNDVh?= =?utf-8?B?YUNJOG1kSVpESWF1V1JXNU1VNmttcVpPK0VKTlVvUUFmN25nWU9TSUkyWGFq?= =?utf-8?B?YkJsOXJXR0dGMlh1QmdWVzViSW44dDRvOURPYS9TakpSSlNaK3l6eDdUSGY4?= =?utf-8?B?SFc0N0IwRlVkdE5jcDlZdHNvRE16S2pUZkFGeVdSc0dSS1h2WGREZHBPKy9v?= =?utf-8?B?MWJkeUEwR2RWdFM5WFBXUVZMMjB3NTZldkVKSFFuVVBhdGlUWVV0eW1RLy9k?= =?utf-8?B?RXJTVk1sZ20vcDFkNXl3TkVuY2taenJlME5scUoxSCtUc3UySHZSUU81V1ps?= =?utf-8?B?NzNubExvSVVMN3JSLzVxemdzV0d1b1ZEcnhMOER4NG4wSjNzd0lZVkE5cEtD?= =?utf-8?B?SFFpOHYyUGQ3TzlFQ0t1NlppWkNBb2NkUy9qM3UrTmxFcXFuZ01wejVGZDZT?= =?utf-8?B?dWZpL1lLakQycGsvcXVOTS8xTjkzc25jRzRlZ3lEQkNPOWM3QVVNT1hRaWND?= =?utf-8?B?Ykp5MHNabXZzTm5BR1R4UVhabVRjRnhzZFZ0aUpCQzFFOEZWRmxiQ1dQVWtX?= =?utf-8?B?b1E0R1FtQWRwUlJ2a3p6RUtmbWpMUUxIUHF2SklDODFvUTBGVFhvcVd2VTRj?= =?utf-8?B?a1hucWJyN0NvUERmWjZNRmhYVUFNWHEwRmdPQVZHN0VXOWcvNU5QbEVtaHF3?= =?utf-8?B?RHA1ZGhrdTNmcEV4UGlrTVpORVVSaStNSEtSVGhkb1RhaXdlWUxJMSthN1pY?= =?utf-8?B?YWRMM2JIdHV4RTV3S2RqN3ArLzNRcFFrSUtWdTJYNTlFbERlYjF0WlBzdys2?= =?utf-8?B?TE44MVNaanpuZmNSYzBReXg3VmgwUklqZEc1Zmw3NlpGa0VNOTRWQzNheU5H?= =?utf-8?B?QnlUWEZyYzdYcE5tODRHanJBRGV0YlJIZHNNTnY5b3JLZ0I3bzREZVUydlox?= =?utf-8?B?RUlxMGl1WnhoTndYanlPaHZMWDhtcW5IdmpCcnI4Y29GOHl3UDhDNkhrK0hJ?= =?utf-8?B?bzI5Z01sTUF1OWVKSGM0bU95V29lRDNBZGZXeStJTTZQSnZtc0haTFpFemNQ?= =?utf-8?B?QXByYkxiTnRMWU54NGYremJKWm96b2NIcDl0ajlaQVh6OHJjcGxTZ2JESlZy?= =?utf-8?B?TzUwZ1pmRXhvdkovclJWbno5T0VET0FWL0xtZVJBMjMxT3diYnRPWURFTnJK?= =?utf-8?B?akxrYktZZ21VMkZKL1Z1WjRUdll4YWhZR1dOK0JWYmZYMEdFaHEyTjY0S1hs?= =?utf-8?B?UVpKN09ZdmFPVG1uSzBPUHJJeE5ueFBWdDkwN1ZmbjM3M2RTWTRxOUVpRjI0?= =?utf-8?B?dXBNRytnOUtJc2VPNUZzbWk3SXdnd2p3T3JRWmk1UUhhT2lPSVlha0lobFJZ?= =?utf-8?B?bEVCcm1jTitQRlNiR3ZaNjlzZ3lnQ3E5YVlHcHlMM2lBcngvUGVjUnFBaC8z?= =?utf-8?B?bkJZTXdMQ3p4Vkp3dXA0TS9tc3JKWnFyREtRbzZidEhCbkoyUU0yVFFpeHpB?= =?utf-8?B?OFgrQUF3eDVoV0JTN0JyU2FoaGMrdmllTmMyM1lLRlRhWXJ5d29GaURqTHJZ?= =?utf-8?B?clh1Q08zM09lcDliVFB0Y3d1MUJTeTJkeDZKUFByaWRpbGYzM0ltckZCNTBV?= =?utf-8?B?SENOTnlwME54d1dzZ0NmUjFja2t2K0JBeFBDbUtxS3UrZVpaWDBqcjFnVHEy?= =?utf-8?B?Q2wySlh6L3E4WlVKdEhGalpuQVdCNCtOdmNkYXA1N3lNR2oxbjF0UWtiRUcx?= =?utf-8?B?RDUwYVJnckdzUnM3d2JDZ2R5M1VtMHRZQVg3b3pkTXVESjJBZHFWQkIwZ3JT?= =?utf-8?B?dmZMZENqa1FoNTFQSFpmMHdCMUN4Lzdld2JZVmM3Yld5eXR3V1B2ejVId1ZI?= =?utf-8?B?djRYaDNwRXpDSFg3Ym8wYWNYNHg2dFlTLytoQnlJUGZndmhPT0RVWnZ3NGtQ?= =?utf-8?B?MmpwNHlqbHZPSEdFV05LYTBnVkU0aVg1d3cwbzlzOWJoZW5nVGdLdXkwQXZS?= =?utf-8?B?YUcwcWNMd0orVUlicG5RNCsrUWlqWWNHQzhsT3FFWGNDUHVrRm4vU3hMc3Rt?= =?utf-8?B?NHdsVDBaZXBNenh1K05wR1BubVd4S0c2L0haU284OHhCMnB1OVRYUkdxMXZX?= =?utf-8?B?cVBlRlgxdCtWNmJzTEFqbEg5ZTMzTnlyOVlnK1J1RVJIY2ZtV29XWWlNL2Fx?= =?utf-8?B?TmxXeFdBWTZHQlJKY0xrdWdydW9lMEZEQ0hJaFhLOXREOHBWUHE5QWdJWWF6?= =?utf-8?B?bkpJTFVNK3hTRjY0ZW5RZENaMUJNZnVFK1N2UlR6QUZ2MHV0T1JxOW1iNXBj?= =?utf-8?B?dDNyV1g3dEoreEZwY240RUhsbVV1cE8wWFBVTzRFQnpwZmdFUjNzQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 48802ec9-0ecf-435d-a52e-08def30fc8af X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:05.1574 (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: FNIH8/0lIFW/VyJKPGuekVc6eAUfvIUCz5jhIpQ74aTz4Dt9v+3atffrbPd+vAjZ4BWe1EAHXDyk9ROORatOkw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 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/regs.rs | 43 +++++++++++++++++++++++++++++++++++++++= +++- 2 files changed, 43 insertions(+), 1 deletion(-) 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/regs.rs b/drivers/gpu/drm/tyr/regs.rs index a62724378ced..3e6edae6e27f 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. @@ -1353,6 +1384,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 +1513,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 +1740,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 +1797,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 +1809,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 Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021105.outbound.protection.outlook.com [52.101.95.105]) (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 C03F335E1A2; Wed, 5 Aug 2026 16:37:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.105 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947849; cv=fail; b=dK4cHUpuQ82PgpUZMIJ/LiAZju9P4Wgb9kNM7bVcHExeQUWX1PCc6o2nnNv2zZVf0mQStdKwC4wbW9PbTs4HRhUVpSunqo3taK/llqV5zBqX9wOlA1EjJQYW+NprOrVJMZEaft1rFcaC2RscvDyNMSS/CxbrvFvkbcRisx8dfbo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947849; c=relaxed/simple; bh=4IYGZYY5yfpiRR/pq59TMlwC0IwSy825+cZG4DHMQFA=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=f9E3jm3si+18K2Yp4+ZjIxIlAviD3EJXSm9Z7MEi83o+zl0cxpMBudKt2Q8nsjnOOX+vPAMjcB0GuzjcfvJ9wm1fl6oqfxl4VubcaLdHekxfkSxyqPaswnesIMHMpqAJXBalKP/cMR6GQXj7KTj3Ku9qb80EBaGPhvYAnW84Kzo= 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=ClOGRdUE; arc=fail smtp.client-ip=52.101.95.105 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="ClOGRdUE" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=FFWQezQU5DkMdW6c7w3VHDpZEfcz4zJCu6Daoiv3Vkmg4fcVz20GGV53xH9eYC2iD4G5yd/ou/iLh2/GtxS3mMtRRpDDQkV+eB8FusGQ8SBMvMwzq5r34Qs9DLbFyRblIUNpZmJontevC9wjhNUUlN60om+JSTe9YK/3pW5LjEnKxpMADcxrSA0Gr7gzWdaw3inPM6JHM+SeTLUSulefnQUifhxATRteATAc1slTI1QaYUeC3uaSLSUlBuV/xshKRaxifJCu8fyybQa7lPY4jbD0oRM0NcsAJEoUrlnAVW0r2WbJm0aQ3Hk3oEaLoDiSPQQlhNAiL9OgHnOM79OHFw== 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=JRSoApiBs3ENHF4NDl1S2MvuWUZ1JJJnqrhhx7x9JNW9qkUhfwij28y310teLGZuZH7ZDVLmumtMI9cJ5uff2SH1zq9vkuVKGEuz0Y78cu7+41j9Th54zs+66uGWin0Qsxb8njfvXv+Mzn+mW4lGO47bhDwJWITbz6vzGZWAieyQekekvAdvOUlvZbKqgBWQkB9vhmA2hRoPqG6IfVv4n0edONELMhVLeJotyBCwxBzO1SlpAvtKIyTaP29F3ovGj8vhhbetr7TTEmLjTQox55z3xCz3zSn6W2YsnUSs5X6mhPwrZpRrPRMoNO35S4kxDO4yyF4z8IbxatfBhfNgYg== 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=ClOGRdUE5Vhv4utGNbMxjSWGYGW9ut5D5HKX4ciCVqNZboYVm+hUKYu8u1ENyYc7Ew+33H17kTgJ3Dof2ty/XJKqD/l+x7w2tmygHTJ7G/Tw5iiBUXUEGVrnJBb5YWUtLe6uSgB95bvgunuOF+t4oApYBwiM4RkxsuJnSnYKPEk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:05 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:05 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:52 +0100 Subject: [PATCH v2 09/16] samples: rust: pci: specify base type for registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-9-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947818; l=939; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=4IYGZYY5yfpiRR/pq59TMlwC0IwSy825+cZG4DHMQFA=; b=w4AsBhVpDXSaEf5w8vJydVaBzWmV9q6jueFMKwjjKDAvq/keAkgyJX087Om0LWnvmKqZkRs24 cjUnd/CCS+LDfFPu3NGj1gQahYQkOQuAyZTUKBlPnXp6YTHTzVj1yZP X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: cbf0b419-80c2-401a-7cf1-08def30fc913 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|6133799003|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: 4vUEl+6O1a2pjklfRkslXkjm4+iHX38iTvUj0Is0OniotLDB0qDuNCpaRwJggarSu/hQ7409aK7YCp1BFW9bn9QQsQKX62R2jo7R//U0t4JCndvS7VnvcDdKZtXhwOKm1Oyqs9vqg6GohknmE+MgPVHleo4VuRWbGGeF+eCpzlOqKcPCq+IcX2Kn7Rpm78Wd42CfPBHiIJyTXg/K8R2HR4LVc51cF4F7/o2DCInZKI7SqhjkUNCI/a+04gEyjiOj6vOaLdtgHxUUY7K8uXLMDjJer6NAv0z9Mn8wRhOrbITJ0J+0FqWp5/1rVCmMWHTOiiuRA49H29H25shApoZLobL4ESuJ6oqTkGPvsZgEOWV13+VdwrVWREDkJ+Wy3J5fG3tQKZCStMOnQWAzElIzxgKJl58XrBrYmfIinuplQ2x3n2zXhrux4xhhdUG+KBFq4XZ3KWbaSRsghd/gJILV0mICnD7USpx+PjeV6hTz0VRBEb4SPM7Y3RsEQ/Q1J1m124+Rhs/s2JalHCKcf4xnvFVRXUSEqehoPFmum0tfKKQKj3nx3JhA2JpS7qeD8R2Mk6TIGnydd0kyG2gm+BVRShVvbzpZkd+n7Zxcb/nCJRGldaX7meulKRQo6Ld4pHgEiqN8vD5gkj1lZtGkY1l2m9cWpouyzJ3UldYa7GdDT55lrlplt1ZOfw4CstQ2oOX4xyeyQ6Qe/bEZI148ajGtpA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(6133799003)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?OGVlRSthL3RSdWNGTStvWTdTNzVEQldhQUpQUjdhR05qemh3cDIxc3pUMWVM?= =?utf-8?B?TWdlZWtQUGFsSWRWVTBHdFY5b25xM1NMNjh2WlorZHRya3JGRlZrY2grcTdU?= =?utf-8?B?VEtOMk5RYURsdjFGWkR0UXV0bm9KZFBlVFgvb3dPSnE3Nnh3VXp0clljSU9p?= =?utf-8?B?aEp3cTYvNk9uL0laZVl5SDRlOU1SZVkxTmxBdlAzcE5CMlNTUU95QWMyeXlE?= =?utf-8?B?Z0NEc0d0Nm5QMy9FOHVGUHl1amN5bDVXSkZ2NFFtWmwwV3hIbjIwb1JuTnU3?= =?utf-8?B?aW85eWZacUxQMkRxNGNKV214aHBGZVc0SXB4NkRNdTBmcnRBcWhiZisvNm9x?= =?utf-8?B?My9KdzA4d3hUQ0tCaXZYUWFEMHkzM05YZGNET3VhM1kzRDlvVVc2cDhxdVVX?= =?utf-8?B?a0lTdGNrL1F1OTh0UTB0OUFWdFNvZlhIbzc4Y2pGTzJqTHFua25IY2lnRnVW?= =?utf-8?B?TFRRWWlwN1ovcjZjUHdiSzN3bFRQMS8vWnB3d1FNdVhPbnRyOXZzdlVqSmZR?= =?utf-8?B?Mm1ncGFDWHJWN3dXTWNHRDhIZUlyQ0w2QzZuZnhPdUJ2cXBIZ3ExOTdkWnZG?= =?utf-8?B?ckx5aVY2NmxTaHBSZ0lib01yM0hrZzdvYzNqN1YxOEd1MHp4M3BySEsxbmtj?= =?utf-8?B?TS83dFdkSTBmWDlyZXVmNGdvc29BMUR3OW5kRlBrZkcwTVBSckd2ZUtiV0hT?= =?utf-8?B?Z3VNM2NIbGlTUzR1c01Jbi9KSlRqWmZIVlhkNjZzV0xoMVdRRWZKTTlkWGJE?= =?utf-8?B?a0Eranp2M2pJUUo3dkkySG9aVjBZUjM5eUcxUWNEUXFCU3ltNGw2R2ZvcEpt?= =?utf-8?B?MTErWk45bFoxVlgxMjluR09sa0ZzYTJqZ2oyWFo3YjRiOGhyZXJiVk52c0Fm?= =?utf-8?B?cFlHYnoyT3JCSXN0b1dLd081L3dvTVNGbDV1VlRZRDdCRnlBRmF2VmM2TUdG?= =?utf-8?B?OEJTOWhUaXhRQXRUeHVGNzVpa01hUzd4NzAzdTAxVEtJaHhzb0wrMEY1SW42?= =?utf-8?B?eDdwSHpTd1k1bkt2MTA4N0FoeTQ0aThkNFI4MHdURjZWZU1GTzlzd3VEMXd0?= =?utf-8?B?ZVFhNCtJVjBaeVJjR2p1UHhTVVlCejdGeXJvTUVRZ2dKR2oySFhRdjROWEFH?= =?utf-8?B?Q0p0Q1F0NnBHY2ZqQVMyaS9lOVQxZFdJVXJvM3drazRjeERDUmUwMXcyY3FF?= =?utf-8?B?VVVXUE1QUDFZNlN1dFZRY1hTY1hKR2NyTW5YamdlQzhTN2FjbHVYY2ZFZmc4?= =?utf-8?B?UVlYSEtLdUNtYzVzNGh4OENveEtYNzlrQmhFWnAyTlNxRy9zdzVjYnZuN2dn?= =?utf-8?B?Q241R1UvZGpRalJ1angwQXU4blowdTZhZnRrQnY3dFp3NEU3bngySTB2SUpm?= =?utf-8?B?M3VFbmRJWUQ3dW0vME9JOHd6eUpUVXhSY1FKNDFZVG1vREZZRDA0SjNSUzVp?= =?utf-8?B?Z21sWlNiUS91bDZDamVtNVdNSXRqUE5KSnV3UURzZGFqanpIWHIrbUxXNTFL?= =?utf-8?B?b1d0ZzJ3cWxqam5BcGlFTFdtVlgvS2RPTkR0VGJZTitFSEhTNmkvSDFHM05O?= =?utf-8?B?RlRBWURBRFNEWjYvenpiclIrL3VIWnlVcHpIZ3RDNGxJY3RVWS9aemp4bHM1?= =?utf-8?B?cEprSzMxWTRLbC90WEtuTEN2d3hMQmFpb2ZHaldGRWtZb0dqbFFBM1YzSldN?= =?utf-8?B?elR1d01lZkJ0MnRsS3VKcUxjTXhUbW5XaGNBK1lPaytXa3g0aGp0NkVMMEJ6?= =?utf-8?B?YXRPaFNka0p0ZG1WL2Nia1F1d1lIcUlqdFFFL3Q2QmJ0ODBCMHpwK012aGUy?= =?utf-8?B?K1djKzRpLzZPWUIvTVJsaWVMZm9Sa2puRXpsaFRjbUR1Wk5JYzUya2pKK3dS?= =?utf-8?B?ei9RK1ovaTMyWUJvQ1c3UWIxMTVFSjZUS1VrVHg2TGRnbWxySmpSV2tXczZC?= =?utf-8?B?aGVRb1oyd1FRaXpxSElRam9LdmdxOTEzYlg5UDgwdFFRcXBNQXFZWHhZcmFt?= =?utf-8?B?Mjd0aHBaMEg4QU4xV200eEhNYmxNejM0WlpUdnBRYUNHTUpMbDhtL2FCVnNE?= =?utf-8?B?MEdMWkhxRmIvREkzSW5CNEYzQW9lSXh6WSsrR3RwOEZYOWdUWWZHdHZ5clpi?= =?utf-8?B?eEIrcEdKaW1HSkZBTmtuemFjb3g1Y1FoZ1lGb0lBbFZUSDlib2R5MytOaTBP?= =?utf-8?B?YnZGbVpGWlFxOUpFSWEvdmNHenV2aU9hWlc0b0JIbVJ0cDh4REZORXpSQ3VJ?= =?utf-8?B?dEQ0OVBPVU1hQ0lxVnRtZFdWdEo5V284UlhnWVJuTW1KUllKQmU2QnRFVTQx?= =?utf-8?B?UmtUNmJqTWl5M0VhRjloNXFvNkNIMlY3MzNKWFNtYnpQanNkT05hdz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: cbf0b419-80c2-401a-7cf1-08def30fc913 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:05.7980 (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: H4xAlMsdajqUE8Dt/L/GSrclP14AciOfIr99Vy2ph9O2PfFhnu3KomoA9UhX89VcerjPGzHWKlen+COxjdZgIg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 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 --- 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 Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021089.outbound.protection.outlook.com [52.101.100.89]) (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 81B47485519; Wed, 5 Aug 2026 16:37:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.89 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947849; cv=fail; b=hEpfn5QK56Tv9OUH2nrOR4k33i+BxYKlfDmY/iScR1iSs+Rx0XqeLwPlxaHeUPJlkFskIeML4Yv/h/yrNLjepCQECzLD7Eweg2tx6WnkjuHng/CpHYNtjWZOl64YZLj/V55JI7gLtMHpeonQUE5glCjF41KHfmkAf0yv50QJf50= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947849; c=relaxed/simple; bh=9J7e7O/qAj2mua8poz9QndiT59xYtbe1AANZj4vu3YI=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=bpwtPmNPa1pT8Lk22k9uMcal1MlWz92mDtdMw49JNtfdJ1en/lkeWaszfbWuae17pETi/iLLlUg7TkCZoNrKvf51hePQVG7w8rhmLXwK91aBbqH0vPT+eJPgYMDjuaQX1ivUZ7xeCUtF0slWPUTzgVuhWh9sDWBkOmnkMzV707Y= 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=ES1c+BCs; arc=fail smtp.client-ip=52.101.100.89 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="ES1c+BCs" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=XI3cfM9Y/G5t7+yCZFoxKAg8iSwUlbn5So0ydmnd1YgomrhjqeUI9XbbEEmh561CiPtjAOj2vQf1H1/LUXJkdU7SqUiO1vuocQ0VAO6Ka/xHEfJp9flpKSl3Sh06ZOSSaBKj1xTALmCDpObTYABGKpPncxAoctfG5I62vQ1M5LJZTGBw2+nnf8RHgKss7UPyuEBFlTscKAhlJd1G+5K1TvOy3OXnTTItd5WC7aSXS9+pe4GWSiIrS8cPuaGzZbX5DPgrpKoy/nJ16BqtEDRGNqh0Ms83lHJGswWhIo3zFIahXdOVByC9yIWUcREVVMdjaVueBPL5rcdtOjjZuFMg2w== 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=Nux8+EyDETbEJDHjTqpkS2LEoYY5YRUMdwH0rR32Y+k=; b=fKjcx2/JnTvu4DQquAQRyurimVmcjQ52BHr7Q2cq2arg7wcT9qRWxyq8/+OGV0kTmU8w3HnFBwZKXE6A8sOKMTQKDyJrjQ/esdkHToXVpEXijSA315k5rWz18CtrLivhhkmQE2W1Qrp32rbRuCWP+QX1m5ozFWLTdR79kf3pfG5QGM2HFIslVOtgonCbSCvHAWIntL/F7yDXHkrR2PCNY+4ahoL1zIcgiyI7PmgXJJfUq+OUNe1T1Q1N/GEOTcl2ffCKjOq1LhbOzYXScDEqRWWM+2aVpETwCpfA8xXvIrNVTpOcJx871Gm9GS2pkgkSkwk0xEv5C2o6eGKURVV0wA== 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=Nux8+EyDETbEJDHjTqpkS2LEoYY5YRUMdwH0rR32Y+k=; b=ES1c+BCsRJoYE1xpYTAtsYq4d5+bdvDftBqambIc8NGWFkqiUa9CR7nAYHVF5la/P78CZQ8057pZ1C9E0pnc3FIIGRwUCrmY7auYb7bgtoHrCW+nc2MNjbZD1muFb1MqJIAgzfT+2dZDOlZ9RhckGb4ewivRB/UX7herUzvIcc0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:06 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:06 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:53 +0100 Subject: [PATCH v2 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: <20260805-typed_register-v2-10-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=9199; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=9J7e7O/qAj2mua8poz9QndiT59xYtbe1AANZj4vu3YI=; b=scaXWrN6oyCt/LjisFokqrFLeMQIBqNbmbPKyco7PEakIrJd7V4a9ol/mprTRtMmOf11jaZv2 ynTDK5UFfxpBm5dC7PxGGJ7uaJqjT7A6Hv2XHmsosaR7zh7AlZ/ckfw X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: c1b7a295-bd94-411e-69aa-08def30fc973 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: eF3Yf7a/HrXb1xcasfy3rFRsRDw8bGKSyAb2SADct+NOC1QC7k11eyJu8jY7rQSfToRWFjJiPH5aYVJhbg8Mb7VGxgrvIdYhzb5FSCSkC2m0F3NRZRsFvIIoLmv2Y2gu8WegUnJw65BUVyXB+nObOD5dUr60aIxNLupqFnFS8g8aVvzojFKMyuAlSUlpU+W8+BNpgr5oO0mBSUm+RIUuwKPSOnuVBV311L7RMnDvLbXojXEAOL6RT58sL5dDw/Fwxod1yjdSn63ok4y2xwrhVUEZwv/Lw5x33CJchx+VtE4JiKOQZCyKkzsYsrq+Ikq+sd7RWuOzkMJKlhMzfuz1ltpXkmK033b/M0HE3lLuM/OLrQzI9Kmkx1qcx6Sj26wDBmV8PpwyUXDfnUOwmBMLQFYPv7w4POA7lpI/0ABLuUtSnONeEtU/mAz/kdagg4NTYLvGPcbovvKY9g/5fzGoD1U+rwV1T5nyOIOc0NYx/LrDagQlX0/cwwOtxUv9PmYFknEtyB4k9e2WfcvplTNgLV9hwH5hIGLSw9CvEML1rLsdvBjN1ar0UY7RtENKOaH+xV7wOmTc826C/9fyIrYZbWeUCp2mAHMyCC2ZzaqR/2Msh2hWY7oeBo4FxbjFgobwJXGHbL45V3kOujneJLB7pbWfytH45ePy2StYZv9MYtlD94cYeWSLJWrQfXp0g08tvRR4l+/dPQVVfaEKYyYlfw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?NTBMcldzWFljQjlXNXlMbEpiOGtHNUFqNzBqUEVnTk84M0pWR0tvZ3p1M2E2?= =?utf-8?B?cFllalFXS3B0UngyQy9yeGpKczVnY1pGSDk3bkttWVdQU256SHp6RGJoR0E2?= =?utf-8?B?UHExdlhDazJ2TUZXRWIzNnkxMVBoQkxKVTF3S2NUMEV3ZFNNZmJhVTU0U0t3?= =?utf-8?B?WEVzM3NoaWpmK0JaSG1pTVNWRkxxOHNJRWJ6ME16dVAydUZVTmE0UUI3ZWpJ?= =?utf-8?B?NjQ3TEdCRHNhSmpxckFFU09iOXVIT21nTHh4WThTS3F3cStTODRYdWgrUTRa?= =?utf-8?B?Wjh6VlpDVTRxNUF0UGVyVFRpZGZDb0FSU3R4ZEtSUVFDUzVzK0NkcjdLakRh?= =?utf-8?B?aXJsdXVkK3J3cXJXV0M0Skx0K2k3TGJiYmdpaUtTL3U1WHpRS3ZTd1FtRHZs?= =?utf-8?B?SER5U3RmUXhYcnkzWTBkVnZkaVdZUW16Wjh0VnMrOE82blpXa3p0NWxoRmgy?= =?utf-8?B?eFBzd3hkNm9DbDdnQjl4Tk5uNVFYcXdEQ3FMLytMRG9La04vK0l1cmI2S240?= =?utf-8?B?cXBoTzVVYzR1OEY2WnRFbUhTdk5YOWVJSjF1Q29qKzVwd0MyNUFwWXkyL0hy?= =?utf-8?B?TXByZnpxbVpiUEJqVFlWQzBjOG53S2wxcWpOSWlhc0p6d0ZTanNtQ0wyRXg3?= =?utf-8?B?QzBZdS9tdGdsbFRXK3V0cmJWR1hKcWt4M3htVFNpc0w0cjJ3NmhLQnhtbUhG?= =?utf-8?B?cnhrbzVONy9RQkVDU2tpc2NCOE0zWWFsNjZBZ3d6SG5iWTJYM29jMGxQR1B6?= =?utf-8?B?UkRjK0NPU28zNnVvY3lHQUkrZ3RqQ2ZhbFozRnlicHRvOWo1ZFpyN01YWElZ?= =?utf-8?B?eHlmTDE5SXk2UDV2cEhLNEtFV0YxTmRpbm1CeE9SYTNSWW90cGtwUnZYWDIz?= =?utf-8?B?cGlzbEdPbDFhNnB0dE15OXhIYjVuTGZoMGFJSnh1bWJ6eU5JdTJpbGxhb3Jl?= =?utf-8?B?QnBRbVZTdVV6NHlhTmJ2dVlMMUl4TUtnV29OQTVZZzRQK2V3Rm1GNXRKamQ5?= =?utf-8?B?Z3h0QjZrUXIrb1RhY2RvVkhTa21GSEc3STlHL0FmSURVbmFYejlWQk9pL010?= =?utf-8?B?c2dFRGJadGhER21lWHo3WFM1bldNZ1ZLeUJrWko1VFpKb0xQbjg2ZXBrOHIy?= =?utf-8?B?eW5FaEYxYkp6a21rNTdLQ2o4NUFnSWVUQzI4dkx0TTVmUjZIS2V2RDJXdENr?= =?utf-8?B?T0VpbThaT05qaGd0U0x3WCtpWUJKSkNHYnRhSU4wSkYwT0I2Mks4Tk53Qm9a?= =?utf-8?B?bXhCVWtndU1HK0dzZ1FZSkd5WmtJQnFWY0NYWDBvUk5LakFHY2lpWE8rTWJ0?= =?utf-8?B?aGU4MjQzTkpWYitLM2RybndxVHJpV3JiYnhZdlBCZGlnMktZTDdhWlFrbjZV?= =?utf-8?B?cGQxdjNMUmhsaWdXT1dWNWhwT09mVFd5YjVPdEw0dFh0d2V1ZXNLZElOTmFm?= =?utf-8?B?dDBXQWJTeUlqOTU3MXEyWVpzemxUK1pQVmxnbVRraFRmTHhTdW9TSHJ3Q3BN?= =?utf-8?B?OE9YRThXeG5kRTVrN2tNN3FIQmlLcHpaUUpkQ1RDcE9tTkdncFBhSTR6d25a?= =?utf-8?B?SXh0NFoxVThscVFYWFQ5dnNDb09HM0lWa2xrZ3NhNG9wSzVSeXhDN2d5SnJT?= =?utf-8?B?WVg2dytWZzgxWWZVdkVLdDErR1k5dnd3ZGJCMXJCNEFLU2RJYUJYZ3lYa3pq?= =?utf-8?B?ME5uak9uZ2xHODY0NHMxQ0wyNXJLaVdyRkh0dnA3cDJBOURMcjJxbHpRMHZG?= =?utf-8?B?QTZhSGxVc0d2NnhoRjdhR3Y5SWZYeGpBeVdhOUhGUy9uWmgySmN0UDJYbk9t?= =?utf-8?B?SFBCY1lmcHZvTThKRHZmbHRaeHJEckVtMHRmaXF1M3pnaWdia25YTkF3c2x2?= =?utf-8?B?MXV1bTBHV2dzYjUrcHFGcHFXemZWclB0YjFZNUZFRTdZRkNvYU0yU1pFdzRQ?= =?utf-8?B?YzF5MHBTUC9WSTM0OS82MWRUd0d0WE11cUNDUXBkVk9IMms2SjIwSWJLeE8z?= =?utf-8?B?blFoekxyd1cxUUNQY2FRYTNjZWl5VVpBUDhZU0J5M05FdnFlVWlvalhzUWdj?= =?utf-8?B?eWsrU3NoSWxUaFltL1dNdy82SjUrcDN6L2dGVjFVaGliYmlVdGtjajlZc3Rq?= =?utf-8?B?c1NBSWVySHJxWlFJMGZ3Zi9DUWhRTjByWFVaSnVLZFhLb2VrNlJJdmtNK1JL?= =?utf-8?B?OTRQVmNqckJoZTY1dEZ5UkFoejlmdWt4WHp1aDRVdm1zQm9zUmFhdFRaSDB5?= =?utf-8?B?ZHBkNkNaZE1IeUlaZEJJMTNZaWk5UmhRbmdMWVRvdS9pY2dxNUVMSWhSeG1V?= =?utf-8?B?WisyemMwK24xVHZ2bzkvdVNUeTVlRHRGYlU1UGI1Z2VEb3NBUjZnUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: c1b7a295-bd94-411e-69aa-08def30fc973 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:06.3992 (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: 4pqlLlO3msJaGohl3Tbd/NWbWsvXfkZSkh2KPvDhoGcuHbaWQC0DVi/IyEbrp3GcRIWsyogai2MTt6RsH4ZFdg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 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 | 64 +++++++++++++++++++-----------------------= ---- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index d92e0b6adc99..d56c8faa7d7c 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -1798,21 +1798,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 7dca2437b551..dc800fc71172 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; @@ -823,12 +824,7 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// ``` #[macro_export] macro_rules! register { - (base: $reg_base:ty;) =3D> { - const _: () =3D { - #[allow(unused)] - type Base =3D $reg_base; - }; - }; + (base: $reg_base:ty;) =3D> {}; =20 // Creates a register at a fixed offset of the MMIO space. // @@ -843,7 +839,7 @@ macro_rules! register { $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name + $crate::register!(@io_base $reg_base; $name @ $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$al= ias_idx])?)?) ); $crate::register!(@io_fixed $(#[$attr])* $vis $name); @@ -858,7 +854,7 @@ macro_rules! register { $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name @ $offset); + $crate::register!(@io_base $reg_base; $name @ $offset); $crate::register!(@io_relative $vis $name @ $base); $crate::register!(base: $reg_base; $($rest)*); }; @@ -871,7 +867,7 @@ macro_rules! register { $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name @ $crate::register!(@offset =3D> = $alias)); + $crate::register!(@io_base $reg_base; $name @ $crate::register!(@o= ffset =3D> $alias)); $crate::register!(@io_relative $vis $name @ $base); $crate::register!(base: $reg_base; $($rest)*); }; @@ -884,7 +880,7 @@ macro_rules! register { $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name @ $offset); + $crate::register!(@io_base $reg_base; $name @ $offset); $crate::register!(@io_array $vis $name [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] ); @@ -900,7 +896,7 @@ macro_rules! register { $($rest:tt)* ) =3D> { $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name @ $offset); + $crate::register!(@io_base $reg_base; $name @ $offset); $crate::register!(@io_relative_array $vis $name [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] @ $base + $offset ); @@ -920,7 +916,7 @@ macro_rules! register { ); =20 $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $name @ $crate::register!(@offset =3D> = $alias [$idx])); + $crate::register!(@io_base $reg_base; $name @ $crate::register!(@o= ffset =3D> $alias [$idx])); $crate::register!(@io_relative $vis $name @ $base); $crate::register!(base: $reg_base; $($rest)*); }; @@ -960,8 +956,10 @@ macro_rules! register { (@stride $ty: ty) =3D> { ::core::mem::size_of::<$ty>() }; =20 // Implementations shared by all registers types. - (@io_base $name:ident @ $offset:expr) =3D> { + (@io_base $reg_base:ty; $name:ident @ $offset:expr) =3D> { impl $crate::io::register::Register for $name { + type Base =3D $reg_base; + const OFFSET: usize =3D $offset; } }; @@ -1010,12 +1008,4 @@ impl $crate::io::register::RegisterArray for $name { =20 impl $crate::io::register::RelativeRegisterArray for $name {} }; - - // Compatibility rule when base is not specified. - ($($rest:tt)*) =3D> { - $crate::register!( - base: $crate::io::Region; - $($rest)* - ); - } } --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from CWXP265CU009.outbound.protection.outlook.com (mail-ukwestazon11021089.outbound.protection.outlook.com [52.101.100.89]) (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 6263E48D890; Wed, 5 Aug 2026 16:37:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.100.89 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947853; cv=fail; b=nzZ2q2OYsFsTczdvzFb0QD65DIM7skDBgEt06zIHUbwHyt0NjfRskyIcgaht0ajAvvbWORwL4jzUxA2dsdcqS2hqBwet6NugcWV2IKGGOKuvuHgJsf7y+1MncZaEZTlws71icOoptKvyKUu9MTIC0j1skxvItuG8NuiR+SHldcA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947853; c=relaxed/simple; bh=Mk3q2f5pRvd0nCg7W6kAzx7EEYWOQcCsfWANveUMhXk=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=iLx2jfMn9UcMUznX11xH5r4RlSYlv+GcfBK+CTWB75xuq6P38RkbQYYWrjT4JWCjGaX1i2KR7aJZ7dRP6u9OOXhvUd2vPr7CsYJIO6RPpRoemeJ/alUHbqNG5P4xujD0psZhSLDrPnzER1urNaOcGjIdSHRCp5AF0vqXxG1c4yY= 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=Jukh3iAL; arc=fail smtp.client-ip=52.101.100.89 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="Jukh3iAL" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=twrak0/rqlASzdm63+v4IbcDjCk7JYr7BILrxOK7gkCRrXAWBWJB86yoef7YoEtbte2oA7obkUXKvLjY3NGbb/0hKEj8HKyCMN3Xst7D8DU3dxC8SQFkBpNnVJ1JB5jIeOTl0YOjFdYko6H3VRt8398apcOHdov9hPTZYUzXOA/2Trhtovvui3eVZboS08KAU0i/ZStvTev+1upmxw3eUnPM4cZ634WGcmMLbeuCVtK+GOJJnLj70q/IF639WWqZbSY6x2gyl7dSKFNnNkVdspjNk2E0yVzqeE/3DjpNn5914aFXHXneQ++O75Elld3OJ2BXlgJToq7Bc3x4onjlxw== 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=WZ1+xWdbI8qs26+1rjXes6seWKT/d3LmyIR+KZonVhM=; b=DFnSQhUClJW0UO+mg3HniUMqN/ACtKZvn0eG9YRqPW3Qhq5R/amEgCFMF6UegP5UUgobEBlgyCrl1ygh8iRoiNqGBCgHLwaxNb+RW8UuBWAjgQkjP+c09zv5HZfI6suQqA3JUyQnZMsLI+LGwRMHHV0/mFbC2iQnYRag2vxnL+BsEsZyhl+t/htwAItYfy/I53NeFfGzDA0qV8E5wrU0aT0HZtqu38Q0q5AN1x7Odv1Ma8ni/MJhHVAlhaRuD8G9+FIcCoQfN6SncUIYn1NW6J0JOvst/6jMsSXj2DMF2v1IZecTOXtBrI2oYfVRCGR37nBfdXBFY72EcMg+aI+riA== 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=WZ1+xWdbI8qs26+1rjXes6seWKT/d3LmyIR+KZonVhM=; b=Jukh3iALmvb6jwXsZMDHTUYfLtWVBuEYpSlpL3Z3yuWogmwQ22+/BOQQYmXG8eBeE0kOGYK5bCZdjVz8AUP1EotKyifxAkmPD3mOrDgKFhBD8R7hOO9yFGPyTC4mTG+OlrMkkaFxPH9UQgnCrQmhpYTfV1e1UKxQPrHmDGcMHlk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by LO2P265MB5822.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:26c::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:07 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:07 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:54 +0100 Subject: [PATCH v2 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: <20260805-typed_register-v2-11-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=3000; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=Mk3q2f5pRvd0nCg7W6kAzx7EEYWOQcCsfWANveUMhXk=; b=5P+em+g+ToV/Rt1UvTKk9A/GkTosuBGOitiBcN/k8ITaaz6e1/la/TTmqzrq1z60RPSsptgr0 Nv47JJFlbOLAF5+f5x7/VgVF94m8hjq4oGwMqlEnRSdUUiX89ZpZK3A X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|LO2P265MB5822:EE_ X-MS-Office365-Filtering-Correlation-Id: 53742004-aea0-4da1-c7a7-08def30fc9cb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|7416014|1800799024|376014|23010399003|366016|3023799007|22082099003|18002099003|5023799004|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: Nz5a0FyX2MBzjXOzyfgMWcV4BLvZRnnuFZjusKiS3rJjiAVz74fv79dAcHo7I3wXsjMyINANqfq/e77wXnggyUd1sw7LzImGPfXCrmKcDPKs1uI8dL/Yv9WN6se3v40k3DlgFi3stmDEOw03a2LC+rKxxfH1tOzClzWuFqzjdW8cMjAFnXWhIW7ja1IJD/adEEwwZztt5JOb6x476RrxTqR33qZbzosZW+RFxnAnQtgdtkZjAWgWEeXbrdbpL3jG/orgxpDsdpQLXNL/v4DstowglzFlKZYfNOhKMumODmVH3Mf3j7FIHB/9s2FPet6NvR+6PWFhKDJGxZ5BknJ4vbDUtHOxwuGTwYehZ17FsWMyBO+AsLJGrNtdQgIL4eNSw+HrjD+ysNxtGHufotifsqK+4kOn1zsU6vF0sx5kJqzIpx3X+gIhRP+51BJnMP+spqwMt8LE8WU3ajXT+rM7EUmNmWWnmMmo18gyWgP6aMy3SlF3ztsOuFeWS1IBMTsMxGFFXLmqaEb6tczb4btuRMaSGLd8hejTp2hkW4sVGIPpA6oRcLeB7HYVGc40jeL/WrzaH3y65ax/fA0OnlOtOU3UFhMBvdpAjpLP+J5Hw9h9M5saghOE5p0aG2qMsWViJXjFgHXz07HpdcCwsA7M2RE9HKbio0x0GXrO3fCkFjcwPrQ+V2tgB4jHsNM/YMZC5hTDB+OZKtNRWMOkfT6wdg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(7416014)(1800799024)(376014)(23010399003)(366016)(3023799007)(22082099003)(18002099003)(5023799004)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?b0IyZnoydzIyTnQvbDZPMENmbUNueHNJRk9TbFRMWHdLTUM2ZEFPaXptd3FF?= =?utf-8?B?aHhkM0FxWEZrbldjZlhqNVBRVitTYXc1eXhhRXVaUEduemxuSVo0Z2ZpQ3lV?= =?utf-8?B?RWJKUFpyYlh0QzRrMlU0elFtaVdmUEJQM2pSMmJacUJNcTN6aXc4cXpTVFly?= =?utf-8?B?ZHI1ZmtKZmRObCtkK3d2UkhCL0hmU2c0cVlGbkNPb2d2bTdNOTBDdlhZNWc0?= =?utf-8?B?VzRWaUVNZTlPWGZVdWtCendpOXIzK3cyR0h4T1lWL2g1TEFhN0U4cHIwczVW?= =?utf-8?B?YUNFYmQ1ZGM0eGlIQWw0SUR2Zm0yRTI1SXZBb2s1elVncFBWWXNiQ2kzTDE0?= =?utf-8?B?aGdSUUs5YTB3bW9USVdQU0JJSG85RnRTY1pJd21zNFNvMVN5MXhnQXh5UzEw?= =?utf-8?B?dTIreUxkaXQxaGVjVFJYZUIzQ05WRS91S3ZKQUQzeEJXUW0rMnBocTArZE8y?= =?utf-8?B?SGlTK1BZZFkxVGxwMEVqV0FEREdQQmx2Wi9OUG81c3FGK0NTTHU2Z1c0MkNv?= =?utf-8?B?M0M0cEhqR3ppOUhueGhPY3Qrbk5TbkFzVEIxcEZrNU5neWZHVjlLaWU4MXBQ?= =?utf-8?B?aWtaZjJNT253U3ZuTWxBMlpGQlpEamltcW9HQkNVM1JzMzMvSlQvTzU1OVNS?= =?utf-8?B?cUUzdjU2a0dtN2JBZksxUC9sZC9lN3NlNmZ4T1pNUWVkTGFTRXdFeEZxeHZl?= =?utf-8?B?VHZVNHRiREE3ZzNndncvZmcvK3ZNcEV2ZCtqV0MxeFI4anozTERVRTNxTk1t?= =?utf-8?B?cGFBZ3ovSUtlSW53K2xsbVpleXdWdThaejF5OHptTGJRNU9Xb0s3bU5Dc1I5?= =?utf-8?B?enRJQVdNZlc1Zk1SV09CRXJEaFV4aVNUWFdmVnpDSFo0blRYVnNSSU55THJK?= =?utf-8?B?R2V5MTU1ZjQ3TFArQ3BLdnplb2ZaRXF6Ymw5ZkI3d1ovTE1CbFJReC9pOG5F?= =?utf-8?B?NkZnak42V1JnSFlDNUpYUVJ2Q3lqVWlGVFpIVk1pSU0xbk5acDFPb25ZbWFz?= =?utf-8?B?VktsSldOSW9SRVQxeEtSVjBsMUtiTVpWd3YrN3JvWlBwdWJCSVk3eThUbVFp?= =?utf-8?B?MEU1YkZjcit5YkxBcTFzeVN1eDUzK3hmOWlQWXhuMDltd2dRNUw3QWN5b3V2?= =?utf-8?B?SUlJOUxCWE5VcElDMk5mZWd6WjgzSmdnRkR3dzh1c0FUVkdFY2FhVGFpMnY1?= =?utf-8?B?Y3NkOW95cWRLemdKQzNRKzlaS1JOVjBFN3E0eXZ3TldEN1N1dEUvNjJ0S3lK?= =?utf-8?B?dkFRK1hBUXQzTW9vbS9XaW91YUppY3UvWmdvZlh2cjJqT3d0VlpHeHhNZiti?= =?utf-8?B?K2NkWHZzT0JJejh4LzNSRDdNMUNVM1NGM0pSQnV5Y0cySDc4eVYxMjlJUkpo?= =?utf-8?B?ZkpxVTh0VG5oaGxaeVQrSHFTVHpGYnkyQTV0Y0pPQWVKWDdpVVpXY3FlemNO?= =?utf-8?B?UENUWHhNTThGaFdtT1NDdFk1YWEvek5RVEMrVk4yVy91WEdLR1FOa3lCZWNw?= =?utf-8?B?eDc3RFU3V2pPRDhlNmExZVVCRHE5MlMxVjZRTjQyaTFUcFJOSXR5TkxyMlJ3?= =?utf-8?B?S2ZVUFZxWGd3RU90Mk83SVVMTFVNQjM5MVZ2Mk5qbGcrTlp6V3FmQUViS3VL?= =?utf-8?B?eDB4SGh3dEEvK21HZ3g3UFhCVXpsTlY1TEhPVElVNDNKeDFyaGR3Rk1OYTVk?= =?utf-8?B?K2FGcDEzK2FvbTE3Yk04SGdQWlh4YTV2YW1OUG5FbmI3bk9FeGhNRTlYSHE1?= =?utf-8?B?dStWakYxeUQ1NnRrOUFHV3R4WHoyOEU1MkVwTGdHd1FQeUl3ZHA4Wk5XcDFH?= =?utf-8?B?ZmRvMm5mSDBITlRvNVZ3WUloYURIQzZXamRUejRwblJPOE9EeXZoTy9MNmFG?= =?utf-8?B?UzNWR0FtcWlrNmFNQXhWWmJRWnU3WnhMNzcvWjNnUGl5UGVKN2Z0Wmp5YnV3?= =?utf-8?B?V0s4YjcrMWxoejdMTWVFQ3BjMmJmeWpEUDMvVjEwTEJ0TzJ1Uk1VT1pVRHV1?= =?utf-8?B?WHNYL1p3NEV3N1lMM0x4aUt3Q0YvQStQTEtVRU1uMnJpcGRLb2lVQ1JvblRD?= =?utf-8?B?RHNHRUQrRXdzK0Q3WWk5M3VUUnRzYmg5NGRqRHRYNllkQ1Jsb1BWTytxaWhD?= =?utf-8?B?OFJuR2VqNS9Va2xNZ2tBdGE0Rnd5ZVVEQVQwQWdITkFqWk5OSFYrdFF0OUJH?= =?utf-8?B?M0piaFU3bzluK2M5Q0gwbTdpUzdtTTR2NGRkMGdOcHQ4WE5XZ05zdEF4aWdC?= =?utf-8?B?RURzL1hocVkxazNVK3VreXVPeDF6RjZadnEybHNmRTdCREVRa1c5Z0tML2o4?= =?utf-8?B?NjhvKzdRWkRYSFBKRVB3WHE1SURQYlkxR2VHWU9BWVFhSlBNS3RjZz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 53742004-aea0-4da1-c7a7-08def30fc9cb X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:06.9777 (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: 0+VB7NpolkSBt+6pF5aQrX76h29gkmpfZJeJSTtJnPj2vJAwhUWH8KYJYk9M4WxxgYW6kFNiRJtCZLdtK4dxLQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: LO2P265MB5822 Add a rule to allow creating `IoLoc` in `regiser!()` 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 --- rust/kernel/io/register.rs | 47 ++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 47 insertions(+) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index dc800fc71172..49a61da106c7 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. /// @@ -499,6 +516,19 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// In this example, `SCRATCH_BOOT_STATUS` uses the same I/O address as `S= CRATCH`, while providing /// its own `completed` field. /// +/// If you do not wish to have a bitfield defined, you can also create a r= egister using an existing +/// type. +/// +/// ```no_run +/// # use kernel::io::*; +/// register! { +/// base: Region<0x1000>; +/// +/// /// TX FIFO register. +/// pub TX_FIFO: u32 @ 0x00001000; +/// } +/// ``` +/// /// ## Relative registers /// /// Relative registers can be instantiated several times at a relative off= set of a group of bases. @@ -826,6 +856,23 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { macro_rules! register { (base: $reg_base:ty;) =3D> {}; =20 + // Creates a register at a fixed offset of the MMIO space with provide= d type. + ( + base: $reg_base:ty; + // `$ty` cannot be `:ty` due to follow-set restrictions. + $(#[$attr:meta])* $vis:vis $name:ident: $ty: ident $(:: $path_frag= :ident)* + $(@ $offset:literal)? + $(=3D> $alias:path $([$alias_idx:expr])? )?; + $($rest:tt)* + ) =3D> { + $(#[$attr])* $vis + const $name: $crate::io::register::OffsetLoc<$reg_base, $ty $(:: $= path_frag)*> =3D + $crate::io::register::OffsetLoc::new( + $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$= alias_idx])?)?) + ); + $crate::register!(base: $reg_base; $($rest)*); + }; + // Creates a register at a fixed offset of the MMIO space. // // This handles all of the fixed offset `@ offset`, alias of register = `=3D> alias` and alias of --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021101.outbound.protection.outlook.com [52.101.95.101]) (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 10A073F23A6; Wed, 5 Aug 2026 16:37:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.101 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947842; cv=fail; b=ViCSOEkxFMFFMdTXmVKeJS20deMWI+vH/M4RkzikXKgl7udwuhllJiSCxL0FepVVimHFjOYxAIbTjM3m/dQBpPUnalomnWa9goZb9FSK6fwcB6zpWK131rnr/tvQ3EW/udp2MHoHSe1Jpa7CpbbENTxrw8ivBS7eLLXZKO72uTk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947842; c=relaxed/simple; bh=J7T0h1H5JiBlAO98luxgcDArI0ekO0PDo9MEHKowcpo=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=m/RL+l3KN+CQOw4hku0UQBSFtASrc9vFOV8FoCuKPcQsZQAsNzywUWI9zWGzR34bGJ3sBrAdg+pRqZ47Kr0indDBFjBARf4c92fEAlYgzoOKVo5VWG8zoON4jc8xItM9GqJ94H4hZY7VJ2B0XeBq/vYTQ9vR1nQM2Fu6pNNgUc0= 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=YwQAogS1; arc=fail smtp.client-ip=52.101.95.101 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="YwQAogS1" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=PwnAy1XQkO0nn+jBob6w+ua9d+Y7h6FXHBRMJhfRTu9JFW11MRFCg6nbsGBArkNnvzJAIm1+CWMax8mtuOnhz5L/HjLAtHfS+kDUyIjPByLR5uBngmxxgsJbLJ70f6IOMFlDhupsqyZvZ6A9I9FSSoZGvAlYdBRRlZBSbmWKVOfFr/vznyDxi2Tptq4a4W9CafB3M4AOdMza11OwaZ5+b/o5d2pMP7sMNvWIWN7ooKWIxK3KuCVx3yqaa26WHokZyNGW0KnN0D5162a90NxhQbTbL2pZmBn9WnkypjfMaFfRsp8DqdvODWfNaa8J0kNaMIFgV1YkcTBY90IOFFfaYA== 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=siKhFg/e4GporWH1i2gXjVNpEbe2iSlWPEbJONPkryk=; b=hT6D8NogCBUlELjslwcbhH54S/s1f5Vmf7yE9kfK8yN8wNs5rUn9Fs9QuYTTadHzssVkVIDHG6Ey9Wv5mwgeCkj89kKGoKIMibVA2B2vuEUMkUXlHNNGHjjGTzr/7rmSRSFqBXMIcY/GYI7uOm5KPDjDq/kJfNsNEDHygjlyGjsDQsTUscnGPCHwlWhoPh05wJIN59OFZWsO44FhYjWfs39rfQN1JX2mqxPP8NA+6s4OKz6Q2ClCANSQhs6+deAAM0OtajW7fhvT2XT0kWSli79YSjhcej3AIL6e3q3EOsGvR0qBXSn9LbFgMTdIHT3VBKcWvqidJebC+GjY/yf9VA== 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=siKhFg/e4GporWH1i2gXjVNpEbe2iSlWPEbJONPkryk=; b=YwQAogS12yFDa2syyuzrPBuWueMrDcgM8sHqBIkaOiBfFTzoJ1adnpSi2RLghpC8OFxMkkZd6qemgKhsLbfuSHH+axLlTmxzOyh7QQxyM+jgdGZUjUWkUgzDQ3hWAH01O1gWaqfGmLVQvG/3utGc7mv+o/NGNghKu+UilGKgabs= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by CWLP265MB3412.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:ea::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:07 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:07 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:55 +0100 Subject: [PATCH v2 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: <20260805-typed_register-v2-12-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=44542; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=J7T0h1H5JiBlAO98luxgcDArI0ekO0PDo9MEHKowcpo=; b=DrWNiRIuEPLxmpeGu0wvP9j4O6UVy2ejT/jZZ4s5icfxe37DJCZq/cCyhFaen7Z5NORpkEz5n 9NyixVGiPHDD4YNe1mjWTzzo0Pz/fWwnYULlsb7D0D2AFjihE66xEn0 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|CWLP265MB3412:EE_ X-MS-Office365-Filtering-Correlation-Id: 77681894-384d-455b-d5bc-08def30fca2b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|10070799003|1800799024|7416014|23010399003|376014|22082099003|18002099003|56012099006|3023799007|6133799003|10067099003|921020; X-Microsoft-Antispam-Message-Info: KFmRVV8WOR7S+IawVWm+z78Dd1cV0LzUmKZS3Ym+Lair2PYKc5vjfKSSXkcR7D3mGR5N6eTTWt9C+Mp2iijMYuTRK0hIDWq/bNrhs9XULT9Ci+TZkqazHz1lO7tiK/mv3OzWHwcJKWVmf2NtGu9M+pwDg+zR6EDof6pSRk9ZsBOVpvaP0HWpu+vlfoeCll/SYUMUsBsXl04KD/Ub0WxvItZbuyzBnA1B9km+9+Se2fm6+Dix8xElIOBYf4sRANa/EbirxFCYohIEhEyV5Q6I1/xXTckU2AgUJWXyfVg8IAPc4N3/PiqG8YwYaN6D0K7fkOz34l/DKv7IsloUhKZOXswXnoAeVrru7uZXVmzsSL6Er6IkIai2TmNB4QvwlWx+IPkXf1VJIwP/Juy5xbHNH6PEQ0K5aPNGAMSeOByrD1lHf+NWD2B9yq7JDPQdMIKy2qGtPqrP0XqCabGVldh5CwmSrwU1bZ4CfePkwuvc+tskS0axo40Q2dXnuUQPwFPZOB980TrclAX6wRyoTF997DmAKPmBCr4fG70CNXa9A6KoUZxe6kbZG0mBPQm9IedWzvd+GZ8WUgWa5xyWlIzb7hN9THPjRVBltqBDTmMNWvoXVmkcb1RbV0gvUSKIqnja+TaRCQAMryoG9djgbeOsmRx59WDb7k2wcL6lzGFyhrxe6jpyWT3UhgzyxfgwxT6pQfRmxfHZqNIforXreg5Q/g== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(10070799003)(1800799024)(7416014)(23010399003)(376014)(22082099003)(18002099003)(56012099006)(3023799007)(6133799003)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?SjFHSDA1alAzckp6VHdEckNHTnhFZlNDMGZzR3Y0SVQ2MXpYNVFzQzAxR25Q?= =?utf-8?B?UmdocFpPMlFlQ3dwakJ1Zlk3bHdZVFlBOTI4NU5zM1MzN21XcHMwTXlneXdR?= =?utf-8?B?WDQ3VkNPeC85VmVUZThPd3JwY3kzSTVXUWVEalc4SUFLa1preGJpeFlLSHVZ?= =?utf-8?B?U2UzRk5palpjZjVzbFA2R1hsSmFOQUZMS3ZCcEl6TnpFMHZtN2FBMS9UOXM0?= =?utf-8?B?S2JwR2FXeEwyMEJ2WHYraFBPTEJ4N2JveTR2VVNoZzA1U3hzTzByWXR5cWJj?= =?utf-8?B?QnNRZERYYk5YQzd5a0VyenZBOElGVEMxMllNbzZiRGlyNWdFRGQySVBZMTZP?= =?utf-8?B?dHJmN21OZzZGZUo1RHZHemVjeEpwQkhQcUVuUGF3V2d6dWw1ZDU0RERMOHNK?= =?utf-8?B?cGc5TW9SWnd6SlBHUnQ2SjRNQ2xvRGJWdVBkSlB4MGE2WTFmSUxZdE9UeUhN?= =?utf-8?B?K0g3bktyNkk2eXFFOGg2cnJkeHovUEcxWjZySXd0VVp5d2VUVmZIb2Qxd2NH?= =?utf-8?B?SWt1WjREQ0ZqcUtkTG9hNm51QXRLQktTREVYRlBScVc2QlgrRVVKSkpkYVlV?= =?utf-8?B?OThaaUhzbkxXUkFzdlNFeURtODk0elJqVzE0UVFuL3dwaUw0MktadW0yQjRs?= =?utf-8?B?VTIyN3VUZzdnSjlobGVEN0FCWGM4V0ZuQlo4ZE9jOEFLWGlOR0xEc1BGODNu?= =?utf-8?B?YVB2OHE4anZTYVdBZXhtamtnVmNvRmt1TGFzZStHTWhxS1E0Rzg0L1NMdS94?= =?utf-8?B?OXcxT3Fad1lNcFF5L3lxZGh4dVFWeDJWT1lGZmd1eGxQajR4Mks0ZEVyT3g5?= =?utf-8?B?WlE3ZGRWMXo3bzRicEdrQkNjQVZVZndHdERaRGEzWUVncFhXQks5NWZKdXdE?= =?utf-8?B?ZEIyaWVpcFZFaWl1NEk2Y043T05IbGNrVFFOSFozVUlMZ3VyWlhHYzRXRU9x?= =?utf-8?B?WG82ZE5icVd2VGdqaDlzakpFUHVOS3lBbzhtRWpHT29CZjZ6TFNTWmJtOGFr?= =?utf-8?B?MStubjRPRitUc05pNTVkY2tiNDU4RVZ5aWlYVjJXWmMwc1ZaR1pyYnN5VWIv?= =?utf-8?B?Z3YzS3NZazRuNlpGSVA2OWVzVmFQSEFDNHZYbTFRL1FhMDcxZlIzTktDRU5F?= =?utf-8?B?OWNVaVZST3lsUkp0MVQzN01yTXdKREt0L0hvbDB0NWR3WnhTL25RYWlNTnR4?= =?utf-8?B?aVF2TGg1RUU3Zk1oSVc4SHdiSjloYUJoMlpTdm01MWp1MzhIcE9QbnZJbU5q?= =?utf-8?B?bzJMbTB1LzNHRHNIQ2oxYVRhMW55d2JaQURIalFBeDhGcXgvSFlRbFNNQzQy?= =?utf-8?B?ejJxNWFFN3pVZGJWZ2xqWCt1WUx0YnZTb2lwNG8zbWdOZWFBZ3g5bVhvZ0JU?= =?utf-8?B?aW1rVUJENjRhaXVzV2MyVW1sbnJ1OEUxOG52L00rTEE0TE1vSnBwbjY3NGdN?= =?utf-8?B?VEZUczlrS085djhlcXBLQm1HYjh1QnNhcHovdmxvU3E1blN4aVJGa3JzZWIv?= =?utf-8?B?anZ5NmVsbXQ2VG1vSmV0UExDUjE1ODdMbExLaEtTZFRoMHE2UDU1Z1VvdkR0?= =?utf-8?B?VG9lMUVtUjBnZUZrNVNBb1BxZTNkRDlGN1hrTWNwN1dsQlRRY1p0bXY4K0ly?= =?utf-8?B?a1V2cjYreG1BRGZOZHg4V1hlRzZYdlN3cEhweUVDTnB2L0ZQSUI0R0hoeENF?= =?utf-8?B?Z0s4TlBWWWxlc2tLRTY2MXNHTkZIMFBMendoL3dkcnA2VmhjWFd1MDFVM2V1?= =?utf-8?B?b0xSeTNUNVNOb1M5VjJEOXNabXRUYm10U1FXbFlOZjZOZ0hjeWVaSEUrRHB1?= =?utf-8?B?bnBaMHExMWlFbmRIaEEvRFU1RXJkVStaSTB6NHg5MXl4aWNqem5rY3locU03?= =?utf-8?B?WExCaDdYc2l3Kzk2bk9tbGd5ekw4ZkhPcEpYSnYvRmJTc0JuZ1d3V3M4ODl1?= =?utf-8?B?MFR3amFiRDN4SzRsMGFkOGxxSTFodkFPbHZEU2V6Tm9zbVdDNDA4dDVBeVls?= =?utf-8?B?MDFNdzh6eE0rdTI4aG1ZUXFHcEFncUF2eGhvQzBRU2JTNTJaOC9UeE5jN3lj?= =?utf-8?B?K3NTSnVQZkYrQVpqbFZ6Z0pEYUNUTDNrWjdaT0lhbmp6MWNvK0g1UG9iU2ZK?= =?utf-8?B?WVlxV0FRTXk0RHFIYmprVmQxY1RxdTJaRGl4TU1MUlFHaFRMdWtmTmFPWG1F?= =?utf-8?B?bWNKa0dDc0JKN3U5Uytza3NuUlNhK0NpOHpqekdBUWU2Nzk1WUR3YmhpSy8r?= =?utf-8?B?c3BFU21zbjUxWFRQRk80MEc3YXliZjEybjV4a29qSFZ3ZmVKeURnanRpSkF3?= =?utf-8?B?QUtCcnJrNnB6Q3N0OVhXZUVjNzBhcHhjQ1RXMnhqQithSmJZVWkzQT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: 77681894-384d-455b-d5bc-08def30fca2b X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:07.6140 (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: w9CnD43HIk66UGosigMIq8lOPp9uhgV7Ua//rpy1lAd+F5oWwTcNDgPj9T9IzJXtms8kp2o+oQehcztIk88F7w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB3412 Add fixed size region types `PFalconRegisters` and `PFalcon2Registers` and update PFALCON and PFALCON 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 --- 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 | 91 ++++++------ 9 files changed, 238 insertions(+), 257 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon= .rs index a91cbdd5d636..ed52572690ff 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -14,13 +14,12 @@ }, io::{ 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(()) } @@ -563,16 +563,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_start >> 8) as u32, - ), - ); - self.bar.write( - WithBase::of::(), + )); + self.pfalcon.write_reg( regs::NV_PFALCON_FALCON_DMATRFBASE1::zeroed().try_with_base(dm= a_start >> 40)?, ); =20 @@ -582,23 +579,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), @@ -630,8 +625,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) }); @@ -642,10 +637,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(()) } @@ -654,7 +647,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), @@ -665,19 +658,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(()) @@ -686,32 +673,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. @@ -776,9 +755,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..cbea6d7b49d3 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<'a>(io: Bar0<'a>) -> Mmio<'a, super::PFalconRegisters> { + io_project!(io, build: PFALCON) + } + + #[inline] + fn pfalcon2<'a>(io: Bar0<'a>) -> Mmio<'a, 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..ebfaff3d960f 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..cfb0a435698d 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 d9fafd2eea5b..f139aeb73f14 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, @@ -26,7 +29,6 @@ }; =20 use crate::{ - driver::Bar0, falcon::{ self, gsp::Gsp, @@ -272,12 +274,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() @@ -287,9 +284,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 e3c365cf4a68..45fc9a213275 100644 --- a/drivers/gpu/nova-core/gsp/hal/tu102.rs +++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs @@ -63,12 +63,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), } } } @@ -89,7 +88,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. @@ -169,7 +168,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..6fdfdb0b3c60 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,10 +13,7 @@ }; =20 use crate::{ - driver::{ - Bar0, - NovaRegisters, // - }, + driver::NovaRegisters, falcon::{ DmaTrfCmdSize, FalconCoreRev, @@ -27,8 +24,8 @@ FalconMem, FalconModSelAlgo, FalconSecurityModel, - PFalcon2Base, - PFalconBase, + PFalcon2Registers, + PFalconRegisters, PeregrineCoreSelect, // }, gpu::{ @@ -202,32 +199,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 +234,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 +252,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 +271,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 +288,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 +304,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 +323,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 +356,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 +382,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<'_, PFalconR= egisters>) { + 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 +402,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 +426,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 Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021101.outbound.protection.outlook.com [52.101.95.101]) (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 043BB484247; Wed, 5 Aug 2026 16:37:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.101 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947836; cv=fail; b=IGqkrrmJ4gtwuUXeLJ5mcxz2e8VyCaVVLzbhDSaXj9pDqXW5fDU5yenlRZSRd78PQ9FbFD0kfNvn7Jg88W+8O6OJPpK6s4Nou5eei5PDAa1vybwQUx+JV2QgsSagxyPu/i96jb8sjkV63QGNrAkcNuj03NO/R0jocvSmw0W9j4I= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947836; c=relaxed/simple; bh=UcdRmVpzRIL5d6EXe2nVU7lPrMffwe962tEbCQsnEq8=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=H5cDbXE+KfRWigHW63tbAoqLvUCspnt2FofFupyhA42TkiFjMLCNopUlrLphlqywY2rGqa+kjqQWY6PNbn25TeWlObKxzLwUnJ7nmWVmqOMTtfGKrIR2OoLIZjrKNm3hyrO5M+LUm7mWD7BiqEhPEhfQS3abwPjJOzmZ/e4xGbg= 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=QMNkJXVe; arc=fail smtp.client-ip=52.101.95.101 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="QMNkJXVe" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=jC1X2zh9JnSvDzSZewe9V88yp2cL23oGN1fW1AUqZb/Q86WtEHpyfKk2h/dgZ/DLA/yz3iD6zWppAqrzPPrPg7DJqDEPbxkAdYjnMJNg1ui5gV3jLl8MgId6VbwkAIivYGyWBgVhBo/MTyZ4k2THqGRL6nk9yr2FSkUvfOcaVktMJJ+Ame65/hFE9vjl/T5Ed/6bp8S2RoHIX/P9v8tTDXL69wSzDKZ7M2ivVHAvYZi1INAsKaR7ZNeAtifV1pJKYhymRUDjvneH+xqYrTmWCu/8MFhmEOTZufsWHwfq5oJkCeIQy0dp1EAQ4gWZfo/5+L+2GLlLkguUzH1KvEFBcQ== 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=Fkw+UMFV2viwEhuJC2bR8i6EOXwpZkMW9bcNxuardHJcfLPqegjPBqhDPIXXGMxzgUWGat54YTCuib8NUI11f+kWNvsPZDa6EpoKXbdpEWxcj9nmRhqug+jqbbutFibXubWOFaicttViGm7qGFDf44Tpo5mAEbmqCmOUuSsFc+MZUMBwRRc+/+CFwJkIC78FknPRGzuxAibuFK1+LVMyTyQgc/F1M3YWiNiEZ2WplbUMs92yKkBo+aJhPT38kTGM31mSxAXPmixyLw+JX0AdZCM3D4Ev2upQ1M0eTDHVlEr0w1JIiToWgZTm/A6VmEoXCJwpDUDigLc6zrRKdNq9HA== 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=QMNkJXVe6CydLiyeABSpIu1fpGH3aerVFAMlYAw9Ld/gucFe3YBNJlvuX8FbhnyNb33asHCujE+gUYlR8RyMALdMuySuzLa0XgejD2pSXz7qom2z5LXrULIlKUwPPMNhHnLJFwQ+v84uDTny2HcuM7WlqJ2YPdizQbdRn7+boIk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by CWLP265MB3412.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:ea::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:08 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:08 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:56 +0100 Subject: [PATCH v2 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: <20260805-typed_register-v2-13-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=6702; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=UcdRmVpzRIL5d6EXe2nVU7lPrMffwe962tEbCQsnEq8=; b=v8NEDerkeR7e8881UUrHp7Lg06WNuZ9vjZ6x/ZMLFytw34MRRTvToNx9+q7DwCynlEezZvL2n wxmOSZ5HYdAB2yeeAqJZE22WenvBRwqVdM6j6MfKywVu6DBvWKdbWpE X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|CWLP265MB3412:EE_ X-MS-Office365-Filtering-Correlation-Id: e0a9809c-a15b-4df1-47ae-08def30fca86 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|10070799003|1800799024|7416014|23010399003|376014|22082099003|18002099003|56012099006|6133799003|10067099003|921020; X-Microsoft-Antispam-Message-Info: 6vTxnPHMdP/x4Uuzp88i4psK5OiZfIY7QKQ8lzkym0AUerHVituXhSLfv/oeJyId6kLhoyyEWp8mRR8yR5wWHCe1i0GJhx+LMaB/g7+18zeUgRFJikDK1ltsfOPkVQTTPvpbCoulaGayCi/WzXp1nOhAslTzerHi9/9UAYYuw00GJOm9Ft3mt2RMc3POI7Cd5LAhpBWXW2ihyOHbjZrzRFHc1ykb5HOrlgBukuM6gvDFAAG9ca+A2SSs2OPWO4Ae0k/kGaH9VPhqG4OPH0dv5SYuP6Rg3FJe2wtk19Yn2MjR4o9hImGdWp56dlf/A5L3lenFv94n0fswKAc8axBAMbqlhGEjwsyi+KMLr1Xw7DUVSctJ43UrtII9NXvm6f6y6eQMhmSiRtrNDLb263JFy2lwu+kXozcoV3wGbQaWJ+xWZGBxTg3/M/f1k3+wuQ2ffy6WUP7H8tNkYmNFr0AiFGK9dyxUh8sE2Yt3Ik+xfQKbIdJvnbgrMe8LC4yjhLKKgS/sAoC3dwiTtZGMPtfIkr+Eff48FMPWZf80nax3iUE4YeVPZ3eBxfGTYum8EUud9T/pGzZjhI0b6y0+MHl7JEeuQiYHDtgY/FEwoW0Qh6mWdcT+s1qLGnlZUNf0W27kHe8MlOgINMG6NcWAbfRXo0q58U5wX3+vv8xHQoqqGE/kULx9a4fhA45xoLhSrJFxOHaeF3FIn1wUJClVgVXZXg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(10070799003)(1800799024)(7416014)(23010399003)(376014)(22082099003)(18002099003)(56012099006)(6133799003)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?Zk1GTHA5bTFKRDR1K0lLd1RYQmxhd1R3NkhuQUJwN2hObFRmekdxdVN2NnNB?= =?utf-8?B?Q0ZocEZkS0xUVmFNK1NoREtIejV6T2lCdTFaQXY3Skdjcnh1K0cvdy9SaWho?= =?utf-8?B?N0tGQTRSS0Z3YjRxK1d2Z2syZHFoQVh5OG9nMVY2UnBwWWhia2lUVmltcVhm?= =?utf-8?B?YjNOSG9hRGFMeGRuRTB1ajkwTERCbWpvZVozOVY4clFLY0FXT0h0TDBJWndT?= =?utf-8?B?RlVxZ3J3aENCbUl2b3RBanZraVRVOGFVRkxGVlFtSTNvQWpIeXRMMkxRczVC?= =?utf-8?B?RklJelNvZzZId00vTWw5OUVNYzRxVHJ6SUhsU25yTTZOQTFwUkxqQTlXWk5E?= =?utf-8?B?bmdsdEY5eDh1RCt3S0Rlc05LL0ZjSnM4VHdzTUhTWmhWYUoxYU5UcGVkTEJZ?= =?utf-8?B?RzIzZGRSTjdvaWh0NFhGQUEwS3B0SlpoVmZwekdtRmQ2a0ZWbzVvV2pkUkxa?= =?utf-8?B?ZjVHbGMvMXFKTGVVKytIdXVCdnNRZXpmVDBBSThJWGh3ZjlicS95MjBuVkFk?= =?utf-8?B?K05YQjUvNFU1SmtZV2JXRGV2UVd4R0N6SmJhRWRNSXEwMXFDTDFsRzBFdURE?= =?utf-8?B?Y0dtODU4Nk9peTdSczdsRVg1Y1h5VkRiRFJDcG5oUFFKSDZNMUNGeUdFRnhx?= =?utf-8?B?eDFBMm0wbjEybStHcVI5Y3d3T2IyU0sxNTloZXJSNDhlUTI1WEkzMmFuMnFy?= =?utf-8?B?UDAxY3pFdWhRbUNJNjRGcDcxQkd5WDUrYmkzZ2lUaGo2MHhEZ21wandCYUhJ?= =?utf-8?B?NjBRUG1mZGJ5Ulh0ZEVrNDA4ekgyZkZKeEt6VkJucHpvUityYWQwMDRxRzk1?= =?utf-8?B?YktJVTZqSXcxSGJLQlREZVlON1lobjJJSlFFdldaeEtwTkNYVHl0REY3dENi?= =?utf-8?B?L2lNSmRmUzc5eGJSUHA4eUJzbm1ST1ZmVWxmbTJqaFpBOE5RVmtEVVRBUXhR?= =?utf-8?B?elVneHJvcmVUalJ3RDdkdGZsN1lkekg3d1ZCMjh1MkVtTzMrY2xXbWhKM3JZ?= =?utf-8?B?eXZQVU1qazZQQjNUWFpBT1ZOVXBUc3pTcHNqcS9hekdlT0Q1WGNsT1Z6V3pz?= =?utf-8?B?Q0JRc01hREJ1MUdBR2tlakY5bitacUdQZTZIbkZQRHBNMllRMEZqZFFNdjEr?= =?utf-8?B?WHRCYUZodUw3V3NCNTh5bE1wK0pucUt5VWVkdzd6S1JRSEdnbFJQZ1l6Z1gv?= =?utf-8?B?WityNFQ5NlV5Q1k0R2FoUHRsSCtNNGg1YmJCTGxJbEZzRkN2Sm1UM2JDUEla?= =?utf-8?B?Q1oyU0I3eVdrSGF2Ui8wZzA0R2ZpeXcxTXp2ZXYyUU1ObXE1MTUvL3BuWDg1?= =?utf-8?B?Lzg2ZTljOWxoTGk3QXR6N3NZRUQzNy8wcnlGR3ZiT0E4dG1vRWl6OGpQWnB2?= =?utf-8?B?bmdYdlZJNnBYSkRxRWZuMFdVdTF1R3h2R3o2MGZBUytEbHdmbXkvNkpFS0Nm?= =?utf-8?B?d0dkUURCV21EZDBRUUlvUklxZGJLMFFUeE9WVWpEbVM2VXNHT3U1bjZ3Mmsw?= =?utf-8?B?eUlheHd5eEJ5VUtNV1pyUm1ySUo3VmVIcytDcDZqZTFoS1I4VkEwbm9oSHJl?= =?utf-8?B?a28xUUdLV1BJM1dmMEsydHg5VGwydXFMYlhFZkw2blFyb0E3Mlh6OTNldG9Q?= =?utf-8?B?aFJ3bGx0MmhXaDhXS25wMTFlZTJOZVFBOXRvc3RRN1VTUFZqdisyU3N5RGZa?= =?utf-8?B?QkZOdU13WXh0aXZPbjd1eUdpbzdCbHUzYXJUNE0vMlQxZVd6cTAzZDQrbjFC?= =?utf-8?B?dlkvVEs0SVlBamY2U1g0ZjRZOGt4TUdHV1VQNDE3R29oN1JJSWhpczBvVnVu?= =?utf-8?B?VG84amFWbkoyZkdiQVdNQ3FiMDdzbDl3NUwxVGVVbWJTVWpkcm0zVzFSZ2xm?= =?utf-8?B?ZDIzdjhGcVR2UHpHWHZvOTFaLzhIVU11eWVWMmIwQytiWm1MQ0QwZE1BcU4z?= =?utf-8?B?czlEa1l4OTdoVkFUWUVicXJTdWNpNlc3Z05OVElFWGR3aXhMTjUvQURnaXAw?= =?utf-8?B?M0tUaW9qTFJKYStrQVpUMSt0NHVuZ0ZxRyszYUh3K25VUGZqSll3T1NDVUw1?= =?utf-8?B?OFdhUE10NVcvVjUzbmtRUjZBYlh4dmxmWG5aaTREVnpzTU5sWjFBSUhTUHhQ?= =?utf-8?B?b0QxUC95LzZPUDhuc0E5YmJPcjBOcjJnMEM5R0dqSXpwVzcybndBREdXTkkw?= =?utf-8?B?Y3hDeUVCaWkzRWRkcTZMNlROendqWjJnZE13ZnlLQkJvVHZSbTFyU3JpRnJx?= =?utf-8?B?NjJ1QVBWZnhlU3J4eUsrRHUzSXZtQlVGWFFCVEtQTktFUEpQZW5oSTBkdURs?= =?utf-8?B?KzNyRkVtcnhwVkhGRi9HOFNMNlM1MjlpQytpYjN6OW1CMGZLUFYrZz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: e0a9809c-a15b-4df1-47ae-08def30fca86 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:08.2039 (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: aKJhfsbSgrMIfVEZuCwA5LzdoPPF87rCy7lehxUFhsy4xq/0aQb9NgE8TBtlzEwNVg8nCWcLtrB0lhjsnHZxqA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB3412 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 --- 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 Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021101.outbound.protection.outlook.com [52.101.95.101]) (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 A17954854FC; Wed, 5 Aug 2026 16:37:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.101 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947848; cv=fail; b=upYCEeh1YQvh7kQO2qDuoCuPqVYtpH9km9CrTQ3LK3WGDU2dNzt9ZMM7Z/aMoK76vomYNibWV0AzawyBg7/6yRArMM5qkUmsu0BmgvmoyS4c0dtZ+SDlO1OGyC53ASsHFjhePnlZ52tX/sRaADMuokD5U4l32aqmojbAvmiK+o4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947848; c=relaxed/simple; bh=3xB5ajs/rdjAAM4S5wz1ExH2hzUqJkEzTD4HHrEC3aM=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=gATvZa1ZNUJPFBTYky/wkxtw1kJFMnFgpLmZ0ZGEvxpyksZwHSMbhcRonyiLEtlPbl5w+jD2Ee+yM565xGcMAg3wOQj+SWudEGdJnzsRGp7aist3cJKtOlRCO+VgJn+q/N9pH36wAxyUtmjuDwxD3kcsh8Ud5CO5mxbc9zR5qh0= 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=oC73A+nV; arc=fail smtp.client-ip=52.101.95.101 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="oC73A+nV" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=f7v27OAdi9DNQQnJNIdJOdZpXT/FpFZmWH962bc4pUE/wNenF9RE7NZggQXylyJ6kUjt/sskvs3cxLultdK4mihjarKZ7iA6fWoPHX7YFIbL9UKUR2/+mKJ0PePk2npFJ+/WKglNz0WEtLb7COf8N4FzpC8freg9wXyK5VlR4XUOxN3m2Y1QaGACFfVaZCLH6cNvSFL24NWy+qVFZymNk1Iom1MUGxRmvZnD5CQzsffK0jqE8e17ajOsOd/YFjXcx5Fd8DSVVBoC58TScJDi+u54snV82qeM/LWzgsuya2V66UbPC5GAMUQzt1cUB/CUdrCWlJxgTNoy/SGQn1ddaQ== 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=DzQlAr0qBA+EiXlfcPFXCAMOy2R0H9ERg+SIW5AEdEE=; b=q1n1m/vxtDl5MJijt+XOS8m9Qq9V3cbqdytNogKoBV4WlFNyaVxL6UV0NQtm0wCIqzPZrwoyUHhYdDxzOfPKQVVtWUb4K191Cut00yD3vIwcXcFPg5VKawIse8q7KrFBM6b7wIhADH8iX/qYPGu14w3GZW3KCbYptENkdWvZy2LILyGbvS/UmpLhY5kZJ72xazg+qi+/9OQcQ+QiT4ORBG88IIlKiet49U816xdsxQAJBDNN7TZIHobRspp3CcLbajQaoQrwmjsulfWw5sQlujEhFDb2rxRYBCSz0pj71JRBEE4zIct00P2ocSYA713djZHC5r/qNAV8fcgsfxeMfg== 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=DzQlAr0qBA+EiXlfcPFXCAMOy2R0H9ERg+SIW5AEdEE=; b=oC73A+nVGNStSeSE3OnJ+n5AJiF5RkZ+qjUgDDWkIUuKzSnTSUvu4UhrriV0Lxpz1gGx6GVwHh53UgsvcwlJyVD0/1cW+xihJ2wsg5IxWLKco9kdOHP8aG7J17yhjRNv6O2WQtOzbZlIf0XVOmH6RNaNohwIEN3k0f4fcyEj5nA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by CWLP265MB3412.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:ea::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:08 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:08 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:57 +0100 Subject: [PATCH v2 14/16] rust: io: register: remove relative registers Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260805-typed_register-v2-14-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=21551; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=3xB5ajs/rdjAAM4S5wz1ExH2hzUqJkEzTD4HHrEC3aM=; b=dZ/SG3yfdo0lfWI/LkeOLgVpdixvuREBb8hCa1R3KTR78kIDA//Yhc5xIbsTZW7GiofioNLdu rJlHes7mti1DY9qa7hPTdj+0CIkiH4/+q7BFykQWTlCiTiwaN8FbmJ5 X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|CWLP265MB3412:EE_ X-MS-Office365-Filtering-Correlation-Id: fe91a777-b827-4b81-546d-08def30fcae1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|10070799003|1800799024|7416014|23010399003|376014|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: CfaWPuzi/DAdWQXVXx97vDo+UG6S0mw5JQJRyKYiHEqjFBOXickAyRNp7itrgAyS7P31PjDvjPI7Cbv/rb0rn6aO72NTIUO/rAP79f9O2d0iG1jW+pYjFhShUExts4rxURUj0G1XB2tPUtrA/raCZotc/TFaj+9JxhpSF5110ETBiKcUo3v9fPGeOwbKuB+n0GsQtxTpWceNj0PgbrcoN4n8ZT9HQtV1r/AgNc5U+TTwK5GdKjEDqr7DFyhIg3a6cu1RoN1Kub3fjF9I+zrt0xsjo8Aqi9fVZ6MPZTlLMb1GAZ5QRjQakWm8G6wTcl7WwE17yXIl5u7WdlIFIN7fbbegG/uFvkYvFaSYav7z5PzWFbvfPOzYUXXNlibBhkkFSLrq8mrCUx2nNPN9iZOcXApqybFJ5NfTY45ehels2ewRTSApngPqxUSfCrKarQ7SXDzhFruZM+ZCRJOKypX7zMHSsaRfSDh6WVsDMuvRe5XIYhK9uXitlC1qdb4vl3+15eJK+7+AN69F4GRuEEw/rUzzSxsQ4xAgzMdzs1H5+iGQO6orJol3mON8Kj13TcWo7AhWc+ud6eYKx++JUziKs45Uw/rRpF0OJJFfD1v+RIKSySvpnfIQ2moo9h65a7WPas+rIlNGOcOJpf0q85xgS6ATHa2VQiRgK/rwh4cPT4iC5AWaZ7l5E8uaqeGxENaVGv5wzqFtJKiGxzcAe7wXeg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(10070799003)(1800799024)(7416014)(23010399003)(376014)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?S0JjbHFnSlN3UDc0VFdOc000TGFpTStmSVVBUjB2UEU1NGRRRExhbGlGNG8r?= =?utf-8?B?b2w1UHVHVXdNbnNWZ2dBMmhIVHdYdHZlYTQ0a09yYnQrejZGMHdnaG1ZQXpQ?= =?utf-8?B?TXk3c2tjWlIxaHJtMmhpYXpoYm92V3lNOU5pMDl2VjgwNitpL1E1R0QzNGI0?= =?utf-8?B?a2JXNkMva01xM0NPT05DOTh2UlVaQU10OExKYUdleUgxU3k5NmxyVEFtaE42?= =?utf-8?B?cDloVVlIZFdnYnJ4MFExVVhPa2hpcmYybVA2TU56eHB6MXlyS0tvUVhxSkdV?= =?utf-8?B?NktwTHFBUmEyL0hjdVRMSVBaeDIvMXhaY3NWNTBEeDlla0dET2lSeWNOZUJt?= =?utf-8?B?M2FrS1BpZGtOak9aNXZvTUV2TS9Wek1KRzNyOS8yQWRkaklIbkNSNWtMRGJU?= =?utf-8?B?dlVteDRUQXFkMk14V1BDQWVxZkE3L3NJcXQvaGZrem83bXBsbjFFRzd1Y3Q0?= =?utf-8?B?L1R4VW1RRE5jOFJqTWpBK3RxWFBuWkZZNk9qZ0xiLzFSeit2Z3RMbUtqRS83?= =?utf-8?B?Tlg1cU53dTB1d0IvTkJzL0xtYjZJV1h1L0RwWWFRS1U5MTR3UDgvQlU3WkNj?= =?utf-8?B?d2d4a2ZqVHJhTS8zY0N6S241Ulk3bzVLVDVOVitHMkg4L2lCZXlRaUZUMElB?= =?utf-8?B?SXpwV3hjdFZ3MkJDajVHeWhLUjFkY1VCWlI2bUZENkY3aUZNVjA2L21zaE9y?= =?utf-8?B?SGErVU1NWmwwWCsySGZjcERRTE5zLy9PNXJRdkkvRFhhQnliekhGVTV4SFlH?= =?utf-8?B?SFFXNTlJRFpabVdpYXN1dkxsd0JwcmU0aXdnY1dKNm94VTkwN1NaZVE4Q3hZ?= =?utf-8?B?WkRWRDBsRnBscVpkZUlBVThtSjdMWjY2QmpQSFgrSHFORitPeDBMRUQrcFFs?= =?utf-8?B?VlJVYWp1ajNXcnBwTHBMc3F4Ym1oRDJjRktzUm91VnlpdzAreUs4TE9nUmJ0?= =?utf-8?B?VmdaNnlJUndvUEExVEhSR0w2bnJoQUZrNzBHSXcydEVWS3U5emkwdjErQ1c1?= =?utf-8?B?RFBYQkhrLzhqV0JuQ0hSbFRRUzBEa0JBNEQzSWtVdVFqOHJ4Z1dPQ1ZLMnI4?= =?utf-8?B?QWdzWFpKWEJvNUU1Y1NvMVRrVjhLL21GcE1FYWhhQnp2QU5IOW5CUzJVc3NY?= =?utf-8?B?MVpMYWU4bmlqSkg2Yk9MZmlxekdPNTQzeUJEQ3dBM2Z4aXhhSklEbW80Z0dr?= =?utf-8?B?a2FBU21JWjBDdU5WcHFWRHFwaWNlZzFYZjJzNTVqdnhJNUxyQzhQL3ZnUmp4?= =?utf-8?B?ZWtrVmVWWkJHbGJRMnR4UmZ3WXAycENvaWM5TmZhM1g3akIzZTZUTVZBUFF6?= =?utf-8?B?bkM4WGYyVHN6anhaK2VZL0NiVERqbElRUlY2cGsreXFienMvT0YwazhnOHhW?= =?utf-8?B?cCs1c1FQdU9yS0Q4b00ybjl1Lzk0QXN0RVF2eU1GRWVTNzg4S3FHdUE3a2Zq?= =?utf-8?B?cUIwUWVUV0piTzJGbmhkVHZFWXZMbEgyUzdZV0RKUFdLQ1VwWWJvemhCalJN?= =?utf-8?B?dGs1enhoZDMraUFZMkJNN2NKY2hpaktYM2FyeUtpb0xCU1pjaFBWVzRKeWtQ?= =?utf-8?B?eEVGMVZSRVZRUWZLRER2eUhMVUhsRkRHSDhZV3Y4QVE3Nk1TeittQnhsNWNJ?= =?utf-8?B?UXNncWpPOEJibDIxTEI1b0NlSGhoYnI3NEtONDBCZ2M4T1VLWkVpcmJvMjcv?= =?utf-8?B?N1o5cyt2dEZJZmRCYm8yMng1V2JUUTdSOGl6cnZEWTVoeHJxeFA4Mm1XZG5I?= =?utf-8?B?bzN4YnNPeTNET1FYZFRWb3dGb1BmVlFFVHhNblN4U2FhUktmbXdkdlMwZWYy?= =?utf-8?B?SXhqUCsxS09wRWlzMkdlM1E1cVd3ejIzdVpRQktKcVlKVDBsK1ZuT0JWM2lx?= =?utf-8?B?akJDWGZZREtvOHZ0YWRLS2RFWUVSSXFuanhpaDE0aWJLa3VWRm9kc1MyS3lE?= =?utf-8?B?VFN5ekZCbW1Ea1dhYm9oQTRndUEzMVpSelAxQ3dtbExzN3VJR1J0ZXVWdTFy?= =?utf-8?B?d3F1WUFKcFhwRnZKZW9ZVUlSVDg5cWtwaGQvRXpyMlJ5Qkh0NzBlNC9xdUdv?= =?utf-8?B?aWlERzJOV3JReEI4SnBkTFZhYmVreFNHd3FvaTk1dGdQMkdmRDFXV0VNMWhh?= =?utf-8?B?aHNLRXlZeW95VzZWY1gvWWZLY1RSZk1Bckhmci9CVkhKdm1mdEUvYm9iWEVp?= =?utf-8?B?L1pZSnU1RUEwbTY5bHF6a0ovWXZ2bTVpM2dZd0UzMGFLekVwR3FzTnc2WWJy?= =?utf-8?B?dVFNRndZQVprTFFrU0N4dnlaYU8yS3dsMTRoSmg1MFpXWUx5Mi9nQUJQMWlo?= =?utf-8?B?QW5IVHZLdkRFZWhuUlBLTHJmSUtzalB5clRpcWxOdDB0eWlpSEhTdz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: fe91a777-b827-4b81-546d-08def30fcae1 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:08.7954 (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: V6zFLvVVgia/rQ2jRN6w/SysXUIjawrhLlXX+noOFn/qWI369gHBTvRZEr+VaAEZwAyeKEdtr0W7sJhqACDC1Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB3412 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 --- rust/kernel/io/register.rs | 474 +++++------------------------------------= ---- 1 file changed, 52 insertions(+), 422 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 49a61da106c7..295b06dd53a7 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`]. +//! items 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. /// @@ -430,8 +295,7 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// This documentation focuses on how to declare registers. See the [modul= e-level /// documentation](mod@kernel::io::register) for examples of how to access= them. /// -/// There are 4 possible kinds of registers: fixed offset registers, relat= ive registers, arrays of -/// registers, and relative arrays of registers. +/// Registers can either be fixed offset registers or arrays of registers. /// /// ## Fixed offset registers /// @@ -529,122 +393,6 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// } /// ``` /// -/// ## Relative registers -/// -/// Relative registers can be instantiated several times at a relative off= set of a group of bases. -/// For instance, imagine the following I/O space: -/// -/// ```text -/// +-----------------------------+ -/// | ... | -/// | | -/// 0x100--->+------------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 @@ -741,115 +489,83 @@ fn into_io_op(self) -> (FixedRegisterLoc, T) { /// # } /// ``` /// -/// ## Relative arrays of registers +/// ## Relative registers /// -/// Combining the two features described in the sections above, arrays of = registers accessible from -/// a base can also be defined: +/// There are cases where a register region is subdivided into small subre= gions, and you may wish to +/// have your register definition be relative to these subregions. This ma= y be needed, for example, +/// if these subregions are instantiated several times, or you just want i= t for encapsulation +/// purpose. /// -/// ```ignore -/// register! { -/// ... -/// pub RELATIVE_REGISTER_ARRAY(u8)[10, stride =3D 4] @ Base + 0x100 { -/// ... -/// } -/// } +/// For instance, imagine the following I/O space: +/// +/// ```text +/// +-----------------------------+ +/// | ... | +/// | | +/// 0x100--->+------------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; -/// } /// -/// // ZST describing `CPU1`. -/// struct Cpu1; -/// impl RegisterBase for Cpu1 { -/// const BASE: usize =3D 0x200; -/// } +/// // Subregion type. Make sure it has adequate size and alignment. +/// #[repr(align(4))] +/// #[derive(FromBytes, IntoBytes)] +/// pub struct CpuCtl([u8; 0x100]); /// -/// // 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] @@ -893,32 +609,6 @@ macro_rules! register { $crate::register!(base: $reg_base; $($rest)*); }; =20 - // Creates a register at a relative offset from a base address provide= r. - ( - base: $reg_base:ty; - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $base:ident= + $offset:literal - { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $reg_base; $name @ $offset); - $crate::register!(@io_relative $vis $name @ $base); - $crate::register!(base: $reg_base; $($rest)*); - }; - - // Creates an alias register of relative offset register `alias` with = its own fields. - ( - base: $reg_base:ty; - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $base:id= ent + $alias:ident - { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $reg_base; $name @ $crate::register!(@o= ffset =3D> $alias)); - $crate::register!(@io_relative $vis $name @ $base); - $crate::register!(base: $reg_base; $($rest)*); - }; - // Creates an array of registers at a fixed offset of the MMIO space. ( base: $reg_base:ty; @@ -934,40 +624,6 @@ macro_rules! register { $crate::register!(base: $reg_base; $($rest)*); }; =20 - // Creates an array of registers at a relative offset from a base addr= ess provider. - ( - base: $reg_base:ty; - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - [ $size:expr $(, stride =3D $stride:expr)? ] - @ $base:ident + $offset:literal { $($fields:tt)* } - $($rest:tt)* - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $reg_base; $name @ $offset); - $crate::register!(@io_relative_array $vis $name - [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] @ $base + $offset - ); - $crate::register!(base: $reg_base; $($rest)*); - }; - - // Creates an alias of register `idx` of relative array of registers `= alias` with its own - // fields. - ( - base: $reg_base:ty; - $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) - =3D> $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)*= } - $($rest: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 $reg_base; $name @ $crate::register!(@o= ffset =3D> $alias [$idx])); - $crate::register!(@io_relative $vis $name @ $base); - $crate::register!(base: $reg_base; $($rest)*); - }; - // All the rules below are private helpers. =20 // Generates the bitfield for the register. @@ -1020,15 +676,6 @@ impl $crate::io::register::FixedRegister for $name {} $crate::io::register::FixedRegisterLoc::<$name>::new(); }; =20 - // Implementations of relative registers. - (@io_relative $vis:vis $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 $vis:vis $name:ident [ $size:expr, stride =3D $stride:expr = ]) =3D> { impl $crate::io::register::Array for $name {} @@ -1038,21 +685,4 @@ impl $crate::io::register::RegisterArray for $name { const STRIDE: usize =3D $stride; } }; - - // Implementations of relative array registers. - ( - @io_relative_array $vis:vis $name:ident [ $size:expr, stride =3D $= stride:expr ] - @ $base:ident + $offset:literal - ) =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 {} - }; } --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021101.outbound.protection.outlook.com [52.101.95.101]) (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 A1EF648EBC1; Wed, 5 Aug 2026 16:37:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.101 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947853; cv=fail; b=FqxFMAjWPhj0t6kJzpEPLyZBJNOVblwBzq1rmdH+27LAWYMhV9kXR2y4ZbcaBig+CVeFPJtCqn6tp0UsjxwUe7NkTwhGOG6GTdLPyLwxahODHzhmT99PiI0YpTGKF40+gaxfwlIinYnPSk/EXY7xIjg5iz4FxmsUkIY5EHOwT90= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947853; c=relaxed/simple; bh=p13WzdC2A1rGj72lh5bQ22cWnQWa7BH0yxfz654p6CE=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=M2GIN+zg/6/zJiqu2nSxj/kHY7SXyrPl4agD69bOITIotKNM0xyoLNezYcpHFNoEwL0CAB5pjpwJVK3eA1ZbrDgJxYDxyyh2oMRfcG1V7nmpw/W5QmBXKISfD3lUK9oufQBHfeRE9xt41ExXWhWwsIFmmw/1OTnMBqiA/SxOAWw= 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=Ky3d2OFC; arc=fail smtp.client-ip=52.101.95.101 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="Ky3d2OFC" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=VuOvIRIjTJBwFK/HU3Qi+KD5TUK/KBudxFQHiuiF+Ckx347d+scyhno1TGGzT7588lf191uGzcU/aqzo27M/6j3a9TtZxXZlI/LUUt+TE3cCgYKkrNnQwYaRqaN6MGPxaaJxOGw2+3O9f9UCtdVP6THUQvlNOUI4ihvdSCr20REaZVanizGUiTtA6e3s8Wezr7lJNQDaoch+8uuFroaeBm3pZt76yfzntbHcyUc66Odw2R1oJYrt9n+qmg9xLc3cgfrnMVngIMp0zWBPV6DGia8ycwii+eCPa2sbOJEubl38QCGcFpRVMB/8FkZwJQ3veAxSA5tPgO15YrMRyXgHYQ== 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=A4zGmAeiy+AGAGCbR+jYSkIZifHZDji7ckyLq5/X0sg=; b=Vb8+vBcIQlXhYacjHODOYqmMJXGd7C3L+G867NIiBws9WQ6nz37kwzrpX6EBsWCkFYDAK9eyIhVnnHAuMOsD/ckxj5KPgP3prmdC70RiW4r0miZ8ERQ7E+lhAmO+jpJiZTYh+k/Cbz4FE0e5ZgAJ5JxHgDEQRM2Zfx1mqpbgYbrojze9aOlm99XmxhWRe1rtDimz+UNAteKO9lxsVOfcPCFcEEQqfAVsOcCSFh9XHldYQ6ig4SbDdIDf8bFv15dQY9/+uTLSqeRYv27TxYcLV7eDZqyOKy4FCSt29RSpGCOrBB3Cx04mgWOchzv97CasCJVnISS/RCeKDUvaBz1HRw== 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=A4zGmAeiy+AGAGCbR+jYSkIZifHZDji7ckyLq5/X0sg=; b=Ky3d2OFCwkEE2Fy9rxPIS9zq938HmN3YvyLZ5NW/uF3Jixw15ALUTQJIc5BNTS5btASdiWYzZHWUOyvW1GALsBLyZc1lId9+iV6ghU7kALa/VCi2sJDScwsGWuKMHeQeX1eXxm0PhJY79nB+RXMRt5KfNVTPBMKQyCr6ExN2DF4= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by CWLP265MB3412.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:ea::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:09 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:09 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:58 +0100 Subject: [PATCH v2 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: <20260805-typed_register-v2-15-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=6756; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=p13WzdC2A1rGj72lh5bQ22cWnQWa7BH0yxfz654p6CE=; b=7Hu54Crzl8xfpC5zmFQa9DbbgK9ENlBAsnKYZdeSYa1tRYDnc+Pb9v/V9Bg2ntDD/Jp9iEsvs 3H+t30CpGo1C24ryXiz2wXAfgglUG8W1ONulQb2ST8AAS/curZmYsLo X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|CWLP265MB3412:EE_ X-MS-Office365-Filtering-Correlation-Id: b05c025c-776b-49c3-107e-08def30fcb3b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|10070799003|1800799024|7416014|23010399003|376014|22082099003|18002099003|56012099006|10067099003|921020; X-Microsoft-Antispam-Message-Info: dkuQ0dMXuwLbkpkfVpDwGn3+ZQVhw5cKeD5eeKfAqjSkzagtgCjj0AskVDf4KkEIkpHlpaV8Y3N+CKxfL42JtPp9lvaNnqzGLIFOj73t9EhX1jAwDUk6lO0Vck90FxIiZo4e9MbyWbTbRk63LWY3jfVHn+8VV26LWdHGcvD6jlF6z/ceLMVGI7jIiB8T9dkjxh/w9K5sDS6oMOwOUJUcclmSW62BSTNj7U5g+/MUUBxtd+V8NKFi/Lne0LBK0LrCRmTnB86MhNIerf+HNn5Ym+SgexzR748voY1N0KwW4EvKadYwG/beZXTp9qV4KQgBpeMTM4RDQfKccnXRdn1LQ46aZpimQTp7TTqZIooj+WlhS7v/g0ugJLJQn3iKLz9wq5uBg0iDdugApGhcFNHIRJ1EMR4khyOEPkljZW97Z7/B+oNI68c82pAqz5vVCf5XyXss5BhwI7q7CxleTgflqpxzRc40UcDZMFRagTwM8E/8Br/1iFVfkSHI5xD/74qzmi+ZkntvRCgME2AmDkKVnfM+iDu6C2n/LgC74nJcw60F/MgUpXbXz2fxSS/EALEk4Gx4HVQl4V+E+91cmBLs8+bMPwuhvg/fe7A0Xdbwrz7pPf7rXLhNcWqm3WGVj7l5S9DRXxrkQ7Mae3q2ryW31BpW+mBhXA8ysSnpIUfkRDs/qR43PBlkRcoZConw1GD0lezVuZFdq7SKRx9ZOSX99Q== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(10070799003)(1800799024)(7416014)(23010399003)(376014)(22082099003)(18002099003)(56012099006)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?aUt4NXc0a0lPa3haWXI4TUN2aU1NbHhFNyszRnMvc3dQVkhrTnpqNGc2V0p0?= =?utf-8?B?b1pqdDdCdXd6L2lwNE04bDBSNzNsZDRWeFFrMnYwbmlrQWUwckI3MXVwQ05u?= =?utf-8?B?QkhXMStQcmwvMStoWTZLK0pYQ2I1Uk8xN1BoQ1l6Mk9jcVF5VWNlSHUxcTZ4?= =?utf-8?B?Tm9WVlZXNCtlMmRsY2NCVzZyOWJpR1EveUVER3dnTXByMGpoTTJTYlVxdGpZ?= =?utf-8?B?QkVwWXdlaFRaNncyQ1FOVURhWHlKcXduRFFkWFVKdlgvbkNjOUdySWRKWGd2?= =?utf-8?B?R3IvTUlaYlhnOWVOdTVZdkJSaG1PT01ZN1c5ajNxMGJlOWdmb1lXVkhmTFNa?= =?utf-8?B?dHNneE1JemhyYU5qRDF4UEJZNXp4bjM0ZlZIanVWcEUvWktkSjFQRzF1YVhs?= =?utf-8?B?ZjdXOG9TOFhFOEJ4TXYxUFBjV0IvUUdIZGNXd1U5MmFuVzU1ZXF4MmUza3Z4?= =?utf-8?B?WXhoWDJMU0I1RStUMkQxZ1BlZndZVThvdzNjOG96NnlhMDdpeTh2c2ZsVXhJ?= =?utf-8?B?RmVVb2dyeTNSMTNvRnUxVUVPT2tMSmM3aVZ1S2lqRm9NSWlaUDZzdi9IQndL?= =?utf-8?B?RWYxTkdBbjU2RTdpd254UVdJQ0d6RWhwSFhvSTg0OC9kdmcvejNxLzBDNEdR?= =?utf-8?B?VUp2UUI4WlE0QlUzZ1dNNDJGc2dKVUhROXl6YWF0ZGNWcFZrbW9Na1h5VUhv?= =?utf-8?B?WlR2V1cwYVNQSENNUGhQVGUwVUQ0S1l0cmwwVDVVeHNnc0pDZDZlYnd2cC9F?= =?utf-8?B?TXhCSW1HcUMxdkFEK1NubzRDZ09aTEIvT2NMUURFdWxjbEFQcXFFRE1YclVn?= =?utf-8?B?R1Q1a0kxWVdGUTNHaHJWRzVBdDNPWUNWcWRDUVhJV1drVE1vOTkxQWNOZEI2?= =?utf-8?B?Ynh5ekREMlllUGZibUhYQVdJSFk0cjdISVM2bDJydkNJRDFvTjFYWlJ3anFR?= =?utf-8?B?aDIyR0FWTUF2b2lFbDY5T3FCbVNWYkJkREl0QlZHSDNzbVgyeDVsTFR3aWRF?= =?utf-8?B?ZUoyMW92Vi9uRXVSWS9hbTlOTlFkOVRoL3RMMlRySXVoUFNHTE80UzFpSnFH?= =?utf-8?B?enlnL1dUSUhxZitsWWk1YkZwQzhta0ViTkZXUHdiaDYrODBoa08raklsQm4x?= =?utf-8?B?UkpDQUtUa3NJSFR1U09SaEVIS2NJQjdHV2ZOVUludjkxNzZqUGNCeDhRNFpj?= =?utf-8?B?Z09sSUhpbHIwZmhueHZucHdQbFY2MGIvRThDLzNWd0czdXF2MHdnT2F4M005?= =?utf-8?B?WWFWSDJYY0Q2UVRxYTJqNllJclRPMzRKa3ZZRmg3RXVRZHFxQk0wTlU5R0tG?= =?utf-8?B?QkdsV3V2eTl2WUVrVFBXT215RDF2TFVaN2dWOWVvRXZiRHpNbnpFTHF0ejVE?= =?utf-8?B?aGxMTWliN1Q2bFJiY3gra2ZmaGlXd2tmSm5mZlNERTFsdWR4OW9aVUk4bnpR?= =?utf-8?B?NTdDRFhaQXB1a0drM0lQdy9oclFVdmp3a2Zsa1RtcTBaNHJiVkY2US9uQlo0?= =?utf-8?B?cjZHYWt5M1RPYzJ4NEJ0Y2h3elBmKzQ4TE1aVkZIaFBlTkZ6RHNjOE5jTXhB?= =?utf-8?B?anBsYTFIY254Z3BNRnFRSGRpNmtZRnRyUUQ3WW04UXlCN2lUcDVoc1RtRVZQ?= =?utf-8?B?eUFjZDNzV0FEZXYrd3hPSG5reCtPWmlybVRGNmJsUmpRN1RsSUUzbHkySnVL?= =?utf-8?B?RGlQajQ3aHBTY1dtcW9HcTBFcVFOZHRqVDVocFYxc1lXQXI3blJ5T01BOEJF?= =?utf-8?B?RXNpa1I2OXFpY2c1dkJjSW9udEE5SlNhWXJPYUhUK0NaNnJrd0Rzc3JDSlE4?= =?utf-8?B?QUMxTVVSWTdPNzFxSW5LT2U1dHppdU4vNEI5TWU1aSsrNlp2bW0vanYwWEY1?= =?utf-8?B?SktudGlVcnFycjRISE9BOEZMaTNsbzhEbjd3bCttRmV4MXVUQnVGdW1pdGZK?= =?utf-8?B?ZlU2SkRRMFdSMlllelRXVHlEL3BRdUZwTm5XK245dXBIRUFGVXV2dHZwWGxs?= =?utf-8?B?OFRjd09qbHZmUStvakZOckVSd2Vvb0Z3TEZaUnhOcU1YYU9VTjcrNDNlNGx3?= =?utf-8?B?Z3ZpajIwOGhWMS9IK3R3NExxVTJKRXh4aEk0TTZ0V2lRYmRhazZJUGxsdDE3?= =?utf-8?B?ZUdQY0ttSXYydGwxcjhjK1VEZGR3YUkrL2dMbmRMS3N4Qld4NTRua3FtQTFN?= =?utf-8?B?d0VnT3lMa1hsM2F3WnIxU2xTUTNaTEN2QzEwdnBtMU9zY0ZIMmU3blFjcUY2?= =?utf-8?B?RUdZRlhKM0xUNWk3NGhZNlp4MWZjUjhMSnFsUm9RMGFyUVB2czl6ckFlMFho?= =?utf-8?B?NkhHUWtrTmRRd0xQRmhqNFpDVDlXaGxXQm01NkExNmh3WDBLeVYzUT09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: b05c025c-776b-49c3-107e-08def30fcb3b X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:09.3939 (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: 0UjhqpDbMJZ8DQhbKU4bVx9oR+fW7ATmF23WLCrgHT4WScefQ5gYRG8u5Yo0PulG4YiJk+MYaYjYxSjVGMeMgg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB3412 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 --- rust/kernel/io/register.rs | 102 +++++++++++++++++++----------------------= ---- 1 file changed, 43 insertions(+), 59 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 295b06dd53a7..fe0e6763a600 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 @@ -601,11 +605,22 @@ macro_rules! register { { $($fields:tt)* } $($rest:tt)* ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $reg_base; $name - @ $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$al= ias_idx])?)?) + $crate::bitfield!( + #[allow(non_camel_case_types)] + $(#[$attr])* $vis struct $name($storage) { $($fields)* } ); - $crate::register!(@io_fixed $(#[$attr])* $vis $name); + + impl $crate::io::register::FixedRegister for $name { + type Base =3D $reg_base; + + const OFFSET: usize =3D + $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$= alias_idx])?)?); + } + + $(#[$attr])* + $vis const $name: $crate::io::register::FixedRegisterLoc<$name> = =3D + $crate::io::register::FixedRegisterLoc::<$name>::new(); + $crate::register!(base: $reg_base; $($rest)*); }; =20 @@ -615,39 +630,36 @@ macro_rules! register { $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:expr $(, stride =3D $stride:expr)? ] @ $offset:literal= { $($fields:tt)* } $($rest:tt)* - ) =3D> { - $crate::register!(@bitfield $(#[$attr])* $vis struct $name($storag= e) { $($fields)* }); - $crate::register!(@io_base $reg_base; $name @ $offset); - $crate::register!(@io_array $vis $name - [ $size, stride =3D $crate::register!(@stride $storage $(, $st= ride)?) ] - ); - $crate::register!(base: $reg_base; $($rest)*); - }; - - // All the rules below are private helpers. - - // 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)* } ); + + impl $crate::io::register::Array for $name {} + + impl $crate::io::register::RegisterArray for $name { + type Base =3D $reg_base; + + const OFFSET: usize =3D $offset; + const SIZE: usize =3D $size; + const STRIDE: usize =3D $crate::register!(@stride $storage $(,= $stride)?); + } + + $crate::register!(base: $reg_base; $($rest)*); }; =20 + // All the rules below are private helpers. + // Offset computation helper rules. (@offset @ $offset:expr) =3D> { $offset }; - (@offset =3D> $alias:path) =3D> { <$alias as $crate::io::register::Reg= ister>::OFFSET }; + (@offset =3D> $alias:path) =3D> { <$alias as $crate::io::register::Fix= edRegister>::OFFSET }; (@offset =3D> $alias:path [$idx:expr]) =3D> {{ $crate::build_assert::static_assert!( $idx < <$alias as $crate::io::register::RegisterArray>::SIZE ); =20 - <$alias as $crate::io::register::Register>::OFFSET + + <$alias as $crate::io::register::RegisterArray>::OFFSET + $idx * <$alias as $crate::io::register::RegisterArray>::STRIDE }}; =20 @@ -657,32 +669,4 @@ macro_rules! register { $stride }}; (@stride $ty: ty) =3D> { ::core::mem::size_of::<$ty>() }; - - // Implementations shared by all registers types. - (@io_base $reg_base:ty; $name:ident @ $offset:expr) =3D> { - impl $crate::io::register::Register for $name { - type Base =3D $reg_base; - - 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 register arrays. - (@io_array $vis:vis $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; - } - }; } --=20 2.54.0 From nobody Fri Oct 2 02:30:53 2026 Received: from LO2P265CU024.outbound.protection.outlook.com (mail-uksouthazon11021101.outbound.protection.outlook.com [52.101.95.101]) (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 82FD54921A1; Wed, 5 Aug 2026 16:37:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.95.101 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947856; cv=fail; b=mLmBD1cUu1vb+Ko00MnhqhFDeDmZvIRrdtsYItG3hBqZPg+7zkW8SWZsXGsZHhYf77xSDsG+88o9ddEq4WZU61GYiGf4udzUbqlXNK97VBtDeT7c1fsBkCVd0hukHufZJOsBhUk1HvnqR+dfL9tSFfDQBrG0mxT7HsK+c5erZ5E= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785947856; c=relaxed/simple; bh=F10t3MNtS+cJHSoHP7GCekos+uPBPiDEMXkwyvWHJn0=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=dWHDQjyRPnMgJA25YswrlEqjUqBrgLrbs2HLAI8ppA1nCCbqTynDcRB/I/xvZQSKUYViEYAmY16aKdmFZ3LyZIssgeqAcYClxLMOIiLTyPNOn4QzVJNpT3gnWT6yWq+0lnuVfeJM3FDEVIZZMR1LlCzvrHuuDNg72rBqKX/euHk= 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=KN1BBCwQ; arc=fail smtp.client-ip=52.101.95.101 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="KN1BBCwQ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ce5EQEQg1hp7S4kIrkEa+n0jVVQa+ZFKIvF3KpfTf/C6iLkdmF1I+Tv2RMs0L9PE+KXS8Yh6vUxfLHY8NSXE5/hBIIE4jqUTsphSHK4oK2IhlAU0JHhvJij10GEbADSn5WK1xxb46bZc4QLIuhqFPohtOXZaulRitQWUV8saUs2YL25JWgBxpgyJ14XxIxSpRKInTnTQgW4nrszNEVQekdj5SI7IgEwvAlE27Sk4Ihwy7aXB4vIpOvZu5UTs107mYlhmmsCmk1Xtno8Km3pfchJ0gTo6mZD97vgcT8TAF+3sNc09jLd28PzGhNZREB9F6gPPhyNP15LAJjQhPCNO7g== 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=0+mMMys6gZ0hWRf/p1uTd+IXfQwdHaQOVVcCl5maNyI=; b=X/B+BwN/msuHJ92ziu3lx7ptqG9agNW/5Va5fbw17qkn/Ui49Tn6GIY1NB+cgcpqjOz6uLURNibkLoYRwOUF1hoIGxOWi86zlN547iVwJV6H33l23OyOPZgdWGK69laoH9CpXZtyo2bayQtE/aGHYWKZjAkJ6klOa+Eb73m8LDYkjdWH4SIUaZmxet7MgFEBQYvhRz1uBmU+s9xMSyylpWPA8RC64JyRSpglQcS3fMJ2EKc4YFhJIlkH+YX98j4JXniU6hzDOEQm3xRm7lKF1obGP1XLXrkQ8AbpiRV5+mjAG225PmKqKmFfAefZgYMKc9Zs+TF3ATc8FJTSRZd/kA== 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=0+mMMys6gZ0hWRf/p1uTd+IXfQwdHaQOVVcCl5maNyI=; b=KN1BBCwQB2EcaDzGoaWRIXkazuO2dPkRKVDwTLQmfrljzMTVmXRP8fvfwGp5E0ghibFT3mm9REvHptAqwKCtSu+RNAtb78MBzLZQGsXPP5UFOaNy31eCr9Jf/x157SBlSvL0Tka8e/EImacni+tb3a21qgu9lnrH8lWj4LTJ250= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=garyguo.net; Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) by CWLP265MB3412.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:ea::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.292.19; Wed, 5 Aug 2026 16:37:10 +0000 Received: from LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a]) by LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM ([fe80::c07d:488c:d4aa:2a4a%4]) with mapi id 15.21.0270.017; Wed, 5 Aug 2026 16:37:10 +0000 From: Gary Guo Date: Wed, 05 Aug 2026 17:35:59 +0100 Subject: [PATCH v2 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: <20260805-typed_register-v2-16-c3ca142220a0@garyguo.net> References: <20260805-typed_register-v2-0-c3ca142220a0@garyguo.net> In-Reply-To: <20260805-typed_register-v2-0-c3ca142220a0@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=1785947819; l=7043; i=gary@garyguo.net; s=20221204; h=from:subject:message-id; bh=F10t3MNtS+cJHSoHP7GCekos+uPBPiDEMXkwyvWHJn0=; b=ED8CUudU9cl/ZAzgaLBKwqYH1wjmloWAcCEveY/y0I/6BYxaB9J6PZQ9sttXFtEtzOJwqn19Z eHA/fuygZSRDVPPOf08aBrlOQacrHnPhvRzjHdXxDqJNwuLc32n0z9n X-Developer-Key: i=gary@garyguo.net; a=ed25519; pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo= X-ClientProxiedBy: LO4P123CA0608.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:314::8) To LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:4b4::24) 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: LOZP265MB8551:EE_|CWLP265MB3412:EE_ X-MS-Office365-Filtering-Correlation-Id: b5ee376b-4354-4fba-ed76-08def30fcb98 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|10070799003|1800799024|7416014|23010399003|376014|22082099003|18002099003|56012099006|3023799007|10067099003|921020; X-Microsoft-Antispam-Message-Info: bOyBZ+KjyXyTBYrhSWLQ/3Jh+UKoP1qX/xuWAK+7ryPaEgbZk814Hbd2yyLfHgio19PHRZelFnG0yVd3Z++mnDj4hNT7qbCouT0m1yQXwzMPo5y7KKoDjS1eUf3EnKNnvF+OiU0+u5dhZ1srilVPrudk/P7J+GXHaGgubQP9ajjsmVANhYBrZ409j8JIUTaj4K6Jq+BEB6k5fZ3h5dyBT+9b6Le1V7YMyyzMoJ95U0c4A/5Ts5jAxzOyqIPHtZug8WZiSSKLXklFFe/NVxaWgH/GxyFGxkpUGlJ75Z117R1m6qBY2/D1NfPmRb8JRTvYyvaoyGsS+XbbXLan/en49gfw3zIo6iljK6kLckOJFelv2F1vBr6M8La6SA0n0GUum1X4qP34wy4CcYjnmRGBVaM37myRUSgu86QoE+AKLnGdQ6xqc3UCa/Epg5ncp7GVJrbUfcnZBjqqefElkSAncgWZ444DFs+ZsIEx6lEzLDvf5azhrFof3R3RvlRmYxW23tmdVavVh0UeLSV9fvjy6n84mPf2DWLbdZ2S4vzfCQFBJQhuLd4fIilUdYyWCLZWk6zEToYejG61Xd23Rnj5SmN/SrscTpYq6Rt/8DquUzrM55c/T11yN1bFWcZWIXAPG7tEp1WOryH/cJJDVEZVyMHr/913awGCpcqCthZAWZwvqiaZj5VqLaBduwlv2tbGIEQxvcpq0Hg0S/0uf8VAcQ== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(10070799003)(1800799024)(7416014)(23010399003)(376014)(22082099003)(18002099003)(56012099006)(3023799007)(10067099003)(921020);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?QW5PQXc3WVlZbVNKZHVhMWR1amh5MzVFNHd5bSsvNjdxNU5RQW1kcEgvNWg2?= =?utf-8?B?cnVvMVZRTVdmalNkdUJmYlJueDZZaVBlUVluREdBcmhOVHhrbW5tWEpzdE91?= =?utf-8?B?Ti9lUk5VWllHZ3ZEZ0F5WXdjb0xwbHVCc2VHMzM3OTZRbW5JR3NZR1czUWxY?= =?utf-8?B?bWpJUXFrYStsSmFrVUs2M3NuUDhWdnliZjZudzM2TXRuYWZkdWlHbzVrUnpp?= =?utf-8?B?SzF4M05JRnA1RDJ6MkFPbEVaTUFJV1hzcG1FQ1B3Q0pOb0g1OXk4RWp6eXJ2?= =?utf-8?B?bDJmaGVwMjdPZ0gzeVNHWTJySk9Rc29mbXE3VGxYYzliOTA5WEhNSnIrcnRk?= =?utf-8?B?QlA4TFZKUlBkWjFyM0dHTUVYaGlWNzFTMVoxOXlEUW1vb0dsYU55d1JENFBU?= =?utf-8?B?c2JxbkY5cWxHRm9YNkUyZ0hwMUMxVHAwQ1RIK3BzRUVrZlV2MTd6Z0E4ZFpk?= =?utf-8?B?dzY1dW5aczhoWmg3ZzRBbGJUTWdnM2YyaVJjcDNWanRXeVZUWjNKQy91akpz?= =?utf-8?B?VXVLcFk1OVp4dFdka3RYeVU0UngyK2Mzc1lyWmxGN016UjRvL0hRZjBEaWwv?= =?utf-8?B?TGRZVmZEQ3E4SklySGdCM1BCMXhqK3JkR2xSNDVYcHRhY3RkRUMwQ09DdUIw?= =?utf-8?B?ZGRPOFlONFR4cE03ZUtjY2kzSm9WQmx0dC9VdzBVRC91cnZpeTE1Nml3d2kv?= =?utf-8?B?Z2tMaG9lNlUxd2tvREZrdFhtazIxdHJ0OUxZa0dUdW1zMEQ4d1o5Sk4zNldC?= =?utf-8?B?emFsNTV1ZGhlM1JMMUduck5Ub0ppZUN2SDNZQkhCWFRVbVdqUFU2dDBYMkN3?= =?utf-8?B?aVpmNWszc1ZtcTVhYTd3bmlnbFVNdjVmQUhNeVh4Q0hRZUVNQ2pobnR0alFZ?= =?utf-8?B?aXFQT01hamw0VWVneVdQWVo3QUhYdWlVMFBlUlVTK0p1YWpJa2xXRFZqRDVm?= =?utf-8?B?cjJiak9obTZJODBIRWVmQy9LTjB6dHMvdGlzSWhlNkxmdkJvbzFsckhMV3Ry?= =?utf-8?B?THZISjVuZG5rb0t4emtxRHNWd2xRRE5iWGtOWDl4b2hzd2llY1plcndzclNJ?= =?utf-8?B?ZWZhYnkwc1lDaE9oWkM5VGRtdU5HWmJyek9Ca3hSdGRyMkplTlE1ZVVzMEpZ?= =?utf-8?B?Yms5L2ZFNkh2Mld6YkxrcVlQK2IzWEw4MWFId1BFUW1UY3ZRUklidWdtcE9a?= =?utf-8?B?QUI2N0FWcEZwK3lRWDZ1U25FUzFCc3B3bzhFZERXRUEwdmkwcG5IRFdFUVZQ?= =?utf-8?B?ZlFPcjJ2VzgzUzlPWXlyUDhidnhRRENZNTlCV2QwbUFTRlJqTWNHbjVZTFpE?= =?utf-8?B?Q0ZUZmVTMmcvdFdpbHRPV01NZkJMdWxRcEFTN0xCUnVyYmtWbFhCdjVrU2RS?= =?utf-8?B?TTBFZXRKd0htWFhGSjJQS1BERGlpM2xnOFV5ZXdnVHZkbkgvbVhWTkhPaXpH?= =?utf-8?B?KytXWUZxZmlFYTA3Tnd1WUpNWTl0c0sxNE1iR3RUZnM0QUdXTzJlcXh3eW9O?= =?utf-8?B?MmZ2MnkrQW1qNURodE9FaURoanpFaUhRVkhHREF2eDZPWmgwUFBORXNObDM1?= =?utf-8?B?aVI0KzBjeTRBZzBsVmNhRnZDaFR5ZUNxOTRteWtlVXJvQzhXVUs2S2VoZ2Yv?= =?utf-8?B?dHZVdjk0YlRYRWJudXJ3M3dnZExRaXVrNjEzTXA5eVgzeWd3RHBYSUluTThX?= =?utf-8?B?TnVSZHdSQk5uRnhjSXp0Szl6V2RKaDZ6QkczeWRkWUZuK3U2dDdySmtFTG9t?= =?utf-8?B?R055UGpscGpQU0FZVGNUNy9DL1k0RXgwYjZOWktQRWJUS0ZlZklydEw1RitR?= =?utf-8?B?RzNNbzdWLzBkM000QnZvNU9aeUhFblhPektiNWJmMTdlL0FqeDN2VFBuSHN4?= =?utf-8?B?Y25aZFdJQkVPZStXenpsNjN1cXRaMjZIaXdDZlozMCtzZHE1NzBGV3J5Z3hX?= =?utf-8?B?TlF2Z3RRMUhRL1B6bENCeGFEUENLS3pMSWN5RWFXUmtTaStOcys1cDA4VlRx?= =?utf-8?B?d0tZdkE1cjkwdkNVQXA2cFpXTVdFZmViZXUrNUFYdTNCUUF5eGFwSHJkZjc4?= =?utf-8?B?aEhGbG51Yy9RZ0czYTY3b2YyTTZ6QXdYN1BwQTM0dXZrUHRzKzNmdWw5L09O?= =?utf-8?B?QTlDWTRad3JwK2Rvb1ZIZW4yRnRPRnRaa0ZMNVUwSFUxUHNza05MRStySDJ0?= =?utf-8?B?TmNsTGJPMGd4dWM3bGVlSnNNUkxERGsvYVFOT083bXVIR0p1YVBkd3NpQTFE?= =?utf-8?B?Ny9TQmQwY0N1N2hweEFjL3NicnAzMkU5UVU5QlFINml1aklHNFFSZFVQdlJU?= =?utf-8?B?VG9pTW84Y0RjK1BDMHhIeC9BQVJPYkYwbVZPcVdLZWZFaVZvNC8wZz09?= X-OriginatorOrg: garyguo.net X-MS-Exchange-CrossTenant-Network-Message-Id: b5ee376b-4354-4fba-ed76-08def30fcb98 X-MS-Exchange-CrossTenant-AuthSource: LOZP265MB8551.GBRP265.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Aug 2026 16:37:09.9909 (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: jxP76ulo6v6NVpfwEIJZC2FBAO1VGOuKGdPo5jiQfB5E5KFg3auuFoj70n4fdie0PBt1Gg2T7cj2aC5fiHO42Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CWLP265MB3412 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). Signed-off-by: Gary Guo --- rust/kernel/io/register.rs | 123 ++++++++++++++++++++---------------------= ---- 1 file changed, 54 insertions(+), 69 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index fe0e6763a600..80282c423868 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, + T: FixedIoLoc, { #[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, -{ - #[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,14 +252,14 @@ 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 @@ -577,6 +547,9 @@ macro_rules! register { (base: $reg_base:ty;) =3D> {}; =20 // Creates a register at a fixed offset of the MMIO space with provide= d type. + // + // This handles all of the fixed offset `@ offset`, alias of register = `=3D> alias` and alias of + // register array element `=3D> alias[idx]` cases. ( base: $reg_base:ty; // `$ty` cannot be `:ty` due to follow-set restrictions. @@ -593,10 +566,29 @@ macro_rules! register { $crate::register!(base: $reg_base; $($rest)*); }; =20 + // `#[unique]` indicates that this is the only register of this type i= n this given register. + // Thus generate a `FixedIoLoc` impl for it as well. + ( + base: $reg_base:ty; + $(#[$attr:meta])* $vis:vis $name:ident: #[unique] $ty: ident $(:: = $path_frag:ident)* + $(@ $offset:literal)? + $(=3D> $alias:path $([$alias_idx:expr])? )?; + $($rest:tt)* + ) =3D> { + impl $crate::io::register::FixedIoLoc<$reg_base> for $name { + type Location =3D $crate::io::register::OffsetLoc<$reg_base, $= ty $(:: $path_frag)*>; + const LOCATION: Self::Location =3D $name; + } + + $crate::register!( + base: $reg_base; + $(#[$attr])* $vis $name: $ty $(:: $path_frag)* + $(@ $offset)? $(=3D> $alias $([$alias_idx])? )?; + $($rest)* + ); + }; + // Creates a register at a fixed offset of the MMIO space. - // - // This handles all of the fixed offset `@ offset`, alias of register = `=3D> alias` and alias of - // register array element `=3D> alias[idx]` cases. ( base: $reg_base:ty; $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @@ -610,18 +602,11 @@ macro_rules! register { $(#[$attr])* $vis struct $name($storage) { $($fields)* } ); =20 - impl $crate::io::register::FixedRegister for $name { - type Base =3D $reg_base; - - const OFFSET: usize =3D - $crate::register!(@offset $(@ $offset)? $(=3D> $alias $([$= alias_idx])?)?); - } - - $(#[$attr])* - $vis const $name: $crate::io::register::FixedRegisterLoc<$name> = =3D - $crate::io::register::FixedRegisterLoc::<$name>::new(); - - $crate::register!(base: $reg_base; $($rest)*); + $crate::register!( + base: $reg_base; + $(#[$attr])* $vis $name: #[unique] $name $(@ $offset)? $(=3D> = $alias $([$alias_idx])? )?; + $($rest)* + ); }; =20 // Creates an array of registers at a fixed offset of the MMIO space. @@ -653,7 +638,7 @@ impl $crate::io::register::RegisterArray for $name { =20 // Offset computation helper rules. (@offset @ $offset:expr) =3D> { $offset }; - (@offset =3D> $alias:path) =3D> { <$alias as $crate::io::register::Fix= edRegister>::OFFSET }; + (@offset =3D> $alias:path) =3D> { $alias.const_offset() }; (@offset =3D> $alias:path [$idx:expr]) =3D> {{ $crate::build_assert::static_assert!( $idx < <$alias as $crate::io::register::RegisterArray>::SIZE --=20 2.54.0