From: Andi Kleen <[email protected]>

The kernel needs to explicitly enable FSGSBASE. So, the application
needs to know if it can safely use these instructions. Just looking
at the CPUID bit is not enough because it may be running in a kernel
that does not enable the instructions.

One way for the application would be to just try and catch the SIGILL.
But that is difficult to do in libraries which may not want
to overwrite the signal handlers of the main application.

So we need to provide a way for the application to discover the kernel
capability.

I used AT_HWCAP2 in the ELF aux vector which is already used by
PPC for similar things. We define a new Linux defined bitmap
returned in AT_HWCAP.  Next to MONITOR/MWAIT, bit 1 is reserved for
FSGSBASE capability checks.

The application can then access it manually or using
the getauxval() function in newer glibc.

Signed-off-by: Andi Kleen <[email protected]>
[chang: Rebase and edit the patch note accordingly]
Signed-off-by: Chang S. Bae <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
---
 arch/x86/include/uapi/asm/hwcap2.h | 3 +++
 arch/x86/kernel/cpu/common.c       | 4 +++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/uapi/asm/hwcap2.h 
b/arch/x86/include/uapi/asm/hwcap2.h
index 6ebaae9..c5ce54e 100644
--- a/arch/x86/include/uapi/asm/hwcap2.h
+++ b/arch/x86/include/uapi/asm/hwcap2.h
@@ -5,4 +5,7 @@
 /* MONITOR/MWAIT enabled in Ring 3 */
 #define HWCAP2_RING3MWAIT              (1 << 0)
 
+/* Kernel allows FSGSBASE instructions available in Ring 3 */
+#define HWCAP2_FSGSBASE                        BIT(1)
+
 #endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0339bb3..5e6b46c 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1303,8 +1303,10 @@ static void identify_cpu(struct cpuinfo_x86 *c)
        setup_umip(c);
 
        /* Enable FSGSBASE instructions if available. */
-       if (cpu_has(c, X86_FEATURE_FSGSBASE))
+       if (cpu_has(c, X86_FEATURE_FSGSBASE)) {
                cr4_set_bits(X86_CR4_FSGSBASE);
+               elf_hwcap2 |= HWCAP2_FSGSBASE;
+       }
 
        /*
         * The vendor-specific functions might have changed features.
-- 
2.7.4

Reply via email to