x86/mm/pkeys: Allow kernel to modify user pkey rights register
[cascardo/linux.git] / arch / x86 / include / asm / pgtable.h
index 0687c47..1ff49ec 100644 (file)
@@ -99,6 +99,14 @@ static inline int pte_dirty(pte_t pte)
        return pte_flags(pte) & _PAGE_DIRTY;
 }
 
+
+static inline u32 read_pkru(void)
+{
+       if (boot_cpu_has(X86_FEATURE_OSPKE))
+               return __read_pkru();
+       return 0;
+}
+
 static inline int pte_young(pte_t pte)
 {
        return pte_flags(pte) & _PAGE_ACCESSED;
@@ -911,6 +919,36 @@ static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
 }
 #endif
 
+#define PKRU_AD_BIT 0x1
+#define PKRU_WD_BIT 0x2
+#define PKRU_BITS_PER_PKEY 2
+
+static inline bool __pkru_allows_read(u32 pkru, u16 pkey)
+{
+       int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
+       return !(pkru & (PKRU_AD_BIT << pkru_pkey_bits));
+}
+
+static inline bool __pkru_allows_write(u32 pkru, u16 pkey)
+{
+       int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
+       /*
+        * Access-disable disables writes too so we need to check
+        * both bits here.
+        */
+       return !(pkru & ((PKRU_AD_BIT|PKRU_WD_BIT) << pkru_pkey_bits));
+}
+
+static inline u16 pte_flags_pkey(unsigned long pte_flags)
+{
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+       /* ifdef to avoid doing 59-bit shift on 32-bit values */
+       return (pte_flags & _PAGE_PKEY_MASK) >> _PAGE_BIT_PKEY_BIT0;
+#else
+       return 0;
+#endif
+}
+
 #include <asm-generic/pgtable.h>
 #endif /* __ASSEMBLY__ */