1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2023 Arm Ltd. 4 * 5 * Based on arch/x86/include/asm/pkeys.h 6 */ 7 8 #ifndef _ASM_ARM64_PKEYS_H 9 #define _ASM_ARM64_PKEYS_H 10 11 #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2) 12 13 #define arch_max_pkey() 8 14 15 int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, 16 unsigned long init_val); 17 18 static inline bool arch_pkeys_enabled(void) 19 { 20 return system_supports_poe(); 21 } 22 23 static inline int vma_pkey(struct vm_area_struct *vma) 24 { 25 return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT; 26 } 27 28 static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma, 29 int prot, int pkey) 30 { 31 if (pkey != -1) 32 return pkey; 33 34 return vma_pkey(vma); 35 } 36 37 static inline int execute_only_pkey(struct mm_struct *mm) 38 { 39 // Execute-only mappings are handled by EPAN/FEAT_PAN3. 40 WARN_ON_ONCE(!cpus_have_final_cap(ARM64_HAS_EPAN)); 41 42 return -1; 43 } 44 45 #define mm_pkey_allocation_map(mm) (mm)->context.pkey_allocation_map 46 #define mm_set_pkey_allocated(mm, pkey) do { \ 47 mm_pkey_allocation_map(mm) |= (1U << pkey); \ 48 } while (0) 49 #define mm_set_pkey_free(mm, pkey) do { \ 50 mm_pkey_allocation_map(mm) &= ~(1U << pkey); \ 51 } while (0) 52 53 static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) 54 { 55 /* 56 * "Allocated" pkeys are those that have been returned 57 * from pkey_alloc() or pkey 0 which is allocated 58 * implicitly when the mm is created. 59 */ 60 if (pkey < 0 || pkey >= arch_max_pkey()) 61 return false; 62 63 return mm_pkey_allocation_map(mm) & (1U << pkey); 64 } 65 66 /* 67 * Returns a positive, 3-bit key on success, or -1 on failure. 68 */ 69 static inline int mm_pkey_alloc(struct mm_struct *mm) 70 { 71 /* 72 * Note: this is the one and only place we make sure 73 * that the pkey is valid as far as the hardware is 74 * concerned. The rest of the kernel trusts that 75 * only good, valid pkeys come out of here. 76 */ 77 u8 all_pkeys_mask = GENMASK(arch_max_pkey() - 1, 0); 78 int ret; 79 80 if (!arch_pkeys_enabled()) 81 return -1; 82 83 /* 84 * Are we out of pkeys? We must handle this specially 85 * because ffz() behavior is undefined if there are no 86 * zeros. 87 */ 88 if (mm_pkey_allocation_map(mm) == all_pkeys_mask) 89 return -1; 90 91 ret = ffz(mm_pkey_allocation_map(mm)); 92 93 mm_set_pkey_allocated(mm, ret); 94 95 return ret; 96 } 97 98 static inline int mm_pkey_free(struct mm_struct *mm, int pkey) 99 { 100 if (!mm_pkey_is_allocated(mm, pkey)) 101 return -EINVAL; 102 103 mm_set_pkey_free(mm, pkey); 104 105 return 0; 106 } 107 108 #endif /* _ASM_ARM64_PKEYS_H */ 109