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 - 2025 Red Hat, Inc.