[PATCH v4] x86: Clear feature bits disabled at compile-time

Maciej Wieczor-Retman posted 1 patch 2 months, 1 week ago
arch/x86/kernel/cpu/common.c       | 3 ++-
arch/x86/tools/cpufeaturemasks.awk | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
[PATCH v4] x86: Clear feature bits disabled at compile-time
Posted by Maciej Wieczor-Retman 2 months, 1 week ago
If some config options are disabled during compile time, they still are
enumerated in macros that use the x86_capability bitmask - cpu_has() or
this_cpu_has().

The features are also visible in /proc/cpuinfo even though they are not
enabled - which is contrary to what the documentation states about the
file. Examples of such feature flags are lam, fred, sgx, ibrs_enhanced,
split_lock_detect, user_shstk, avx_vnni and enqcmd.

Add a DISABLED_MASK_INITIALIZER macro that creates an initializer list
filled with DISABLED_MASKx bitmasks.

Initialize the cpu_caps_cleared array with the autogenerated disabled
bitmask.

Fixes: ea4e3bef4c94 ("Documentation/x86: Add documentation for /proc/cpuinfo feature flags")
Reported-by: Farrah Chen <farrah.chen@intel.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Cc: <stable@vger.kernel.org>
---
Changelog v4:
- Fix macro name to match with the patch message.
- Add Peter's SoB.

Changelog v3:
- Remove Fixes: tags, keep only one at the point where the documentation
  changed and promised feature bits wouldn't show up if they're not
  enabled.
- Don't use a helper to initialize cpu_caps_cleared, just statically
  initialize it.
- Remove changes to cpu_caps_set.
- Rewrite patch message to account for changes.

Changelog v2:
- Redo the patch to utilize a more generic solution, not just fix the
  LAM and FRED feature bits.
- Note more feature flags that shouldn't be present.
- Add fixes and cc tags.

 arch/x86/kernel/cpu/common.c       | 3 ++-
 arch/x86/tools/cpufeaturemasks.awk | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 77afca95cced..a9040038ad9d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -704,7 +704,8 @@ static const char *table_lookup_model(struct cpuinfo_x86 *c)
 }
 
 /* Aligned to unsigned long to avoid split lock in atomic bitmap ops */
-__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
+__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long)) =
+	DISABLED_MASK_INITIALIZER;
 __u32 cpu_caps_set[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/tools/cpufeaturemasks.awk b/arch/x86/tools/cpufeaturemasks.awk
index 173d5bf2d999..1eabbc69f50d 100755
--- a/arch/x86/tools/cpufeaturemasks.awk
+++ b/arch/x86/tools/cpufeaturemasks.awk
@@ -84,5 +84,11 @@ END {
 		printf "\t) & (1U << ((x) & 31)))\n\n";
 	}
 
+		printf "\n#define DISABLED_MASK_INITIALIZER\t\t\t\\";
+		printf "\n\t{\t\t\t\t\t\t\\";
+		for (i = 0; i < ncapints; i++)
+			printf "\n\t\tDISABLED_MASK%d,\t\t\t\\", i;
+		printf "\n\t}\n\n";
+
 	printf "#endif /* _ASM_X86_CPUFEATUREMASKS_H */\n";
 }
-- 
2.49.0
Re: [PATCH v4] x86: Clear feature bits disabled at compile-time
Posted by Xin Li 2 months, 1 week ago
On 7/24/2025 5:53 AM, Maciej Wieczor-Retman wrote:
> If some config options are disabled during compile time, they still are
> enumerated in macros that use the x86_capability bitmask - cpu_has() or
> this_cpu_has().
> 
> The features are also visible in /proc/cpuinfo even though they are not
> enabled - which is contrary to what the documentation states about the
> file. Examples of such feature flags are lam, fred, sgx, ibrs_enhanced,
> split_lock_detect, user_shstk, avx_vnni and enqcmd.
> 
> Add a DISABLED_MASK_INITIALIZER macro that creates an initializer list
> filled with DISABLED_MASKx bitmasks.
> 
> Initialize the cpu_caps_cleared array with the autogenerated disabled
> bitmask.

It's worth appending:

And apply_forced_caps() will clear the corresponding bits in 
boot_cpu_data.x86_capability[] and APs' cpu_data.x86_capability[].
Thus features disabled at build time won't show up in /proc/cpuinfo.

> 
> Fixes: ea4e3bef4c94 ("Documentation/x86: Add documentation for /proc/cpuinfo feature flags")
> Reported-by: Farrah Chen <farrah.chen@intel.com>
> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> Cc: <stable@vger.kernel.org>
> ---
> Changelog v4:
> - Fix macro name to match with the patch message.
> - Add Peter's SoB.
> 
> Changelog v3:
> - Remove Fixes: tags, keep only one at the point where the documentation
>    changed and promised feature bits wouldn't show up if they're not
>    enabled.
> - Don't use a helper to initialize cpu_caps_cleared, just statically
>    initialize it.
> - Remove changes to cpu_caps_set.
> - Rewrite patch message to account for changes.
> 
> Changelog v2:
> - Redo the patch to utilize a more generic solution, not just fix the
>    LAM and FRED feature bits.
> - Note more feature flags that shouldn't be present.
> - Add fixes and cc tags.
> 
>   arch/x86/kernel/cpu/common.c       | 3 ++-
>   arch/x86/tools/cpufeaturemasks.awk | 6 ++++++
>   2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 77afca95cced..a9040038ad9d 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -704,7 +704,8 @@ static const char *table_lookup_model(struct cpuinfo_x86 *c)
>   }
>   
>   /* Aligned to unsigned long to avoid split lock in atomic bitmap ops */
> -__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
> +__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long)) =
> +	DISABLED_MASK_INITIALIZER;
>   __u32 cpu_caps_set[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
>   
>   #ifdef CONFIG_X86_32
> diff --git a/arch/x86/tools/cpufeaturemasks.awk b/arch/x86/tools/cpufeaturemasks.awk
> index 173d5bf2d999..1eabbc69f50d 100755
> --- a/arch/x86/tools/cpufeaturemasks.awk
> +++ b/arch/x86/tools/cpufeaturemasks.awk
> @@ -84,5 +84,11 @@ END {
>   		printf "\t) & (1U << ((x) & 31)))\n\n";
>   	}
>   
> +		printf "\n#define DISABLED_MASK_INITIALIZER\t\t\t\\";
> +		printf "\n\t{\t\t\t\t\t\t\\";
> +		for (i = 0; i < ncapints; i++)
> +			printf "\n\t\tDISABLED_MASK%d,\t\t\t\\", i;
> +		printf "\n\t}\n\n";
> +

The indentation is incorrect.

And I think it's no harm to generate both REQUIRED_MASK_INITIALIZER and
DISABLED_MASK_INITIALIZER, so you can put this new code block inside the
above

	for (ns in sets) {
		...
	}

loop.

>   	printf "#endif /* _ASM_X86_CPUFEATUREMASKS_H */\n";
>   }