@@ -86,7 +86,34 @@ int __noreturn __put_user_bad(void);
8686#define get_put_user_noinstr_attributes __always_inline
8787#endif
8888
89- #define DEFINE_PUT_USER (type ) \
89+ #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
90+
91+ #define DEFINE_PUT_USER_NOINSTR (type ) \
92+ static get_put_user_noinstr_attributes int \
93+ __put_user_##type##_noinstr(unsigned type __user *to, \
94+ unsigned type *from, \
95+ unsigned long size) \
96+ { \
97+ asm goto( \
98+ " llilh %%r0,%[spec]\n" \
99+ "0: mvcos %[to],%[from],%[size]\n" \
100+ "1: nopr %%r7\n" \
101+ EX_TABLE(0b, %l[Efault]) \
102+ EX_TABLE(1b, %l[Efault]) \
103+ : [to] "+Q" (*to) \
104+ : [size] "d" (size), [from] "Q" (*from), \
105+ [spec] "I" (0x81) \
106+ : "cc", "0" \
107+ : Efault \
108+ ); \
109+ return 0; \
110+ Efault: \
111+ return -EFAULT; \
112+ }
113+
114+ #else /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
115+
116+ #define DEFINE_PUT_USER_NOINSTR (type ) \
90117static get_put_user_noinstr_attributes int \
91118__put_user_##type##_noinstr(unsigned type __user *to, \
92119 unsigned type *from, \
@@ -106,8 +133,16 @@ __put_user_##type##_noinstr(unsigned type __user *to, \
106133 [spec] "I" (0x81) \
107134 : "cc", "0"); \
108135 return rc; \
109- } \
110- \
136+ }
137+
138+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
139+
140+ DEFINE_PUT_USER_NOINSTR (char );
141+ DEFINE_PUT_USER_NOINSTR (short );
142+ DEFINE_PUT_USER_NOINSTR (int );
143+ DEFINE_PUT_USER_NOINSTR (long );
144+
145+ #define DEFINE_PUT_USER (type ) \
111146static __always_inline int \
112147__put_user_##type(unsigned type __user *to, unsigned type *from, \
113148 unsigned long size) \
@@ -166,7 +201,35 @@ DEFINE_PUT_USER(long);
166201
167202int __noreturn __get_user_bad (void );
168203
169- #define DEFINE_GET_USER (type ) \
204+ #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
205+
206+ #define DEFINE_GET_USER_NOINSTR (type ) \
207+ static get_put_user_noinstr_attributes int \
208+ __get_user_##type##_noinstr(unsigned type *to, \
209+ const unsigned type __user *from, \
210+ unsigned long size) \
211+ { \
212+ asm goto( \
213+ " lhi %%r0,%[spec]\n" \
214+ "0: mvcos %[to],%[from],%[size]\n" \
215+ "1: nopr %%r7\n" \
216+ EX_TABLE(0b, %l[Efault]) \
217+ EX_TABLE(1b, %l[Efault]) \
218+ : [to] "=Q" (*to) \
219+ : [size] "d" (size), [from] "Q" (*from), \
220+ [spec] "I" (0x81) \
221+ : "cc", "0" \
222+ : Efault \
223+ ); \
224+ return 0; \
225+ Efault: \
226+ *to = 0; \
227+ return -EFAULT; \
228+ }
229+
230+ #else /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
231+
232+ #define DEFINE_GET_USER_NOINSTR (type ) \
170233static get_put_user_noinstr_attributes int \
171234__get_user_##type##_noinstr(unsigned type *to, \
172235 const unsigned type __user *from, \
@@ -189,8 +252,16 @@ __get_user_##type##_noinstr(unsigned type *to, \
189252 return 0; \
190253 *to = 0; \
191254 return rc; \
192- } \
193- \
255+ }
256+
257+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
258+
259+ DEFINE_GET_USER_NOINSTR (char );
260+ DEFINE_GET_USER_NOINSTR (short );
261+ DEFINE_GET_USER_NOINSTR (int );
262+ DEFINE_GET_USER_NOINSTR (long );
263+
264+ #define DEFINE_GET_USER (type ) \
194265static __always_inline int \
195266__get_user_##type(unsigned type *to, const unsigned type __user *from, \
196267 unsigned long size) \
0 commit comments