From nobody Sun Jun 14 07:35:30 2026 Received: from BYAPR05CU005.outbound.protection.outlook.com (mail-westusazon11010045.outbound.protection.outlook.com [52.101.85.45]) (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 233B52DCBEC; Fri, 1 May 2026 06:04:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.85.45 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615466; cv=fail; b=d8TtWJhijlQ80MTvg5doA2kDLER2zmBd9Ds/SwdMdEbtE7GZmG4DJJ5qnSI0DkPVVgJadiijdcvIoAWHK9twY+K2v7Kfd2ljgmyTOhff6l+VbrKmyhee4g0UlR8iH+e1F4huSkVO/p3E0yQeW8gf64o1PAGkXsGFgleFfnW0JJo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615466; c=relaxed/simple; bh=PU2LyDDG7z6hcbH+Aip3FtwHLLoqCYokGL97ezxuVLY=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=GaQ8hlbk1kLGofPZIn4Vr0WoKPb7ssEfiDz4sMhLDK/PGjAcxnvYjy7UARtjb0JHPTF3K1JhJ50F8Xl5TWcS3huHob01eyNlzlWg6jpFvcNbK6FYDODUJ/YGaMUt3FAYsw0mhxy3IT3EUv/XfoOE81295sp38r2kIjAP3fI1BVo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=dcEqJcYa; arc=fail smtp.client-ip=52.101.85.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="dcEqJcYa" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=J4eYWynDqnwftFVQA0mQE8EO66hCm1mtfcdCmbGjF+IPmsgWlCjPrbZSaXbqpwCs2sZzvZK1LtOjUtt2HWlY1Woqsy/JeRn8VjCtCppGpT1YQpy2tXM//9hJ7RtnLdKd7sOC/S8RaRbbmI9cEop24BeC6KnGuN9korw2Ch7W+1fb/mqcnc5PWFG5gtEIr79DWk/NsWDs7wSpEgmZiTcyGMZSlrDLDIU33RB8kBMMQnJPPx19zJ+Lp9tIKCEf9hOhvgmlgheXNQUlUGDxyuwCDe9GV9kPdEvGnyhyhiNgb+3qv31kNSPmgfgYOjhIGXm/KkM9nGUohJopsIHcgp0ZOA== 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=S/ZG6zCu6ofRvrF0GQdW6RpuEAwgrw3aqHEpWriP8MU=; b=LPJbfGaDKSrYhqvOV2yYATuFG0XupXY5JszT5SC9FY2SWcxhAmS5GgE7SBtMHdy9OOMj+JNupL0TuzlgwwdiAuyrLnwQ1nMMZUDoU28J8k0VHaCTFIoFukx13JMrkdoOfNUm+9MAggKU+4HJgAALIhnE66BM3/T4n3Lf7MWhyZrGGPwFnr5C71Q6S+acrXOywlNj6vvO1yHPfIfVD7Nj0/QtbquGKnFPa8cy8DKy8tmzOm9q4eBcSOGDGNJ83sGFgE6/OCvBi+B3W8wboyfYaRb5A7FOSa0Vqf56Z4CnpRSBgISJRw9sHeJVIeezXZQz7PsTd9i5UFGDoXPf5TxQiQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=S/ZG6zCu6ofRvrF0GQdW6RpuEAwgrw3aqHEpWriP8MU=; b=dcEqJcYaIuK5zvx+mfecl5BWiTzv1WNFiu2ikR+kuk2IDu///jXM0H9CwOSyjN9znYLNjffQvar8R/RgBisGpCoPVSIB/QBXfDFzfmTVoIQr95veuvNQ0sN9Ab3NomUf5jh1BL032QKWvsLLCMl8RGZPs8byxbMGBrCQG2nsJE5nrKbTEV/paWfYDNz97HzdNdTIT2IX1DafypA/6TqG2/Gv900PJJC5jYvG8X2AhurWEqG5fUb1pmT3IxLYgVdk3eNiQoZYu8uFvUPe2milZkpIAI6FNd3lxEHkKNy/8pc4gjTotWh4m4ohNjZcEBKEm/orsoWYSkW3ZjCkF2rkfA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by CH3PR12MB8584.namprd12.prod.outlook.com (2603:10b6:610:164::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.22; Fri, 1 May 2026 06:04:17 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%4]) with mapi id 15.20.9870.013; Fri, 1 May 2026 06:04:17 +0000 From: Alexandre Courbot Date: Fri, 01 May 2026 15:03:18 +0900 Subject: [PATCH v3 1/5] rust: extract `bitfield!` macro from `register!` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260501-bitfield-v3-1-aa1076c3337d@nvidia.com> References: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> In-Reply-To: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> To: Joel Fernandes , Yury Norov , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , David Airlie , Simona Vetter Cc: John Hubbard , Alistair Popple , Timur Tabi , Zhi Wang , Eliot Courtney , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, nova-gpu@lists.linux.dev, driver-core@lists.linux.dev, Alexandre Courbot , Yury Norov X-Mailer: b4 0.15.2 X-ClientProxiedBy: OS7PR01CA0190.jpnprd01.prod.outlook.com (2603:1096:604:250::12) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) 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: CH2PR12MB3990:EE_|CH3PR12MB8584:EE_ X-MS-Office365-Filtering-Correlation-Id: 73b3bb60-11f9-4213-1086-08dea7477a9e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|7416014|376014|10070799003|18002099003|921020|56012099003|22082099003; X-Microsoft-Antispam-Message-Info: u8QuQuvEdy8XxmNluwjcW9GpLsv+eyBp2es3nQdoSc5/S8XieeGLygPTifNHP7OaW5lcUNyMsbPpHrQGuprRsoHrSjig3oyftErzHLHM5fQ07UnqEwBwP6sB4wjLlHISxyZ+1ENYbxS23SgnWN4bFgqLxAr2TnW3A2PAIJUQ5GKCVQmjujx/Uyvcu42IaFUheRt3YQwsnTiyRCHMlgGTQTbPwZ7Kzy7BIt7zyJbAHaXziJg+qQaa6fB5mRE4TT6aZ4+uh4cYLWN7nPJT4cITaaXOXcuqe5jid99JKC+4WKQMSe6qBYux49ObUPgLyXKobLY0oTWa/FZXw3Be9WsDlpCiEFTNmG/xLZ725vWnunRfaFLW0bAqFH861gce8TjtFVxvgIb8jScEvAYJPAivGHVVg6H5TN7A+tO/NfksSq/rY61TT5ZomULR+wTmP354/x6meh/Au8Ps5/IAjGEWfXB2USpUIyjqnZFucRhGDRMa8rBy0YipNs2K7wQQE7TRfyezcS6HDSqidVktesc7Zhqq+stvlfeaFrx3q+pXIRQntVgKMIQHQ7VasLYysXsQTGAve7bFKSI6tsUXXjfxtEBQ6kF0k1wWMAcFg1dki/nEAhpqQSn3UqPuy3kefD/dIgHUDzchx+M+kw54hKsFuJoQVENSUki7OVWfxFyzFHp6iKGMHxzuXIZ4HgogK/JqDCEyWKWSuJE5JKKfwAm3OW/Umb8XQfn2ICiBI6aN98abDaVLVEQ3e/fkEQZ6E3/+ X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(7416014)(376014)(10070799003)(18002099003)(921020)(56012099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?bWt5eXZBRGZsZTZUeHdVVDliN0h3bXRxOHJuRHI3YkFWbTRIT0lzeEl0NHl2?= =?utf-8?B?NUZnWGNXRGk5elNZSzllZjNjZUo5UzlXN0c0Y2hpUi9UVWRBbXZUYlZTZks2?= =?utf-8?B?cDdBc0EzZnJ3c1RVR3ptNDBDdTZ3SGJUOU5XanNyS2lMRCtrVGFMS1VtdlM1?= =?utf-8?B?ZUpZbXlzeXdZK1BlZS9uUkFMYWF4Yno0RUFOOUtaOVp1WFllTkxEd0s5aVlr?= =?utf-8?B?WGltcWJFWXpsUDhZcnhsdmk1TWZKalI4MDlPQytxUVl4S3RLZzBacE54clFm?= =?utf-8?B?SFppNTUzNm05aUNtQVdjMm5CNFFVTTJiNi9PMG1oMHBjbWZXQ1k1dWpLUnR6?= =?utf-8?B?UVZjZFdXcVJteVRtNWwwR0M4NGZGY01DYVlObzgzN2QwOGFDcW5HQmIvZVJZ?= =?utf-8?B?aFlhTlIyQ0l5VVpOQjVBUEFLV3RzM2JpQ0FsdWlDbmlmU0l3bEUzei95Tk1I?= =?utf-8?B?NXUyZFRvbVVtcFVyMlE4SDQvbW1wMHcrMGNsUXdJNmltdEF2T09QcmZjMGJC?= =?utf-8?B?bWNiOG8wRUFDWkc5R1RlcDlVRkhYeTk2NU1vckpDMURZNUM3b09tQnZkNVVw?= =?utf-8?B?VXJtR0hZczFrWnZMZCtPRU05ekdlU3BxR056UG5EREJLcGhLc2JBS09PQzly?= =?utf-8?B?QXlyL0ozYlRrV1d0YXo4TWVOb0NyaGEzaUVnb0tWbVhpbytMdzQrMjFFZ1h3?= =?utf-8?B?eitCUlJUUk9rSUdac3NLT0ZEODNWYXFkV0NiKzlUbHE3OEUvdWQ3aksrR1Qy?= =?utf-8?B?cXZOV2ZnMi9WdjdSM0FPdFViRUg1aDhxZk80NS9VYWpNQ3ZDMlM2Ui9vZDJk?= =?utf-8?B?K1p5MEoxNWM1VUUwNk0wSW03M3FFaEhKWlhOTGw5M0FINkZjc3U2MStDVzR4?= =?utf-8?B?WkNnTmdIV0lZSVNsWGlWSkFrSERsbVF6ZytrMERVRVQyeGpybldQNTVRZDhG?= =?utf-8?B?eDU3aTdpU3RTWjRCejlDQjJndFB2bW9LbzRzb3JEN0tuL2Mra1pCeE9UcTAy?= =?utf-8?B?aGdZWWpvQjFpQmRBTEV3eHVxZ0hBQVU4UlltazNHb09sK2VUREJSbkRYT2dq?= =?utf-8?B?djhvSVNZVTgxM0JJYkNpVUt1ZDlvaUlHWElJMmJZM1VQenpTTGZnbmRlSHdN?= =?utf-8?B?aHNzM2M2OGRkd3lpdjZQRVpnTGRtTUVIRlNXMzYraVJuV3duN0tQL1I0ck5G?= =?utf-8?B?ZnVzd00vU25kMDNmQjFRN3plTzJHck15cTVtQUVrdkZyUDY2QVE5OHNmQVVi?= =?utf-8?B?VTU1dk1iWERJNXlmcVZkN05KWFlKNng3K0VLWEFUcHhYdUdIM1NyWm9BQWs4?= =?utf-8?B?Z2VrNlRvNGRZQ0ljZHpOY1BhSDBFQlRMQ1NyRThWRW0zT1JVMWFFckJ1c1RM?= =?utf-8?B?ci9md2xtbWV0Z3RiSkFnQWFMZGw0UDhZQzU2ejFFL3VSN2xVV1kzUGZmN2lx?= =?utf-8?B?OURKU3FrZ25vU1VudXByMTBhYThrS0g2eXMvVm9yRDRjSSsrTFpuV25wRFYz?= =?utf-8?B?bzg5VHBUUENVZkJZdzg3RXhodWtQeDloN0wvbGhZOGpDdXhnMEhNbXZEU2VR?= =?utf-8?B?UEFUaVFKUEZvMC9SY1lHdURMa0F5cTE2ZFlEaTN1KzhFdzBDbUlFSm1zeEFB?= =?utf-8?B?ZE1XUVlIYlVMOXVqVjRQMERrZEM0ZU15R0xMTG5QZGtGL1dsbTNXM1p0MDJE?= =?utf-8?B?dzFxOWNmUytDb3k4Nm4vTWlqSllESzByN3RXa29Dc0Njb2UwMkN2eTlWK0V2?= =?utf-8?B?RGRRR1k1aTdZdTkvcGJJa2FHRTdzMW5RMkFQSzU3SFBrMUlrUE5ZdjRVRmxW?= =?utf-8?B?aVFld2pma0s5Y2xzUzBxQ3d5Q2VyR1lHK0VJVHJNNEJndU9HOEhPZHFlVzl5?= =?utf-8?B?UElnSG02T2NuQ1FvTUlSa2x6ZFNxdHdFMVFPMitUYnd6eEtaWHFtcTVpdW1D?= =?utf-8?B?SkI3V2IrbmxQOGtHWDFBQjlXMDFTcUJmRGQ1L0grM1VYS051UEpqUW5ST1Y1?= =?utf-8?B?MHdJbUlOY3JhR1Nxb0VyTHJhV3gvVXp0dmpPTVN0VDVEWm1EUVpWRW1pTzNj?= =?utf-8?B?Z0FQQlFSaGs0V09mZXdVblJWbU9GdjhPY1pNbUdyc0dVYTN6aUtiMW80TDlG?= =?utf-8?B?QjdFRk5YTW1XNUR1VEJFOUJQMEZmMU1ka01TQzhlSDNBKzZUQjk5REtHRU91?= =?utf-8?B?cW4vMGhBeDduZS9aQ285d1FVcGF3RXVueGtNZFhJRERyb3lUVlJTaUhUSWV5?= =?utf-8?B?d09yVi9xc3V1UXRFZ3hJOVVJOFNYZ0xzWTJiSGRBdlJjOTRpalVDbWVVdFk2?= =?utf-8?B?cm1QN29RL3RFanRCRzdSalJITkYwblF2eWxGcFNKMGFMd1hxd1MybHRwRkli?= =?utf-8?Q?cRXlL6DVSStJC6rsIlBQQkcNZ7p47pe7ItEjV8nBfrMhB?= X-MS-Exchange-AntiSpam-MessageData-1: tRPaQppXMbNwWw== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 73b3bb60-11f9-4213-1086-08dea7477a9e X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 May 2026 06:04:17.6486 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 210ljDhwoxuwi6/0/zFoqqEwvk9gaBqgCFLfQLVIXzU+eADsYw+esRvesGoXUWBJlXvzVTieuuGECy8bQ3r6YA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR12MB8584 Extract the bitfield-defining part of the `register!` macro into an independent macro used to define bitfield types with bounds-checked accessors. Each field is represented as a `Bounded` of the appropriate bit width, ensuring field values are never silently truncated. Fields can optionally be converted to/from custom types, either fallibly or infallibly. Appropriate documentation is also added, and a MAINTAINERS entry created for the new module. Signed-off-by: Alexandre Courbot Acked-by: Yury Norov --- MAINTAINERS | 8 + rust/kernel/bitfield.rs | 546 ++++++++++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/lib.rs | 1 + 3 files changed, 555 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2fb1c75afd16..b685f364cee4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23377,6 +23377,14 @@ T: git https://github.com/Rust-for-Linux/linux.git= alloc-next F: rust/kernel/alloc.rs F: rust/kernel/alloc/ =20 +RUST [BITFIELD] +M: Alexandre Courbot +M: Joel Fernandes +R: Yury Norov +L: rust-for-linux@vger.kernel.org +S: Maintained +F: rust/kernel/bitfield.rs + RUST [INTEROP] M: Joel Fernandes M: Alexandre Courbot diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs new file mode 100644 index 000000000000..4083e7b7a307 --- /dev/null +++ b/rust/kernel/bitfield.rs @@ -0,0 +1,546 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Support for defining bitfields as Rust structures. +//! +//! The [`bitfield!`](kernel::bitfield!) macro declares integer types that= are split into distinct +//! bit fields of arbitrary length. Each field is typed using [`Bounded`](= kernel::num::Bounded) to +//! ensure values are properly validated and to avoid implicit data loss. +//! +//! # Example +//! +//! ```rust +//! use kernel::bitfield; +//! use kernel::num::Bounded; +//! +//! bitfield! { +//! pub struct Rgb(u16) { +//! 15:11 blue; +//! 10:5 green; +//! 4:0 red; +//! } +//! } +//! +//! // Valid value for the `blue` field. +//! let blue =3D Bounded::::new::<0x18>(); +//! +//! // Setters can be chained. Values ranges are checked at compile-time. +//! let color =3D Rgb::zeroed() +//! // Compile-time bounds check of constant value. +//! .with_const_red::<0x10>() +//! .with_const_green::<0x1f>() +//! // A `Bounded` can also be passed. +//! .with_blue(blue); +//! +//! assert_eq!(color.red(), 0x10); +//! assert_eq!(color.green(), 0x1f); +//! assert_eq!(color.blue(), 0x18); +//! assert_eq!( +//! color.into_raw(), +//! (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10, +//! ); +//! +//! // Convert to/from the backing storage type. +//! let raw: u16 =3D color.into(); +//! assert_eq!(Rgb::from(raw), color); +//! ``` +//! +//! # Syntax +//! +//! ```text +//! bitfield! { +//! #[attributes] +//! // Documentation for `Name`. +//! pub struct Name(storage_type) { +//! // `field_1` documentation. +//! hi:lo field_1; +//! // `field_2` documentation. +//! hi:lo field_2 =3D> ConvertedType; +//! // `field_3` documentation. +//! hi:lo field_3 ?=3D> ConvertedType; +//! ... +//! } +//! } +//! ``` +//! +//! - `storage_type`: The underlying unsigned integer type (`u8`, `u16`, `= u32`, `u64`). +//! Signed integer storage types are not supported. +//! - `hi:lo`: Bit range (inclusive), where `hi >=3D lo`. +//! - `=3D> Type`: Optional infallible conversion (see [below](#infallible= -conversion-)). +//! - `?=3D> Type`: Optional fallible conversion (see [below](#fallible-co= nversion-)). +//! - Documentation strings and attributes are optional. +//! +//! # Generated code +//! +//! Each field is internally represented as a [`Bounded`] parameterized by= its bit width. Field +//! values can either be set/retrieved directly, or converted from/to anot= her type. +//! +//! The use of `Bounded` for each field enforces bounds-checking (at build= time or runtime) of every +//! value assigned to a field. This ensures that data is never accidentall= y truncated. +//! +//! The macro generates the bitfield type, [`From`] and [`Into`] implement= ations for its storage +//! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implem= entations. +//! +//! For each field, it also generates: +//! +//! - `field()`: Getter method for the field value. +//! - `with_field(value)`: Infallible setter; the argument type must fit w= ithin the field's width. +//! - `with_const_field::()`: `const` setter; the value is validate= d at compile time. +//! Usually shorter to use than `with_field` for constant values as it d= oesn't require +//! constructing a [`Bounded`]. +//! - `try_with_field(value)`: Fallible setter. Returns an error if the va= lue is out of range. +//! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit= manipulation. +//! +//! # Reserved names for field identifiers +//! +//! Field identifiers are used to generate methods and associated constant= s on the bitfield type. +//! For a field named `field`, the macro may generate methods named `field= `, `with_field`, +//! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as= well as constants named +//! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`. +//! +//! Therefore, field identifiers must not use names that would collide wit= h generated items for +//! any field in the same bitfield. The following prefixes are thus reserv= ed for field identifiers: +//! +//! - `with_` +//! - `const_` +//! - `try_with_` +//! - `__` +//! +//! The field identifiers `from_raw`, `into_raw`, and `into` are also rese= rved. +//! +//! In addition, field identifiers should follow Rust `snake_case` convent= ions, since the associated +//! constants are generated by uppercasing the field name. +//! +//! # Implicit conversions +//! +//! Types that fit entirely within a field's bit width can be used directl= y with setters. For +//! example, `bool` works with single-bit fields, and `u8` works with 8-bi= t fields: +//! +//! ```rust +//! use kernel::bitfield; +//! +//! bitfield! { +//! pub struct Flags(u32) { +//! 15:8 byte_field; +//! 0:0 flag; +//! } +//! } +//! +//! let flags =3D Flags::zeroed() +//! .with_byte_field(0x42_u8) +//! .with_flag(true); +//! +//! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1); +//! ``` +//! +//! # Runtime bounds checking +//! +//! When a value is not known at compile time, use `try_with_field()` to c= heck bounds at runtime: +//! +//! ```rust +//! use kernel::bitfield; +//! +//! bitfield! { +//! pub struct Config(u8) { +//! 3:0 nibble; +//! } +//! } +//! +//! fn set_nibble(config: Config, value: u8) -> Result { +//! // Returns `EOVERFLOW` if `value > 0xf`. +//! config.try_with_nibble(value) +//! } +//! # Ok::<(), Error>(()) +//! ``` +//! +//! # Type conversion +//! +//! Fields can be automatically converted to/from a custom type using `=3D= >` (infallible) or `?=3D>` +//! (fallible). The custom type must implement the appropriate `From` or `= TryFrom` traits with +//! `Bounded`. +//! +//! ## Infallible conversion (`=3D>`) +//! +//! Use this when all possible bit patterns of a field map to valid values: +//! +//! ```rust +//! use kernel::bitfield; +//! use kernel::num::Bounded; +//! +//! #[derive(Debug, Clone, Copy, PartialEq)] +//! enum Power { +//! Off, +//! On, +//! } +//! +//! impl From> for Power { +//! fn from(v: Bounded) -> Self { +//! match *v { +//! 0 =3D> Power::Off, +//! _ =3D> Power::On, +//! } +//! } +//! } +//! +//! impl From for Bounded { +//! fn from(p: Power) -> Self { +//! (p as u32 !=3D 0).into() +//! } +//! } +//! +//! bitfield! { +//! pub struct Control(u32) { +//! 0:0 power =3D> Power; +//! } +//! } +//! +//! let ctrl =3D Control::zeroed().with_power(Power::On); +//! assert_eq!(ctrl.power(), Power::On); +//! ``` +//! +//! ## Fallible conversion (`?=3D>`) +//! +//! Use this when some bit patterns of a field are invalid. The getter ret= urns a [`Result`]: +//! +//! ```rust +//! use kernel::bitfield; +//! use kernel::num::Bounded; +//! +//! #[derive(Debug, Clone, Copy, PartialEq)] +//! enum Mode { +//! Low =3D 0, +//! High =3D 1, +//! Auto =3D 2, +//! // 3 is invalid +//! } +//! +//! impl TryFrom> for Mode { +//! type Error =3D u32; +//! +//! fn try_from(v: Bounded) -> Result { +//! match *v { +//! 0 =3D> Ok(Mode::Low), +//! 1 =3D> Ok(Mode::High), +//! 2 =3D> Ok(Mode::Auto), +//! n =3D> Err(n), +//! } +//! } +//! } +//! +//! impl From for Bounded { +//! fn from(m: Mode) -> Self { +//! match m { +//! Mode::Low =3D> Bounded::::new::<0>(), +//! Mode::High =3D> Bounded::::new::<1>(), +//! Mode::Auto =3D> Bounded::::new::<2>(), +//! } +//! } +//! } +//! +//! bitfield! { +//! pub struct Config(u32) { +//! 1:0 mode ?=3D> Mode; +//! } +//! } +//! +//! let cfg =3D Config::zeroed().with_mode(Mode::Auto); +//! assert_eq!(cfg.mode(), Ok(Mode::Auto)); +//! +//! // Invalid bit pattern returns an error. +//! assert_eq!(Config::from(0b11).mode(), Err(3)); +//! ``` +//! +//! # Bits outside of declared fields +//! +//! Bits of the storage type that are not part of any declared field are p= reserved by the setter +//! methods, and can only be modified through `from_raw` or the [`From`] i= mplementation from the +//! storage type. +//! +//! ```rust +//! use kernel::bitfield; +//! +//! bitfield! { +//! pub struct Sparse(u8) { +//! 7:6 high; +//! // Bits 5:1 are not covered by any field. +//! 0:0 low; +//! } +//! } +//! +//! // Set the gap bits via `from_raw`, then mutate the declared fields. +//! let val =3D Sparse::from_raw(0b0010_1010) +//! .with_const_high::<0b11>() +//! .with_low(true); +//! +//! // Bits 5:1 are unchanged. +//! assert_eq!(val.into_raw(), 0b1110_1011); +//! ``` +//! +//! # Signed field values +//! +//! Bitfield storage types are unsigned. Since field getter methods return= a [`Bounded`] of the +//! storage type, fields are also unsigned by default. +//! +//! If a field needs to encode a signed value, use a custom conversion typ= e with `=3D>` or `?=3D>` to +//! perform the sign interpretation explicitly. +//! +//! [`Bounded`]: kernel::num::Bounded + +/// Defines a bitfield struct with bounds-checked accessors for individual= bit ranges. +/// +/// See the [`mod@kernel::bitfield`] module for full documentation and exa= mples. +#[macro_export] +macro_rules! bitfield { + // Entry point defining the bitfield struct, its implementations and i= ts field accessors. + ( + $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fi= elds:tt)* } + ) =3D> { + $crate::bitfield!(@core + #[allow(non_camel_case_types)] + $(#[$attr])* $vis $name $storage + ); + $crate::bitfield!(@fields $vis $name $storage { $($fields)* }); + }; + + // All rules below are helpers. + + // Defines the wrapper `$name` type and its conversions from/to the st= orage type. + (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) =3D> { + $(#[$attr])* + #[repr(transparent)] + #[derive(Clone, Copy, PartialEq, Eq)] + $vis struct $name { + inner: $storage, + } + + #[allow(dead_code)] + impl $name { + /// Creates a bitfield from a raw value. + #[inline(always)] + $vis const fn from_raw(value: $storage) -> Self { + Self{ inner: value } + } + + /// Turns this bitfield into its raw value. + /// + /// This is similar to the [`From`] implementation, but is sho= rter to invoke in + /// most cases. + #[inline(always)] + $vis const fn into_raw(self) -> $storage { + self.inner + } + } + + // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. + unsafe impl ::pin_init::Zeroable for $name {} + + impl ::core::convert::From<$name> for $storage { + #[inline(always)] + fn from(val: $name) -> $storage { + val.into_raw() + } + } + + impl ::core::convert::From<$storage> for $name { + #[inline(always)] + fn from(val: $storage) -> $name { + Self::from_raw(val) + } + } + }; + + // Definitions requiring knowledge of individual fields: private and p= ublic field accessors, + // and `Debug` implementation. + (@fields $vis:vis $name:ident $storage:ty { + $($(#[doc =3D $doc:expr])* $hi:literal:$lo:literal $field:ident + $(?=3D> $try_into_type:ty)? + $(=3D> $into_type:ty)? + ; + )* + } + ) =3D> { + #[allow(dead_code)] + impl $name { + $( + $crate::bitfield!(@private_field_accessors $vis $name $storage : $= hi:$lo $field); + $crate::bitfield!( + @public_field_accessors $(#[doc =3D $doc])* $vis $name $storag= e : $hi:$lo $field + $(?=3D> $try_into_type)? + $(=3D> $into_type)? + ); + )* + } + + $crate::bitfield!(@debug $name { $($field;)* }); + }; + + // Private field accessors working with the exact `Bounded` type for t= he field. + ( + @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt= :$lo:tt $field:ident + ) =3D> { + ::kernel::macros::paste!( + $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive =3D $lo..=3D$hi; + $vis const [<$field:upper _MASK>]: $storage =3D + ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); + $vis const [<$field:upper _SHIFT>]: u32 =3D $lo; + ); + + ::kernel::macros::paste!( + fn [<__ $field>](self) -> + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { + // Left shift to align the field's MSB with the storage MSB. + const ALIGN_TOP: u32 =3D $storage::BITS - ($hi + 1); + // Right shift to move the top-aligned field to bit 0 of the s= torage. + const ALIGN_BOTTOM: u32 =3D ALIGN_TOP + $lo; + + // Extract the field using two shifts. `Bounded::shr` produces= the correctly-sized + // output type. + let val =3D ::kernel::num::Bounded::<$storage, { $storage::BIT= S }>::from( + self.inner << ALIGN_TOP + ); + val.shr::() + } + + const fn [<__with_ $field>]( + mut self, + value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, + ) -> Self + { + const MASK: $storage =3D <$name>::[<$field:upper _MASK>]; + const SHIFT: u32 =3D <$name>::[<$field:upper _SHIFT>]; + + let value =3D value.get() << SHIFT; + self.inner =3D (self.inner & !MASK) | value; + + self + } + ); + }; + + // Public accessors for fields infallibly (`=3D>`) converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:literal:$lo:literal $field:ident =3D> $into_type:ty + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> $into_type + { + self.[<__ $field>]().into() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn [](self, value: $into_type) -> Self + { + self.[<__with_ $field>](value.into()) + } + + ); + }; + + // Public accessors for fields fallibly (`?=3D>`) converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:tt:$lo:tt $field:ident ?=3D> $try_into_type:ty + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> + Result< + $try_into_type, + <$try_into_type as ::core::convert::TryFrom< + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> + >>::Error + > + { + self.[<__ $field>]().try_into() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn [](self, value: $try_into_type) -> Self + { + self.[<__with_ $field>](value.into()) + } + + ); + }; + + // Public accessors for fields not converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:tt:$lo:tt $field:ident + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> + { + self.[<__ $field>]() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the compile-time constant `VALUE`."] + #[inline(always)] + $vis const fn [](self) = -> Self { + self.[<__with_ $field>]( + ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new= ::() + ) + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn []( + self, + value: T, + ) -> Self + where T: Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo= }>>, + { + self.[<__with_ $field>](value.into()) + } + + $(#[doc =3D $doc])* + #[doc =3D "Tries to set this field to `value`, returning an error = if it is out of range."] + #[inline(always)] + $vis fn []( + self, + value: T, + ) -> ::kernel::error::Result + where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $= lo }>, + { + Ok( + self.[<__with_ $field>]( + value.try_into_bounded().ok_or(::kernel::error::code::= EOVERFLOW)? + ) + ) + } + + ); + }; + + // `Debug` implementation. + (@debug $name:ident { $($field:ident;)* }) =3D> { + impl ::kernel::fmt::Debug for $name { + fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kerne= l::fmt::Result { + f.debug_struct(stringify!($name)) + .field("", &::kernel::prelude::fmt!("{:#x}", self= .inner)) + $( + .field(stringify!($field), &self.$field()) + )* + .finish() + } + } + }; +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index b72b2fbe046d..9512af7156df 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -44,6 +44,7 @@ pub mod alloc; #[cfg(CONFIG_AUXILIARY_BUS)] pub mod auxiliary; +pub mod bitfield; pub mod bitmap; pub mod bits; #[cfg(CONFIG_BLOCK)] --=20 2.54.0 From nobody Sun Jun 14 07:35:30 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011045.outbound.protection.outlook.com [40.93.194.45]) (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 9ABB034AAF2; Fri, 1 May 2026 06:04:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.45 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615469; cv=fail; b=igKC6erbnA+TgUaFXZ410dVZbAm6kGDR2oi7gOd/rRMKJ057I7K8Vh/3TNuX3hbHDLLVOJd98F9bjDufsv3P+wlEpRZltNuAYhGWd+uRnDdwbtDBiZ+rjs2QE/pdggbLuZlUuAjLa40GRGGJFt6nlcjv/3OkvVi9YZZ7nW2W27c= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615469; c=relaxed/simple; bh=3YZJjm3Cf45diHV7cv+Eh7Pe+VhW1QWp+Qov68ZU/0g=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=m7lcXufdTsw722aOItpGgNaY4LMV6cp7HkSXBBg84VS1nAnkypu2xL2//kqClozYo/eefoi3d02UChoMqD+lML/oEoEyAJu8wfzNGBNFLtUp4hT1Yt38KfDoRkqVPyUGONOQRiQOuZ8SWt81BBzk9NplqEa4rnCVXctWoexHk44= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=SBY6sK1i; arc=fail smtp.client-ip=40.93.194.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="SBY6sK1i" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ucr1RXJRgBEuoDQsCylvCVHlq0RLOcZ8gcpyFNEJIxTZ1HUNizycbtHACsg4myLJ6s6cGwFzyMwxFVQSAXdKWeL+a+6KeOcSEi2G7+wbIw87aFBRydctRP6R08QotIB1iygRlrwAR2NkjK2l0R19CbD7h6ujVFCbZ1LYK9b/0EYTqisrsO4QHclgzu2LlFX66yodEJQpLhfYFtpank42ejT4b53BTCTPDbILM7BLOy7x3H2N+oncC4l+UYUVGb7EGiRLmrNyFX8Vsa7BknMy77Bjd2rif20aDkPusd2OJn1HA9LC4sF3NtuQHNP/8u96EIzqQS+lR3Bibm4tym0Jtg== 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=XjCYBrCqA31WEFNVLPNt1+SphBEc0iS5+z7lPgsoFc8=; b=Yqqyw9tdPB1ECcrKc97Q83z2+cCicy3M84KIKj06el2OdzGmLiCtjnXAmtbJqFfXfqC+CYqujgaJFSWASzEGbw+oksT3TJ49gH4nAZuhxDBNMQkcEcgOo51fe4Bp46HF4Ty5okeeCEo8zlkyq0ID8rkwg8AkGarHOqF/No4vP8s1+Ii0EIaL11A9rR8UGILNbG+LuQjT1jStZ+atAd3FpVawkkjqYSkNk6JZhaACs1c+7CEC1eRqF0S7STHB8pz+LAKSkLWmt7WVdiraIZeNU0nCjkwEg6BToiPQNg3sqYo9K6+y/aYQcXnb7ZadBF2VftbNaEOhTR9e3iJGEd4aGA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XjCYBrCqA31WEFNVLPNt1+SphBEc0iS5+z7lPgsoFc8=; b=SBY6sK1iyIY3kbHT1uWj1rOwn1fRhU6ENQzQEkjaxPGtayN3RCuJzFMW1svu06kWvuq89yuS4z3sQd7UWSIB6UiPqrl5IPbtqR38l7GkXyyjPtRsX/7rztWlkXpgTUztUG3rUnRyQdzIsgn47IPgepbKw5Zv3ETIEDJ7nyoX+bPM/WUsTvPL8axutDPt34L2uoHqYeUe/3nGIeD67Xiv9PX4JeS9WnwAqQQdQbhIyOfP6SonHTxdkHfvd3m+yH3JxFFO7uFyAuAHL3IuhvSwcrqRTsHWd5qm5sWkLzIEt8Y3rYIFt96GtlfVEXOFmueSS14w1qYNj5ksCBXsSk3JEg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by CH3PR12MB8584.namprd12.prod.outlook.com (2603:10b6:610:164::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.22; Fri, 1 May 2026 06:04:21 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%4]) with mapi id 15.20.9870.013; Fri, 1 May 2026 06:04:21 +0000 From: Alexandre Courbot Date: Fri, 01 May 2026 15:03:19 +0900 Subject: [PATCH v3 2/5] rust: bitfield: Add KUnit tests for bitfield Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260501-bitfield-v3-2-aa1076c3337d@nvidia.com> References: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> In-Reply-To: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> To: Joel Fernandes , Yury Norov , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , David Airlie , Simona Vetter Cc: John Hubbard , Alistair Popple , Timur Tabi , Zhi Wang , Eliot Courtney , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, nova-gpu@lists.linux.dev, driver-core@lists.linux.dev, Alexandre Courbot X-Mailer: b4 0.15.2 X-ClientProxiedBy: TYCP286CA0364.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:79::8) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) 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: CH2PR12MB3990:EE_|CH3PR12MB8584:EE_ X-MS-Office365-Filtering-Correlation-Id: 00b8bc49-6f77-42d2-912b-08dea7477ce1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|7416014|376014|10070799003|18002099003|921020|56012099003|22082099003; X-Microsoft-Antispam-Message-Info: Fg6JQLtaQWiWczYv5OQqfxQgCPUbdo0Dzn0D0Uhu2TGqH1eAIV1Y/U0FOv4HrkycbWb75APcFh7K48FhN6SKj6Fi5x73dvZQtB0KghJxABsuD3YISifKO4A4k0BF6kP7lRIK3Ar/oxfzJmx3RtNxhczR5JriHjt5PGyUnnSeS/vchwb+P46fPKWCH4EWZmc+hR2cCpSSr3uK+e8l4oZk7bk62Ct/t90Q1SAl7Ha+ZvcUY93+gKkAZ7fW5p/2B+54fOQmaWEM+gLp0zVy8Ppx0ODr1ohyE1FSvdcsVWv6GN8vLd6B7CPeHcSTdtXAih2swFXHOnzKUTVW0OqlxRgaJnsOQ423/haGMas8NkgmQkhyLmAjwreC3UF1O/HyJtXy1WR7WDCg7MAHApSjhLjCjjqKAmomFBOXjLSbMF4qTDsjYjBAtmNWuAtnq3JGeFq0KQ/0SR052Rnf2an699a+jYjzNEXRJE1C/Z6vsK32mFOQKilXRj0CeLbNgh2+j2ttowKOo3CfrH8SdK9mspvaU9xFIUV5el2q+6HHu8+7a4WJwA0hr5xJBHp/I+53HQ+Q9n5fErYaDwxuybHW4BZhOKL1rZ3myrtU5upbuw/N/oq9m5oUQitvtDhX+Luer01JSOnualazXHqafR4c67NEiVWmgoJvahuPkhcdsRduBG7yfvi1wPgIKRn0ocDcSJvZyouBY2O54cfaVEJWEnWQ3XQhuHvY5PlUu/Y3hcDgNTE= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(7416014)(376014)(10070799003)(18002099003)(921020)(56012099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?Z1dWemlQeHgvVEpzVWVQdU5KL1R6T0pDYjVqQlpwL0F6ZWF6b2F4MFcwekUr?= =?utf-8?B?RWVEUmw1cU1IeVlDMGRYRVlLV0NOdERrcGJGdnRiZHo4MitRSmtHL002cTEx?= =?utf-8?B?SkpEbUxMZEUxem95aVpCRjVHakF0VGU0UnZxU05vc0ROUXJJOUJ1L1ZNdjQ2?= =?utf-8?B?ckdXVyt6NXFnc2Qyampsd3lzeWtTVU9INVNkZEFTK3pEWGVHSXpVc1B5WUhM?= =?utf-8?B?L0MrZWhiWWhTTHRkKzNiMGdmMTJOQ1E4d3ZvZHROR0lva2xCbjJ5TDdISVRC?= =?utf-8?B?aE4zbjBnNkJWS3ZhSFh6MTl6MWY0OEx0dXgySU5PeWRhbE9jcHIzejJ4cHRT?= =?utf-8?B?emg5Zmt6UDF1cFZiNzI1YUtmUHdoYmRXQzFhaU5NWGM1bE5wcm45MVN6KzZa?= =?utf-8?B?bE5ManRpd2htTkhXMmNPc3lRM0N5R3ZoRWZiSzVVL3dDR0RCL2ozNzlVOEpQ?= =?utf-8?B?MGdDdnJ6M0ZqTVdUaXc3VU9aTFRhRkw1aGQ4WWtnYzdwMEZLdnNiQ1E3a0w3?= =?utf-8?B?QXVQTC80eGR1YUR4ZXZiMVhhRkVNZExHYjZHdUhSVEZ3elRHU2FDYS9mbCto?= =?utf-8?B?ODc4TTIzbkdNN0twZjdwSlY0THlOSDZ4NjZmMFgyc1VxM1FEU1FxUUllWXY3?= =?utf-8?B?bzF1QUFUbkltbWNJKzJ3TXVMWGtpc0UvVjdENVlydjlURGJOWjhpQktEZSt6?= =?utf-8?B?MzRYb3FlMzNtK3F3aVJVWEFSS0ZBV1NvWnY1Yi96VlgyUHhaSVQ2UHpON0FK?= =?utf-8?B?Y3Vob0FVNG83dTRSNkpTRm10eENSM2hwV0M5b1FFTzJNdjVWelAzWjdlQ2oy?= =?utf-8?B?dHB5TkZuOFZwV3ZTNk52M3d1ZWR5VVFJblZNWXp3SzE1N042SHJxdTVsMStT?= =?utf-8?B?eUZiMnhGRUZwcmpON3F0Rlg4bS93VnJRZS9DaS82SjZGcXhaMHJFSUdxcXkw?= =?utf-8?B?Zy9sMWlIZmFpTGdUaUJCTnFZdkxJVStvbjhWNG02Vk1nZWwvQXlNZ1c2TFdn?= =?utf-8?B?cmhkQkFPWFl2dldINWdnd3pZNXBkdEhPRjBUbmd2bDRXWVE0dzFDYlJCRXR6?= =?utf-8?B?YzZuQ3lRUngvNW4rN2VPdzRISXAwZm4xcFk5NFJ6eUc2UXdGekQ4TUlmK0Fr?= =?utf-8?B?V2o4S0k3djVtTWl3aGNzb1pWQUc3Q2RTK1Vvem1ibXMwMUVkWGRobE55NG81?= =?utf-8?B?RFFleTZnMmpGQkRaNVpQMGFzWHZRNHRpMFpZNE1tUWtudXN5dloxUldud2w5?= =?utf-8?B?Rzc2ZE9xZTVCblhUbWxrUmFBOHVyWmlhdFVpY3BGZ1h2S01GNFpYREY3YlBO?= =?utf-8?B?UEJpOU5ZbXRCTEV3dWRjMnkxaVo4Rk1iVEJRUVRHbzluMTVmN2hPUUNZUy9L?= =?utf-8?B?RW1pUFJWWEtFd3BCTm9XaGcyYTZWZWRZbWxrTHdrQTZzdStNK3NmMXFiaUow?= =?utf-8?B?RU1PZlFHbnhuUzlERzN5Wms2S1hLaktqKzQ3YmFDZmxycTMvWlJoVm8zMlB5?= =?utf-8?B?Y05QUG9UdzF0ZjJWSXVRY2ZkZkIwQUtNbFNhTjB2c0c4SURpRmtLQytKK0xB?= =?utf-8?B?YUVEVXJua1grRm9jY0VlNzR6S0d5WXpOTkZEQTlZbkR0elRtM0xjR1AxNEJF?= =?utf-8?B?Q1o4NHdWNHRjMWZlNDg3bHZlRGxIUVpvellIZnVMSVFMRHNYaUdFeUVPbDVh?= =?utf-8?B?VnI1MlRyWUdkYzVNMlYzZ2JQdmFoSWo4Vm5hUS82OGNsbzQ1T0RMNGFVbHZP?= =?utf-8?B?NFo2NHAvQ2NpZ0laR2ZLTXBOeEV6UGZKWXFZUnN4WUZVTW9YVlg0aTl3UFll?= =?utf-8?B?RG42bjlMaXZkVzZmNUhMa3ltSWJIWklKWDNveUJjL1g5UXg0elpkcW02R2Y2?= =?utf-8?B?U3VCY2YwTW15QlpOdjdzVzI0VmRVYnRMSmY1dEdJUytsTWhPVFhyeHdOQlR4?= =?utf-8?B?MkpoY1VmZU8wSUt3OEIrS1ppRndvbkpySGhyTGpGTGJ4NHMvTmZVaUJKK2Q0?= =?utf-8?B?YUhVUVdqcnZ1My9ablBDaHdVeEc5bGF5YVdKRXoybU5FdURDMzFoZERZU05i?= =?utf-8?B?U0VUM1lWWTAxNUdTOW5hUC9WTVhRRlNGaHFBQXpVQjk0VHZHRjN6amk5Q1pl?= =?utf-8?B?S3lnMlBIcDM0dUY2MjUrRnNEWTNhREpHUjFrakdPeXlHQmRjd2dCdDJRMnBY?= =?utf-8?B?RXJ3SE9WRlN0VjFhb1hsOWorak9rWFl3dlFhNmZCOTk4YWVaalhZMkJCNEQ2?= =?utf-8?B?MU10bEhjZHMyYWNSVmdlOVAvTWlYc2FhUDFmL2JmVk95Qmh1Snk1ekhwVUE2?= =?utf-8?B?aFlXRmZWRG10S1ZuNjkvcUc4Mk50ck1QbWtyNnJOTy83QXY0QmVjWXp0ZFFo?= =?utf-8?Q?IPm1f8DmeRbbIprcTqeW+OGW6m1R94a8/RdJE8OWq/WV4?= X-MS-Exchange-AntiSpam-MessageData-1: PX8HnTHSKWOTIA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 00b8bc49-6f77-42d2-912b-08dea7477ce1 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 May 2026 06:04:21.4308 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: BNF+gnbRDROVDo+RvIubwFsgZlJfCaPMvAvuL1PGcM9OKQprD4Nj1ziIzBIpY4dA3+v6ivo+dzt0xP+5Qp26tQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR12MB8584 From: Joel Fernandes Add KUNIT tests to make sure the macro is working correctly. The unit tests are put behind the new `RUST_KERNEL_BITFIELD_KUNIT_TEST` Kconfig option. Signed-off-by: Joel Fernandes Co-developed-by: Alexandre Courbot Signed-off-by: Alexandre Courbot Reviewed-by: Eliot Courtney --- lib/Kconfig.debug | 12 ++ rust/kernel/bitfield.rs | 319 ++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 331 insertions(+) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 8ff5adcfe1e0..916bf066c016 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -3608,6 +3608,18 @@ config RUST_KERNEL_DOCTESTS =20 If unsure, say N. =20 +config RUST_KERNEL_BITFIELD_KUNIT_TEST + bool "KUnit tests for the Rust `bitfield!` macro" if !KUNIT_ALL_TESTS + depends on RUST && KUNIT=3Dy + default KUNIT_ALL_TESTS + help + This builds the KUnit tests for the Rust `bitfield!` macro. + + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. + config RUST_INLINE_HELPERS bool "Inline C helpers into Rust code (EXPERIMENTAL)" depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs index 4083e7b7a307..66358e6371f1 100644 --- a/rust/kernel/bitfield.rs +++ b/rust/kernel/bitfield.rs @@ -544,3 +544,322 @@ fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -= > ::kernel::fmt::Result { } }; } + +#[cfg(CONFIG_RUST_KERNEL_BITFIELD_KUNIT_TEST)] +#[::kernel::macros::kunit_tests(kernel_bitfield)] +mod tests { + use core::convert::TryFrom; + + use pin_init::Zeroable; + + use kernel::num::Bounded; + + // Enum types for testing =3D> and ?=3D> conversions + #[derive(Debug, Clone, Copy, PartialEq)] + enum MemoryType { + Unmapped =3D 0, + Normal =3D 1, + Device =3D 2, + Reserved =3D 3, + } + + impl TryFrom> for MemoryType { + type Error =3D u64; + fn try_from(value: Bounded) -> Result { + match value.get() { + 0 =3D> Ok(MemoryType::Unmapped), + 1 =3D> Ok(MemoryType::Normal), + 2 =3D> Ok(MemoryType::Device), + 3 =3D> Ok(MemoryType::Reserved), + _ =3D> Err(value.get()), + } + } + } + + impl From for Bounded { + fn from(mt: MemoryType) -> Bounded { + Bounded::from_expr(mt as u64) + } + } + + #[derive(Debug, Clone, Copy, PartialEq)] + enum Priority { + Low =3D 0, + Medium =3D 1, + High =3D 2, + Critical =3D 3, + } + + impl From> for Priority { + fn from(value: Bounded) -> Self { + match value & 0x3 { + 0 =3D> Priority::Low, + 1 =3D> Priority::Medium, + 2 =3D> Priority::High, + _ =3D> Priority::Critical, + } + } + } + + impl From for Bounded { + fn from(p: Priority) -> Bounded { + Bounded::from_expr(p as u16) + } + } + + bitfield! { + struct TestPageTableEntry(u64) { + 61:52 available2; + 51:16 pfn; + 15:12 mem_type ?=3D> MemoryType; + 11:9 available; + 1:1 writable; + 0:0 present; + } + } + + bitfield! { + struct TestControlRegister(u16) { + 15:8 channel; + 7:4 priority_nibble; + 5:4 priority =3D> Priority; + 3:1 mode; + 0:0 enable; + } + } + + bitfield! { + struct TestStatusRegister(u8) { + 7:0 full_byte; // For entire register + 7:4 reserved; + 3:2 state; + 1:1 error; + 0:0 ready; + } + } + + #[test] + fn test_single_bits() { + let mut pte =3D TestPageTableEntry::zeroed(); + + assert!(!pte.present().into_bool()); + assert!(!pte.writable().into_bool()); + assert_eq!(u64::from(pte), 0x0); + + pte =3D pte.with_present(true); + assert!(pte.present().into_bool()); + assert_eq!(u64::from(pte), 0x1); + + pte =3D pte.with_writable(true); + assert!(pte.writable().into_bool()); + assert_eq!(u64::from(pte), 0x3); + + pte =3D pte.with_writable(false); + assert!(!pte.writable().into_bool()); + assert_eq!(u64::from(pte), 0x1); + + assert_eq!(pte.available(), 0); + pte =3D pte.with_const_available::<0x5>(); + assert_eq!(pte.available(), 0x5); + assert_eq!(u64::from(pte), 0xA01); + } + + #[test] + fn test_range_fields() { + let mut pte =3D TestPageTableEntry::zeroed(); + assert_eq!(u64::from(pte), 0x0); + + pte =3D pte.with_const_pfn::<0x123456>(); + assert_eq!(pte.pfn(), 0x123456); + assert_eq!(u64::from(pte), 0x1234560000); + + pte =3D pte.with_const_available::<0x7>(); + assert_eq!(pte.available(), 0x7); + assert_eq!(u64::from(pte), 0x1234560E00); + + pte =3D pte.with_const_available2::<0x3FF>(); + assert_eq!(pte.available2(), 0x3FF); + assert_eq!(u64::from(pte), 0x3FF0_0012_3456_0E00u64); + + // Test TryFrom with ?=3D> for MemoryType + pte =3D pte.with_mem_type(MemoryType::Device); + assert_eq!(pte.mem_type(), Ok(MemoryType::Device)); + assert_eq!(u64::from(pte), 0x3FF0_0012_3456_2E00u64); + + pte =3D pte.with_mem_type(MemoryType::Normal); + assert_eq!(pte.mem_type(), Ok(MemoryType::Normal)); + assert_eq!(u64::from(pte), 0x3FF0_0012_3456_1E00u64); + + // Test all valid values for mem_type + pte =3D pte.with_mem_type(MemoryType::Reserved); + assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved)); + assert_eq!(u64::from(pte), 0x3FF0_0012_3456_3E00u64); + + // Test failure case using mem_type field which has 4 bits (0-15) + // MemoryType only handles 0-3, so values 4-15 should return Err + let mut raw =3D pte.into_raw(); + // Set bits 15:12 to 7 (invalid for MemoryType) + raw =3D (raw & !::kernel::bits::genmask_u64(12..=3D15)) | (0x7 << = 12); + let invalid_pte =3D TestPageTableEntry::from_raw(raw); + // Should return Err with the invalid value + assert_eq!(invalid_pte.mem_type(), Err(0x7)); + + // Test a valid value after testing invalid to ensure both cases w= ork + // Set bits 15:12 to 2 (valid: Device) + raw =3D (raw & !::kernel::bits::genmask_u64(12..=3D15)) | (0x2 << = 12); + let valid_pte =3D TestPageTableEntry::from_raw(raw); + assert_eq!(valid_pte.mem_type(), Ok(MemoryType::Device)); + + const MAX_PFN: u64 =3D ::kernel::bits::genmask_u64(0..=3D35); + pte =3D pte.with_const_pfn::<{ MAX_PFN }>(); + assert_eq!(pte.pfn(), MAX_PFN); + } + + #[test] + fn test_builder_pattern() { + let pte =3D TestPageTableEntry::zeroed() + .with_present(true) + .with_writable(true) + .with_const_available::<0x7>() + .with_const_pfn::<0xABCDEF>() + .with_mem_type(MemoryType::Reserved) + .with_const_available2::<0x3FF>(); + + assert!(pte.present().into_bool()); + assert!(pte.writable().into_bool()); + assert_eq!(pte.available(), 0x7); + assert_eq!(pte.pfn(), 0xABCDEF); + assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved)); + assert_eq!(pte.available2(), 0x3FF); + } + + #[test] + fn test_raw_operations() { + let raw_value =3D 0x3FF0000031233E03u64; + + let pte =3D TestPageTableEntry::from_raw(raw_value); + assert_eq!(u64::from(pte), raw_value); + + assert!(pte.present().into_bool()); + assert!(pte.writable().into_bool()); + assert_eq!(pte.available(), 0x7); + assert_eq!(pte.pfn(), 0x3123); + assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved)); + assert_eq!(pte.available2(), 0x3FF); + + // Test using direct constructor syntax TestStruct(value) + let pte2 =3D TestPageTableEntry::from_raw(raw_value); + assert_eq!(u64::from(pte2), raw_value); + } + + #[test] + fn test_u16_bitfield() { + let mut ctrl =3D TestControlRegister::zeroed(); + + assert!(!ctrl.enable().into_bool()); + assert_eq!(ctrl.mode(), 0); + assert_eq!(ctrl.priority(), Priority::Low); + assert_eq!(ctrl.priority_nibble(), 0); + assert_eq!(ctrl.channel(), 0); + + ctrl =3D ctrl.with_enable(true); + assert!(ctrl.enable().into_bool()); + + ctrl =3D ctrl.with_const_mode::<0x5>(); + assert_eq!(ctrl.mode(), 0x5); + + // Test From conversion with =3D> + ctrl =3D ctrl.with_priority(Priority::High); + assert_eq!(ctrl.priority(), Priority::High); + assert_eq!(ctrl.priority_nibble(), 0x2); // High =3D 2 in bits 5:4 + + ctrl =3D ctrl.with_channel(0xAB); + assert_eq!(ctrl.channel(), 0xAB); + + // Test overlapping fields + ctrl =3D ctrl.with_const_priority_nibble::<0xF>(); + assert_eq!(ctrl.priority_nibble(), 0xF); + assert_eq!(ctrl.priority(), Priority::Critical); // bits 5:4 =3D 0= x3 + + let ctrl2 =3D TestControlRegister::zeroed() + .with_enable(true) + .with_const_mode::<0x3>() + .with_priority(Priority::Medium) + .with_channel(0x42); + + assert!(ctrl2.enable().into_bool()); + assert_eq!(ctrl2.mode(), 0x3); + assert_eq!(ctrl2.priority(), Priority::Medium); + assert_eq!(ctrl2.channel(), 0x42); + + let raw_value: u16 =3D 0x4217; + let ctrl3 =3D TestControlRegister::from_raw(raw_value); + assert_eq!(u16::from(ctrl3), raw_value); + assert!(ctrl3.enable().into_bool()); + assert_eq!(ctrl3.priority(), Priority::Medium); + assert_eq!(ctrl3.priority_nibble(), 0x1); + assert_eq!(ctrl3.channel(), 0x42); + } + + #[test] + fn test_u8_bitfield() { + let mut status =3D TestStatusRegister::zeroed(); + + assert!(!status.ready().into_bool()); + assert!(!status.error().into_bool()); + assert_eq!(status.state(), 0); + assert_eq!(status.reserved(), 0); + assert_eq!(status.full_byte(), 0); + + status =3D status.with_ready(true); + assert!(status.ready().into_bool()); + assert_eq!(status.full_byte(), 0x01); + + status =3D status.with_error(true); + assert!(status.error().into_bool()); + assert_eq!(status.full_byte(), 0x03); + + status =3D status.with_const_state::<0x3>(); + assert_eq!(status.state(), 0x3); + assert_eq!(status.full_byte(), 0x0F); + + status =3D status.with_const_reserved::<0xA>(); + assert_eq!(status.reserved(), 0xA); + assert_eq!(status.full_byte(), 0xAF); + + // Test overlapping field + status =3D status.with_full_byte(0x55); + assert_eq!(status.full_byte(), 0x55); + assert!(status.ready().into_bool()); + assert!(!status.error().into_bool()); + assert_eq!(status.state(), 0x1); + assert_eq!(status.reserved(), 0x5); + + let status2 =3D TestStatusRegister::zeroed() + .with_ready(true) + .with_const_state::<0x2>() + .with_const_reserved::<0x5>(); + + assert!(status2.ready().into_bool()); + assert!(!status2.error().into_bool()); + assert_eq!(status2.state(), 0x2); + assert_eq!(status2.reserved(), 0x5); + assert_eq!(status2.full_byte(), 0x59); + + let raw_value: u8 =3D 0x59; + let status3 =3D TestStatusRegister::from_raw(raw_value); + assert_eq!(u8::from(status3), raw_value); + assert!(status3.ready().into_bool()); + assert!(!status3.error().into_bool()); + assert_eq!(status3.state(), 0x2); + assert_eq!(status3.reserved(), 0x5); + assert_eq!(status3.full_byte(), 0x59); + + let status4 =3D TestStatusRegister::from_raw(0xFF); + assert!(status4.ready().into_bool()); + assert!(status4.error().into_bool()); + assert_eq!(status4.state(), 0x3); + assert_eq!(status4.reserved(), 0xF); + assert_eq!(status4.full_byte(), 0xFF); + } +} --=20 2.54.0 From nobody Sun Jun 14 07:35:30 2026 Received: from BYAPR05CU005.outbound.protection.outlook.com (mail-westusazon11010007.outbound.protection.outlook.com [52.101.85.7]) (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 418FF2E413; Fri, 1 May 2026 06:04:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.85.7 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615473; cv=fail; b=AQHMPezHUm0Awbz+wnbJo0Hj17S0soMpID4vUKBuyQsPqFlMsRyAIbyAyWZsIeBY0W6kqMnxY/cuSWIPvf9HsS1b3682dSAPkTqDN+qnCoPC4qMPRrtu2sgQw3DwyRDcZQA29N03sRYkKTXirhjPREGhZ0ueY+hVQAujAn+7g6o= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615473; c=relaxed/simple; bh=HI6519Hj5pIT85k4di3iKX5oE6aObarsKP2NZiZ11ks=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=bYk+k4MeDxw6xuVPL5pcccArkOZ+6JrrK0bzXwGCElGRXL+vUFAAAGyu/U9o+6OJVRPzXyO7wPRT2xMME9kdP9FY6pGI8dYSLRNjBO1FopyZJ5WvPManOQxb1lgyVfPco8Cf2yJj9amT/WKvs/nFcrNomaSwFm6ClQlAyqeHlXk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=mFnxYpI+; arc=fail smtp.client-ip=52.101.85.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="mFnxYpI+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=cyQu+S5wZ2JHUOvMCKZGFsvOGrG9Vs7ZwTMRM5exAV0lxgPbOt8YprZ6Uwd5JX7NDi++XtQbB8pYkaj/s0t/oLY68AIiDkGNdNIEaFECHzOQh+w31lGkQSeWrRBYvdUkkXJYt3bz9gBtZkIpudvVieNsHuFeY9sB0JoKlWy/SklUFwW4nRkiySx6cbc2rNjWbFvMI3fFPhNcSnYIeukD8hijD18FulCWNCVbs9pPxHUjPu8FbdCNRUg0McSnPTEZBCELwAawyaLfJgKqd0oqhF2JW96/eM0cg9yKmqYEWW1nQ2/UJtb/6wk18+SYw443iEVGJ92QxBGtq/7BFlhatg== 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=ZSrbg1Y2P58RRyH5l/aFJm3jOVlJATKkSvLtKCEVtJE=; b=I5V+4nsu9FmeKHHuKwl2aIX3EEnkA8GjoOIp8SZJMVkPbZyEM1TiT78JifzlpylHTBTwVvwzXEpdtFaZHpoHTFahWhVPqp12hou53w9H8eNi7k9FA9/G05Z0wGz01ghS3mEfPSzJ0mXQNzFRvUL529cpAymnhMwbZhTWgZvc3UrKT+Eq6hOgvMkuUIUiNKWKZloagYys+RtZViHqdxyHCdQt3TeDEjy15MAc8zZ6ak1rp1hwMoy7h5wyeQ4cEbfhG/A60M0IaMqVaiattdMHgOZSwPE5IZLhEHVM7A3VVdc1Yd1XQ0ljvnfOvN4FUF7fCcndBRWkM8HkOOtOm3kVUA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ZSrbg1Y2P58RRyH5l/aFJm3jOVlJATKkSvLtKCEVtJE=; b=mFnxYpI+PM4gzqh8I3oSf94m8xCRQhF5a4z9hwYZ/+pgeZNdkiepCfywBGWLf8WlsEpX1Xw5jPAcKjP5JQD6TMBkmPxSi7Y9ydsYxBAkmXtq63aeKGN5XfHGn9vfAW3KH0LfglyHhpL+5yVFkKW3EMWQNliUZlCEmzzr4t3VeBtEMc8+q02yC404l593m1oENCpjlenL9QZw0LdV4OvPSyMbhB7o7XDoFSiEzeLIEtQurHZBDkdRcXv3wJtrvxQ9K0xDkGn9m84KfffZSFtwGyU1cwxzf48xNMHuWnSxjymLeO6TN7WmmhTH1mL2DTJIEJuToeJtCVU6QASUKT2ndw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by CH3PR12MB8584.namprd12.prod.outlook.com (2603:10b6:610:164::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.22; Fri, 1 May 2026 06:04:25 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%4]) with mapi id 15.20.9870.013; Fri, 1 May 2026 06:04:25 +0000 From: Alexandre Courbot Date: Fri, 01 May 2026 15:03:20 +0900 Subject: [PATCH v3 3/5] rust: io: use the `bitfield!` macro in `register!` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260501-bitfield-v3-3-aa1076c3337d@nvidia.com> References: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> In-Reply-To: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> To: Joel Fernandes , Yury Norov , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , David Airlie , Simona Vetter Cc: John Hubbard , Alistair Popple , Timur Tabi , Zhi Wang , Eliot Courtney , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, nova-gpu@lists.linux.dev, driver-core@lists.linux.dev, Alexandre Courbot X-Mailer: b4 0.15.2 X-ClientProxiedBy: TYCP286CA0092.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:2b4::10) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) 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: CH2PR12MB3990:EE_|CH3PR12MB8584:EE_ X-MS-Office365-Filtering-Correlation-Id: 139741d9-5dab-48e2-7f27-08dea7477f59 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|7416014|376014|10070799003|18002099003|921020|56012099003|22082099003; X-Microsoft-Antispam-Message-Info: Xfjwcazw/lvStiO1ZdiVd2+N3yPjw8K2BshhG3V638tmEG0tuBPaQQuBGiPdY5NOQTzmQ3CY33VKtT5ytm2SCy28eWCpdAC4x1h1iCWnxyzynAystFIObw86Pbz/87XR47aIxmdD1cm8FM4J7S0/S1TqSMzxa7kZwazuj4JYM7kV7IND1+aa7pjgu0TVReRR3TEafZ4/69LFX6anHr6rvbBg30nrN94S4OMPR3sgRrCP9OFOMcK6L5QRbzUFUuguaOvC/IKWB5dt81SlJl5472uybqlNRLTpS2f4SsTlk2k97pSAXyMOAZb/jCi+ZLXVX90XY3wh1Kl1eLM3cDr3kjSGZCXRqQQuAfvYQzFPSG8nwoIcR4bZRqWiXoX0VTsiUXSkUXVJnNFbbFEJzI8D9LCvEs+ZNNMGBrBgoYcyAjERCCcygBWIsABMZJLgqXtpYoX2PTte4KM08OytPt8dpT/WFZ0UOQNEPi4exq08iEs0TlOukcUlpzc82dtEJbhjBO9ebzMA+VXoFRhFntkgUkN6+eO0SGEU5NaIKImWPrUCyy9v74cWX+npoaH/Z1vyEStbtG8aVg2SFGoq/UuIpa4cSrVlsmdN7EuCqv3abFvCNZHd+tKKE81jnZwADMYKuKIBrtAALncwfghamxtjcdaf8fXzRhdyw2Wqsx0FML+PiYQZSsjhdIpEM/ByK4v8/UMHhJVFRQSHKq4edXXsmrrdTW3WblhC6e6/lGleaKY= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(7416014)(376014)(10070799003)(18002099003)(921020)(56012099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?bnRibjZSajdKS1hHZUxQcXFzaCtjcTc4L29CNUdVTVVpZ1dyZ01QM0VFSHVO?= =?utf-8?B?NjBRczBlZWxWRm1LRklqSkExZmM4WlNoUzkwK1JoUjBRbDh4SXptdEd6L2Fv?= =?utf-8?B?cFdnSHB4VXZUU2oxTlYvbWJtTDA4Nm9PWjRQNkxiQVlXV3Q2Q1lBTkRpd1Za?= =?utf-8?B?N2YxUm5lZ0pYd0Q1ZVRFSWgydlF3UFlla1ppRWVzTEhnUXZZVEZzc0FRUFky?= =?utf-8?B?WktWMnVieHowUmF3ajBuK2FwdWRwT0hmaGEzdXBSQm9qeEcvT1prZmMvWWxx?= =?utf-8?B?ejk5WUh6UGgrcWYxR24zMWt1dDUzaEs3NjdYZXlCQXcrVmRaanMxbTd1alRE?= =?utf-8?B?TythYXNjMDhuZkNzakdnQ2picjFGVWJqdWd1dG14eXpLemhmMmN0OEJKN2dI?= =?utf-8?B?MlQ1R2xvQS9FUUNlZ2xVT2hyWWdMaHUzV2tYazNDWFlBbUM3amZpTVNWblJk?= =?utf-8?B?enFucUZicEcycXYvaDl2SHFMc2hUZ0Mzbkl5SEI5ME9QRVFMTTh5bUovOHR4?= =?utf-8?B?NEFaOFpSWm8rSFgxeGZ5STNNdVpqdzU2cVhadzBiNDNHdlVRcUMxL1NXMGE2?= =?utf-8?B?cnB0UlljUDZncklrTGJwUHlYQlJmU0ZCc0JHbzJsWEkzZDd6UmxaQUJhY05R?= =?utf-8?B?Q0lCZ3FRN2Nsc21xTWZQV010OXFzQ3Q1cE5hUWFUSStRLytsRHpibzZNMngy?= =?utf-8?B?UXBEaHAzdkhnRHJmWjVDTEVEQjE3ZXJLMm9YVFFjVFdiejd2SU9pd3FBakZV?= =?utf-8?B?bkp4KzIwODhaV2hqRXhZMUVQQVFjcmtYdEsyNXNjZHF3SE03OUlPYmpSbFFU?= =?utf-8?B?QnhVRkdrYUxORWpZYnRyTTEvaGEzeUlLbHNYNmdGSndnOUY3cjEraDFFaEE0?= =?utf-8?B?M1pXYzlMZHVkRUR6ejJ4ai9OWnhYeFlsNy9tcFFhNHRiVkw1alovWDlnQ3hq?= =?utf-8?B?dENFRUFaYW9meXhNcGVmZ05RNzNlSnVCZC8xaHdmY29LNGlXdEpsUWtOdWoz?= =?utf-8?B?cUhYb09YWksxK3RFVUo3eENqZHkwS1A5WlhISUtDd0ZURFk0ak1ydWxrdjJB?= =?utf-8?B?YUJ4ZUQwQjBtSE1ualJ6aU1JeUxDT2lkRjYyVHM5ZnNkWVNiT2NicHZ0ZmdK?= =?utf-8?B?dGxVQ25kZGhzZXFSelZSSzJWTzZ3Wkhzc2VDTG9PVmNpSE04ODVnRXRoRW8w?= =?utf-8?B?bFFYbkhzc0ZacW9PZnJxaUhnVlJ5UXpyaHpvaVdiNmRyRG43a1RZcS9MRmMy?= =?utf-8?B?VzdFN3ppelJ0RGJkdDlnUGtpaGxQVFYrVFBjSEswYit1bXl5MTluU21zcFhx?= =?utf-8?B?RE82azZJS3lRR0UyTzJUS2NvUWdKKy80S3lDaWtRQ3lSdDcyUmV5Rm5laG9L?= =?utf-8?B?eWNzSzRNSVlaTkpGRVJXaVducnRmTzFIRlpZT3BsYjh0S05Tdkt6MDQ4ZXRB?= =?utf-8?B?RldXWVJmSXdQRk0zeHRCRi85R3RpQXptZEgrT3NyY2dyQm9kK1NEVnQ5Rklj?= =?utf-8?B?RjQ3Y1l2b1kzZlNhODNNSjBpRitXN3BUQ1ZUT2krUTM0UzRySU82V1VUNnNI?= =?utf-8?B?UVl3eEF4UjF2cFdLL0ovUURsMFhLRW5iMXJOZEw4OGZSU1F1RGk3enFzRTNL?= =?utf-8?B?UHp1bEpKVFJLK0Zpdlk2WWxLbjRSM2RmR0hyZm5CRXRIc3lQd2FhOG40Vm9z?= =?utf-8?B?UFFnaHF6K2ZyNHZXR1MvYm4zOHMyeW5BTU1sVVRoTVkrdU5LQUdPdlkxK0JZ?= =?utf-8?B?RFIvZ1lhU212cDJxbmY1WTdyc0pOYVN1VE1rZHpOOEwyOStNcHBabGNFczY4?= =?utf-8?B?cFB2KzBUVDJJak5KcnVSL2w4OTZLeFNhVm5nV0tnNWhwWFE2djhhajZySEsr?= =?utf-8?B?Um8zbUNpQXVTalNMQkh6V09PdHo2MXFFYjZRVTUyZVFXYmZqWml1cDJSMUVC?= =?utf-8?B?aUtackF3R0lWeXppNjFGbjZaeWROSDA2Q1V2SGxzQ0ZuNktZTzJ3djB4QVVD?= =?utf-8?B?azVmNGNPKzF2S1E0cmUvRmNGaG5IOGZBWlhib1pmNElGaGdLd3BHQXhQNVBm?= =?utf-8?B?YUhUN3E2Rnc4NXVBNTR3RmRLMEtBTHVtQ3pHVmJudTZoZDd4TWhTRWtDZHRz?= =?utf-8?B?ZW9BdHpqRnNzcHQ2elQxaXRHTEliOGZwSkoyM2FEaXhrNFFSaUJpNFhaekhW?= =?utf-8?B?QnRFeFdncnRLelhLYk9ZNE1vYVBuNXJJTzBGc1hEN01KK2REbmZGdHVCTXdy?= =?utf-8?B?RmI3a3M5VTVYa3U4SVlsbVR0OVJiV1dVMm5kOVY3MnNlMmJ2VXZkejgwUXlJ?= =?utf-8?B?V1l5amNpZUhadTNlK2I0Q1VoYlVidy9SOHRtNytwdERmaG5DTEVYNkFja2Rl?= =?utf-8?Q?q8safPPSjE+hfu6q0jwEdCSLALsxrV1Ey9lzfJ5ZtrDSK?= X-MS-Exchange-AntiSpam-MessageData-1: gWOQSbyZuJF4dw== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 139741d9-5dab-48e2-7f27-08dea7477f59 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 May 2026 06:04:25.6440 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: K8aRv5nB4aL6wsi09oFCLIF/ZYns9gFeWgiOzOG95S8vi4FVllI/HhdmmcJr1jw/cfzCvQ6p2BaluIUUjMhncw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR12MB8584 Replace the local bitfield rules by the equivalent invocation of the `bitfield!` macro. No functional change should be introduced as the `bitfield!` macro has been extracted from the rules of `register!`. Signed-off-by: Alexandre Courbot Acked-by: Yury Norov --- rust/kernel/io/register.rs | 246 +----------------------------------------= ---- 1 file changed, 2 insertions(+), 244 deletions(-) diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index abc49926abfe..388647f28292 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -956,11 +956,10 @@ macro_rules! register { ( @bitfield $(#[$attr:meta])* $vis:vis struct $name:ident($storage:t= y) { $($fields:tt)* } ) =3D> { - $crate::register!(@bitfield_core + $crate::bitfield!( #[allow(non_camel_case_types)] - $(#[$attr])* $vis $name $storage + $(#[$attr])* $vis struct $name($storage) { $($fields)* } ); - $crate::register!(@bitfield_fields $vis $name $storage { $($fields= )* }); }; =20 // Implementations shared by all registers types. @@ -1016,245 +1015,4 @@ impl $crate::io::register::RegisterArray for $name { =20 impl $crate::io::register::RelativeRegisterArray for $name {} }; - - // Defines the wrapper `$name` type and its conversions from/to the st= orage type. - (@bitfield_core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) = =3D> { - $(#[$attr])* - #[repr(transparent)] - #[derive(Clone, Copy, PartialEq, Eq)] - $vis struct $name { - inner: $storage, - } - - #[allow(dead_code)] - impl $name { - /// Creates a bitfield from a raw value. - #[inline(always)] - $vis const fn from_raw(value: $storage) -> Self { - Self{ inner: value } - } - - /// Turns this bitfield into its raw value. - /// - /// This is similar to the [`From`] implementation, but is sho= rter to invoke in - /// most cases. - #[inline(always)] - $vis const fn into_raw(self) -> $storage { - self.inner - } - } - - // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. - unsafe impl ::pin_init::Zeroable for $name {} - - impl ::core::convert::From<$name> for $storage { - #[inline(always)] - fn from(val: $name) -> $storage { - val.into_raw() - } - } - - impl ::core::convert::From<$storage> for $name { - #[inline(always)] - fn from(val: $storage) -> $name { - Self::from_raw(val) - } - } - }; - - // Definitions requiring knowledge of individual fields: private and p= ublic field accessors, - // and `Debug` implementation. - (@bitfield_fields $vis:vis $name:ident $storage:ty { - $($(#[doc =3D $doc:expr])* $hi:literal:$lo:literal $field:ident - $(?=3D> $try_into_type:ty)? - $(=3D> $into_type:ty)? - ; - )* - } - ) =3D> { - #[allow(dead_code)] - impl $name { - $( - $crate::register!(@private_field_accessors $vis $name $storage : $= hi:$lo $field); - $crate::register!( - @public_field_accessors $(#[doc =3D $doc])* $vis $name $storag= e : $hi:$lo $field - $(?=3D> $try_into_type)? - $(=3D> $into_type)? - ); - )* - } - - $crate::register!(@debug $name { $($field;)* }); - }; - - // Private field accessors working with the exact `Bounded` type for t= he field. - ( - @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt= :$lo:tt $field:ident - ) =3D> { - ::kernel::macros::paste!( - $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive =3D $lo..=3D$hi; - $vis const [<$field:upper _MASK>]: $storage =3D - ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); - $vis const [<$field:upper _SHIFT>]: u32 =3D $lo; - ); - - ::kernel::macros::paste!( - fn [<__ $field>](self) -> - ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { - // Left shift to align the field's MSB with the storage MSB. - const ALIGN_TOP: u32 =3D $storage::BITS - ($hi + 1); - // Right shift to move the top-aligned field to bit 0 of the s= torage. - const ALIGN_BOTTOM: u32 =3D ALIGN_TOP + $lo; - - // Extract the field using two shifts. `Bounded::shr` produces= the correctly-sized - // output type. - let val =3D ::kernel::num::Bounded::<$storage, { $storage::BIT= S }>::from( - self.inner << ALIGN_TOP - ); - val.shr::() - } - - const fn [<__with_ $field>]( - mut self, - value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, - ) -> Self - { - const MASK: $storage =3D <$name>::[<$field:upper _MASK>]; - const SHIFT: u32 =3D <$name>::[<$field:upper _SHIFT>]; - - let value =3D value.get() << SHIFT; - self.inner =3D (self.inner & !MASK) | value; - - self - } - ); - }; - - // Public accessors for fields infallibly (`=3D>`) converted to a type. - ( - @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : - $hi:literal:$lo:literal $field:ident =3D> $into_type:ty - ) =3D> { - ::kernel::macros::paste!( - - $(#[doc =3D $doc])* - #[doc =3D "Returns the value of this field."] - #[inline(always)] - $vis fn $field(self) -> $into_type - { - self.[<__ $field>]().into() - } - - $(#[doc =3D $doc])* - #[doc =3D "Sets this field to the given `value`."] - #[inline(always)] - $vis fn [](self, value: $into_type) -> Self - { - self.[<__with_ $field>](value.into()) - } - - ); - }; - - // Public accessors for fields fallibly (`?=3D>`) converted to a type. - ( - @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : - $hi:tt:$lo:tt $field:ident ?=3D> $try_into_type:ty - ) =3D> { - ::kernel::macros::paste!( - - $(#[doc =3D $doc])* - #[doc =3D "Returns the value of this field."] - #[inline(always)] - $vis fn $field(self) -> - Result< - $try_into_type, - <$try_into_type as ::core::convert::TryFrom< - ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> - >>::Error - > - { - self.[<__ $field>]().try_into() - } - - $(#[doc =3D $doc])* - #[doc =3D "Sets this field to the given `value`."] - #[inline(always)] - $vis fn [](self, value: $try_into_type) -> Self - { - self.[<__with_ $field>](value.into()) - } - - ); - }; - - // Public accessors for fields not converted to a type. - ( - @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : - $hi:tt:$lo:tt $field:ident - ) =3D> { - ::kernel::macros::paste!( - - $(#[doc =3D $doc])* - #[doc =3D "Returns the value of this field."] - #[inline(always)] - $vis fn $field(self) -> - ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> - { - self.[<__ $field>]() - } - - $(#[doc =3D $doc])* - #[doc =3D "Sets this field to the compile-time constant `VALUE`."] - #[inline(always)] - $vis const fn [](self) = -> Self { - self.[<__with_ $field>]( - ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new= ::() - ) - } - - $(#[doc =3D $doc])* - #[doc =3D "Sets this field to the given `value`."] - #[inline(always)] - $vis fn []( - self, - value: T, - ) -> Self - where T: Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo= }>>, - { - self.[<__with_ $field>](value.into()) - } - - $(#[doc =3D $doc])* - #[doc =3D "Tries to set this field to `value`, returning an error = if it is out of range."] - #[inline(always)] - $vis fn []( - self, - value: T, - ) -> ::kernel::error::Result - where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $= lo }>, - { - Ok( - self.[<__with_ $field>]( - value.try_into_bounded().ok_or(::kernel::error::code::= EOVERFLOW)? - ) - ) - } - - ); - }; - - // `Debug` implementation. - (@debug $name:ident { $($field:ident;)* }) =3D> { - impl ::kernel::fmt::Debug for $name { - fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kerne= l::fmt::Result { - f.debug_struct(stringify!($name)) - .field("", &::kernel::prelude::fmt!("{:#x}", self= .inner)) - $( - .field(stringify!($field), &self.$field()) - )* - .finish() - } - } - }; } --=20 2.54.0 From nobody Sun Jun 14 07:35:30 2026 Received: from BYAPR05CU005.outbound.protection.outlook.com (mail-westusazon11010010.outbound.protection.outlook.com [52.101.85.10]) (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 F011619E839; Fri, 1 May 2026 06:04:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.85.10 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615475; cv=fail; b=NdNatg9o05WlpU/+ssR7Xwu/XGzZffZduXDS/Je8+DlzaNGZSbSog5PjVT+kJAyEBEqCdXZ7NEzc+F+PTjgoJ40biIXmYBQXA8pWzUpZEIgM8HTg/59kx+Xx9nAarq60NvuFtJvXRk3RKx7HiabXc/dQFmZ/VzIOUmzPONPuRo0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615475; c=relaxed/simple; bh=8x9okYaVHopE+Wjy3M752aOu3+fAsudWFYy2V8YGIJs=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=uy9X8C73frh93S28YvDDv9g7f5LC2TFkEwdMuW/5b50DrpLeOcYQSa15uoPWxvJBIb+XNK8cIwxY4MNBmyUw+pjb5jL9hx4ovS0clM9QU+rkrr4j6dfVq6XerGiRnlou9vxs2bSMJhjfOo5X1ifa5ORyGxmqzD+TtIRZbZgQfi8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=p55pQuyq; arc=fail smtp.client-ip=52.101.85.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="p55pQuyq" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=GqoIB8MJemfVhntjyTBmh+Bn7peUxakN9WtiwcQXPz3pqcD1UjjeR8PEGO5ampq4gQmTk9bumTX1LaIgP+VHxFAAC0hJi92JDGl9n+GpuWuIJIYuvZlyJbbIo0E2Ci2RhYjkyTSnsHVwM0pZVUuvZa+bKf3MkV3hI2sHwzrudTxkWcO6K22Gw3sOL/9fx9zc2e4pXr7i3oPNZrNfWBngNYmK4n/ZNVrVgnTNLf32LHY8ZUShhVhL/yCXgFcVZ9ZQh23TcjTX7rjTlmlaOZjdpPhxDDt7pVrHM4p8STlXvgCOH5NA6aGdL+kmIPcc8hKjD9ziURrH8Bxv0Ky0lYuICA== 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=tYiYsK5tHRDNs6gpnUFafZw04n3r0z4GvEPFr0uhMbY=; b=XVSeo0Q8Lnsf3PR9NjZ7FbGpQStzjCT0RjR0qcxir7dsrS6CAMu+SW/GlP9ycA4KZcEJlRFMNvqhgnaOdZTKWd9agdB1ATyCPjtHz/i3fjPdB7u8+8fvXpcnwRNA7PYsTXVFC0UciKwreIlvetqEPi7VUpmeiawVv2JbAhFBIccI6fUclPgU+0fX67YGTXQngGUkE7vsfNoe1EyNeMprPZXsWbuADqpf/zm2qXSOK+9smiaNboGzwQw02A8wfyk6Ap3+5Hxb4dE0+mGNvtYgu7UongSKTun8uNkoWKGctk/gNi3pjXGpELFNNXFkHSDEd6xg2p3kkoYaY+tf1aqnvg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=tYiYsK5tHRDNs6gpnUFafZw04n3r0z4GvEPFr0uhMbY=; b=p55pQuyqlTjoUWbTYsep5I84Q3A+3qpUuxWLuFfsWnrZp3OyZoYwzlEchr1xksvWRRK4miF6UpezCJD7/CjU7kUilekBlE1Nh/XcYqOjrzkqU+lbK+77+G8KvJAuV0QRFkYBDph3IxokUKYIQP3QQZ6v8ssU2fdKNYBUJMUwAuFFcxBJ9aIIUvgf0ZDieVygDclQ3XXI/APF4aQnY6nan2i4pF+jNijz90Y9VTPHsfZqXQovBORukhSPNrh4XbxPJ2rq+M3YVv6E016q+5bHxXSF4amaoRCrKALadapqv70+FBhGg6MoOl4zftxJqIEMoaZxSWHUqy5OsvycNkaXcw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by CH3PR12MB8584.namprd12.prod.outlook.com (2603:10b6:610:164::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.22; Fri, 1 May 2026 06:04:29 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%4]) with mapi id 15.20.9870.013; Fri, 1 May 2026 06:04:29 +0000 From: Alexandre Courbot Date: Fri, 01 May 2026 15:03:21 +0900 Subject: [PATCH v3 4/5] gpu: nova-core: switch to kernel bitfield macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260501-bitfield-v3-4-aa1076c3337d@nvidia.com> References: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> In-Reply-To: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> To: Joel Fernandes , Yury Norov , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , David Airlie , Simona Vetter Cc: John Hubbard , Alistair Popple , Timur Tabi , Zhi Wang , Eliot Courtney , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, nova-gpu@lists.linux.dev, driver-core@lists.linux.dev, Alexandre Courbot X-Mailer: b4 0.15.2 X-ClientProxiedBy: TYCP286CA0138.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:31b::13) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) 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: CH2PR12MB3990:EE_|CH3PR12MB8584:EE_ X-MS-Office365-Filtering-Correlation-Id: d13048c1-84ef-4c56-a9ee-08dea74781a1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|7416014|376014|10070799003|18002099003|921020|56012099003|22082099003; X-Microsoft-Antispam-Message-Info: FsG6WRwXgQPbQD2vRy55uz3cHjsE/TtQzVzeT4A2Pf4kcpGGVRv1L6DZUupw5UD+iFQ9R2XzkzjR0+5oyZev6bBbDqm0vQ5903HqzclGLOJN2jzpSLKA2ez95G1nCRd/9xUQNq/6w07ITr4xvrWa+N1jiR35IvodgrLCZJb0lLkYEb3DPLcBfaG+g+H8D90pWXQ60VHwzt264soyzmNAHAZpBwMx9CGlSGeAN5oRR0dPPGMEIz5PqqXSLfGwdLDhgAb5bSJPWNsn2xeYIiMErkaSAdG53Kc++rl0odU1DYSsEgBMi1/Nbxu+a0podQSHm3rrrEs/8fA+qKxenErYNXCks/rl9W6vo2f6zw3Gd+iK8f3ITyPQNSZlG7f8EubNddCdOSVbwkQYUWbfNi5bK3VKRo/tIW2zyQF0mdDQR1TyCH5o8eLvMZ9XhL/J06RoJ12XF9N1YqulIlVtrVQi2ft1IS4vyU4jGx5tBUbSXbKZbm5STJnwcJxU2xaX6Ijsy+yiCe9CLcmwXZ0dcsatYtOZB4M8h8CVhufcF6kefA5Tu50J8J+Ivv/MD/0vJcPykKl4KmhqO2C/dhj98EqaXw/x657Z6iEkySDDzuVHK/kJRSBEm8rcRQqvAmvvOdCusq6tAYjfnajm4mfwjalqgLjVZQKlIogZnCPIpbbKBFbKoqy4LTnSolMYHaoPHpLsrs8cSLmEXKlYu2oDXuuo9BllYa1QgxREOxASa6adgsc= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(7416014)(376014)(10070799003)(18002099003)(921020)(56012099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?MHJoMzZ0QmxBODBrb1NHUW5VUDl2UllwNHF3UmttZmVwZ1BpY1RtTlowRWk4?= =?utf-8?B?bmdGMjJYdFNlVDl1TStFQW1OMTdNcDV1My9DdWZkRldzdkV0enA0M05QOWNz?= =?utf-8?B?WVVpOXc0di9yMDRNTHFTWnJ4YlYvQmd5WWhIRnpuYnVucVhlVFB0eWZFVG15?= =?utf-8?B?ckd1Nll4MGhnOVFLN0VJSi8rZ0sySzR0QjV3dncwN3dOR0R6NmFhMWhFUVhz?= =?utf-8?B?TFYvdHJXQTB2OCtYQ2xvSzZEUXpZVWZNOEh0Um9QSUJDTXMyUUZQMXZDcE9P?= =?utf-8?B?cWZFcXp1N3BDc2tUNDNzS2xBMnRFV1Y3SGduQmd4UEdVNEd4L2lHMFdsZVpN?= =?utf-8?B?TEhQTFRRa2pwQ2NvVTA4enNYNkFxZXZ1c2l1ZnhsMUpHRlAvNFhwejBqU0tR?= =?utf-8?B?K21SNmlaOGZlY2Erd2kybXJsbHArMXc1RWxTVHEvNDJUN0IxcXlTbElUSTl5?= =?utf-8?B?ZzYyMmw0VlJ5VkF3TWJJSHZuS3FYTVRXV0V4OElEWFMwZkIrWEE0U3Z0RVNW?= =?utf-8?B?amNhR0k2L1VKS3k0am15Qk1iWUFFUFZSb3BDKzROa1RKQVJRRXQyUVkrUEpU?= =?utf-8?B?Wmx3MnU4ZGVlY21jM0pGTVpPcWgvL0VYbHRhOFZLTS96REJ3S1lUc0pQZy9W?= =?utf-8?B?dUViYk1Ha0VoL1IxaTRhZndSdFdRM2NPMzFNeFB0OFE3ZXRpMnFFQ1lNNHNF?= =?utf-8?B?TlhhRVE1SEJjRytzQkFGL1locStwdXdWUDUwUUJqRGh6RGluM2dObUJDZU5B?= =?utf-8?B?VlVFU0VKaFF2Z0JyRzVCTHJtemhUWlgzUHNidWdWRHBvY3I0Vi9QQUc0VmhZ?= =?utf-8?B?RDJ6Y0xCUzYyZlBMNnNFVFRZUk92UlYvbUwwZG04ZEh5U0NDZ2ZWSnpMNlR6?= =?utf-8?B?V0ExVmJhbldyaXRKYjF0YUdlZVFOQmtpYy9Db1MvRlp5NHZ2SmF0eHZqN0ZE?= =?utf-8?B?T1NoOFJaenA0UG5pQy90cGhnc2gvK1UvSGFvNkNLK2FrYkY1TEZQZEMrb2hX?= =?utf-8?B?R1VGUjZlbXFWNmxTVThOQldtR0d4OWZXRzNGWk5QNXdKNWtvTkZTVTYvOFJx?= =?utf-8?B?VDVLS244OFhSZzNWNlZseFc0Ly82OXk1ZkNlam5FVnppeWJGTXJWczQybFN3?= =?utf-8?B?QkxONk1Dd0VDSmw5VU5kc3pwd2twN0R6S2JyQTZPNzJkbXZ4em0vci9teHlH?= =?utf-8?B?eFpIem5sVW5tMmxJSnR1dmpqb1lsRU1aU2dUeVVaTExyUWg2cFFGZWc2eFpC?= =?utf-8?B?MTQ4dzRCTjMrUE9JQ1hHUzFxbjVmQjd3M1Q3NnJOcHNMZzlLdUJja0crZUdj?= =?utf-8?B?dDNHbUprYnBRZzgyT0d2eHZoWXBvMmZzOFBlczJNVzVxRkVsZ09FeGU0clRS?= =?utf-8?B?M3J4UmVDM0RJNHowcDhUMElqVjBCZFMzSUhiN3hXM3Q3RGh0ajQzcUFnTVpo?= =?utf-8?B?OWNaMlZ5L2xFTm1rRG1PRytXbzdCZXJSV1dDdTRlcE13QW1mT1RSUEU1UFFY?= =?utf-8?B?bUQ4dGdXZlhkL21sOVBVeFJkcjZxRTBOV21JV0xsV0JWMWxYRFM2aG85OEs5?= =?utf-8?B?emUwZUdGcCtSb0xhcU9UdGg4Mm40T1ZxWWVyaVo1QStpWjlVQnZFb1VydVZz?= =?utf-8?B?UUFnZHdtbW1ac3Rub0plUWFnMVY0SHR6TkRUZmc0SkF1NmhyUlNySzNjdzlS?= =?utf-8?B?SUdLQlFUUFErbGgrMWJVVlp5SGp0bDl2OWcyYjY5RkFZU0g0VE1ReHdMZ2FC?= =?utf-8?B?dXlIWTFvMXJYTXFJYlNMNndKVC9ra0xoYWcxMHk3YmhtcnA3dFVjMStmREp3?= =?utf-8?B?Nmx0QWg1d0FxOEdYK280Y2ZwZ2xueUxpU1BFbFE3dzBSWlkwMGMycVFYOFh6?= =?utf-8?B?a05yZVpudnRKV3h4RUVKUWxtWkVYcGx3SnRvL0xUbXZucG44a0RkVnZpYk5G?= =?utf-8?B?OE84RXF3dzJQM2ZJOTRGY29VNW5GcTE5Z2RqTUJrNUJuMlI0VG85UmZ4SWZK?= =?utf-8?B?cWxCcEVqQXg3WE9lazRRUFk3OHpIM2RpK0NmMTN1SnYwTmI1c0lsdmR4M3hs?= =?utf-8?B?QVZzaG1vekpES1QxY2YvSlA5UVF6Tm9nWDJVWkFrSXJUcktGNm9QZkNueDZ6?= =?utf-8?B?VDA0ejZpMThkVm5vRlJxb0VPazZOalpVZ29MVTMyMTdmL3ZscFVpMit2RDda?= =?utf-8?B?bWdqWGw0bEdHTTNyZm5sUk1sKzEwYkRHMlNDZmZ1Mk8rOU9NeWV1WnV5S3BY?= =?utf-8?B?OTRGbXAxRUJHZHFhMGQ2bVp1MXlhcGxIeFQ3d1hURVgzcjhqWVV6Vk9xNFFp?= =?utf-8?B?T3hLRDJCOHVjNWF0TVpuNEw5MnZjS0VYSEZWVmxYaHZPZnZ5KytpMmdLVkxh?= =?utf-8?Q?SIIIeRyeMAYaTP2BdkexSttTaaJeSVVvCpDh+pC1K9IIi?= X-MS-Exchange-AntiSpam-MessageData-1: 0MtJkg9sHY4Dvg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: d13048c1-84ef-4c56-a9ee-08dea74781a1 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 May 2026 06:04:29.5627 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: G1awz24PvL91PGrlW6QD+enMJFr2XsRIslV+Oayl2B1O0VOdf6mEXGWWpO0EgECZCJne698v/ms6TSuYgQbUyQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR12MB8584 Replace uses of the Nova-internal `bitfield!` macro with the kernel one. Signed-off-by: Alexandre Courbot Reviewed-by: Eliot Courtney --- drivers/gpu/nova-core/gsp/fw.rs | 11 ++++++----- drivers/gpu/nova-core/nova_core.rs | 3 --- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw= .rs index 0c8a74f0e8ac..d54688904740 100644 --- a/drivers/gpu/nova-core/gsp/fw.rs +++ b/drivers/gpu/nova-core/gsp/fw.rs @@ -9,6 +9,7 @@ use core::ops::Range; =20 use kernel::{ + bitfield, dma::Coherent, prelude::*, ptr::{ @@ -728,8 +729,8 @@ unsafe impl AsBytes for MsgqRxHeader {} =20 bitfield! { struct MsgHeaderVersion(u32) { - 31:24 major as u8; - 23:16 minor as u8; + 31:24 major; + 23:16 minor; } } =20 @@ -738,9 +739,9 @@ impl MsgHeaderVersion { const MINOR_TOT: u8 =3D 0; =20 fn new() -> Self { - Self::default() - .set_major(Self::MAJOR_TOT) - .set_minor(Self::MINOR_TOT) + Self::zeroed() + .with_major(Self::MAJOR_TOT) + .with_minor(Self::MINOR_TOT) } } =20 diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nov= a_core.rs index 04a1fa6b25f8..3a0c45481a92 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -10,9 +10,6 @@ InPlaceModule, // }; =20 -#[macro_use] -mod bitfield; - mod driver; mod falcon; mod fb; --=20 2.54.0 From nobody Sun Jun 14 07:35:30 2026 Received: from CY7PR03CU001.outbound.protection.outlook.com (mail-westcentralusazon11010039.outbound.protection.outlook.com [40.93.198.39]) (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 9FA322E413; Fri, 1 May 2026 06:04:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.198.39 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615482; cv=fail; b=fMhPEU7I78eR/M/UrAeqfLCxb1t7ZSBcpx3xOgP2c/SIjIhfzWtpq9XZl2FMhEWISmFPSzFskA5L3tUwUK7A1Vd7Vdq52Q64YKUYAkYr9zGlulnu/16rhjyglw9RmgkGqJMg+AvbC60Td18jBgCsPQDQaUAxvH/uBxAlnFt3F0o= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777615482; c=relaxed/simple; bh=fjSJYEPYULh8RvSPD67pmBCbnp0blXYr8tR0yugCaWU=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=dRBztQ52QTaDJO4eXhSPDbSuTA3DdGth9oYEPMvBvOToECfUgfp0RRmCDaRUh+wBGNxqQp+tIHpvevO64ZhVtb8ivWl54va3L+zR6Hcxk7rVj9q74xantizJXaeSsFJvfeGnHZFPDcEGDkXiJv9wK5kscSpCPxMmrX6jdNK++y0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=dR3jjlU9; arc=fail smtp.client-ip=40.93.198.39 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="dR3jjlU9" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=L3j/Dg5kqrqBY9orszTCceaslM/2FR5YE7KxpSc7cGalsk/Bgz7f+MAVdNCrxWLM3hATvrGb1KfCZgGXGLbF17uDAJGm42zWGbk/VdwvjPXhM9/E+eyxSTrHrxmLYzXgcwKZDYZ9m5ugVZySqjD+ItwHjbkfVIdM55XGY2si5/e/vkkEPJGm1v0DwCvBb8x9d71dsTvdjZtCytPIagPetfcBRD0eITNx/LXfL5eY7w8Up+tI9a9+UYzw9bEIbzFGEtexJZTUeUEsi3zPrQAKWYsZlBnRV/ObaXR7A4Z2MDX1LJdBIWE7pTpZZm3Z5g45eZQCsgtKPWs6v/TgdAgqTQ== 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=kaUwfN8D+p4cTRgcYePzP3koNrYATKjVPot5EVr+kaw=; b=FJ+n1xiXJBgULeVtw88pntcuXGb87PQ+l4SqQgiswsRElZ6fHCe4EJHLhKZw8WibxCVKq5bLHjUHf4LYNYGoeOhYSAfLkr5jtKglN0hu2XHAN5PH+ivZKIqXc5bL+n0FC9S0MI/SBnL92AIN9ac4cyJzrCUQwxrPiS68nR03L/yYOkcKD4+vbGVWD0RqBlRJZ4idgeNMdgRncH0f+IuHMFsEOiLZc1pWft21krefR06JES8SM0K2xzIlarYFHOxFNfmFmA8aKEjMiZW26OCGrquqdCN9yGDWQ5UdBcx9ETXKzl6vURyribPtg1Az99RTzv1RZ39IBckKRfGxg+NkfQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kaUwfN8D+p4cTRgcYePzP3koNrYATKjVPot5EVr+kaw=; b=dR3jjlU9i/QZdqKkncp9olbIRNTfdGIJY7qUEGXJeGQ2sSkz5ObMi//qrvq/ozQPsjPmfKXxTfWLXPcet2NzvpDNIrN9MAnU4WzUMC/omqbu3COkxSSddnvUtLDG9nYcBCow0KgiGLOLLYZdwdAYT1wefhCwXfzvDVJs2L5HGyWo4Nla4Xah4uf0L8IsWW11t8xEBelZ//nOQ0P73IT4hZ0nCWFitDn4Ki8y2PG3KvHZJHFwtH9d7iFw/lA5m+Nwtb5XtW55WN1oE/JxLweg2DXCt9d6fR5BeGFdFCAgaNU1wbwEqvZRyials64yMERuINHgxYobG3c3M1KwB20/Mw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by CH3PR12MB8584.namprd12.prod.outlook.com (2603:10b6:610:164::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9870.22; Fri, 1 May 2026 06:04:34 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%4]) with mapi id 15.20.9870.013; Fri, 1 May 2026 06:04:34 +0000 From: Alexandre Courbot Date: Fri, 01 May 2026 15:03:22 +0900 Subject: [PATCH v3 5/5] gpu: nova-core: remove the driver-local `bitfield!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260501-bitfield-v3-5-aa1076c3337d@nvidia.com> References: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> In-Reply-To: <20260501-bitfield-v3-0-aa1076c3337d@nvidia.com> To: Joel Fernandes , Yury Norov , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , David Airlie , Simona Vetter Cc: John Hubbard , Alistair Popple , Timur Tabi , Zhi Wang , Eliot Courtney , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, nova-gpu@lists.linux.dev, driver-core@lists.linux.dev, Alexandre Courbot X-Mailer: b4 0.15.2 X-ClientProxiedBy: OSAPR01CA0232.jpnprd01.prod.outlook.com (2603:1096:604:28::28) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) 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: CH2PR12MB3990:EE_|CH3PR12MB8584:EE_ X-MS-Office365-Filtering-Correlation-Id: 12768989-a882-4d4e-bed0-08dea74784c4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|7416014|376014|10070799003|18002099003|921020|56012099003|22082099003; X-Microsoft-Antispam-Message-Info: 9s9yJMtbhU2s8wVYwpriIyBOZT9Prar8zU1fGr1Dum2sI1ylQhPc5f9mAAmBLBn4JcqT/juaHq3SBNzYS/7RhatwNRJON/5iXIofkm1bqA5yE6D6yf+7gCvjGMUu1FGXdsSz2v1HcRU9777BJNawPvLBmF7MK1NZaDnFwVOdHP3hIsjNAyeVzJC8IGQOOLTibd2UloWZh0EiYYsZZvFbH2kXkzg5RsvomQZXvcbUp3+Hcp/S7pAJo2276qhMCSyBhw6obghlKkQrWHwEeLJJiXkOpRXWrVqZSJdCLGe54lIg635m/eAgyvKCie4Mz3H19LQyPJsi6VIs2i2mdBPuT5WHZlYI5249A4ckrBGWem6mRcJbC96KNRwmmtcOygusXJ6NnQ37QriPvI9J41wLlwnrPq2CYxAHd6Rn+teCABeb+/0mkLJdi5082kRd3rYqUwphIALNioqpIejIsKBIAoW6JOz66XNgehLRsJsWhCIDvZdjwmy/TVF/9OAB8ZN17EHmYjCNdLYGE9CCrD+xcS6FatUf4VZvdqO9h9XT3ziAq5V8gFaGPAsCjCdD85bQIMyX55icy9qYiagCRYGLJWL838TCjYR2BIj/93zefA8WE7yF0e1FjLwMtZOI2tcx90J9uFqryndjkP3FraFLBMTizbMbDXEVMTnaCozvsiKbb+QkSR/t48U+UqKvfiSDXR/G8zamKUerFVTFURhenSCvirErZmjpil6FndRA598= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(7416014)(376014)(10070799003)(18002099003)(921020)(56012099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?NWJyd0hVVER6ZFZVUFN6UkNVUDVrTWl1NkozRHlFSGNjUWNoYVZvS3RDL0pI?= =?utf-8?B?ODlXNEF5WEhkYlhXRThyZVZ0NjFWNytaMkhpanNnTDdhOEkrQ3V4OGlIcDJu?= =?utf-8?B?azNwUnJKZDFyUGlXT0xoaktiOWwwRCtvSmw5dExLV1d3MHltbDlDM2dpZDNi?= =?utf-8?B?U2xZd2wrSjJuNWVmMTBOOHAxQk0zWUZBcWxhcUpaOWZJTWlJR0YzZ2VHRXFZ?= =?utf-8?B?TmlDbkUxTWlBUzhUVXpVU01EV2l4UThpVkYzVUFtU2toYytSMXJuRFd0NjdH?= =?utf-8?B?VW92dms3UTFVQmNVKzFBMHk3ZXF3bzgrV2VNU3ZxQnJPWHY3Z0U5MkF5YTR1?= =?utf-8?B?QVpXOWFVYSt1M28rUDFoN1dlY2Y5WlRwSGV6eWp6cEgxOUE5eStYYWZOOEVi?= =?utf-8?B?MEF4cDZrS0pNd3A1Y09ZelBkbXN6dWxWMk1FUG9DOEtkYy85YVlOaG5hVnJs?= =?utf-8?B?TWhCdG9JWEo1N1lJWU4wdzhQVWVmOW5KRFpkSGUxUG1GM00zQzhiRURYTjcz?= =?utf-8?B?ZEd1V1laWWhwV2loc2Y0clNBNU9OMWFBQkdDMFgzQVM1a2VBZlNJY2M5ZStq?= =?utf-8?B?VzI1WG8zbGVVWlgrN2o5NHEyM05FVXlUK041alExYkFTM09OUHJGbWZrVis4?= =?utf-8?B?bG8yNVJEemtOM1kwRC82M1BlM3BaTC9aeEFSUHdjdmZJVW5raHBNeFlVQURa?= =?utf-8?B?K241VUw2TnUyWkd0VWZFOUJBcE9wNmNJTDUvOW83VVlRc29tRFloQWtXbCs5?= =?utf-8?B?dXozRnYxOTZDMXpnTXFTaFFmUHdSaXI4eEw5WGl2YzZaU1hXUWRoaXVQWVBT?= =?utf-8?B?MUpnRXJrK25VSk1OdisrZDR6QTJWSzRlS3paL2VRaCtyeG5WcmgwU1lQNk5n?= =?utf-8?B?bmNnMUkyRXZIV3lsQmRUTUFvdFVSZ2xTcllxdXdJaDBTRmQ1L0JuakNFQmEx?= =?utf-8?B?SWE0UzZVZ1ZzWXgzbmJxbVhxdWEvZG9EK2Q4Z1BCOVRoWlNxbnpXZVdjU1BB?= =?utf-8?B?K3dlVkpRQVVaSGg1a0Y0RzFnck1TUVE4c3grNHJKcUZaR0tsSFh6SWdhdGxH?= =?utf-8?B?dnpXWkJ5SExTTVVyVnNiZVRPTWYzclo2SHZkRnFxK3dBUFBDVTR6eHF6RGZu?= =?utf-8?B?elc2NFJGOWM1bW8wc0JNNktWUHdXQ2FpZXNWdUd6b1VUM241NytORVh1TndH?= =?utf-8?B?SE5aY0sxK3NqUHdHS1kvK2svek9jbkFkSHY4Q0d0bzJnUVJRT2twRzZhS29n?= =?utf-8?B?b0RTcXJZdElFQUwvRjlRMGpPemNLd3R0Vmdpa0gvbjdOMEJvWUx1OHRhZGJ3?= =?utf-8?B?em1uaVFSWkF3MkJuZ0Fzd28zNExTZ0ZSQjl4VTBRTzVmZkkwb0NSK1g1Mk5z?= =?utf-8?B?aU4wZTI4N2Nia0F4UnA3YUZ4dFZlM2xXQnpkRkRmWkZKaWFWVkNyK01WT1Zr?= =?utf-8?B?cXoyUXpNc2thaW1BMlQvdTB6UkkxSlpydDFmcnovUnYvKzkvYkR6NmN5YVAy?= =?utf-8?B?MGcwZWRjVEM3RXVNcWhtV1pkVDhNdVAxOXVhM2RrRWY3Ym5WUFhlU21rNHJ3?= =?utf-8?B?ejdqeW5WSGU1b0RnUU8yRnlDMzJKSjRUSURHQS9zV1FHQnVEcy9iK28zVlc5?= =?utf-8?B?eTZ6MTVyR0FicnZTajlnTi8rM1ErS3dEUU1aTXMvTzA4cUZWNGFNTGNBalhP?= =?utf-8?B?alhkS2pqaVF6L1NmanY2U2xkeHBWV3JieFIrQW04SWJ5VEl3eDBUSGJyNzZC?= =?utf-8?B?NXkyRjZRSnI2RXpRMnQ1WVlTN09ST3VOWUZSWmlJdHhSOWZ2VU1ETVNUMFJq?= =?utf-8?B?TFlObU9vQzVuYXJ2NUtnQWo5eC9velUvMlVZbW0zeTlVUkJGbUw3alpTeDVG?= =?utf-8?B?c0xtR25nTER5QmZlajVRU2daRmR4Qm5Da1hjOENGQTc3a3l3aEdOVUtWLzcw?= =?utf-8?B?K1RpZndmdDNTTFpOR1RmTmozeGdNUWs3aUhrUXYvWjkyYXJIN1Y2NmZ2WjVp?= =?utf-8?B?UnpybEZvVlBjbmtJVnRTRzV3dVFJQmROZDdSUXUzOHB0ODdRamVINWhjNjQ4?= =?utf-8?B?QjZreFdob2dTU0dYaXdpTlB5NUsxNDMxOXd5ZTBmOEFMSzlDOVBOM2lISS9j?= =?utf-8?B?dnhYMS9LSEZGOTMrMUN5WnNDMzdYOU1qWlBJVk00RmJpb3BDRFdlTXlYUmxC?= =?utf-8?B?RmxoNVdzWUlQVng4RXcxSDJMRHJlRTdoQWdNMWg3dkgyOURIaVd3RnN1cTJ4?= =?utf-8?B?UVNQMzl0MDFsd21BRVI1QThtZWpWckxVb3p6SEQzTGErMTlGN3Z3ODVxdW5u?= =?utf-8?B?Ym9sNi91V2lwaXRUU1hvOHd2b3VYam5ZKzAwZk9JbmlOWFY4dUpLc0tsaVJ6?= =?utf-8?Q?vfXwE/j5ozWlEDyT3TIXnue4pzmcOq/qepJUFHbUOHvWB?= X-MS-Exchange-AntiSpam-MessageData-1: +Ie3quflMwQqww== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 12768989-a882-4d4e-bed0-08dea74784c4 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 May 2026 06:04:34.8111 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Yzdv+mipwRNqmqcdl0KqiMWsvX5TX2bHmdlr1JUIHECWshN4N3KpfUS0NOtrgdWHeTTO5xRuNvmJurQ5DebKyg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH3PR12MB8584 This module is now orphaned code replaced by a kernel-global implementation, so remove it. Signed-off-by: Alexandre Courbot Reviewed-by: Eliot Courtney --- drivers/gpu/nova-core/bitfield.rs | 329 ----------------------------------= ---- 1 file changed, 329 deletions(-) diff --git a/drivers/gpu/nova-core/bitfield.rs b/drivers/gpu/nova-core/bitf= ield.rs deleted file mode 100644 index 02efdcf78d89..000000000000 --- a/drivers/gpu/nova-core/bitfield.rs +++ /dev/null @@ -1,329 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Bitfield library for Rust structures -//! -//! Support for defining bitfields in Rust structures. Also used by the [`= register!`] macro. - -/// Defines a struct with accessors to access bits within an inner unsigne= d integer. -/// -/// # Syntax -/// -/// ```rust -/// use nova_core::bitfield; -/// -/// #[derive(Debug, Clone, Copy, Default)] -/// enum Mode { -/// #[default] -/// Low =3D 0, -/// High =3D 1, -/// Auto =3D 2, -/// } -/// -/// impl TryFrom for Mode { -/// type Error =3D u8; -/// fn try_from(value: u8) -> Result { -/// match value { -/// 0 =3D> Ok(Mode::Low), -/// 1 =3D> Ok(Mode::High), -/// 2 =3D> Ok(Mode::Auto), -/// _ =3D> Err(value), -/// } -/// } -/// } -/// -/// impl From for u8 { -/// fn from(mode: Mode) -> u8 { -/// mode as u8 -/// } -/// } -/// -/// #[derive(Debug, Clone, Copy, Default)] -/// enum State { -/// #[default] -/// Inactive =3D 0, -/// Active =3D 1, -/// } -/// -/// impl From for State { -/// fn from(value: bool) -> Self { -/// if value { State::Active } else { State::Inactive } -/// } -/// } -/// -/// impl From for bool { -/// fn from(state: State) -> bool { -/// match state { -/// State::Inactive =3D> false, -/// State::Active =3D> true, -/// } -/// } -/// } -/// -/// bitfield! { -/// pub struct ControlReg(u32) { -/// 7:7 state as bool =3D> State; -/// 3:0 mode as u8 ?=3D> Mode; -/// } -/// } -/// ``` -/// -/// This generates a struct with: -/// - Field accessors: `mode()`, `state()`, etc. -/// - Field setters: `set_mode()`, `set_state()`, etc. (supports chaining = with builder pattern). -/// Note that the compiler will error out if the size of the setter's ar= g exceeds the -/// struct's storage size. -/// - Debug and Default implementations. -/// -/// Note: Field accessors and setters inherit the same visibility as the s= truct itself. -/// In the example above, both `mode()` and `set_mode()` methods will be `= pub`. -/// -/// Fields are defined as follows: -/// -/// - `as ` simply returns the field value casted to , typical= ly `u32`, `u16`, `u8` or -/// `bool`. Note that `bool` fields must have a range of 1 bit. -/// - `as =3D> ` calls ``'s `From::<>` = implementation and returns -/// the result. -/// - `as ?=3D> ` calls ``'s `TryFrom= ::<>` implementation -/// and returns the result. This is useful with fields for which not all= values are valid. -macro_rules! bitfield { - // Main entry point - defines the bitfield struct with fields - ($vis:vis struct $name:ident($storage:ty) $(, $comment:literal)? { $($= fields:tt)* }) =3D> { - bitfield!(@core $vis $name $storage $(, $comment)? { $($fields)* }= ); - }; - - // All rules below are helpers. - - // Defines the wrapper `$name` type, as well as its relevant implement= ations (`Debug`, - // `Default`, and conversion to the value type) and field accessor met= hods. - (@core $vis:vis $name:ident $storage:ty $(, $comment:literal)? { $($fi= elds:tt)* }) =3D> { - $( - #[doc=3D$comment] - )? - #[repr(transparent)] - #[derive(Clone, Copy)] - $vis struct $name($storage); - - impl ::core::convert::From<$name> for $storage { - fn from(val: $name) -> $storage { - val.0 - } - } - - bitfield!(@fields_dispatcher $vis $name $storage { $($fields)* }); - }; - - // Captures the fields and passes them to all the implementers that re= quire field information. - // - // Used to simplify the matching rules for implementers, so they don't= need to match the entire - // complex fields rule even though they only make use of part of it. - (@fields_dispatcher $vis:vis $name:ident $storage:ty { - $($hi:tt:$lo:tt $field:ident as $type:tt - $(?=3D> $try_into_type:ty)? - $(=3D> $into_type:ty)? - $(, $comment:literal)? - ; - )* - } - ) =3D> { - bitfield!(@field_accessors $vis $name $storage { - $( - $hi:$lo $field as $type - $(?=3D> $try_into_type)? - $(=3D> $into_type)? - $(, $comment)? - ; - )* - }); - bitfield!(@debug $name { $($field;)* }); - bitfield!(@default $name { $($field;)* }); - }; - - // Defines all the field getter/setter methods for `$name`. - ( - @field_accessors $vis:vis $name:ident $storage:ty { - $($hi:tt:$lo:tt $field:ident as $type:tt - $(?=3D> $try_into_type:ty)? - $(=3D> $into_type:ty)? - $(, $comment:literal)? - ; - )* - } - ) =3D> { - $( - bitfield!(@check_field_bounds $hi:$lo $field as $type); - )* - - #[allow(dead_code)] - impl $name { - $( - bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field = as $type - $(?=3D> $try_into_type)? - $(=3D> $into_type)? - $(, $comment)? - ; - ); - )* - } - }; - - // Boolean fields must have `$hi =3D=3D $lo`. - (@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) =3D> { - #[allow(clippy::eq_op)] - const _: () =3D { - ::kernel::build_assert!( - $hi =3D=3D $lo, - concat!("boolean field `", stringify!($field), "` covers m= ore than one bit") - ); - }; - }; - - // Non-boolean fields must have `$hi >=3D $lo`. - (@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) =3D> { - #[allow(clippy::eq_op)] - const _: () =3D { - ::kernel::build_assert!( - $hi >=3D $lo, - concat!("field `", stringify!($field), "`'s MSB is smaller= than its LSB") - ); - }; - }; - - // Catches fields defined as `bool` and convert them into a boolean va= lue. - ( - @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $f= ield:ident as bool - =3D> $into_type:ty $(, $comment:literal)?; - ) =3D> { - bitfield!( - @leaf_accessor $vis $name $storage, $hi:$lo $field - { |f| <$into_type>::from(f !=3D 0) } - bool $into_type =3D> $into_type $(, $comment)?; - ); - }; - - // Shortcut for fields defined as `bool` without the `=3D>` syntax. - ( - @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $f= ield:ident as bool - $(, $comment:literal)?; - ) =3D> { - bitfield!( - @field_accessor $vis $name $storage, $hi:$lo $field as bool = =3D> bool $(, $comment)?; - ); - }; - - // Catches the `?=3D>` syntax for non-boolean fields. - ( - @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $f= ield:ident as $type:tt - ?=3D> $try_into_type:ty $(, $comment:literal)?; - ) =3D> { - bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field - { |f| <$try_into_type>::try_from(f as $type) } $type $try_into= _type =3D> - ::core::result::Result< - $try_into_type, - <$try_into_type as ::core::convert::TryFrom<$type>>::Error - > - $(, $comment)?;); - }; - - // Catches the `=3D>` syntax for non-boolean fields. - ( - @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $f= ield:ident as $type:tt - =3D> $into_type:ty $(, $comment:literal)?; - ) =3D> { - bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field - { |f| <$into_type>::from(f as $type) } $type $into_type =3D> $= into_type $(, $comment)?;); - }; - - // Shortcut for non-boolean fields defined without the `=3D>` or `?=3D= >` syntax. - ( - @field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $f= ield:ident as $type:tt - $(, $comment:literal)?; - ) =3D> { - bitfield!( - @field_accessor $vis $name $storage, $hi:$lo $field as $type = =3D> $type $(, $comment)?; - ); - }; - - // Generates the accessor methods for a single field. - ( - @leaf_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $fi= eld:ident - { $process:expr } $prim_type:tt $to_type:ty =3D> $res_type:ty = $(, $comment:literal)?; - ) =3D> { - ::kernel::macros::paste!( - const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive =3D= $lo..=3D$hi; - const [<$field:upper _MASK>]: $storage =3D { - // Generate mask for shifting - match ::core::mem::size_of::<$storage>() { - 1 =3D> ::kernel::bits::genmask_u8($lo..=3D$hi) as $storage, - 2 =3D> ::kernel::bits::genmask_u16($lo..=3D$hi) as $storag= e, - 4 =3D> ::kernel::bits::genmask_u32($lo..=3D$hi) as $storag= e, - 8 =3D> ::kernel::bits::genmask_u64($lo..=3D$hi) as $storag= e, - _ =3D> ::kernel::build_error!("Unsupported storage type si= ze") - } - }; - const [<$field:upper _SHIFT>]: u32 =3D $lo; - ); - - $( - #[doc=3D"Returns the value of this field:"] - #[doc=3D$comment] - )? - #[inline(always)] - $vis fn $field(self) -> $res_type { - ::kernel::macros::paste!( - const MASK: $storage =3D $name::[<$field:upper _MASK>]; - const SHIFT: u32 =3D $name::[<$field:upper _SHIFT>]; - ); - let field =3D ((self.0 & MASK) >> SHIFT); - - $process(field) - } - - ::kernel::macros::paste!( - $( - #[doc=3D"Sets the value of this field:"] - #[doc=3D$comment] - )? - #[inline(always)] - $vis fn [](mut self, value: $to_type) -> Self { - const MASK: $storage =3D $name::[<$field:upper _MASK>]; - const SHIFT: u32 =3D $name::[<$field:upper _SHIFT>]; - let value =3D ($storage::from($prim_type::from(value)) << SHIF= T) & MASK; - self.0 =3D (self.0 & !MASK) | value; - - self - } - ); - }; - - // Generates the `Debug` implementation for `$name`. - (@debug $name:ident { $($field:ident;)* }) =3D> { - impl ::kernel::fmt::Debug for $name { - fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kerne= l::fmt::Result { - f.debug_struct(stringify!($name)) - .field("", &::kernel::prelude::fmt!("{:#x}", &sel= f.0)) - $( - .field(stringify!($field), &self.$field()) - )* - .finish() - } - } - }; - - // Generates the `Default` implementation for `$name`. - (@default $name:ident { $($field:ident;)* }) =3D> { - /// Returns a value for the bitfield where all fields are set to t= heir default value. - impl ::core::default::Default for $name { - fn default() -> Self { - let value =3D Self(Default::default()); - - ::kernel::macros::paste!( - $( - let value =3D value.[](Default::default()); - )* - ); - - value - } - } - }; -} --=20 2.54.0