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 #ifdef __ASSEMBLY__ 11 12 .macro kuap_save_and_lock sp, thread, gpr1, gpr2, gpr3 13 lis \gpr2, MD_APG_KUAP@h /* only APG0 and APG1 are used */ 14 mfspr \gpr1, SPRN_MD_AP 15 mtspr SPRN_MD_AP, \gpr2 16 stw \gpr1, STACK_REGS_KUAP(\sp) 17 .endm 18 19 .macro kuap_restore sp, current, gpr1, gpr2, gpr3 20 lwz \gpr1, STACK_REGS_KUAP(\sp) 21 mtspr SPRN_MD_AP, \gpr1 22 .endm 23 24 .macro kuap_check current, gpr 25 #ifdef CONFIG_PPC_KUAP_DEBUG 26 mfspr \gpr, SPRN_MD_AP 27 rlwinm \gpr, \gpr, 16, 0xffff 28 999: twnei \gpr, MD_APG_KUAP@h 29 EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE) 30 #endif 31 .endm 32 33 #else /* !__ASSEMBLY__ */ 34 35 #include <asm/reg.h> 36 37 static inline void allow_user_access(void __user *to, const void __user *from, 38 unsigned long size, unsigned long dir) 39 { 40 mtspr(SPRN_MD_AP, MD_APG_INIT); 41 } 42 43 static inline void prevent_user_access(void __user *to, const void __user *from, 44 unsigned long size, unsigned long dir) 45 { 46 mtspr(SPRN_MD_AP, MD_APG_KUAP); 47 } 48 49 static inline unsigned long prevent_user_access_return(void) 50 { 51 unsigned long flags = mfspr(SPRN_MD_AP); 52 53 mtspr(SPRN_MD_AP, MD_APG_KUAP); 54 55 return flags; 56 } 57 58 static inline void restore_user_access(unsigned long flags) 59 { 60 mtspr(SPRN_MD_AP, flags); 61 } 62 63 static inline bool 64 bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) 65 { 66 return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000), 67 "Bug: fault blocked by AP register !"); 68 } 69 70 #endif /* !__ASSEMBLY__ */ 71 72 #endif /* CONFIG_PPC_KUAP */ 73 74 #endif /* _ASM_POWERPC_KUP_8XX_H_ */ 75