1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _ASM_X86_PKRU_H
3  #define _ASM_X86_PKRU_H
4  
5  #include <asm/cpufeature.h>
6  
7  #define PKRU_AD_BIT 0x1u
8  #define PKRU_WD_BIT 0x2u
9  #define PKRU_BITS_PER_PKEY 2
10  
11  #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
12  extern u32 init_pkru_value;
13  #define pkru_get_init_value()	READ_ONCE(init_pkru_value)
14  #else
15  #define init_pkru_value	0
16  #define pkru_get_init_value()	0
17  #endif
18  
__pkru_allows_read(u32 pkru,u16 pkey)19  static inline bool __pkru_allows_read(u32 pkru, u16 pkey)
20  {
21  	int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
22  	return !(pkru & (PKRU_AD_BIT << pkru_pkey_bits));
23  }
24  
__pkru_allows_write(u32 pkru,u16 pkey)25  static inline bool __pkru_allows_write(u32 pkru, u16 pkey)
26  {
27  	int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
28  	/*
29  	 * Access-disable disables writes too so we need to check
30  	 * both bits here.
31  	 */
32  	return !(pkru & ((PKRU_AD_BIT|PKRU_WD_BIT) << pkru_pkey_bits));
33  }
34  
read_pkru(void)35  static inline u32 read_pkru(void)
36  {
37  	if (cpu_feature_enabled(X86_FEATURE_OSPKE))
38  		return rdpkru();
39  	return 0;
40  }
41  
write_pkru(u32 pkru)42  static inline void write_pkru(u32 pkru)
43  {
44  	if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
45  		return;
46  	/*
47  	 * WRPKRU is relatively expensive compared to RDPKRU.
48  	 * Avoid WRPKRU when it would not change the value.
49  	 */
50  	if (pkru != rdpkru())
51  		wrpkru(pkru);
52  }
53  
pkru_write_default(void)54  static inline void pkru_write_default(void)
55  {
56  	if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
57  		return;
58  
59  	wrpkru(pkru_get_init_value());
60  }
61  
62  #endif
63