arch/x86/kernel/cpu/common.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
If LAM (CONFIG_ADDRESS_MASKING) or FRED (CONFIG_X86_FRED) are disabled
during compile time, they still are enumerated in macros such as
cpu_has() or this_cpu_has() that use the x86_capability bitmask. 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.
The documentation for x86/cpuinfo.rst also states how to handle features
disabled at compile time:
The kernel disabled support for it at compile-time
--------------------------------------------------
For example, if Linear Address Masking (LAM) is not enabled when
building (i.e., CONFIG_ADDRESS_MASKING is not selected) the flag
"lam" will not show up. Even though the feature will still be
detected via CPUID, the kernel disables it by clearing via
setup_clear_cpu_cap(X86_FEATURE_LAM).
Clear feature bits if they are present in the DISABLED_MASK.
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
arch/x86/kernel/cpu/common.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 77afca95cced..1c5af795cedc 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1782,6 +1782,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
if (!pgtable_l5_enabled())
setup_clear_cpu_cap(X86_FEATURE_LA57);
+ /*
+ * If a feature is disabled during compile time clear its feature
+ * bit to prevent it from showing up in the x86_capability bitmask.
+ */
+ if (!cpu_feature_enabled(X86_FEATURE_LAM))
+ setup_clear_cpu_cap(X86_FEATURE_LAM);
+
+ if (!cpu_feature_enabled(X86_FEATURE_FRED))
+ setup_clear_cpu_cap(X86_FEATURE_FRED);
+
detect_nopl();
}
--
2.49.0
> On Jul 22, 2025, at 12:54 AM, Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> wrote:
>
> If LAM (CONFIG_ADDRESS_MASKING) or FRED (CONFIG_X86_FRED) are disabled
> during compile time, they still are enumerated in macros such as
> cpu_has() or this_cpu_has() that use the x86_capability bitmask. 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.
I'm curious how this bug is introduced with my patch set that adds the
AWK script which automatically generates the CPU feature mask header.
>
> The documentation for x86/cpuinfo.rst also states how to handle features
> disabled at compile time:
>
> The kernel disabled support for it at compile-time
> --------------------------------------------------
>
> For example, if Linear Address Masking (LAM) is not enabled when
> building (i.e., CONFIG_ADDRESS_MASKING is not selected) the flag
> "lam" will not show up. Even though the feature will still be
> detected via CPUID, the kernel disables it by clearing via
> setup_clear_cpu_cap(X86_FEATURE_LAM).
>
> Clear feature bits if they are present in the DISABLED_MASK.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
And we need a Fixes tag and CC stable.
> ---
> arch/x86/kernel/cpu/common.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 77afca95cced..1c5af795cedc 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -1782,6 +1782,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
> if (!pgtable_l5_enabled())
> setup_clear_cpu_cap(X86_FEATURE_LA57);
>
> + /*
> + * If a feature is disabled during compile time clear its feature
> + * bit to prevent it from showing up in the x86_capability bitmask.
> + */
> + if (!cpu_feature_enabled(X86_FEATURE_LAM))
> + setup_clear_cpu_cap(X86_FEATURE_LAM);
> +
> + if (!cpu_feature_enabled(X86_FEATURE_FRED))
> + setup_clear_cpu_cap(X86_FEATURE_FRED);
> +
The following code will work as a generic fix:
c->x86_capability[i] &= ~DISABLED_MASK(i);
And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x).
Thanks!
Xin
On July 22, 2025 2:08:28 AM PDT, Xin Li <xin@zytor.com> wrote: > >> On Jul 22, 2025, at 12:54 AM, Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> wrote: >> >> If LAM (CONFIG_ADDRESS_MASKING) or FRED (CONFIG_X86_FRED) are disabled >> during compile time, they still are enumerated in macros such as >> cpu_has() or this_cpu_has() that use the x86_capability bitmask. 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. > >I'm curious how this bug is introduced with my patch set that adds the >AWK script which automatically generates the CPU feature mask header. > >> >> The documentation for x86/cpuinfo.rst also states how to handle features >> disabled at compile time: >> >> The kernel disabled support for it at compile-time >> -------------------------------------------------- >> >> For example, if Linear Address Masking (LAM) is not enabled when >> building (i.e., CONFIG_ADDRESS_MASKING is not selected) the flag >> "lam" will not show up. Even though the feature will still be >> detected via CPUID, the kernel disables it by clearing via >> setup_clear_cpu_cap(X86_FEATURE_LAM). >> >> Clear feature bits if they are present in the DISABLED_MASK. >> >> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> > >And we need a Fixes tag and CC stable. > >> --- >> arch/x86/kernel/cpu/common.c | 10 ++++++++++ >> 1 file changed, 10 insertions(+) >> >> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c >> index 77afca95cced..1c5af795cedc 100644 >> --- a/arch/x86/kernel/cpu/common.c >> +++ b/arch/x86/kernel/cpu/common.c >> @@ -1782,6 +1782,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) >> if (!pgtable_l5_enabled()) >> setup_clear_cpu_cap(X86_FEATURE_LA57); >> >> + /* >> + * If a feature is disabled during compile time clear its feature >> + * bit to prevent it from showing up in the x86_capability bitmask. >> + */ >> + if (!cpu_feature_enabled(X86_FEATURE_LAM)) >> + setup_clear_cpu_cap(X86_FEATURE_LAM); >> + >> + if (!cpu_feature_enabled(X86_FEATURE_FRED)) >> + setup_clear_cpu_cap(X86_FEATURE_FRED); >> + > >The following code will work as a generic fix: > > c->x86_capability[i] &= ~DISABLED_MASK(i); > >And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x). > >Thanks! > Xin The easiest thing would be to initialize the setup disabled mask with the DISABLED bitmask instead of zero. This can be done statically; if it isn't already the awk script can produce the disabled bitmask in array form.
On 2025-07-22 at 09:46:42 -0700, H. Peter Anvin wrote: >On July 22, 2025 2:08:28 AM PDT, Xin Li <xin@zytor.com> wrote: >>> On Jul 22, 2025, at 12:54 AM, Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> wrote: >>> --- >>> arch/x86/kernel/cpu/common.c | 10 ++++++++++ >>> 1 file changed, 10 insertions(+) >>> >>> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c >>> index 77afca95cced..1c5af795cedc 100644 >>> --- a/arch/x86/kernel/cpu/common.c >>> +++ b/arch/x86/kernel/cpu/common.c >>> @@ -1782,6 +1782,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) >>> if (!pgtable_l5_enabled()) >>> setup_clear_cpu_cap(X86_FEATURE_LA57); >>> >>> + /* >>> + * If a feature is disabled during compile time clear its feature >>> + * bit to prevent it from showing up in the x86_capability bitmask. >>> + */ >>> + if (!cpu_feature_enabled(X86_FEATURE_LAM)) >>> + setup_clear_cpu_cap(X86_FEATURE_LAM); >>> + >>> + if (!cpu_feature_enabled(X86_FEATURE_FRED)) >>> + setup_clear_cpu_cap(X86_FEATURE_FRED); >>> + >> >>The following code will work as a generic fix: >> >> c->x86_capability[i] &= ~DISABLED_MASK(i); >> >>And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x). >> >>Thanks! >> Xin > >The easiest thing would be to initialize the setup disabled mask with the >DISABLED bitmask instead of zero. This can be done statically; if it isn't >already the awk script can produce the disabled bitmask in array form. Oh, that does sound simple. I'll try that too, see what ends up with cleaner code. Thanks :) -- Kind regards Maciej Wieczór-Retman
On 2025-07-22 11:19, Maciej Wieczor-Retman wrote: >> >> The easiest thing would be to initialize the setup disabled mask with the >> DISABLED bitmask instead of zero. This can be done statically; if it isn't >> already the awk script can produce the disabled bitmask in array form. > > Oh, that does sound simple. I'll try that too, see what ends up with cleaner > code. > Xin should have code from me for exactly this. -hpa
On 7/22/2025 9:46 AM, H. Peter Anvin wrote:
>> The following code will work as a generic fix:
>>
>> c->x86_capability[i] &= ~DISABLED_MASK(i);
>>
>> And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x).
>>
>> Thanks!
>> Xin
> The easiest thing would be to initialize the setup disabled mask with the DISABLED bitmask instead of zero. This can be done statically; if it isn't already the awk script can produce the disabled bitmask in array form.
Yes, something like:
void __init init_cpu_cap(void)
{
for (i = 0; i < NCAPINTS; i++) {
cpu_caps_set[i] = REQUIRED_MASK(i);
cpu_caps_cleared[i] = DISABLED_MASK(i);
}
}
And it would be better if it could be done at build time (to avoid
changing Xen which has a dedicated startup code path):
__u32 cpu_caps_{set,cleared}[NCAPINTS + NBUGINTS] = {
{REQUIRED,DISABLED}_MASK(i),
};
And then apply_forced_caps() will do the rest automatically :)
On 2025-07-22 at 02:08:28 -0700, Xin Li wrote: > >> On Jul 22, 2025, at 12:54 AM, Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> wrote: >> >> If LAM (CONFIG_ADDRESS_MASKING) or FRED (CONFIG_X86_FRED) are disabled >> during compile time, they still are enumerated in macros such as >> cpu_has() or this_cpu_has() that use the x86_capability bitmask. 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. > >I'm curious how this bug is introduced with my patch set that adds the >AWK script which automatically generates the CPU feature mask header. While your patch works great in setting up the DISABLED_MASKs, there is no place that would read that mask and clear x86_capability bitmask. Most other features seem to have a call to setup_clear_cpu_cap() somewhere, or they're in the required bitmask. LAM doesn't have one at all, and FRED only has a kernel command line check - so no compile-time support is checked anywhere. > >> >> The documentation for x86/cpuinfo.rst also states how to handle features >> disabled at compile time: >> >> The kernel disabled support for it at compile-time >> -------------------------------------------------- >> >> For example, if Linear Address Masking (LAM) is not enabled when >> building (i.e., CONFIG_ADDRESS_MASKING is not selected) the flag >> "lam" will not show up. Even though the feature will still be >> detected via CPUID, the kernel disables it by clearing via >> setup_clear_cpu_cap(X86_FEATURE_LAM). >> >> Clear feature bits if they are present in the DISABLED_MASK. >> >> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> > >And we need a Fixes tag and CC stable. Ah, thank you for reminding me :) > >> --- >> arch/x86/kernel/cpu/common.c | 10 ++++++++++ >> 1 file changed, 10 insertions(+) >> >> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c >> index 77afca95cced..1c5af795cedc 100644 >> --- a/arch/x86/kernel/cpu/common.c >> +++ b/arch/x86/kernel/cpu/common.c >> @@ -1782,6 +1782,16 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) >> if (!pgtable_l5_enabled()) >> setup_clear_cpu_cap(X86_FEATURE_LA57); >> >> + /* >> + * If a feature is disabled during compile time clear its feature >> + * bit to prevent it from showing up in the x86_capability bitmask. >> + */ >> + if (!cpu_feature_enabled(X86_FEATURE_LAM)) >> + setup_clear_cpu_cap(X86_FEATURE_LAM); >> + >> + if (!cpu_feature_enabled(X86_FEATURE_FRED)) >> + setup_clear_cpu_cap(X86_FEATURE_FRED); >> + > >The following code will work as a generic fix: > > c->x86_capability[i] &= ~DISABLED_MASK(i); > >And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x). Thanks, I'll add a helper for that and put the call in the same place this patch changes are. Seems like a good place with a lot of other setup_clear_cpu_cap() calls. > >Thanks! > Xin -- Kind regards Maciej Wieczór-Retman
On 7/22/25 02:08, Xin Li wrote: >> + /* >> + * If a feature is disabled during compile time clear its feature >> + * bit to prevent it from showing up in the x86_capability bitmask. >> + */ >> + if (!cpu_feature_enabled(X86_FEATURE_LAM)) >> + setup_clear_cpu_cap(X86_FEATURE_LAM); >> + >> + if (!cpu_feature_enabled(X86_FEATURE_FRED)) >> + setup_clear_cpu_cap(X86_FEATURE_FRED); >> + > > The following code will work as a generic fix: > > c->x86_capability[i] &= ~DISABLED_MASK(i); > > And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x). Maciej, I would much rather have a generic fix than force everyone to remember to open-code this for every new feature that gets disabled.
On 2025-07-22 at 07:11:47 -0700, Dave Hansen wrote: >On 7/22/25 02:08, Xin Li wrote: >>> + /* >>> + * If a feature is disabled during compile time clear its feature >>> + * bit to prevent it from showing up in the x86_capability bitmask. >>> + */ >>> + if (!cpu_feature_enabled(X86_FEATURE_LAM)) >>> + setup_clear_cpu_cap(X86_FEATURE_LAM); >>> + >>> + if (!cpu_feature_enabled(X86_FEATURE_FRED)) >>> + setup_clear_cpu_cap(X86_FEATURE_FRED); >>> + >> >> The following code will work as a generic fix: >> >> c->x86_capability[i] &= ~DISABLED_MASK(i); >> >> And DISABLED_MASK(x) needs to be defined like DISABLED_MASK_BIT_SET(x). > >Maciej, I would much rather have a generic fix than force everyone to >remember to open-code this for every new feature that gets disabled. I'll apply Xin's suggestions, test and resend. -- Kind regards Maciej Wieczór-Retman
© 2016 - 2026 Red Hat, Inc.