diff options
Diffstat (limited to 'arch/s390/include/asm/processor.h')
-rw-r--r-- | arch/s390/include/asm/processor.h | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 7f2953c15c37..43494a014d5b 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -250,6 +250,55 @@ static inline unsigned short stap(void) | |||
250 | return cpu_address; | 250 | return cpu_address; |
251 | } | 251 | } |
252 | 252 | ||
253 | #define CALL_ARGS_0() \ | ||
254 | register unsigned long r2 asm("2") | ||
255 | #define CALL_ARGS_1(arg1) \ | ||
256 | register unsigned long r2 asm("2") = (unsigned long)(arg1) | ||
257 | #define CALL_ARGS_2(arg1, arg2) \ | ||
258 | CALL_ARGS_1(arg1); \ | ||
259 | register unsigned long r3 asm("3") = (unsigned long)(arg2) | ||
260 | #define CALL_ARGS_3(arg1, arg2, arg3) \ | ||
261 | CALL_ARGS_2(arg1, arg2); \ | ||
262 | register unsigned long r4 asm("4") = (unsigned long)(arg3) | ||
263 | #define CALL_ARGS_4(arg1, arg2, arg3, arg4) \ | ||
264 | CALL_ARGS_3(arg1, arg2, arg3); \ | ||
265 | register unsigned long r4 asm("5") = (unsigned long)(arg4) | ||
266 | #define CALL_ARGS_5(arg1, arg2, arg3, arg4, arg5) \ | ||
267 | CALL_ARGS_4(arg1, arg2, arg3, arg4); \ | ||
268 | register unsigned long r4 asm("6") = (unsigned long)(arg5) | ||
269 | |||
270 | #define CALL_FMT_0 | ||
271 | #define CALL_FMT_1 CALL_FMT_0, "0" (r2) | ||
272 | #define CALL_FMT_2 CALL_FMT_1, "d" (r3) | ||
273 | #define CALL_FMT_3 CALL_FMT_2, "d" (r4) | ||
274 | #define CALL_FMT_4 CALL_FMT_3, "d" (r5) | ||
275 | #define CALL_FMT_5 CALL_FMT_4, "d" (r6) | ||
276 | |||
277 | #define CALL_CLOBBER_5 "0", "1", "14", "cc", "memory" | ||
278 | #define CALL_CLOBBER_4 CALL_CLOBBER_5 | ||
279 | #define CALL_CLOBBER_3 CALL_CLOBBER_4, "5" | ||
280 | #define CALL_CLOBBER_2 CALL_CLOBBER_3, "4" | ||
281 | #define CALL_CLOBBER_1 CALL_CLOBBER_2, "3" | ||
282 | #define CALL_CLOBBER_0 CALL_CLOBBER_1 | ||
283 | |||
284 | #define CALL_ON_STACK(fn, stack, nr, args...) \ | ||
285 | ({ \ | ||
286 | CALL_ARGS_##nr(args); \ | ||
287 | unsigned long prev; \ | ||
288 | \ | ||
289 | asm volatile( \ | ||
290 | " la %[_prev],0(15)\n" \ | ||
291 | " la 15,0(%[_stack])\n" \ | ||
292 | " stg %[_prev],%[_bc](15)\n" \ | ||
293 | " brasl 14,%[_fn]\n" \ | ||
294 | " la 15,0(%[_prev])\n" \ | ||
295 | : "+&d" (r2), [_prev] "=&a" (prev) \ | ||
296 | : [_stack] "a" (stack), \ | ||
297 | [_bc] "i" (offsetof(struct stack_frame, back_chain)), \ | ||
298 | [_fn] "X" (fn) CALL_FMT_##nr : CALL_CLOBBER_##nr); \ | ||
299 | r2; \ | ||
300 | }) | ||
301 | |||
253 | /* | 302 | /* |
254 | * Give up the time slice of the virtual PU. | 303 | * Give up the time slice of the virtual PU. |
255 | */ | 304 | */ |