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_lock(void)
24 {
25 }
26 
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 
33 static inline void kuap_user_restore(struct pt_regs *regs)
34 {
35 }
36 
37 static inline void __kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
38 {
39 	mtspr(SPRN_MD_AP, regs->kuap);
40 }
41 
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 
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 
60 static inline void __prevent_user_access(unsigned long dir)
61 {
62 	mtspr(SPRN_MD_AP, MD_APG_KUAP);
63 }
64 
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 
76 static inline void __restore_user_access(unsigned long flags)
77 {
78 	mtspr(SPRN_MD_AP, flags);
79 }
80 
81 static inline bool
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