aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86/paravirt.h
diff options
context:
space:
mode:
authorGlauber de Oliveira Costa <gcosta@redhat.com>2008-01-30 07:32:05 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:32:05 -0500
commita4746364da0c7caa155cc945a5c10312e7925b46 (patch)
tree0ebcd0f8457d607699bfea555bf5a30ddcc1cf5e /include/asm-x86/paravirt.h
parentb1df07bd6674a84fbd9248759dc3fa3ff5c78e5b (diff)
x86: adjust PVOP_CALL/VCALL macros for 64-bit
This patch adjust the PVOP_VCALL and PVOP_CALL macros to work with x86_64. It has a different calling convention, and we use auxiliary macros to account for both calling conventions as cleanly as possible Comments are adjusted accordingly. Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include/asm-x86/paravirt.h')
-rw-r--r--include/asm-x86/paravirt.h87
1 files changed, 65 insertions, 22 deletions
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 24406703007f..bef932772661 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -320,7 +320,7 @@ int paravirt_disable_iospace(void);
320 * runtime. 320 * runtime.
321 * 321 *
322 * Normally, a call to a pv_op function is a simple indirect call: 322 * Normally, a call to a pv_op function is a simple indirect call:
323 * (paravirt_ops.operations)(args...). 323 * (pv_op_struct.operations)(args...).
324 * 324 *
325 * Unfortunately, this is a relatively slow operation for modern CPUs, 325 * Unfortunately, this is a relatively slow operation for modern CPUs,
326 * because it cannot necessarily determine what the destination 326 * because it cannot necessarily determine what the destination
@@ -330,11 +330,17 @@ int paravirt_disable_iospace(void);
330 * calls are essentially free, because the call and return addresses 330 * calls are essentially free, because the call and return addresses
331 * are completely predictable.) 331 * are completely predictable.)
332 * 332 *
333 * These macros rely on the standard gcc "regparm(3)" calling 333 * For i386, these macros rely on the standard gcc "regparm(3)" calling
334 * convention, in which the first three arguments are placed in %eax, 334 * convention, in which the first three arguments are placed in %eax,
335 * %edx, %ecx (in that order), and the remaining arguments are placed 335 * %edx, %ecx (in that order), and the remaining arguments are placed
336 * on the stack. All caller-save registers (eax,edx,ecx) are expected 336 * on the stack. All caller-save registers (eax,edx,ecx) are expected
337 * to be modified (either clobbered or used for return values). 337 * to be modified (either clobbered or used for return values).
338 * X86_64, on the other hand, already specifies a register-based calling
339 * conventions, returning at %rax, with parameteres going on %rdi, %rsi,
340 * %rdx, and %rcx. Note that for this reason, x86_64 does not need any
341 * special handling for dealing with 4 arguments, unlike i386.
342 * However, x86_64 also have to clobber all caller saved registers, which
343 * unfortunately, are quite a bit (r8 - r11)
338 * 344 *
339 * The call instruction itself is marked by placing its start address 345 * The call instruction itself is marked by placing its start address
340 * and size into the .parainstructions section, so that 346 * and size into the .parainstructions section, so that
@@ -357,10 +363,12 @@ int paravirt_disable_iospace(void);
357 * the return type. The macro then uses sizeof() on that type to 363 * the return type. The macro then uses sizeof() on that type to
358 * determine whether its a 32 or 64 bit value, and places the return 364 * determine whether its a 32 or 64 bit value, and places the return
359 * in the right register(s) (just %eax for 32-bit, and %edx:%eax for 365 * in the right register(s) (just %eax for 32-bit, and %edx:%eax for
360 * 64-bit). 366 * 64-bit). For x86_64 machines, it just returns at %rax regardless of
367 * the return value size.
361 * 368 *
362 * 64-bit arguments are passed as a pair of adjacent 32-bit arguments 369 * 64-bit arguments are passed as a pair of adjacent 32-bit arguments
363 * in low,high order. 370 * i386 also passes 64-bit arguments as a pair of adjacent 32-bit arguments
371 * in low,high order
364 * 372 *
365 * Small structures are passed and returned in registers. The macro 373 * Small structures are passed and returned in registers. The macro
366 * calling convention can't directly deal with this, so the wrapper 374 * calling convention can't directly deal with this, so the wrapper
@@ -370,46 +378,67 @@ int paravirt_disable_iospace(void);
370 * means that all uses must be wrapped in inline functions. This also 378 * means that all uses must be wrapped in inline functions. This also
371 * makes sure the incoming and outgoing types are always correct. 379 * makes sure the incoming and outgoing types are always correct.
372 */ 380 */
381#ifdef CONFIG_X86_32
382#define PVOP_VCALL_ARGS unsigned long __eax, __edx, __ecx
383#define PVOP_CALL_ARGS PVOP_VCALL_ARGS
384#define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \
385 "=c" (__ecx)
386#define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS
387#define EXTRA_CLOBBERS
388#define VEXTRA_CLOBBERS
389#else
390#define PVOP_VCALL_ARGS unsigned long __edi, __esi, __edx, __ecx
391#define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax
392#define PVOP_VCALL_CLOBBERS "=D" (__edi), \
393 "=S" (__esi), "=d" (__edx), \
394 "=c" (__ecx)
395
396#define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax)
397
398#define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11"
399#define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11"
400#endif
401
373#define __PVOP_CALL(rettype, op, pre, post, ...) \ 402#define __PVOP_CALL(rettype, op, pre, post, ...) \
374 ({ \ 403 ({ \
375 rettype __ret; \ 404 rettype __ret; \
376 unsigned long __eax, __edx, __ecx; \ 405 PVOP_CALL_ARGS; \
406 /* This is 32-bit specific, but is okay in 64-bit */ \
407 /* since this condition will never hold */ \
377 if (sizeof(rettype) > sizeof(unsigned long)) { \ 408 if (sizeof(rettype) > sizeof(unsigned long)) { \
378 asm volatile(pre \ 409 asm volatile(pre \
379 paravirt_alt(PARAVIRT_CALL) \ 410 paravirt_alt(PARAVIRT_CALL) \
380 post \ 411 post \
381 : "=a" (__eax), "=d" (__edx), \ 412 : PVOP_CALL_CLOBBERS \
382 "=c" (__ecx) \
383 : paravirt_type(op), \ 413 : paravirt_type(op), \
384 paravirt_clobber(CLBR_ANY), \ 414 paravirt_clobber(CLBR_ANY), \
385 ##__VA_ARGS__ \ 415 ##__VA_ARGS__ \
386 : "memory", "cc"); \ 416 : "memory", "cc" EXTRA_CLOBBERS); \
387 __ret = (rettype)((((u64)__edx) << 32) | __eax); \ 417 __ret = (rettype)((((u64)__edx) << 32) | __eax); \
388 } else { \ 418 } else { \
389 asm volatile(pre \ 419 asm volatile(pre \
390 paravirt_alt(PARAVIRT_CALL) \ 420 paravirt_alt(PARAVIRT_CALL) \
391 post \ 421 post \
392 : "=a" (__eax), "=d" (__edx), \ 422 : PVOP_CALL_CLOBBERS \
393 "=c" (__ecx) \
394 : paravirt_type(op), \ 423 : paravirt_type(op), \
395 paravirt_clobber(CLBR_ANY), \ 424 paravirt_clobber(CLBR_ANY), \
396 ##__VA_ARGS__ \ 425 ##__VA_ARGS__ \
397 : "memory", "cc"); \ 426 : "memory", "cc" EXTRA_CLOBBERS); \
398 __ret = (rettype)__eax; \ 427 __ret = (rettype)__eax; \
399 } \ 428 } \
400 __ret; \ 429 __ret; \
401 }) 430 })
402#define __PVOP_VCALL(op, pre, post, ...) \ 431#define __PVOP_VCALL(op, pre, post, ...) \
403 ({ \ 432 ({ \
404 unsigned long __eax, __edx, __ecx; \ 433 PVOP_VCALL_ARGS; \
405 asm volatile(pre \ 434 asm volatile(pre \
406 paravirt_alt(PARAVIRT_CALL) \ 435 paravirt_alt(PARAVIRT_CALL) \
407 post \ 436 post \
408 : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ 437 : PVOP_VCALL_CLOBBERS \
409 : paravirt_type(op), \ 438 : paravirt_type(op), \
410 paravirt_clobber(CLBR_ANY), \ 439 paravirt_clobber(CLBR_ANY), \
411 ##__VA_ARGS__ \ 440 ##__VA_ARGS__ \
412 : "memory", "cc"); \ 441 : "memory", "cc" VEXTRA_CLOBBERS); \
413 }) 442 })
414 443
415#define PVOP_CALL0(rettype, op) \ 444#define PVOP_CALL0(rettype, op) \
@@ -418,22 +447,26 @@ int paravirt_disable_iospace(void);
418 __PVOP_VCALL(op, "", "") 447 __PVOP_VCALL(op, "", "")
419 448
420#define PVOP_CALL1(rettype, op, arg1) \ 449#define PVOP_CALL1(rettype, op, arg1) \
421 __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1))) 450 __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)))
422#define PVOP_VCALL1(op, arg1) \ 451#define PVOP_VCALL1(op, arg1) \
423 __PVOP_VCALL(op, "", "", "0" ((u32)(arg1))) 452 __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)))
424 453
425#define PVOP_CALL2(rettype, op, arg1, arg2) \ 454#define PVOP_CALL2(rettype, op, arg1, arg2) \
426 __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) 455 __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \
456 "1" ((unsigned long)(arg2)))
427#define PVOP_VCALL2(op, arg1, arg2) \ 457#define PVOP_VCALL2(op, arg1, arg2) \
428 __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) 458 __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \
459 "1" ((unsigned long)(arg2)))
429 460
430#define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ 461#define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \
431 __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), \ 462 __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \
432 "1"((u32)(arg2)), "2"((u32)(arg3))) 463 "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)))
433#define PVOP_VCALL3(op, arg1, arg2, arg3) \ 464#define PVOP_VCALL3(op, arg1, arg2, arg3) \
434 __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1"((u32)(arg2)), \ 465 __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \
435 "2"((u32)(arg3))) 466 "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)))
436 467
468/* This is the only difference in x86_64. We can make it much simpler */
469#ifdef CONFIG_X86_32
437#define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ 470#define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \
438 __PVOP_CALL(rettype, op, \ 471 __PVOP_CALL(rettype, op, \
439 "push %[_arg4];", "lea 4(%%esp),%%esp;", \ 472 "push %[_arg4];", "lea 4(%%esp),%%esp;", \
@@ -444,6 +477,16 @@ int paravirt_disable_iospace(void);
444 "push %[_arg4];", "lea 4(%%esp),%%esp;", \ 477 "push %[_arg4];", "lea 4(%%esp),%%esp;", \
445 "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ 478 "0" ((u32)(arg1)), "1" ((u32)(arg2)), \
446 "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) 479 "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4)))
480#else
481#define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \
482 __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \
483 "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \
484 "3"((unsigned long)(arg4)))
485#define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \
486 __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \
487 "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \
488 "3"((unsigned long)(arg4)))
489#endif
447 490
448static inline int paravirt_enabled(void) 491static inline int paravirt_enabled(void)
449{ 492{