162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_X86_PKRU_H 362306a36Sopenharmony_ci#define _ASM_X86_PKRU_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <asm/cpufeature.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define PKRU_AD_BIT 0x1u 862306a36Sopenharmony_ci#define PKRU_WD_BIT 0x2u 962306a36Sopenharmony_ci#define PKRU_BITS_PER_PKEY 2 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS 1262306a36Sopenharmony_ciextern u32 init_pkru_value; 1362306a36Sopenharmony_ci#define pkru_get_init_value() READ_ONCE(init_pkru_value) 1462306a36Sopenharmony_ci#else 1562306a36Sopenharmony_ci#define init_pkru_value 0 1662306a36Sopenharmony_ci#define pkru_get_init_value() 0 1762306a36Sopenharmony_ci#endif 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic inline bool __pkru_allows_read(u32 pkru, u16 pkey) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY; 2262306a36Sopenharmony_ci return !(pkru & (PKRU_AD_BIT << pkru_pkey_bits)); 2362306a36Sopenharmony_ci} 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline bool __pkru_allows_write(u32 pkru, u16 pkey) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci int pkru_pkey_bits = pkey * PKRU_BITS_PER_PKEY; 2862306a36Sopenharmony_ci /* 2962306a36Sopenharmony_ci * Access-disable disables writes too so we need to check 3062306a36Sopenharmony_ci * both bits here. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci return !(pkru & ((PKRU_AD_BIT|PKRU_WD_BIT) << pkru_pkey_bits)); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic inline u32 read_pkru(void) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci if (cpu_feature_enabled(X86_FEATURE_OSPKE)) 3862306a36Sopenharmony_ci return rdpkru(); 3962306a36Sopenharmony_ci return 0; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic inline void write_pkru(u32 pkru) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci if (!cpu_feature_enabled(X86_FEATURE_OSPKE)) 4562306a36Sopenharmony_ci return; 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * WRPKRU is relatively expensive compared to RDPKRU. 4862306a36Sopenharmony_ci * Avoid WRPKRU when it would not change the value. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci if (pkru != rdpkru()) 5162306a36Sopenharmony_ci wrpkru(pkru); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic inline void pkru_write_default(void) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci if (!cpu_feature_enabled(X86_FEATURE_OSPKE)) 5762306a36Sopenharmony_ci return; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci wrpkru(pkru_get_init_value()); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#endif 63