lkml.org 
[lkml]   [2019]   [Feb]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v3 08/10] x86/setcpuid: Add kernel option setcpuid
Date
On some platforms, a feature (e.g. #AC for split lock) may not be
enumerated by CPUID or non architectural way in IA32_CORE_CAPABILITY.
To enable the feature on the platforms, a new kernel option setcpuid
is added.

The feature is defined in cpufeatures.h. The kernel option setcpuid
takes either feature bit or cpu cap flag corresponding to the feature.
The format of the option:
setcpuid=<feature bit>
setcpuid=<feature capability flag>

Check cpufeatures.h for valid feature bit numbers and check capflags.c
or /proc/cpuinfo for valid feature capability flags.

Enabling multiple features are supported.

Please note kernel may malfunction if some features are enabled by
the option.

This option behaves like existing kernel option clearcpuid.

Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
---
Documentation/admin-guide/kernel-parameters.txt | 15 +++++++++
arch/x86/include/asm/cpufeature.h | 1 +
arch/x86/kernel/cpu/cpuid-deps.c | 42 +++++++++++++++++++------
arch/x86/kernel/fpu/init.c | 4 +++
4 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 13bf223c7739..5de364078c69 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4083,6 +4083,21 @@
incurs a small amount of overhead in the scheduler
but is useful for debugging and performance tuning.

+ setcpuid=BITNUM | FLAG [X86]
+ Enable CPUID feature X for the kernel. See
+ arch/x86/include/asm/cpufeatures.h for the valid bit
+ numbers or /proc/cpuinfo for the valid CPU flags.
+ Multiple options can be used to enable a few features.
+ Note the Linux specific bits are not necessarily
+ stable over kernel options, but the vendor specific
+ ones should be.
+ Also note that user programs calling CPUID directly
+ or using the feature without checking anything
+ may still disable it.
+ Also note the kernel might malfunction if you enable
+ some critical bits.
+ Please refer to clearcpuid for disabling CPUID feature.
+
skew_tick= [KNL] Offset the periodic timer tick per cpu to mitigate
xtime_lock contention on larger systems, and/or RCU lock
contention on all systems with CONFIG_MAXSMP set.
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 6792088525e3..6b580687f261 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -131,6 +131,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define set_cpu_cap(c, bit) set_bit(bit, (unsigned long *)((c)->x86_capability))

extern void setup_clear_cpu_cap(unsigned int bit);
+void setup_set_cpu_cap(unsigned int bit);
extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
bool find_cpu_cap(char *cap_flag, unsigned int *pfeature);

diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 19bfab0858ac..ae534b5d0b4d 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -62,25 +62,39 @@ static const struct cpuid_dep cpuid_deps[] = {
{}
};

-static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
+static inline void
+setup_feature(struct cpuinfo_x86 *c, unsigned int feature, bool enable)
{
/*
* Note: This could use the non atomic __*_bit() variants, but the
* rest of the cpufeature code uses atomics as well, so keep it for
* consistency. Cleanup all of it separately.
*/
- if (!c) {
- clear_cpu_cap(&boot_cpu_data, feature);
- set_bit(feature, (unsigned long *)cpu_caps_cleared);
+ if (enable) {
+ /* Set the feature */
+ if (!c) {
+ set_cpu_cap(&boot_cpu_data, feature);
+ clear_bit(feature, (unsigned long *)cpu_caps_cleared);
+ setup_force_cpu_cap(feature);
+ } else {
+ set_bit(feature, (unsigned long *)c->x86_capability);
+ }
} else {
- clear_bit(feature, (unsigned long *)c->x86_capability);
+ /* Clear the feature */
+ if (!c) {
+ clear_cpu_cap(&boot_cpu_data, feature);
+ set_bit(feature, (unsigned long *)cpu_caps_cleared);
+ } else {
+ clear_bit(feature, (unsigned long *)c->x86_capability);
+ }
}
}

/* Take the capabilities and the BUG bits into account */
#define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)

-static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
+static void
+do_setup_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature, bool enable)
{
DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
const struct cpuid_dep *d;
@@ -89,7 +103,7 @@ static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
if (WARN_ON(feature >= MAX_FEATURE_BITS))
return;

- clear_feature(c, feature);
+ setup_feature(c, feature, enable);

/* Collect all features to disable, handling dependencies */
memset(disable, 0, sizeof(disable));
@@ -105,19 +119,27 @@ static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
continue;

changed = true;
- clear_feature(c, d->feature);
+ setup_feature(c, d->feature, enable);
}
} while (changed);
}

void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
{
- do_clear_cpu_cap(c, feature);
+ /* Disable the feature. */
+ do_setup_cpu_cap(c, feature, false);
}

void setup_clear_cpu_cap(unsigned int feature)
{
- do_clear_cpu_cap(NULL, feature);
+ /* Disable the feature. */
+ do_setup_cpu_cap(NULL, feature, false);
+}
+
+void setup_set_cpu_cap(unsigned int feature)
+{
+ /* Enable the feature. */
+ do_setup_cpu_cap(NULL, feature, true);
}

/**
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index a9a67645a607..cb1e2f8129a5 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -251,6 +251,9 @@ static void __init setup_cpuid_option(char *setup_cpuid_option)

if (!strcmp(setup_cpuid_option, "clearcpuid"))
setup_cpu_cap = setup_clear_cpu_cap;
+ else if (!strcmp(setup_cpuid_option, "setcpuid"))
+ setup_cpu_cap = setup_set_cpu_cap;
+ else
return;

/* Find each option in boot_command_line and clear specified cpu cap. */
@@ -293,6 +296,7 @@ static void __init fpu__init_parse_early_param(void)
setup_clear_cpu_cap(X86_FEATURE_XSAVES);

setup_cpuid_option("clearcpuid");
+ setup_cpuid_option("setcpuid");
}

/*
--
2.7.4
\
 
 \ /
  Last update: 2019-02-02 06:22    [W:0.229 / U:0.064 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site