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 Hansenstatic 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 Hansenstatic 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 Hansenstatic 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 Hansenstatic 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 Gleixnerstatic 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