1
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
16extern struct static_key_false disable_kuap_key;
17
18static __always_inline bool kuap_is_disabled(void)
19{
20 return static_branch_unlikely(&disable_kuap_key);
21}
22
23static inline void kuap_save_and_lock(struct pt_regs *regs)
24{
25 if (kuap_is_disabled())
26 return;
27
28 regs->kuap = mfspr(SPRN_MD_AP);
29 mtspr(SPRN_MD_AP, MD_APG_KUAP);
30}
31
32static inline void kuap_user_restore(struct pt_regs *regs)
33{
34}
35
36static inline void kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
37{
38 if (kuap_is_disabled())
39 return;
40
41 mtspr(SPRN_MD_AP, regs->kuap);
42}
43
44static inline unsigned long kuap_get_and_assert_locked(void)
45{
46 unsigned long kuap;
47
48 if (kuap_is_disabled())
49 return MD_APG_INIT;
50
51 kuap = mfspr(SPRN_MD_AP);
52
53 if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG))
54 WARN_ON_ONCE(kuap >> 16 != MD_APG_KUAP >> 16);
55
56 return kuap;
57}
58
59static inline void kuap_assert_locked(void)
60{
61 if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG) && !kuap_is_disabled())
62 kuap_get_and_assert_locked();
63}
64
65static inline void allow_user_access(void __user *to, const void __user *from,
66 unsigned long size, unsigned long dir)
67{
68 if (kuap_is_disabled())
69 return;
70
71 mtspr(SPRN_MD_AP, MD_APG_INIT);
72}
73
74static inline void prevent_user_access(unsigned long dir)
75{
76 if (kuap_is_disabled())
77 return;
78
79 mtspr(SPRN_MD_AP, MD_APG_KUAP);
80}
81
82static inline unsigned long prevent_user_access_return(void)
83{
84 unsigned long flags;
85
86 if (kuap_is_disabled())
87 return MD_APG_INIT;
88
89 flags = mfspr(SPRN_MD_AP);
90
91 mtspr(SPRN_MD_AP, MD_APG_KUAP);
92
93 return flags;
94}
95
96static inline void restore_user_access(unsigned long flags)
97{
98 if (kuap_is_disabled())
99 return;
100
101 mtspr(SPRN_MD_AP, flags);
102}
103
104static inline bool
105bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
106{
107 if (kuap_is_disabled())
108 return false;
109
110 return !((regs->kuap ^ MD_APG_KUAP) & 0xff000000);
111}
112
113#endif
114
115#endif
116
117#endif
118