x86/cpufeature, x86/mm/pkeys: Add protection keys related CPUID definitions
authorDave Hansen <dave.hansen@linux.intel.com>
Fri, 12 Feb 2016 21:02:01 +0000 (13:02 -0800)
committerIngo Molnar <mingo@kernel.org>
Tue, 16 Feb 2016 09:11:13 +0000 (10:11 +0100)
There are two CPUID bits for protection keys.  One is for whether
the CPU contains the feature, and the other will appear set once
the OS enables protection keys.  Specifically:

Bit 04: OSPKE. If 1, OS has set CR4.PKE to enable
Protection keys (and the RDPKRU/WRPKRU instructions)

This is because userspace can not see CR4 contents, but it can
see CPUID contents.

X86_FEATURE_PKU is referred to as "PKU" in the hardware documentation:

CPUID.(EAX=07H,ECX=0H):ECX.PKU [bit 3]

X86_FEATURE_OSPKE is "OSPKU":

CPUID.(EAX=07H,ECX=0H):ECX.OSPKE [bit 4]

These are the first CPU features which need to look at the
ECX word in CPUID leaf 0x7, so this patch also includes
fetching that word in to the cpuinfo->x86_capability[] array.

Add it to the disabled-features mask when its config option is
off.  Even though we are not using it here, we also extend the
REQUIRED_MASK_BIT_SET() macro to keep it mirroring the
DISABLED_MASK_BIT_SET() version.

This means that in almost all code, you should use:

cpu_has(c, X86_FEATURE_PKU)

and *not* the CONFIG option.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave@sr71.net>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: linux-mm@kvack.org
Link: http://lkml.kernel.org/r/20160212210201.7714C250@viggo.jf.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/disabled-features.h
arch/x86/include/asm/required-features.h
arch/x86/kernel/cpu/common.c

index 68e4e8258b84126d59094ea1023568a8272dcdbd..50e292a73a7b9077ffc394ad8af9e904e82736b8 100644 (file)
@@ -26,6 +26,7 @@ enum cpuid_leafs
        CPUID_8000_0008_EBX,
        CPUID_6_EAX,
        CPUID_8000_000A_EDX,
+       CPUID_7_ECX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -48,28 +49,42 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
         test_bit(bit, (unsigned long *)((c)->x86_capability))
 
 #define REQUIRED_MASK_BIT_SET(bit)                                     \
-        ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||     \
-          (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) ||     \
-          (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) ||     \
-          (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) ||     \
-          (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) ||     \
-          (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) ||     \
-          (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) ||     \
-          (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ||     \
-          (((bit)>>5)==8 && (1UL<<((bit)&31) & REQUIRED_MASK8)) ||     \
-          (((bit)>>5)==9 && (1UL<<((bit)&31) & REQUIRED_MASK9)) )
+        ( (((bit)>>5)==0  && (1UL<<((bit)&31) & REQUIRED_MASK0 )) ||   \
+          (((bit)>>5)==1  && (1UL<<((bit)&31) & REQUIRED_MASK1 )) ||   \
+          (((bit)>>5)==2  && (1UL<<((bit)&31) & REQUIRED_MASK2 )) ||   \
+          (((bit)>>5)==3  && (1UL<<((bit)&31) & REQUIRED_MASK3 )) ||   \
+          (((bit)>>5)==4  && (1UL<<((bit)&31) & REQUIRED_MASK4 )) ||   \
+          (((bit)>>5)==5  && (1UL<<((bit)&31) & REQUIRED_MASK5 )) ||   \
+          (((bit)>>5)==6  && (1UL<<((bit)&31) & REQUIRED_MASK6 )) ||   \
+          (((bit)>>5)==7  && (1UL<<((bit)&31) & REQUIRED_MASK7 )) ||   \
+          (((bit)>>5)==8  && (1UL<<((bit)&31) & REQUIRED_MASK8 )) ||   \
+          (((bit)>>5)==9  && (1UL<<((bit)&31) & REQUIRED_MASK9 )) ||   \
+          (((bit)>>5)==10 && (1UL<<((bit)&31) & REQUIRED_MASK10)) ||   \
+          (((bit)>>5)==11 && (1UL<<((bit)&31) & REQUIRED_MASK11)) ||   \
+          (((bit)>>5)==12 && (1UL<<((bit)&31) & REQUIRED_MASK12)) ||   \
+          (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) ||   \
+          (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK14)) ||   \
+          (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK15)) ||   \
+          (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK16)) )
 
 #define DISABLED_MASK_BIT_SET(bit)                                     \
