1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * PowerPC Memory Protection Keys management 4 * 5 * Copyright 2017, Ram Pai, IBM Corporation. 6 */ 7 8 #ifndef _ASM_POWERPC_KEYS_H 9 #define _ASM_POWERPC_KEYS_H 10 11 #include <linux/jump_label.h> 12 #include <asm/firmware.h> 13 14 DECLARE_STATIC_KEY_TRUE(pkey_disabled); 15 extern int pkeys_total; /* total pkeys as per device tree */ 16 extern u32 initial_allocation_mask; /* bits set for reserved keys */ 17 18 /* 19 * Define these here temporarily so we're not dependent on patching linux/mm.h. 20 * Once it's updated we can drop these. 21 */ 22 #ifndef VM_PKEY_BIT0 23 # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0 24 # define VM_PKEY_BIT0 VM_HIGH_ARCH_0 25 # define VM_PKEY_BIT1 VM_HIGH_ARCH_1 26 # define VM_PKEY_BIT2 VM_HIGH_ARCH_2 27 # define VM_PKEY_BIT3 VM_HIGH_ARCH_3 28 # define VM_PKEY_BIT4 VM_HIGH_ARCH_4 29 #endif 30 31 #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \ 32 VM_PKEY_BIT3 | VM_PKEY_BIT4) 33 34 /* Override any generic PKEY permission defines */ 35 #define PKEY_DISABLE_EXECUTE 0x4 36 #define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS | \ 37 PKEY_DISABLE_WRITE | \ 38 PKEY_DISABLE_EXECUTE) 39 40 static inline u64 pkey_to_vmflag_bits(u16 pkey) 41 { 42 return (((u64)pkey << VM_PKEY_SHIFT) & ARCH_VM_PKEY_FLAGS); 43 } 44 45 static inline u64 vmflag_to_pte_pkey_bits(u64 vm_flags) 46 { 47 if (static_branch_likely(&pkey_disabled)) 48 return 0x0UL; 49 50 return (((vm_flags & VM_PKEY_BIT0) ? H_PTE_PKEY_BIT4 : 0x0UL) | 51 ((vm_flags & VM_PKEY_BIT1) ? H_PTE_PKEY_BIT3 : 0x0UL) | 52 ((vm_flags & VM_PKEY_BIT2) ? H_PTE_PKEY_BIT2 : 0x0UL) | 53 ((vm_flags & VM_PKEY_BIT3) ? H_PTE_PKEY_BIT1 : 0x0UL) | 54 ((vm_flags & VM_PKEY_BIT4) ? H_PTE_PKEY_BIT0 : 0x0UL)); 55 } 56 57 static inline int vma_pkey(struct vm_area_struct *vma) 58 { 59 if (static_branch_likely(&pkey_disabled)) 60 return 0; 61 return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT; 62 } 63 64 #define arch_max_pkey() pkeys_total 65 66 static inline u64 pte_to_hpte_pkey_bits(u64 pteflags) 67 { 68 return (((pteflags & H_PTE_PKEY_BIT0) ? HPTE_R_KEY_BIT0 : 0x0UL) | 69 ((pteflags & H_PTE_PKEY_BIT1) ? HPTE_R_KEY_BIT1 : 0x0UL) | 70 ((pteflags & H_PTE_PKEY_BIT2) ? HPTE_R_KEY_BIT2 : 0x0UL) | 71 ((pteflags & H_PTE_PKEY_BIT3) ? HPTE_R_KEY_BIT3 : 0x0UL) | 72 ((pteflags & H_PTE_PKEY_BIT4) ? HPTE_R_KEY_BIT4 : 0x0UL)); 73 } 74 75 static inline u16 pte_to_pkey_bits(u64 pteflags) 76 { 77 return (((pteflags & H_PTE_PKEY_BIT0) ? 0x10 : 0x0UL) | 78 ((pteflags & H_PTE_PKEY_BIT1) ? 0x8 : 0x0UL) | 79 ((pteflags & H_PTE_PKEY_BIT2) ? 0x4 : 0x0UL) | 80 ((pteflags & H_PTE_PKEY_BIT3) ? 0x2 : 0x0UL) | 81 ((pteflags & H_PTE_PKEY_BIT4) ? 0x1 : 0x0UL)); 82 } 83 84 #define pkey_alloc_mask(pkey) (0x1 << pkey) 85 86 #define mm_pkey_allocation_map(mm) (mm->context.pkey_allocation_map) 87 88 #define __mm_pkey_allocated(mm, pkey) { \ 89 mm_pkey_allocation_map(mm) |= pkey_alloc_mask(pkey); \ 90 } 91 92 #define __mm_pkey_free(mm, pkey) { \ 93 mm_pkey_allocation_map(mm) &= ~pkey_alloc_mask(pkey); \ 94 } 95 96 #define __mm_pkey_is_allocated(mm, pkey) \ 97 (mm_pkey_allocation_map(mm) & pkey_alloc_mask(pkey)) 98 99 #define __mm_pkey_is_reserved(pkey) (initial_allocation_mask & \ 100 pkey_alloc_mask(pkey)) 101 102 static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) 103 { 104 /* A reserved key is never considered as 'explicitly allocated' */ 105 return ((pkey < arch_max_pkey()) && 106 !__mm_pkey_is_reserved(pkey) && 107 __mm_pkey_is_allocated(mm, pkey)); 108 } 109 110 extern void __arch_activate_pkey(int pkey); 111 extern void __arch_deactivate_pkey(int pkey); 112 /* 113 * Returns a positive, 5-bit key on success, or -1 on failure. 114 * Relies on the mmap_sem to protect against concurrency in mm_pkey_alloc() and 115 * mm_pkey_free(). 116 */ 117 static inline int mm_pkey_alloc(struct mm_struct *mm) 118 { 119 /* 120 * Note: this is the one and only place we make sure that the pkey is 121 * valid as far as the hardware is concerned. The rest of the kernel 122 * trusts that only good, valid pkeys come out of here. 123 */ 124 u32 all_pkeys_mask = (u32)(~(0x0)); 125 int ret; 126 127 if (static_branch_likely(&pkey_disabled)) 128 return -1; 129 130 /* 131 * Are we out of pkeys? We must handle this specially because ffz() 132 * behavior is undefined if there are no zeros. 133 */ 134 if (mm_pkey_allocation_map(mm) == all_pkeys_mask) 135 return -1; 136 137 ret = ffz((u32)mm_pkey_allocation_map(mm)); 138 __mm_pkey_allocated(mm, ret); 139 140 /* 141 * Enable the key in the hardware 142 */ 143 if (ret > 0) 144 __arch_activate_pkey(ret); 145 return ret; 146 } 147 148 static inline int mm_pkey_free(struct mm_struct *mm, int pkey) 149 { 150 if (static_branch_likely(&pkey_disabled)) 151 return -1; 152 153 if (!mm_pkey_is_allocated(mm, pkey)) 154 return -EINVAL; 155 156 /* 157 * Disable the key in the hardware 158 */ 159 __arch_deactivate_pkey(pkey); 160 __mm_pkey_free(mm, pkey); 161 162 return 0; 163 } 164 165 /* 166 * Try to dedicate one of the protection keys to be used as an 167 * execute-only protection key. 168 */ 169 extern int __execute_only_pkey(struct mm_struct *mm); 170 static inline int execute_only_pkey(struct mm_struct *mm) 171 { 172 if (static_branch_likely(&pkey_disabled)) 173 return -1; 174 175 return __execute_only_pkey(mm); 176 } 177 178 extern int __arch_override_mprotect_pkey(struct vm_area_struct *vma, 179 int prot, int pkey); 180 static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma, 181 int prot, int pkey) 182 { 183 if (static_branch_likely(&pkey_disabled)) 184 return 0; 185 186 /* 187 * Is this an mprotect_pkey() call? If so, never override the value that 188 * came from the user. 189 */ 190 if (pkey != -1) 191 return pkey; 192 193 return __arch_override_mprotect_pkey(vma, prot, pkey); 194 } 195 196 extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey, 197 unsigned long init_val); 198 static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, 199 unsigned long init_val) 200 { 201 if (static_branch_likely(&pkey_disabled)) 202 return -EINVAL; 203 return __arch_set_user_pkey_access(tsk, pkey, init_val); 204 } 205 206 static inline bool arch_pkeys_enabled(void) 207 { 208 return !static_branch_likely(&pkey_disabled); 209 } 210 211 extern void pkey_mm_init(struct mm_struct *mm); 212 extern bool arch_supports_pkeys(int cap); 213 extern unsigned int arch_usable_pkeys(void); 214 extern void thread_pkey_regs_save(struct thread_struct *thread); 215 extern void thread_pkey_regs_restore(struct thread_struct *new_thread, 216 struct thread_struct *old_thread); 217 extern void thread_pkey_regs_init(struct thread_struct *thread); 218 #endif /*_ASM_POWERPC_KEYS_H */ 219