xref: /linux/arch/x86/include/asm/pkru.h (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1784a4661SDave Hansen /* SPDX-License-Identifier: GPL-2.0 */
2784a4661SDave Hansen #ifndef _ASM_X86_PKRU_H
3784a4661SDave Hansen #define _ASM_X86_PKRU_H
4784a4661SDave Hansen 
5b50854ecSThomas Gleixner #include <asm/cpufeature.h>
6784a4661SDave Hansen 
7*57690554SAndrew Cooper #define PKRU_AD_BIT 0x1u
8*57690554SAndrew Cooper #define PKRU_WD_BIT 0x2u
9784a4661SDave Hansen #define PKRU_BITS_PER_PKEY 2
10784a4661SDave Hansen 
11784a4661SDave Hansen #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
12784a4661SDave Hansen extern u32 init_pkru_value;
13739e2eecSThomas Gleixner #define pkru_get_init_value()	READ_ONCE(init_pkru_value)
14784a4661SDave Hansen #else
15784a4661SDave Hansen #define init_pkru_value	0
16739e2eecSThomas Gleixner #define pkru_get_init_value()	0
17784a4661SDave Hansen #endif
18784a4661SDave Hansen 
__pkru_allows_read(u32 pkru,u16 pkey)19784a4661SDave Hansen static inline bool __pkru_allows_read(u32 pkru, u16 pkey)
20784a4661SDave Hansen {
21784a4661SDave Hansen 	int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
22784a4661SDave Hansen 	return !(pkru & (PKRU_AD_BIT << pkru_pkey_bits));
23784a4661SDave Hansen }
24784a4661SDave Hansen 
__pkru_allows_write(u32 pkru,u16 pkey)25784a4661SDave Hansen static inline bool __pkru_allows_write(u32 pkru, u16 pkey)
26784a4661SDave Hansen {
27784a4661SDave Hansen 	int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY;
28784a4661SDave Hansen 	/*
29784a4661SDave Hansen 	 * Access-disable disables writes too so we need to check
30784a4661SDave Hansen 	 * both bits here.
31784a4661SDave Hansen 	 */
32784a4661SDave Hansen 	return !(pkru & ((PKRU_AD_BIT|PKRU_WD_BIT) << pkru_pkey_bits));
33784a4661SDave Hansen }
34784a4661SDave Hansen 
read_pkru(void)35784a4661SDave Hansen static inline u32 read_pkru(void)
36784a4661SDave Hansen {
378a1dc55aSThomas Gleixner 	if (cpu_feature_enabled(X86_FEATURE_OSPKE))
38784a4661SDave Hansen 		return rdpkru();
39784a4661SDave Hansen 	return 0;
40784a4661SDave Hansen }
41784a4661SDave Hansen 
write_pkru(u32 pkru)42784a4661SDave Hansen static inline void write_pkru(u32 pkru)
43784a4661SDave Hansen {
448a1dc55aSThomas Gleixner 	if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
45784a4661SDave Hansen 		return;
46784a4661SDave Hansen 	/*
4772a6c08cSThomas Gleixner 	 * WRPKRU is relatively expensive compared to RDPKRU.
4872a6c08cSThomas Gleixner 	 * Avoid WRPKRU when it would not change the value.
49784a4661SDave Hansen 	 */
5072a6c08cSThomas Gleixner 	if (pkru != rdpkru())
5172a6c08cSThomas Gleixner 		wrpkru(pkru);
52784a4661SDave Hansen }
53784a4661SDave Hansen 
pkru_write_default(void)54ff7ebff4SThomas Gleixner static inline void pkru_write_default(void)
55ff7ebff4SThomas Gleixner {
56ff7ebff4SThomas Gleixner 	if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
57ff7ebff4SThomas Gleixner 		return;
58ff7ebff4SThomas Gleixner 
59ff7ebff4SThomas Gleixner 	wrpkru(pkru_get_init_value());
60ff7ebff4SThomas Gleixner }
61ff7ebff4SThomas Gleixner 
62784a4661SDave Hansen #endif
63