Prior to 0c2a3913d6f5, clearcpuid= could be specified several times on the command line to clear several bits. The old multiple option is a little anachronistic so change clearcpuid to accept a comma-separated list of numbers. Up to about eight bits can be cleared. Fixes: 0c2a3913d6f5 ("x86/fpu: Parse clearcpuid= as early XSAVE argument") Signed-off-by: John Haxby <john.haxby@xxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx --- .../admin-guide/kernel-parameters.txt | 24 ++++++++++--------- arch/x86/kernel/fpu/init.c | 18 ++++++++------ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index f2a93c8679e8..f380781be9e0 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -577,18 +577,20 @@ loops can be debugged more effectively on production systems. - clearcpuid=BITNUM [X86] - Disable CPUID feature X for the kernel. See + clearcpuid=BITNUM[,BITNUM,...] [X86] + Disable CPUID features for the kernel. See arch/x86/include/asm/cpufeatures.h for the valid bit - numbers. 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 - will still see it. This just prevents it from - being used by the kernel or shown in /proc/cpuinfo. - Also note the kernel might malfunction if you disable - some critical bits. + numbers. Up to about eight bits can be cleared. 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 will still + see it. This just prevents it from being used by the + kernel or shown in /proc/cpuinfo. Also note the kernel + might malfunction if you disable some critical bits. + Consider using a virtual machine emulating an older CPU + type for clearing many bits or for making the cleared + bits visible to user programs. cma=nn[MG]@[start[MG][-end[MG]]] [ARM,X86,KNL] diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 6ce7e0a23268..8d826505c22e 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -243,8 +243,6 @@ static void __init fpu__init_system_ctx_switch(void) static void __init fpu__init_parse_early_param(void) { char arg[32]; - char *argptr = arg; - int bit; #ifdef CONFIG_X86_32 if (cmdline_find_option_bool(boot_command_line, "no387")) @@ -268,11 +266,17 @@ static void __init fpu__init_parse_early_param(void) setup_clear_cpu_cap(X86_FEATURE_XSAVES); if (cmdline_find_option(boot_command_line, "clearcpuid", arg, - sizeof(arg)) && - get_option(&argptr, &bit) && - bit >= 0 && - bit < NCAPINTS * 32) - setup_clear_cpu_cap(bit); + sizeof(arg))) { + /* cpuid bit numbers are mostly three digits */ + enum { nints = sizeof(arg)/(3+1) + 1 }; + int i, bits[nints]; + + get_options(arg, nints, bits); + for (i = 1; i <= bits[0]; i++) { + if (bits[i] >= 0 && bits[i] < NCAPINTS * 32) + setup_clear_cpu_cap(bits[i]); + } + } } /* -- 2.25.3