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
kuap_is_disabled(void)18 static __always_inline bool kuap_is_disabled(void)
19 {
20 return static_branch_unlikely(&disable_kuap_key);
21 }
22
__kuap_lock(void)23 static inline void __kuap_lock(void)
24 {
25 }
26
__kuap_save_and_lock(struct pt_regs * regs)27 static inline void __kuap_save_and_lock(struct pt_regs *regs)
28 {
29 regs->kuap = mfspr(SPRN_MD_AP);
30 mtspr(SPRN_MD_AP, MD_APG_KUAP);
31 }
32
kuap_user_restore(struct pt_regs * regs)33 static inline void kuap_user_restore(struct pt_regs *regs)
34 {
35 }
36
__kuap_kernel_restore(struct pt_regs * regs,unsigned long kuap)37 static inline void __kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
38 {
39 mtspr(SPRN_MD_AP, regs->kuap);
40 }
41
__kuap_get_and_assert_locked(void)42 static inline unsigned long __kuap_get_and_assert_locked(void)
43 {
44 unsigned long kuap;
45
46 kuap = mfspr(SPRN_MD_AP);
47
48 if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG))
49 WARN_ON_ONCE(kuap >> 16 != MD_APG_KUAP >> 16);
50
51 return kuap;
52 }
53
__allow_user_access(void __user * to,const void __user * from,unsigned long size,unsigned long dir)54 static inline void __allow_user_access(void __user *to, const void __user *from,
55 unsigned long size, unsigned long dir)
56 {
57 mtspr(SPRN_MD_AP, MD_APG_INIT);
58 }
59
__prevent_user_access(unsigned long dir)60 static inline void __prevent_user_access(unsigned long dir)
61 {
62 mtspr(SPRN_MD_AP, MD_APG_KUAP);
63 }
64
__prevent_user_access_return(void)65 static inline unsigned long __prevent_user_access_return(void)
66 {
67 unsigned long flags;
68
69 flags = mfspr(SPRN_MD_AP);
70
71 mtspr(SPRN_MD_AP, MD_APG_KUAP);
72
73 return flags;
74 }
75
__restore_user_access(unsigned long flags)76 static inline void __restore_user_access(unsigned long flags)
77 {
78 mtspr(SPRN_MD_AP, flags);
79 }
80
81 static inline bool
__bad_kuap_fault(struct pt_regs * regs,unsigned long address,bool is_write)82 __bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
83 {
84 return !((regs->kuap ^ MD_APG_KUAP) & 0xff000000);
85 }
86
87 #endif /* !__ASSEMBLY__ */
88
89 #endif /* CONFIG_PPC_KUAP */
90
91 #endif /* _ASM_POWERPC_KUP_8XX_H_ */
92