18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_KUP_8XX_H_ 38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_KUP_8XX_H_ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <asm/bug.h> 68c2ecf20Sopenharmony_ci#include <asm/mmu.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_KUAP 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifdef __ASSEMBLY__ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci.macro kuap_save_and_lock sp, thread, gpr1, gpr2, gpr3 138c2ecf20Sopenharmony_ci lis \gpr2, MD_APG_KUAP@h /* only APG0 and APG1 are used */ 148c2ecf20Sopenharmony_ci mfspr \gpr1, SPRN_MD_AP 158c2ecf20Sopenharmony_ci mtspr SPRN_MD_AP, \gpr2 168c2ecf20Sopenharmony_ci stw \gpr1, STACK_REGS_KUAP(\sp) 178c2ecf20Sopenharmony_ci.endm 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci.macro kuap_restore sp, current, gpr1, gpr2, gpr3 208c2ecf20Sopenharmony_ci lwz \gpr1, STACK_REGS_KUAP(\sp) 218c2ecf20Sopenharmony_ci mtspr SPRN_MD_AP, \gpr1 228c2ecf20Sopenharmony_ci.endm 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci.macro kuap_check current, gpr 258c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_KUAP_DEBUG 268c2ecf20Sopenharmony_ci mfspr \gpr, SPRN_MD_AP 278c2ecf20Sopenharmony_ci rlwinm \gpr, \gpr, 16, 0xffff 288c2ecf20Sopenharmony_ci999: twnei \gpr, MD_APG_KUAP@h 298c2ecf20Sopenharmony_ci EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE) 308c2ecf20Sopenharmony_ci#endif 318c2ecf20Sopenharmony_ci.endm 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#else /* !__ASSEMBLY__ */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <asm/reg.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic inline void allow_user_access(void __user *to, const void __user *from, 388c2ecf20Sopenharmony_ci unsigned long size, unsigned long dir) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci mtspr(SPRN_MD_AP, MD_APG_INIT); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic inline void prevent_user_access(void __user *to, const void __user *from, 448c2ecf20Sopenharmony_ci unsigned long size, unsigned long dir) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci mtspr(SPRN_MD_AP, MD_APG_KUAP); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic inline unsigned long prevent_user_access_return(void) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci unsigned long flags = mfspr(SPRN_MD_AP); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci mtspr(SPRN_MD_AP, MD_APG_KUAP); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return flags; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic inline void restore_user_access(unsigned long flags) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci mtspr(SPRN_MD_AP, flags); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic inline bool 648c2ecf20Sopenharmony_cibad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000), 678c2ecf20Sopenharmony_ci "Bug: fault blocked by AP register !"); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_KUAP */ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_KUP_8XX_H_ */ 75