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 | |
| 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>
| -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) |
