* [PATCH v3 1/4] x86/cpu: Remove some macros about feature names
2025-02-18 18:59 [PATCH v3 0/4] x86/cpu: Add facility to force-enable CPU caps and bugs Brendan Jackman
@ 2025-02-18 18:59 ` Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 2/4] x86/cpu: Create helper to parse clearcpuid param Brendan Jackman
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Brendan Jackman @ 2025-02-18 18:59 UTC (permalink / raw)
To: Jonathan Corbet, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra
Cc: linux-doc, linux-kernel, Brendan Jackman
These macros used to abstract over CONFIG_X86_FEATURE_NAMES, but that
was removed in commit 7583e8fbdc49 ("x86/cpu: Remove
X86_FEATURE_NAMES"). Now they are just unnecessary indirection, remove
them.
Signed-off-by: Brendan Jackman <jackmanb@google.com>
---
arch/x86/include/asm/cpufeature.h | 5 -----
arch/x86/kernel/cpu/common.c | 12 ++++++------
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index de1ad09fe8d7..f23942108b85 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -37,13 +37,8 @@ enum cpuid_leafs
NR_CPUID_WORDS,
};
-#define X86_CAP_FMT_NUM "%d:%d"
-#define x86_cap_flag_num(flag) ((flag) >> 5), ((flag) & 31)
-
extern const char * const x86_cap_flags[NCAPINTS*32];
extern const char * const x86_power_flags[32];
-#define X86_CAP_FMT "%s"
-#define x86_cap_flag(flag) x86_cap_flags[flag]
/*
* In order to save room, we index into this array by doing
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 76598a93a8fa..f96a3a4829bd 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -667,8 +667,8 @@ static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
if (!warn)
continue;
- pr_warn("CPU: CPU feature " X86_CAP_FMT " disabled, no CPUID level 0x%x\n",
- x86_cap_flag(df->feature), df->level);
+ pr_warn("CPU: CPU feature %s disabled, no CPUID level 0x%x\n",
+ x86_cap_flags[df->feature], df->level);
}
}
@@ -1539,9 +1539,9 @@ static void __init cpu_parse_early_param(void)
/* empty-string, i.e., ""-defined feature flags */
if (!x86_cap_flags[bit])
- pr_cont(" " X86_CAP_FMT_NUM, x86_cap_flag_num(bit));
+ pr_cont(" %d:%d", bit >> 5, bit & 31);
else
- pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
+ pr_cont(" %s", x86_cap_flags[bit]);
setup_clear_cpu_cap(bit);
taint++;
@@ -1554,10 +1554,10 @@ static void __init cpu_parse_early_param(void)
}
for (bit = 0; bit < 32 * NCAPINTS; bit++) {
- if (!x86_cap_flag(bit))
+ if (!x86_cap_flags[bit])
continue;
- if (strcmp(x86_cap_flag(bit), opt))
+ if (strcmp(x86_cap_flags[bit], opt))
continue;
pr_cont(" %s", opt);
--
2.48.1.601.g30ceb7b040-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 2/4] x86/cpu: Create helper to parse clearcpuid param
2025-02-18 18:59 [PATCH v3 0/4] x86/cpu: Add facility to force-enable CPU caps and bugs Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 1/4] x86/cpu: Remove some macros about feature names Brendan Jackman
@ 2025-02-18 18:59 ` Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 3/4] x86/cpu: Add setcpuid cmdline param Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 4/4] x86/cpu: Enable modifying bug flags with {clear,set}cpuid Brendan Jackman
3 siblings, 0 replies; 5+ messages in thread
From: Brendan Jackman @ 2025-02-18 18:59 UTC (permalink / raw)
To: Jonathan Corbet, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra
Cc: linux-doc, linux-kernel, Brendan Jackman
This is in preparation for a later commit that will reuse this code, to
make review convenient.
Factor out a helper function which does the full handling for this arg
including printing info to the console.
No functional change intended.
Signed-off-by: Brendan Jackman <jackmanb@google.com>
---
arch/x86/kernel/cpu/common.c | 97 ++++++++++++++++++++++++--------------------
1 file changed, 53 insertions(+), 44 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index f96a3a4829bd..1241c205b9d0 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1479,56 +1479,18 @@ static void detect_nopl(void)
#endif
}
-/*
- * We parse cpu parameters early because fpu__init_system() is executed
- * before parse_early_param().
- */
-static void __init cpu_parse_early_param(void)
+static inline void parse_clearcpuid(char *arg)
{
- char arg[128];
- char *argptr = arg, *opt;
- int arglen, taint = 0;
-
-#ifdef CONFIG_X86_32
- if (cmdline_find_option_bool(boot_command_line, "no387"))
-#ifdef CONFIG_MATH_EMULATION
- setup_clear_cpu_cap(X86_FEATURE_FPU);
-#else
- pr_err("Option 'no387' required CONFIG_MATH_EMULATION enabled.\n");
-#endif
-
- if (cmdline_find_option_bool(boot_command_line, "nofxsr"))
- setup_clear_cpu_cap(X86_FEATURE_FXSR);
-#endif
-
- if (cmdline_find_option_bool(boot_command_line, "noxsave"))
- setup_clear_cpu_cap(X86_FEATURE_XSAVE);
-
- if (cmdline_find_option_bool(boot_command_line, "noxsaveopt"))
- setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
-
- if (cmdline_find_option_bool(boot_command_line, "noxsaves"))
- setup_clear_cpu_cap(X86_FEATURE_XSAVES);
-
- if (cmdline_find_option_bool(boot_command_line, "nousershstk"))
- setup_clear_cpu_cap(X86_FEATURE_USER_SHSTK);
-
- /* Minimize the gap between FRED is available and available but disabled. */
- arglen = cmdline_find_option(boot_command_line, "fred", arg, sizeof(arg));
- if (arglen != 2 || strncmp(arg, "on", 2))
- setup_clear_cpu_cap(X86_FEATURE_FRED);
-
- arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg));
- if (arglen <= 0)
- return;
+ char *opt;
+ int taint = 0;
pr_info("Clearing CPUID bits:");
- while (argptr) {
+ while (arg) {
bool found __maybe_unused = false;
unsigned int bit;
- opt = strsep(&argptr, ",");
+ opt = strsep(&arg, ",");
/*
* Handle naked numbers first for feature flags which don't
@@ -1570,10 +1532,57 @@ static void __init cpu_parse_early_param(void)
if (!found)
pr_cont(" (unknown: %s)", opt);
}
- pr_cont("\n");
if (taint)
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+
+ pr_cont("\n");
+}
+
+
+/*
+ * Parse cpu parameters early because fpu__init_system() is executed
+ * before parse_early_param().
+ */
+static void __init cpu_parse_early_param(void)
+{
+ char arg[128];
+ int arglen;
+
+#ifdef CONFIG_X86_32
+ if (cmdline_find_option_bool(boot_command_line, "no387"))
+#ifdef CONFIG_MATH_EMULATION
+ setup_clear_cpu_cap(X86_FEATURE_FPU);
+#else
+ pr_err("Option 'no387' required CONFIG_MATH_EMULATION enabled.\n");
+#endif
+
+ if (cmdline_find_option_bool(boot_command_line, "nofxsr"))
+ setup_clear_cpu_cap(X86_FEATURE_FXSR);
+#endif
+
+ if (cmdline_find_option_bool(boot_command_line, "noxsave"))
+ setup_clear_cpu_cap(X86_FEATURE_XSAVE);
+
+ if (cmdline_find_option_bool(boot_command_line, "noxsaveopt"))
+ setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
+
+ if (cmdline_find_option_bool(boot_command_line, "noxsaves"))
+ setup_clear_cpu_cap(X86_FEATURE_XSAVES);
+
+ if (cmdline_find_option_bool(boot_command_line, "nousershstk"))
+ setup_clear_cpu_cap(X86_FEATURE_USER_SHSTK);
+
+ /* Minimize the gap between FRED is available and available but disabled. */
+ arglen = cmdline_find_option(boot_command_line, "fred", arg, sizeof(arg));
+ if (arglen != 2 || strncmp(arg, "on", 2))
+ setup_clear_cpu_cap(X86_FEATURE_FRED);
+
+ arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg));
+ if (arglen <= 0)
+ return;
+
+ parse_clearcpuid(arg);
}
/*
--
2.48.1.601.g30ceb7b040-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 3/4] x86/cpu: Add setcpuid cmdline param
2025-02-18 18:59 [PATCH v3 0/4] x86/cpu: Add facility to force-enable CPU caps and bugs Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 1/4] x86/cpu: Remove some macros about feature names Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 2/4] x86/cpu: Create helper to parse clearcpuid param Brendan Jackman
@ 2025-02-18 18:59 ` Brendan Jackman
2025-02-18 18:59 ` [PATCH v3 4/4] x86/cpu: Enable modifying bug flags with {clear,set}cpuid Brendan Jackman
3 siblings, 0 replies; 5+ messages in thread
From: Brendan Jackman @ 2025-02-18 18:59 UTC (permalink / raw)
To: Jonathan Corbet, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra
Cc: linux-doc, linux-kernel, Brendan Jackman
In preparation for adding support to fake out CPU bugs, add a general
facility to force-enable CPU flags.
The flag taints the kernel and the documentation attempts to be clear
that this is highly unsuitable for uses outside of kernel development
and platform experimentation.
The new arg is parsed just like clearcpuid, but instead of leading to
setup_clear_cpu_cap() it leads to setup_force_cpu_cap().
Signed-off-by: Brendan Jackman <jackmanb@google.com>
---
Notes:
I've tested this by booting a nested QEMU
guest on an Intel host, which with setcpuid=svm
will claim that it supports AMD virtualization.
arch/x86/kernel/cpu/common.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1241c205b9d0..245807f9351d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1479,12 +1479,12 @@ static void detect_nopl(void)
#endif
}
-static inline void parse_clearcpuid(char *arg)
+static inline void parse_set_clear_cpuid(char *arg, bool set)
{
char *opt;
int taint = 0;
- pr_info("Clearing CPUID bits:");
+ pr_info("%s CPUID bits:", set ? "Force-enabling" : "Clearing");
while (arg) {
bool found __maybe_unused = false;
@@ -1505,7 +1505,10 @@ static inline void parse_clearcpuid(char *arg)
else
pr_cont(" %s", x86_cap_flags[bit]);
- setup_clear_cpu_cap(bit);
+ if (set)
+ setup_force_cpu_cap(bit);
+ else
+ setup_clear_cpu_cap(bit);
taint++;
}
/*
@@ -1523,7 +1526,10 @@ static inline void parse_clearcpuid(char *arg)
continue;
pr_cont(" %s", opt);
- setup_clear_cpu_cap(bit);
+ if (set)
+ setup_force_cpu_cap(bit);
+ else
+ setup_clear_cpu_cap(bit);
taint++;
found = true;
break;
@@ -1579,10 +1585,12 @@ static void __init cpu_parse_early_param(void)
setup_clear_cpu_cap(X86_FEATURE_FRED);
arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg));
- if (arglen <= 0)
- return;
+ if (arglen > 0)
+ parse_set_clear_cpuid(arg, false);
- parse_clearcpuid(arg);
+ arglen = cmdline_find_option(boot_command_line, "setcpuid", arg, sizeof(arg));
+ if (arglen > 0)
+ parse_set_clear_cpuid(arg, true);
}
/*
@@ -2014,15 +2022,23 @@ void print_cpu_info(struct cpuinfo_x86 *c)
}
/*
- * clearcpuid= was already parsed in cpu_parse_early_param(). This dummy
- * function prevents it from becoming an environment variable for init.
+ * clearcpuid= and setcpuid= were already parsed in cpu_parse_early_param().
+ * These dummy functions prevent them from becoming an environment variable for
+ * init.
*/
+
static __init int setup_clearcpuid(char *arg)
{
return 1;
}
__setup("clearcpuid=", setup_clearcpuid);
+static __init int setup_setcpuid(char *arg)
+{
+ return 1;
+}
+__setup("setcpuid=", setup_setcpuid);
+
DEFINE_PER_CPU_ALIGNED(struct pcpu_hot, pcpu_hot) = {
.current_task = &init_task,
.preempt_count = INIT_PREEMPT_COUNT,
--
2.48.1.601.g30ceb7b040-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 4/4] x86/cpu: Enable modifying bug flags with {clear,set}cpuid
2025-02-18 18:59 [PATCH v3 0/4] x86/cpu: Add facility to force-enable CPU caps and bugs Brendan Jackman
` (2 preceding siblings ...)
2025-02-18 18:59 ` [PATCH v3 3/4] x86/cpu: Add setcpuid cmdline param Brendan Jackman
@ 2025-02-18 18:59 ` Brendan Jackman
3 siblings, 0 replies; 5+ messages in thread
From: Brendan Jackman @ 2025-02-18 18:59 UTC (permalink / raw)
To: Jonathan Corbet, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra
Cc: linux-doc, linux-kernel, Brendan Jackman
Sometimes it can be very useful to run CPU vulnerability mitigations on
systems where they aren't known to mitigate any real-world
vulnerabilities. This can be handy for mundane reasons like debugging
HW-agnostic logic on whatever machine is to hand, but also for research
reasons: while some mitigations are focused on individual vulns and
uarches, others are fairly general, and it's strategically useful to
have an idea how they'd perform on systems where they aren't currently
needed.
As evidence for this being useful, a flag specifically for Retbleed was
added in commit 5c9a92dec323 ("x86/bugs: Add retbleed=force").
Since CPU bugs are tracked using the same basic mechanism as features,
and there are already parameters for manipulating them by hand, extend
that mechanism to support bug as well as capabilities.
Signed-off-by: Brendan Jackman <jackmanb@google.com>
---
Notes:
With this patch and setcpuid=srso, a QEMU guest running
on an Intel host will boot with Safe-RET enabled.
arch/x86/include/asm/cpufeature.h | 1 +
arch/x86/kernel/cpu/common.c | 16 ++++++++++++----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index f23942108b85..e955da397e0e 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -45,6 +45,7 @@ extern const char * const x86_power_flags[32];
* X86_BUG_<name> - NCAPINTS*32.
*/
extern const char * const x86_bug_flags[NBUGINTS*32];
+#define x86_bug_flag(flag) x86_bug_flags[flag]
#define test_cpu_cap(c, bit) \
arch_test_bit(bit, (unsigned long *)((c)->x86_capability))
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 245807f9351d..08d984ba0347 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1494,7 +1494,8 @@ static inline void parse_set_clear_cpuid(char *arg, bool set)
/*
* Handle naked numbers first for feature flags which don't
- * have names.
+ * have names. It doesn't make sense for a bug not to have a
+ * name so don't handle bug flags here.
*/
if (!kstrtouint(opt, 10, &bit)) {
if (bit < NCAPINTS * 32) {
@@ -1518,11 +1519,18 @@ static inline void parse_set_clear_cpuid(char *arg, bool set)
continue;
}
- for (bit = 0; bit < 32 * NCAPINTS; bit++) {
- if (!x86_cap_flags[bit])
+ for (bit = 0; bit < 32 * (NCAPINTS + NBUGINTS); bit++) {
+ const char *flag;
+
+ if (bit < 32 * NCAPINTS)
+ flag = x86_cap_flags[bit];
+ else
+ flag = x86_bug_flags[bit - (32 * NCAPINTS)];
+
+ if (!flag)
continue;
- if (strcmp(x86_cap_flags[bit], opt))
+ if (strcmp(flag, opt))
continue;
pr_cont(" %s", opt);
--
2.48.1.601.g30ceb7b040-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread