diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2009-01-28 17:35:06 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-01-30 17:51:45 -0500 |
commit | 791bad9d28d405d9397ea0c370ffb7c7bdd2aa6e (patch) | |
tree | 3a067d90415de66711bdaf9cd624d1a38cd4b8f0 /arch/x86/include/asm/paravirt.h | |
parent | ecb93d1ccd0aac63f03be2db3cac3fa974716f4c (diff) |
x86/paravirt: implement PVOP_CALL macros for callee-save functions
Impact: Optimization
Functions with the callee save calling convention clobber many fewer
registers than the normal C calling convention. Implement variants of
PVOP_V?CALL* accordingly. This only bothers with functions up to 3
args, since functions with more args may as well use the normal
calling convention.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/include/asm/paravirt.h')
-rw-r--r-- | arch/x86/include/asm/paravirt.h | 134 |
1 files changed, 99 insertions, 35 deletions
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index f9107b88631b..beb10ecdbe67 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
@@ -510,25 +510,45 @@ int paravirt_disable_iospace(void); | |||
510 | * makes sure the incoming and outgoing types are always correct. | 510 | * makes sure the incoming and outgoing types are always correct. |
511 | */ | 511 | */ |
512 | #ifdef CONFIG_X86_32 | 512 | #ifdef CONFIG_X86_32 |
513 | #define PVOP_VCALL_ARGS unsigned long __eax, __edx, __ecx | 513 | #define PVOP_VCALL_ARGS \ |
514 | unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx | ||
514 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS | 515 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS |
516 | |||
517 | #define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x)) | ||
518 | #define PVOP_CALL_ARG2(x) "d" ((unsigned long)(x)) | ||
519 | #define PVOP_CALL_ARG3(x) "c" ((unsigned long)(x)) | ||
520 | |||
515 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ | 521 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ |
516 | "=c" (__ecx) | 522 | "=c" (__ecx) |
517 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS | 523 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS |
524 | |||
525 | #define PVOP_VCALLEE_CLOBBERS "=a" (__eax) | ||
526 | #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS | ||
527 | |||
518 | #define EXTRA_CLOBBERS | 528 | #define EXTRA_CLOBBERS |
519 | #define VEXTRA_CLOBBERS | 529 | #define VEXTRA_CLOBBERS |
520 | #else | 530 | #else /* CONFIG_X86_64 */ |
521 | #define PVOP_VCALL_ARGS unsigned long __edi, __esi, __edx, __ecx | 531 | #define PVOP_VCALL_ARGS \ |
532 | unsigned long __edi = __edi, __esi = __esi, \ | ||
533 | __edx = __edx, __ecx = __ecx | ||
522 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax | 534 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax |
535 | |||
536 | #define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x)) | ||
537 | #define PVOP_CALL_ARG2(x) "S" ((unsigned long)(x)) | ||
538 | #define PVOP_CALL_ARG3(x) "d" ((unsigned long)(x)) | ||
539 | #define PVOP_CALL_ARG4(x) "c" ((unsigned long)(x)) | ||
540 | |||
523 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ | 541 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ |
524 | "=S" (__esi), "=d" (__edx), \ | 542 | "=S" (__esi), "=d" (__edx), \ |
525 | "=c" (__ecx) | 543 | "=c" (__ecx) |
526 | |||
527 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) | 544 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) |
528 | 545 | ||
546 | #define PVOP_VCALLEE_CLOBBERS "=a" (__eax) | ||
547 | #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS | ||
548 | |||
529 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" | 549 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" |
530 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" | 550 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" |
531 | #endif | 551 | #endif /* CONFIG_X86_32 */ |
532 | 552 | ||
533 | #ifdef CONFIG_PARAVIRT_DEBUG | 553 | #ifdef CONFIG_PARAVIRT_DEBUG |
534 | #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) | 554 | #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) |
@@ -536,10 +556,11 @@ int paravirt_disable_iospace(void); | |||
536 | #define PVOP_TEST_NULL(op) ((void)op) | 556 | #define PVOP_TEST_NULL(op) ((void)op) |
537 | #endif | 557 | #endif |
538 | 558 | ||
539 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ | 559 | #define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr, \ |
560 | pre, post, ...) \ | ||
540 | ({ \ | 561 | ({ \ |
541 | rettype __ret; \ | 562 | rettype __ret; \ |
542 | PVOP_CALL_ARGS; \ | 563 | PVOP_CALL_ARGS; \ |
543 | PVOP_TEST_NULL(op); \ | 564 | PVOP_TEST_NULL(op); \ |
544 | /* This is 32-bit specific, but is okay in 64-bit */ \ | 565 | /* This is 32-bit specific, but is okay in 64-bit */ \ |
545 | /* since this condition will never hold */ \ | 566 | /* since this condition will never hold */ \ |
@@ -547,70 +568,113 @@ int paravirt_disable_iospace(void); | |||
547 | asm volatile(pre \ | 568 | asm volatile(pre \ |
548 | paravirt_alt(PARAVIRT_CALL) \ | 569 | paravirt_alt(PARAVIRT_CALL) \ |
549 | post \ | 570 | post \ |
550 | : PVOP_CALL_CLOBBERS \ | 571 | : call_clbr \ |
551 | : paravirt_type(op), \ | 572 | : paravirt_type(op), \ |
552 | paravirt_clobber(CLBR_ANY), \ | 573 | paravirt_clobber(clbr), \ |
553 | ##__VA_ARGS__ \ | 574 | ##__VA_ARGS__ \ |
554 | : "memory", "cc" EXTRA_CLOBBERS); \ | 575 | : "memory", "cc" extra_clbr); \ |
555 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ | 576 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ |
556 | } else { \ | 577 | } else { \ |
557 | asm volatile(pre \ | 578 | asm volatile(pre \ |
558 | paravirt_alt(PARAVIRT_CALL) \ | 579 | paravirt_alt(PARAVIRT_CALL) \ |
559 | post \ | 580 | post \ |
560 | : PVOP_CALL_CLOBBERS \ | 581 | : call_clbr \ |
561 | : paravirt_type(op), \ | 582 | : paravirt_type(op), \ |
562 | paravirt_clobber(CLBR_ANY), \ | 583 | paravirt_clobber(clbr), \ |
563 | ##__VA_ARGS__ \ | 584 | ##__VA_ARGS__ \ |
564 | : "memory", "cc" EXTRA_CLOBBERS); \ | 585 | : "memory", "cc" extra_clbr); \ |
565 | __ret = (rettype)__eax; \ | 586 | __ret = (rettype)__eax; \ |
566 | } \ | 587 | } \ |
567 | __ret; \ | 588 | __ret; \ |
568 | }) | 589 | }) |
569 | #define __PVOP_VCALL(op, pre, post, ...) \ | 590 | |
591 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ | ||
592 | ____PVOP_CALL(rettype, op, CLBR_ANY, PVOP_CALL_CLOBBERS, \ | ||
593 | EXTRA_CLOBBERS, pre, post, ##__VA_ARGS__) | ||
594 | |||
595 | #define __PVOP_CALLEESAVE(rettype, op, pre, post, ...) \ | ||
596 | ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ | ||
597 | PVOP_CALLEE_CLOBBERS, , \ | ||
598 | pre, post, ##__VA_ARGS__) | ||
599 | |||
600 | |||
601 | #define ____PVOP_VCALL(op, clbr, call_clbr, extra_clbr, pre, post, ...) \ | ||
570 | ({ \ | 602 | ({ \ |
571 | PVOP_VCALL_ARGS; \ | 603 | PVOP_VCALL_ARGS; \ |
572 | PVOP_TEST_NULL(op); \ | 604 | PVOP_TEST_NULL(op); \ |
573 | asm volatile(pre \ | 605 | asm volatile(pre \ |
574 | paravirt_alt(PARAVIRT_CALL) \ | 606 | paravirt_alt(PARAVIRT_CALL) \ |
575 | post \ | 607 | post \ |
576 | : PVOP_VCALL_CLOBBERS \ | 608 | : call_clbr \ |
577 | : paravirt_type(op), \ | 609 | : paravirt_type(op), \ |
578 | paravirt_clobber(CLBR_ANY), \ | 610 | paravirt_clobber(clbr), \ |
579 | ##__VA_ARGS__ \ | 611 | ##__VA_ARGS__ \ |
580 | : "memory", "cc" VEXTRA_CLOBBERS); \ | 612 | : "memory", "cc" extra_clbr); \ |
581 | }) | 613 | }) |
582 | 614 | ||
615 | #define __PVOP_VCALL(op, pre, post, ...) \ | ||
616 | ____PVOP_VCALL(op, CLBR_ANY, PVOP_VCALL_CLOBBERS, \ | ||
617 | VEXTRA_CLOBBERS, \ | ||
618 | pre, post, ##__VA_ARGS__) | ||
619 | |||
620 | #define __PVOP_VCALLEESAVE(rettype, op, pre, post, ...) \ | ||
621 | ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ | ||
622 | PVOP_VCALLEE_CLOBBERS, , \ | ||
623 | pre, post, ##__VA_ARGS__) | ||
624 | |||
625 | |||
626 | |||
583 | #define PVOP_CALL0(rettype, op) \ | 627 | #define PVOP_CALL0(rettype, op) \ |
584 | __PVOP_CALL(rettype, op, "", "") | 628 | __PVOP_CALL(rettype, op, "", "") |
585 | #define PVOP_VCALL0(op) \ | 629 | #define PVOP_VCALL0(op) \ |
586 | __PVOP_VCALL(op, "", "") | 630 | __PVOP_VCALL(op, "", "") |
587 | 631 | ||
632 | #define PVOP_CALLEE0(rettype, op) \ | ||
633 | __PVOP_CALLEESAVE(rettype, op, "", "") | ||
634 | #define PVOP_VCALLEE0(op) \ | ||
635 | __PVOP_VCALLEESAVE(op, "", "") | ||
636 | |||
637 | |||
588 | #define PVOP_CALL1(rettype, op, arg1) \ | 638 | #define PVOP_CALL1(rettype, op, arg1) \ |
589 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1))) | 639 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) |
590 | #define PVOP_VCALL1(op, arg1) \ | 640 | #define PVOP_VCALL1(op, arg1) \ |
591 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1))) | 641 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1)) |
642 | |||
643 | #define PVOP_CALLEE1(rettype, op, arg1) \ | ||
644 | __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) | ||
645 | #define PVOP_VCALLEE1(op, arg1) \ | ||
646 | __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1)) | ||
647 | |||
592 | 648 | ||
593 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ | 649 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ |
594 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 650 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ |
595 | "1" ((unsigned long)(arg2))) | 651 | PVOP_CALL_ARG2(arg2)) |
596 | #define PVOP_VCALL2(op, arg1, arg2) \ | 652 | #define PVOP_VCALL2(op, arg1, arg2) \ |
597 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 653 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ |
598 | "1" ((unsigned long)(arg2))) | 654 | PVOP_CALL_ARG2(arg2)) |
655 | |||
656 | #define PVOP_CALLEE2(rettype, op, arg1, arg2) \ | ||
657 | __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ | ||
658 | PVOP_CALL_ARG2(arg2)) | ||
659 | #define PVOP_VCALLEE2(op, arg1, arg2) \ | ||
660 | __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1), \ | ||
661 | PVOP_CALL_ARG2(arg2)) | ||
662 | |||
599 | 663 | ||
600 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ | 664 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ |
601 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 665 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ |
602 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) | 666 | PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) |
603 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ | 667 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ |
604 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 668 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ |
605 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) | 669 | PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) |
606 | 670 | ||
607 | /* This is the only difference in x86_64. We can make it much simpler */ | 671 | /* This is the only difference in x86_64. We can make it much simpler */ |
608 | #ifdef CONFIG_X86_32 | 672 | #ifdef CONFIG_X86_32 |
609 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 673 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
610 | __PVOP_CALL(rettype, op, \ | 674 | __PVOP_CALL(rettype, op, \ |
611 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 675 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
612 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ | 676 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
613 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 677 | PVOP_CALL_ARG3(arg3), [_arg4] "mr" ((u32)(arg4))) |
614 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | 678 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ |
615 | __PVOP_VCALL(op, \ | 679 | __PVOP_VCALL(op, \ |
616 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 680 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
@@ -618,13 +682,13 @@ int paravirt_disable_iospace(void); | |||
618 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 682 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) |
619 | #else | 683 | #else |
620 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 684 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
621 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 685 | __PVOP_CALL(rettype, op, "", "", \ |
622 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | 686 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
623 | "3"((unsigned long)(arg4))) | 687 | PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) |
624 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | 688 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ |
625 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 689 | __PVOP_VCALL(op, "", "", \ |
626 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | 690 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
627 | "3"((unsigned long)(arg4))) | 691 | PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) |
628 | #endif | 692 | #endif |
629 | 693 | ||
630 | static inline int paravirt_enabled(void) | 694 | static inline int paravirt_enabled(void) |