From nobody Mon Feb 9 20:10:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8831C221F34 for ; Thu, 6 Mar 2025 11:31:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741260667; cv=none; b=H8dGgk1lJfYhMYSIlVgM4MyxqMXeQYrfqWtZdMifaTJXGZ572Ho3C32in28fdB99Aw8zb6aVG45XV3Pippqvj8+ugT53PtptbQ3wloLtrLwmnDEWFsuaUIzPNseWn7OINcWghJQ5+L3JmE6pOW4pyOx3k8vy3+Nm+BWejP81+xQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741260667; c=relaxed/simple; bh=uug9inllF4CNSANoPBqQB3dQ7vQ0q5GoGzuCCGBSFTw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WJM6mfcqBvCZ+NnoReTsC7uZ5RdRVPqZej3epztqq6Hw3vEj2INfiVFnYiUbROjDhzIxVDfVEq8Y/dM0d6JZ3w71arWLC3BcYk9K5ULyEx+c2rj4O6Xe3jCg/eBq/woNvipMGEAPkWJFAcNPEjjieHQh66NsWC77l1wLzmkSZHk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YZ1bZ9kf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YZ1bZ9kf" Received: by smtp.kernel.org (Postfix) with ESMTPS id 30ED7C4CEED; Thu, 6 Mar 2025 11:31:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741260667; bh=uug9inllF4CNSANoPBqQB3dQ7vQ0q5GoGzuCCGBSFTw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=YZ1bZ9kfuN2coPnZYb6RL3KXBJz/y+oqlPX3btAZCdz3MfbA9Pj6bLxa/b9ztF54g IpzgEGDK04Qsueij0GYhlvwHKVE+WYKkE7W4mHo6GaAk3p0HQ0XfEfPkt5F9wW8voZ EPnMhcd5671ancwwIvQWG1aZ6uzxFuXAq7qyDYkE6rMIrJIuwl7V8AU1yw5OqmtrTi 0KnvSZIq1Tmxq7o3AE+3CnPLDnX+XDXfboUGPc59gMSb76IxOK+Ax1oEXDL7txBMIY JL70piZXnYuEvcUhEqZnT7JyfFPVIlbCFzgiNuXXu5ny+YL7t8Sij97R5Q54uQXoov i7AG+m4hzDufw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 280B3C282EC; Thu, 6 Mar 2025 11:31:07 +0000 (UTC) From: Vincent Mailhol via B4 Relay Date: Thu, 06 Mar 2025 20:29:53 +0900 Subject: [PATCH v5 2/7] bits: introduce fixed-type genmasks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250306-fixed-type-genmasks-v5-2-b443e9dcba63@wanadoo.fr> References: <20250306-fixed-type-genmasks-v5-0-b443e9dcba63@wanadoo.fr> In-Reply-To: <20250306-fixed-type-genmasks-v5-0-b443e9dcba63@wanadoo.fr> To: Yury Norov , Lucas De Marchi , Rasmus Villemoes , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , David Airlie , Simona Vetter , Andrew Morton Cc: linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org, Andi Shyti , David Laight , Dmitry Baryshkov , Andy Shevchenko , Jani Nikula , Vincent Mailhol X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6204; i=mailhol.vincent@wanadoo.fr; h=from:subject:message-id; bh=vj/U/kjA58bTl4i1RhDtnqOvx6EVzI9EZBNsPBTwNpg=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDOkn29PZuTl7vW/23/zLIMFWaTl31v7N00LKnC3/znCw/ bf/2uaijlIWBjEuBlkxRZZl5ZzcCh2F3mGH/lrCzGFlAhnCwMUpABP585mRYe2ea3+PfvxX537M TzyMu2GVhaCi4e+yrvM3p/sEuvlf42L4Kzovsu7xBF9p6bxoX8Mnl8PdSxvnuH805fi4S15pacQ CFgA= X-Developer-Key: i=mailhol.vincent@wanadoo.fr; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 X-Endpoint-Received: by B4 Relay for mailhol.vincent@wanadoo.fr/default with auth_id=291 X-Original-From: Vincent Mailhol Reply-To: mailhol.vincent@wanadoo.fr From: Yury Norov Add GENMASK_TYPE() which generalizes __GENMASK() to support different types, and implement fixed-types versions of GENMASK() based on it. The fixed-type version allows more strict checks to the min/max values accepted, which is useful for defining registers like implemented by i915 and xe drivers with their REG_GENMASK*() macros. The strict checks rely on shift-count-overflow compiler check to fail the build if a number outside of the range allowed is passed. Example: #define FOO_MASK GENMASK_U32(33, 4) will generate a warning like: include/linux/bits.h:51:27: error: right shift count >=3D width of type [= -Werror=3Dshift-count-overflow] 51 | type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) | ^~ Signed-off-by: Yury Norov Signed-off-by: Lucas De Marchi Acked-by: Jani Nikula Co-developed-by: Vincent Mailhol Signed-off-by: Vincent Mailhol --- Changelog: v4 -> v5: - Rename GENMASK_t() to GENMASK_TYPE(). - Fix typo in patch description. - Use tab indentations instead of single space to separate the macro name from its body. - s/__GENMASK_U*()/GENMASK_U*()/g in the comment. - Add a tag to credit myself as Co-developer. Keep Yury as the main author. - Modify GENMASK_TYPE() to match the changes made to __GENMASK() in: https://github.com/norov/linux/commit/1e7933a575ed - Replace (t)~_ULL(0) with type_max(t). This is OK because GENMASK_TYPE() is not available in asm. - linux/const.h and asm/bitsperlong.h are not used anymore. Remove them. - Apply GENMASK_TYPE() to GENMASK_U128(). - Remove the unsigned int cast for the U8 and U16 variants. Cast to the target type instead. Do that cast directly in GENMASK_TYPE(). v3 -> v4: - The v3 is one year old. Meanwhile people started using __GENMASK() directly. So instead of generalizing __GENMASK() to support different types, add a new GENMASK_t(). - replace ~0ULL by ~_ULL(0). Otherwise, GENMASK_t() would fail in asm code. - Make GENMASK_U8() and GENMASK_U16() return an unsigned int. In v3, due to the integer promotion rules, these were returning a signed integer. By casting these to unsigned int, at least the signedness is kept. --- include/linux/bitops.h | 1 - include/linux/bits.h | 47 +++++++++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/include/linux/bitops.h b/include/linux/bitops.h index c1cb53cf2f0f8662ed3e324578f74330e63f935d..9be2d50da09a417966b3d11c840= 92bb2f4cd0bef 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -8,7 +8,6 @@ =20 #include =20 -#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) #define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) #define BITS_TO_U64(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64)) #define BITS_TO_U32(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32)) diff --git a/include/linux/bits.h b/include/linux/bits.h index 4819cbe7bd48fbae796fc6005c9f92b1c93a034c..74219521a56e2639ccff7fdc899= d6805ee355a0c 100644 --- a/include/linux/bits.h +++ b/include/linux/bits.h @@ -2,16 +2,15 @@ #ifndef __LINUX_BITS_H #define __LINUX_BITS_H =20 -#include #include #include -#include =20 #define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) #define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) #define BITS_PER_BYTE 8 +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) =20 /* * Create a contiguous bitmask starting at bit position @l and ending at @@ -20,28 +19,44 @@ */ #if !defined(__ASSEMBLY__) =20 +/* + * Missing asm support + * + * GENMASK_U*() depends on BITS_PER_TYPE() which relies on sizeof(), + * something not available in asm. Nethertheless, fixed width integers + * is a C concept. Assembly code can rely on the long and long long + * versions instead. + */ + #include #include +#include =20 #define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h))) =20 -#define GENMASK(h, l) \ - (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) -#define GENMASK_ULL(h, l) \ - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l)) - /* - * Missing asm support + * Generate a mask for the specified type @t. Additional checks are made to + * guarantee the value returned fits in that type, relying on + * shift-count-overflow compiler check to detect incompatible arguments. + * For example, all these create build errors or warnings: * - * __GENMASK_U128() depends on _BIT128() which would not work - * in the asm code, as it shifts an 'unsigned __int128' data - * type instead of direct representation of 128 bit constants - * such as long and unsigned long. The fundamental problem is - * that a 128 bit constant will get silently truncated by the - * gcc compiler. + * - GENMASK(15, 20): wrong argument order + * - GENMASK(72, 15): doesn't fit unsigned long + * - GENMASK_U32(33, 15): doesn't fit in a u32 */ -#define GENMASK_U128(h, l) \ - (GENMASK_INPUT_CHECK(h, l) + __GENMASK_U128(h, l)) +#define GENMASK_TYPE(t, h, l) \ + ((t)(GENMASK_INPUT_CHECK(h, l) + \ + (type_max(t) << (l) & \ + type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) + +#define GENMASK(h, l) GENMASK_TYPE(unsigned long, h, l) +#define GENMASK_ULL(h, l) GENMASK_TYPE(unsigned long long, h, l) + +#define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l) +#define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l) +#define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l) +#define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l) +#define GENMASK_U128(h, l) GENMASK_TYPE(u128, h, l) =20 #else /* defined(__ASSEMBLY__) */ =20 --=20 2.45.3