1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_POWERPC_KUP_8XX_H_ 3 #define _ASM_POWERPC_KUP_8XX_H_ 4 5 #include <asm/bug.h> 6 #include <asm/mmu.h> 7 8 #ifdef CONFIG_PPC_KUAP 9 10 #ifndef __ASSEMBLY__ 11 12 #include <linux/jump_label.h> 13 14 #include <asm/reg.h> 15 16 extern struct static_key_false disable_kuap_key; 17 18 static __always_inline bool kuap_is_disabled(void) 19 { 20 return static_branch_unlikely(&disable_kuap_key); 21 } 22 23 static inline void kuap_save_and_lock(struct pt_regs *regs) 24 { 25 if (kuap_is_disabled()) 26 return; 27 28 regs->kuap = mfspr(SPRN_MD_AP); 29 mtspr(SPRN_MD_AP, MD_APG_KUAP); 30 } 31 32 static inline void kuap_user_restore(struct pt_regs *regs) 33 { 34 } 35 36 static inline void kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap) 37 { 38 if (kuap_is_disabled()) 39 return; 40 41 mtspr(SPRN_MD_AP, regs->kuap); 42 } 43 44 static inline unsigned long kuap_get_and_assert_locked(void) 45 { 46 unsigned long kuap; 47 48 if (kuap_is_disabled()) 49 return MD_APG_INIT; 50 51 kuap = mfspr(SPRN_MD_AP); 52 53 if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG)) 54 WARN_ON_ONCE(kuap >> 16 != MD_APG_KUAP >> 16); 55 56 return kuap; 57 } 58 59 static inline void kuap_assert_locked(void) 60 { 61 if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG) && !kuap_is_disabled()) 62 kuap_get_and_assert_locked(); 63 } 64 65 static inline void allow_user_access(void __user *to, const void __user *from, 66 unsigned long size, unsigned long dir) 67 { 68 if (kuap_is_disabled()) 69 return; 70 71 mtspr(SPRN_MD_AP, MD_APG_INIT); 72 } 73 74 static inline void prevent_user_access(unsigned long dir) 75 { 76 if (kuap_is_disabled()) 77 return; 78 79 mtspr(SPRN_MD_AP, MD_APG_KUAP); 80 } 81 82 static inline unsigned long prevent_user_access_return(void) 83 { 84 unsigned long flags; 85 86 if (kuap_is_disabled()) 87 return MD_APG_INIT; 88 89 flags = mfspr(SPRN_MD_AP); 90 91 mtspr(SPRN_MD_AP, MD_APG_KUAP); 92 93 return flags; 94 } 95 96 static inline void restore_user_access(unsigned long flags) 97 { 98 if (kuap_is_disabled()) 99 return; 100 101 mtspr(SPRN_MD_AP, flags); 102 } 103 104 static inline bool 105 bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) 106 { 107 if (kuap_is_disabled()) 108 return false; 109 110 return !((regs->kuap ^ MD_APG_KUAP) & 0xff000000); 111 } 112 113 #endif /* !__ASSEMBLY__ */ 114 115 #endif /* CONFIG_PPC_KUAP */ 116 117 #endif /* _ASM_POWERPC_KUP_8XX_H_ */ 118