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 <asm/reg.h>
13 
14 static inline void kuap_save_and_lock(struct pt_regs *regs)
15 {
16 	regs->kuap = mfspr(SPRN_MD_AP);
17 	mtspr(SPRN_MD_AP, MD_APG_KUAP);
18 }
19 
20 static inline void kuap_user_restore(struct pt_regs *regs)
21 {
22 }
23 
24 static inline void kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
25 {
26 	mtspr(SPRN_MD_AP, regs->kuap);
27 }
28 
29 static inline unsigned long kuap_get_and_assert_locked(void)
30 {
31 	unsigned long kuap = mfspr(SPRN_MD_AP);
32 
33 	if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG))
34 		WARN_ON_ONCE(kuap >> 16 != MD_APG_KUAP >> 16);
35 
36 	return kuap;
37 }
38 
39 static inline void kuap_assert_locked(void)
40 {
41 	if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG))
42 		kuap_get_and_assert_locked();
43 }
44 
45 static inline void allow_user_access(void __user *to, const void __user *from,
46 				     unsigned long size, unsigned long dir)
47 {
48 	mtspr(SPRN_MD_AP, MD_APG_INIT);
49 }
50 
51 static inline void prevent_user_access(void __user *to, const void __user *from,
52 				       unsigned long size, unsigned long dir)
53 {
54 	mtspr(SPRN_MD_AP, MD_APG_KUAP);
55 }
56 
57 static inline unsigned long prevent_user_access_return(void)
58 {
59 	unsigned long flags = mfspr(SPRN_MD_AP);
60 
61 	mtspr(SPRN_MD_AP, MD_APG_KUAP);
62 
63 	return flags;
64 }
65 
66 static inline void restore_user_access(unsigned long flags)
67 {
68 	mtspr(SPRN_MD_AP, flags);
69 }
70 
71 static inline bool
72 bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
73 {
74 	return !((regs->kuap ^ MD_APG_KUAP) & 0xff000000);
75 }
76 
77 #endif /* !__ASSEMBLY__ */
78 
79 #endif /* CONFIG_PPC_KUAP */
80 
81 #endif /* _ASM_POWERPC_KUP_8XX_H_ */
82