-        ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0)) ||     \
-          (((bit)>>5)==1 && (1UL<<((bit)&31) & DISABLED_MASK1)) ||     \
-          (((bit)>>5)==2 && (1UL<<((bit)&31) & DISABLED_MASK2)) ||     \
-          (((bit)>>5)==3 && (1UL<<((bit)&31) & DISABLED_MASK3)) ||     \
-          (((bit)>>5)==4 && (1UL<<((bit)&31) & DISABLED_MASK4)) ||     \
-          (((bit)>>5)==5 && (1UL<<((bit)&31) & DISABLED_MASK5)) ||     \
-          (((bit)>>5)==6 && (1UL<<((bit)&31) & DISABLED_MASK6)) ||     \
-          (((bit)>>5)==7 && (1UL<<((bit)&31) & DISABLED_MASK7)) ||     \
-          (((bit)>>5)==8 && (1UL<<((bit)&31) & DISABLED_MASK8)) ||     \
-          (((bit)>>5)==9 && (1UL<<((bit)&31) & DISABLED_MASK9)) )
+        ( (((bit)>>5)==0  && (1UL<<((bit)&31) & DISABLED_MASK0 )) ||   \
+          (((bit)>>5)==1  && (1UL<<((bit)&31) & DISABLED_MASK1 )) ||   \
+          (((bit)>>5)==2  && (1UL<<((bit)&31) & DISABLED_MASK2 )) ||   \
+          (((bit)>>5)==3  && (1UL<<((bit)&31) & DISABLED_MASK3 )) ||   \
+          (((bit)>>5)==4  && (1UL<<((bit)&31) & DISABLED_MASK4 )) ||   \
+          (((bit)>>5)==5  && (1UL<<((bit)&31) & DISABLED_MASK5 )) ||   \
+          (((bit)>>5)==6  && (1UL<<((bit)&31) & DISABLED_MASK6 )) ||   \
+          (((bit)>>5)==7  && (1UL<<((bit)&31) & DISABLED_MASK7 )) ||   \
+          (((bit)>>5)==8  && (1UL<<((bit)&31) & DISABLED_MASK8 )) ||   \
+          (((bit)>>5)==9  && (1UL<<((bit)&31) & DISABLED_MASK9 )) ||   \
+          (((bit)>>5)==10 && (1UL<<((bit)&31) & DISABLED_MASK10)) ||   \
+          (((bit)>>5)==11 && (1UL<<((bit)&31) & DISABLED_MASK11)) ||   \
+          (((bit)>>5)==12 && (1UL<<((bit)&31) & DISABLED_MASK12)) ||   \
+          (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) ||   \
+          (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK14)) ||   \
+          (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK15)) ||   \
+          (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK16)) )
 
 #define cpu_has(c, bit)                                                        \
        (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
@@ -79,6 +94,10 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
        (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :  \
         x86_this_cpu_test_bit(bit, (unsigned long *)&cpu_info.x86_capability))
 
+/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
+#define X86_FEATURE_PKU                (16*32+ 3) /* Protection Keys for Userspace */
+#define X86_FEATURE_OSPKE      (16*32+ 4) /* OS Protection Keys Enable */
+
 /*
  * This macro is for detection of features which need kernel
  * infrastructure to be used.  It may *not* directly test the CPU
index 0ceb6adc8a48c41aa74072075d369bac3566c225..cbb2c568a19ebf8ce56c38314a355ee47e283c50 100644 (file)
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS       16      /* N 32-bit words worth of info */
+#define NCAPINTS       17      /* N 32-bit words worth of info */
 #define NBUGINTS       1       /* N 32-bit bug flags */
 
 /*
index f226df064660464e6bf8663314dfb6bcf7379ac5..39343be7d4f4315592da1026c700533ec435204b 100644 (file)
 # define DISABLE_CENTAUR_MCR   0
 #endif /* CONFIG_X86_64 */
 
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+# define DISABLE_PKU           (1<<(X86_FEATURE_PKU))
+# define DISABLE_OSPKE         (1<<(X86_FEATURE_OSPKE))
+#else
+# define DISABLE_PKU           0
+# define DISABLE_OSPKE         0
+#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
+
 /*
  * Make sure to add features to the correct mask
  */
 #define DISABLED_MASK7 0
 #define DISABLED_MASK8 0
 #define DISABLED_MASK9 (DISABLE_MPX)
+#define DISABLED_MASK10        0
+#define DISABLED_MASK11        0
+#define DISABLED_MASK12        0
+#define DISABLED_MASK13        0
+#define DISABLED_MASK14        0
+#define DISABLED_MASK15        0
+#define DISABLED_MASK16        (DISABLE_PKU|DISABLE_OSPKE)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
index 5c6e4fb370f5aac25ee36002022ed72a59592f5e..4916144e3c42668a3e07af33859b4a1af3f2985b 100644 (file)
 #define REQUIRED_MASK7 0
 #define REQUIRED_MASK8 0
 #define REQUIRED_MASK9 0
+#define REQUIRED_MASK10        0
+#define REQUIRED_MASK11        0
+#define REQUIRED_MASK12        0
+#define REQUIRED_MASK13        0
+#define REQUIRED_MASK14        0
+#define REQUIRED_MASK15        0
+#define REQUIRED_MASK16        0
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
index f4bb2c420969aaf6e12b17c60443fec199e51ac4..a719ad7551d20ed0e5559e50eb25b16109b4857e 100644 (file)
@@ -627,6 +627,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
                c->x86_capability[CPUID_7_0_EBX] = ebx;
 
                c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006);
+               c->x86_capability[CPUID_7_ECX] = ecx;
        }
 
        /* Extended state features: level 0x0000000d */