Commit 41a80ca4 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 6e0b9391 f789383f
...@@ -7,27 +7,74 @@ x86 Feature Flags ...@@ -7,27 +7,74 @@ x86 Feature Flags
Introduction Introduction
============ ============
On x86, flags appearing in /proc/cpuinfo have an X86_FEATURE definition The list of feature flags in /proc/cpuinfo is not complete and
in arch/x86/include/asm/cpufeatures.h. If the kernel cares about a feature represents an ill-fated attempt from long time ago to put feature flags
or KVM want to expose the feature to a KVM guest, it can and should have in an easy to find place for userspace.
an X86_FEATURE_* defined. These flags represent hardware features as
well as software features. However, the amount of feature flags is growing by the CPU generation,
leading to unparseable and unwieldy /proc/cpuinfo.
If users want to know if a feature is available on a given system, they
try to find the flag in /proc/cpuinfo. If a given flag is present, it What is more, those feature flags do not even need to be in that file
means that the kernel supports it and is currently making it available. because userspace doesn't care about them - glibc et al already use
If such flag represents a hardware feature, it also means that the CPUID to find out what the target machine supports and what not.
hardware supports it.
And even if it doesn't show a particular feature flag - although the CPU
If the expected flag does not appear in /proc/cpuinfo, things are murkier. still does have support for the respective hardware functionality and
Users need to find out the reason why the flag is missing and find the way said CPU supports CPUID faulting - userspace can simply probe for the
how to enable it, which is not always easy. There are several factors that feature and figure out if it is supported or not, regardless of whether
can explain missing flags: the expected feature failed to enable, the feature it is being advertised somewhere.
is missing in hardware, platform firmware did not enable it, the feature is
disabled at build or run time, an old kernel is in use, or the kernel does Furthermore, those flag strings become an ABI the moment they appear
not support the feature and thus has not enabled it. In general, /proc/cpuinfo there and maintaining them forever when nothing even uses them is a lot
shows features which the kernel supports. For a full list of CPUID flags of wasted effort.
which the CPU supports, use tools/arch/x86/kcpuid.
So, the current use of /proc/cpuinfo is to show features which the
kernel has *enabled* and *supports*. As in: the CPUID feature flag is
there, there's an additional setup which the kernel has done while
booting and the functionality is ready to use. A perfect example for
that is "user_shstk" where additional code enablement is present in the
kernel to support shadow stack for user programs.
So, if users want to know if a feature is available on a given system,
they try to find the flag in /proc/cpuinfo. If a given flag is present,
it means that
* the kernel knows about the feature enough to have an X86_FEATURE bit
* the kernel supports it and is currently making it available either to
userspace or some other part of the kernel
* if the flag represents a hardware feature the hardware supports it.
The absence of a flag in /proc/cpuinfo by itself means almost nothing to
an end user.
On the one hand, a feature like "vaes" might be fully available to user
applications on a kernel that has not defined X86_FEATURE_VAES and thus
there is no "vaes" in /proc/cpuinfo.
On the other hand, a new kernel running on non-VAES hardware would also
have no "vaes" in /proc/cpuinfo. There's no way for an application or
user to tell the difference.
The end result is that the flags field in /proc/cpuinfo is marginally
useful for kernel debugging, but not really for anything else.
Applications should instead use things like the glibc facilities for
querying CPU support. Users should rely on tools like
tools/arch/x86/kcpuid and cpuid(1).
Regarding implementation, flags appearing in /proc/cpuinfo have an
X86_FEATURE definition in arch/x86/include/asm/cpufeatures.h. These flags
represent hardware features as well as software features.
If the kernel cares about a feature or KVM want to expose the feature to
a KVM guest, it should only then expose it to the guest when the guest
needs to parse /proc/cpuinfo. Which, as mentioned above, is highly
unlikely. KVM can synthesize the CPUID bit and the KVM guest can simply
query CPUID and figure out what the hypervisor supports and what not. As
already stated, /proc/cpuinfo is not a dumping ground for useless
feature flags.
How are feature flags created? How are feature flags created?
============================== ==============================
......
...@@ -150,7 +150,7 @@ do { \ ...@@ -150,7 +150,7 @@ do { \
((x)->e_machine == EM_X86_64) ((x)->e_machine == EM_X86_64)
#define compat_elf_check_arch(x) \ #define compat_elf_check_arch(x) \
((elf_check_arch_ia32(x) && ia32_enabled()) || \ ((elf_check_arch_ia32(x) && ia32_enabled_verbose()) || \
(IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64))
static inline void elf_common_init(struct thread_struct *t, static inline void elf_common_init(struct thread_struct *t,
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#ifndef _ASM_X86_IA32_H #ifndef _ASM_X86_IA32_H
#define _ASM_X86_IA32_H #define _ASM_X86_IA32_H
#ifdef CONFIG_IA32_EMULATION #ifdef CONFIG_IA32_EMULATION
#include <linux/compat.h> #include <linux/compat.h>
...@@ -91,4 +90,14 @@ static inline void ia32_disable(void) {} ...@@ -91,4 +90,14 @@ static inline void ia32_disable(void) {}
#endif #endif
static inline bool ia32_enabled_verbose(void)
{
bool enabled = ia32_enabled();
if (IS_ENABLED(CONFIG_IA32_EMULATION) && !enabled)
pr_notice_once("32-bit emulation disabled. You can reenable with ia32_emulation=on\n");
return enabled;
}
#endif /* _ASM_X86_IA32_H */ #endif /* _ASM_X86_IA32_H */
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
*/ */
int num_digits(int val) int num_digits(int val)
{ {
int m = 10; long long m = 10;
int d = 1; int d = 1;
if (val < 0) { if (val < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment