1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _ASM_POWERPC_KUP_H_
3*4882a593Smuzhiyun #define _ASM_POWERPC_KUP_H_
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #define KUAP_READ 1
6*4882a593Smuzhiyun #define KUAP_WRITE 2
7*4882a593Smuzhiyun #define KUAP_READ_WRITE (KUAP_READ | KUAP_WRITE)
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun * For prevent_user_access() only.
10*4882a593Smuzhiyun * Use the current saved situation instead of the to/from/size params.
11*4882a593Smuzhiyun * Used on book3s/32
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun #define KUAP_CURRENT_READ 4
14*4882a593Smuzhiyun #define KUAP_CURRENT_WRITE 8
15*4882a593Smuzhiyun #define KUAP_CURRENT (KUAP_CURRENT_READ | KUAP_CURRENT_WRITE)
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #ifdef CONFIG_PPC_BOOK3S_64
18*4882a593Smuzhiyun #include <asm/book3s/64/kup-radix.h>
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun #ifdef CONFIG_PPC_8xx
21*4882a593Smuzhiyun #include <asm/nohash/32/kup-8xx.h>
22*4882a593Smuzhiyun #endif
23*4882a593Smuzhiyun #ifdef CONFIG_PPC_BOOK3S_32
24*4882a593Smuzhiyun #include <asm/book3s/32/kup.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #ifdef __ASSEMBLY__
28*4882a593Smuzhiyun #ifndef CONFIG_PPC_KUAP
29*4882a593Smuzhiyun .macro kuap_save_and_lock sp, thread, gpr1, gpr2, gpr3
30*4882a593Smuzhiyun .endm
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun .macro kuap_restore sp, current, gpr1, gpr2, gpr3
33*4882a593Smuzhiyun .endm
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun .macro kuap_check current, gpr
36*4882a593Smuzhiyun .endm
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun .macro kuap_check_amr gpr1, gpr2
39*4882a593Smuzhiyun .endm
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #endif
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #else /* !__ASSEMBLY__ */
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #include <linux/pgtable.h>
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun void setup_kup(void);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #ifdef CONFIG_PPC_KUEP
50*4882a593Smuzhiyun void setup_kuep(bool disabled);
51*4882a593Smuzhiyun #else
setup_kuep(bool disabled)52*4882a593Smuzhiyun static inline void setup_kuep(bool disabled) { }
53*4882a593Smuzhiyun #endif /* CONFIG_PPC_KUEP */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #ifdef CONFIG_PPC_KUAP
56*4882a593Smuzhiyun void setup_kuap(bool disabled);
57*4882a593Smuzhiyun #else
setup_kuap(bool disabled)58*4882a593Smuzhiyun static inline void setup_kuap(bool disabled) { }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun static inline bool
bad_kuap_fault(struct pt_regs * regs,unsigned long address,bool is_write)61*4882a593Smuzhiyun bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun return false;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
kuap_check_amr(void)66*4882a593Smuzhiyun static inline void kuap_check_amr(void) { }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /*
69*4882a593Smuzhiyun * book3s/64/kup-radix.h defines these functions for the !KUAP case to flush
70*4882a593Smuzhiyun * the L1D cache after user accesses. Only include the empty stubs for other
71*4882a593Smuzhiyun * platforms.
72*4882a593Smuzhiyun */
73*4882a593Smuzhiyun #ifndef CONFIG_PPC_BOOK3S_64
allow_user_access(void __user * to,const void __user * from,unsigned long size,unsigned long dir)74*4882a593Smuzhiyun static inline void allow_user_access(void __user *to, const void __user *from,
75*4882a593Smuzhiyun unsigned long size, unsigned long dir) { }
prevent_user_access(void __user * to,const void __user * from,unsigned long size,unsigned long dir)76*4882a593Smuzhiyun static inline void prevent_user_access(void __user *to, const void __user *from,
77*4882a593Smuzhiyun unsigned long size, unsigned long dir) { }
prevent_user_access_return(void)78*4882a593Smuzhiyun static inline unsigned long prevent_user_access_return(void) { return 0UL; }
restore_user_access(unsigned long flags)79*4882a593Smuzhiyun static inline void restore_user_access(unsigned long flags) { }
80*4882a593Smuzhiyun #endif /* CONFIG_PPC_BOOK3S_64 */
81*4882a593Smuzhiyun #endif /* CONFIG_PPC_KUAP */
82*4882a593Smuzhiyun
allow_read_from_user(const void __user * from,unsigned long size)83*4882a593Smuzhiyun static inline void allow_read_from_user(const void __user *from, unsigned long size)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun allow_user_access(NULL, from, size, KUAP_READ);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
allow_write_to_user(void __user * to,unsigned long size)88*4882a593Smuzhiyun static inline void allow_write_to_user(void __user *to, unsigned long size)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun allow_user_access(to, NULL, size, KUAP_WRITE);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
allow_read_write_user(void __user * to,const void __user * from,unsigned long size)93*4882a593Smuzhiyun static inline void allow_read_write_user(void __user *to, const void __user *from,
94*4882a593Smuzhiyun unsigned long size)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun allow_user_access(to, from, size, KUAP_READ_WRITE);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
prevent_read_from_user(const void __user * from,unsigned long size)99*4882a593Smuzhiyun static inline void prevent_read_from_user(const void __user *from, unsigned long size)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun prevent_user_access(NULL, from, size, KUAP_READ);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
prevent_write_to_user(void __user * to,unsigned long size)104*4882a593Smuzhiyun static inline void prevent_write_to_user(void __user *to, unsigned long size)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun prevent_user_access(to, NULL, size, KUAP_WRITE);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
prevent_read_write_user(void __user * to,const void __user * from,unsigned long size)109*4882a593Smuzhiyun static inline void prevent_read_write_user(void __user *to, const void __user *from,
110*4882a593Smuzhiyun unsigned long size)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun prevent_user_access(to, from, size, KUAP_READ_WRITE);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
prevent_current_access_user(void)115*4882a593Smuzhiyun static inline void prevent_current_access_user(void)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun prevent_user_access(NULL, NULL, ~0UL, KUAP_CURRENT);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
prevent_current_read_from_user(void)120*4882a593Smuzhiyun static inline void prevent_current_read_from_user(void)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun prevent_user_access(NULL, NULL, ~0UL, KUAP_CURRENT_READ);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
prevent_current_write_to_user(void)125*4882a593Smuzhiyun static inline void prevent_current_write_to_user(void)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun prevent_user_access(NULL, NULL, ~0UL, KUAP_CURRENT_WRITE);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun #endif /* !__ASSEMBLY__ */
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #endif /* _ASM_POWERPC_KUAP_H_ */
133