Skip to content

Commit 41a80ca

Browse files
committed
Merge tag 'x86_misc_for_v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull misc x86 updates from Borislav Petkov: - Add an informational message which gets issued when IA32 emulation has been disabled on the cmdline - Clarify in detail how /proc/cpuinfo is used on x86 - Fix a theoretical overflow in num_digits() * tag 'x86_misc_for_v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/ia32: State that IA32 emulation is disabled Documentation/x86: Document what /proc/cpuinfo is for x86/lib: Fix overflow when counting digits
2 parents 6e0b939 + f789383 commit 41a80ca

4 files changed

Lines changed: 80 additions & 24 deletions

File tree

Documentation/arch/x86/cpuinfo.rst

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,74 @@ x86 Feature Flags
77
Introduction
88
============
99

10-
On x86, flags appearing in /proc/cpuinfo have an X86_FEATURE definition
11-
in arch/x86/include/asm/cpufeatures.h. If the kernel cares about a feature
12-
or KVM want to expose the feature to a KVM guest, it can and should have
13-
an X86_FEATURE_* defined. These flags represent hardware features as
14-
well as software features.
15-
16-
If users want to know if a feature is available on a given system, they
17-
try to find the flag in /proc/cpuinfo. If a given flag is present, it
18-
means that the kernel supports it and is currently making it available.
19-
If such flag represents a hardware feature, it also means that the
20-
hardware supports it.
21-
22-
If the expected flag does not appear in /proc/cpuinfo, things are murkier.
23-
Users need to find out the reason why the flag is missing and find the way
24-
how to enable it, which is not always easy. There are several factors that
25-
can explain missing flags: the expected feature failed to enable, the feature
26-
is missing in hardware, platform firmware did not enable it, the feature is
27-
disabled at build or run time, an old kernel is in use, or the kernel does
28-
not support the feature and thus has not enabled it. In general, /proc/cpuinfo
29-
shows features which the kernel supports. For a full list of CPUID flags
30-
which the CPU supports, use tools/arch/x86/kcpuid.
10+
The list of feature flags in /proc/cpuinfo is not complete and
11+
represents an ill-fated attempt from long time ago to put feature flags
12+
in an easy to find place for userspace.
13+
14+
However, the amount of feature flags is growing by the CPU generation,
15+
leading to unparseable and unwieldy /proc/cpuinfo.
16+
17+
What is more, those feature flags do not even need to be in that file
18+
because userspace doesn't care about them - glibc et al already use
19+
CPUID to find out what the target machine supports and what not.
20+
21+
And even if it doesn't show a particular feature flag - although the CPU
22+
still does have support for the respective hardware functionality and
23+
said CPU supports CPUID faulting - userspace can simply probe for the
24+
feature and figure out if it is supported or not, regardless of whether
25+
it is being advertised somewhere.
26+
27+
Furthermore, those flag strings become an ABI the moment they appear
28+
there and maintaining them forever when nothing even uses them is a lot
29+
of wasted effort.
30+
31+
So, the current use of /proc/cpuinfo is to show features which the
32+
kernel has *enabled* and *supports*. As in: the CPUID feature flag is
33+
there, there's an additional setup which the kernel has done while
34+
booting and the functionality is ready to use. A perfect example for
35+
that is "user_shstk" where additional code enablement is present in the
36+
kernel to support shadow stack for user programs.
37+
38+
So, if users want to know if a feature is available on a given system,
39+
they try to find the flag in /proc/cpuinfo. If a given flag is present,
40+
it means that
41+
42+
* the kernel knows about the feature enough to have an X86_FEATURE bit
43+
44+
* the kernel supports it and is currently making it available either to
45+
userspace or some other part of the kernel
46+
47+
* if the flag represents a hardware feature the hardware supports it.
48+
49+
The absence of a flag in /proc/cpuinfo by itself means almost nothing to
50+
an end user.
51+
52+
On the one hand, a feature like "vaes" might be fully available to user
53+
applications on a kernel that has not defined X86_FEATURE_VAES and thus
54+
there is no "vaes" in /proc/cpuinfo.
55+
56+
On the other hand, a new kernel running on non-VAES hardware would also
57+
have no "vaes" in /proc/cpuinfo. There's no way for an application or
58+
user to tell the difference.
59+
60+
The end result is that the flags field in /proc/cpuinfo is marginally
61+
useful for kernel debugging, but not really for anything else.
62+
Applications should instead use things like the glibc facilities for
63+
querying CPU support. Users should rely on tools like
64+
tools/arch/x86/kcpuid and cpuid(1).
65+
66+
Regarding implementation, flags appearing in /proc/cpuinfo have an
67+
X86_FEATURE definition in arch/x86/include/asm/cpufeatures.h. These flags
68+
represent hardware features as well as software features.
69+
70+
If the kernel cares about a feature or KVM want to expose the feature to
71+
a KVM guest, it should only then expose it to the guest when the guest
72+
needs to parse /proc/cpuinfo. Which, as mentioned above, is highly
73+
unlikely. KVM can synthesize the CPUID bit and the KVM guest can simply
74+
query CPUID and figure out what the hypervisor supports and what not. As
75+
already stated, /proc/cpuinfo is not a dumping ground for useless
76+
feature flags.
77+
3178

3279
How are feature flags created?
3380
==============================

arch/x86/include/asm/elf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ do { \
150150
((x)->e_machine == EM_X86_64)
151151

152152
#define compat_elf_check_arch(x) \
153-
((elf_check_arch_ia32(x) && ia32_enabled()) || \
153+
((elf_check_arch_ia32(x) && ia32_enabled_verbose()) || \
154154
(IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64))
155155

156156
static inline void elf_common_init(struct thread_struct *t,

arch/x86/include/asm/ia32.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#ifndef _ASM_X86_IA32_H
33
#define _ASM_X86_IA32_H
44

5-
65
#ifdef CONFIG_IA32_EMULATION
76

87
#include <linux/compat.h>
@@ -91,4 +90,14 @@ static inline void ia32_disable(void) {}
9190

9291
#endif
9392

93+
static inline bool ia32_enabled_verbose(void)
94+
{
95+
bool enabled = ia32_enabled();
96+
97+
if (IS_ENABLED(CONFIG_IA32_EMULATION) && !enabled)
98+
pr_notice_once("32-bit emulation disabled. You can reenable with ia32_emulation=on\n");
99+
100+
return enabled;
101+
}
102+
94103
#endif /* _ASM_X86_IA32_H */

arch/x86/lib/misc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99
int num_digits(int val)
1010
{
11-
int m = 10;
11+
long long m = 10;
1212
int d = 1;
1313

1414
if (val < 0) {

0 commit comments

Comments
 (0)