diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-09 06:16:59 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 06:16:59 -0500 |
commit | eca217b36e5d7d4377493d5cedd89105e66a5a72 (patch) | |
tree | 71f0ecd5225c3033d509b77a23ad7bc576cf0ab6 /arch/x86/include/asm/paravirt.h | |
parent | 54a353a0f845c1dad5fc8183872e750d667838ac (diff) | |
parent | e4d0407185cdbdcfd99fc23bde2e5454bbc46329 (diff) |
Merge branch 'x86/paravirt' into x86/apic
Conflicts:
arch/x86/mach-voyager/voyager_smp.c
Diffstat (limited to 'arch/x86/include/asm/paravirt.h')
-rw-r--r-- | arch/x86/include/asm/paravirt.h | 435 |
1 files changed, 301 insertions, 134 deletions
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 7e674ea80f0d..ff691736f5e9 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
@@ -12,21 +12,38 @@ | |||
12 | #define CLBR_EAX (1 << 0) | 12 | #define CLBR_EAX (1 << 0) |
13 | #define CLBR_ECX (1 << 1) | 13 | #define CLBR_ECX (1 << 1) |
14 | #define CLBR_EDX (1 << 2) | 14 | #define CLBR_EDX (1 << 2) |
15 | #define CLBR_EDI (1 << 3) | ||
15 | 16 | ||
16 | #ifdef CONFIG_X86_64 | 17 | #ifdef CONFIG_X86_32 |
17 | #define CLBR_RSI (1 << 3) | 18 | /* CLBR_ANY should match all regs platform has. For i386, that's just it */ |
18 | #define CLBR_RDI (1 << 4) | 19 | #define CLBR_ANY ((1 << 4) - 1) |
20 | |||
21 | #define CLBR_ARG_REGS (CLBR_EAX | CLBR_EDX | CLBR_ECX) | ||
22 | #define CLBR_RET_REG (CLBR_EAX | CLBR_EDX) | ||
23 | #define CLBR_SCRATCH (0) | ||
24 | #else | ||
25 | #define CLBR_RAX CLBR_EAX | ||
26 | #define CLBR_RCX CLBR_ECX | ||
27 | #define CLBR_RDX CLBR_EDX | ||
28 | #define CLBR_RDI CLBR_EDI | ||
29 | #define CLBR_RSI (1 << 4) | ||
19 | #define CLBR_R8 (1 << 5) | 30 | #define CLBR_R8 (1 << 5) |
20 | #define CLBR_R9 (1 << 6) | 31 | #define CLBR_R9 (1 << 6) |
21 | #define CLBR_R10 (1 << 7) | 32 | #define CLBR_R10 (1 << 7) |
22 | #define CLBR_R11 (1 << 8) | 33 | #define CLBR_R11 (1 << 8) |
34 | |||
23 | #define CLBR_ANY ((1 << 9) - 1) | 35 | #define CLBR_ANY ((1 << 9) - 1) |
36 | |||
37 | #define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ | ||
38 | CLBR_RCX | CLBR_R8 | CLBR_R9) | ||
39 | #define CLBR_RET_REG (CLBR_RAX) | ||
40 | #define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) | ||
41 | |||
24 | #include <asm/desc_defs.h> | 42 | #include <asm/desc_defs.h> |
25 | #else | ||
26 | /* CLBR_ANY should match all regs platform has. For i386, that's just it */ | ||
27 | #define CLBR_ANY ((1 << 3) - 1) | ||
28 | #endif /* X86_64 */ | 43 | #endif /* X86_64 */ |
29 | 44 | ||
45 | #define CLBR_CALLEE_SAVE ((CLBR_ARG_REGS | CLBR_SCRATCH) & ~CLBR_RET_REG) | ||
46 | |||
30 | #ifndef __ASSEMBLY__ | 47 | #ifndef __ASSEMBLY__ |
31 | #include <linux/types.h> | 48 | #include <linux/types.h> |
32 | #include <linux/cpumask.h> | 49 | #include <linux/cpumask.h> |
@@ -40,6 +57,14 @@ struct tss_struct; | |||
40 | struct mm_struct; | 57 | struct mm_struct; |
41 | struct desc_struct; | 58 | struct desc_struct; |
42 | 59 | ||
60 | /* | ||
61 | * Wrapper type for pointers to code which uses the non-standard | ||
62 | * calling convention. See PV_CALL_SAVE_REGS_THUNK below. | ||
63 | */ | ||
64 | struct paravirt_callee_save { | ||
65 | void *func; | ||
66 | }; | ||
67 | |||
43 | /* general info */ | 68 | /* general info */ |
44 | struct pv_info { | 69 | struct pv_info { |
45 | unsigned int kernel_rpl; | 70 | unsigned int kernel_rpl; |
@@ -189,11 +214,15 @@ struct pv_irq_ops { | |||
189 | * expected to use X86_EFLAGS_IF; all other bits | 214 | * expected to use X86_EFLAGS_IF; all other bits |
190 | * returned from save_fl are undefined, and may be ignored by | 215 | * returned from save_fl are undefined, and may be ignored by |
191 | * restore_fl. | 216 | * restore_fl. |
217 | * | ||
218 | * NOTE: These functions callers expect the callee to preserve | ||
219 | * more registers than the standard C calling convention. | ||
192 | */ | 220 | */ |
193 | unsigned long (*save_fl)(void); | 221 | struct paravirt_callee_save save_fl; |
194 | void (*restore_fl)(unsigned long); | 222 | struct paravirt_callee_save restore_fl; |
195 | void (*irq_disable)(void); | 223 | struct paravirt_callee_save irq_disable; |
196 | void (*irq_enable)(void); | 224 | struct paravirt_callee_save irq_enable; |
225 | |||
197 | void (*safe_halt)(void); | 226 | void (*safe_halt)(void); |
198 | void (*halt)(void); | 227 | void (*halt)(void); |
199 | 228 | ||
@@ -279,11 +308,11 @@ struct pv_mmu_ops { | |||
279 | void (*ptep_modify_prot_commit)(struct mm_struct *mm, unsigned long addr, | 308 | void (*ptep_modify_prot_commit)(struct mm_struct *mm, unsigned long addr, |
280 | pte_t *ptep, pte_t pte); | 309 | pte_t *ptep, pte_t pte); |
281 | 310 | ||
282 | pteval_t (*pte_val)(pte_t); | 311 | struct paravirt_callee_save pte_val; |
283 | pte_t (*make_pte)(pteval_t pte); | 312 | struct paravirt_callee_save make_pte; |
284 | 313 | ||
285 | pgdval_t (*pgd_val)(pgd_t); | 314 | struct paravirt_callee_save pgd_val; |
286 | pgd_t (*make_pgd)(pgdval_t pgd); | 315 | struct paravirt_callee_save make_pgd; |
287 | 316 | ||
288 | #if PAGETABLE_LEVELS >= 3 | 317 | #if PAGETABLE_LEVELS >= 3 |
289 | #ifdef CONFIG_X86_PAE | 318 | #ifdef CONFIG_X86_PAE |
@@ -298,12 +327,12 @@ struct pv_mmu_ops { | |||
298 | 327 | ||
299 | void (*set_pud)(pud_t *pudp, pud_t pudval); | 328 | void (*set_pud)(pud_t *pudp, pud_t pudval); |
300 | 329 | ||
301 | pmdval_t (*pmd_val)(pmd_t); | 330 | struct paravirt_callee_save pmd_val; |
302 | pmd_t (*make_pmd)(pmdval_t pmd); | 331 | struct paravirt_callee_save make_pmd; |
303 | 332 | ||
304 | #if PAGETABLE_LEVELS == 4 | 333 | #if PAGETABLE_LEVELS == 4 |
305 | pudval_t (*pud_val)(pud_t); | 334 | struct paravirt_callee_save pud_val; |
306 | pud_t (*make_pud)(pudval_t pud); | 335 | struct paravirt_callee_save make_pud; |
307 | 336 | ||
308 | void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); | 337 | void (*set_pgd)(pgd_t *pudp, pgd_t pgdval); |
309 | #endif /* PAGETABLE_LEVELS == 4 */ | 338 | #endif /* PAGETABLE_LEVELS == 4 */ |
@@ -388,6 +417,8 @@ extern struct pv_lock_ops pv_lock_ops; | |||
388 | asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":") | 417 | asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":") |
389 | 418 | ||
390 | unsigned paravirt_patch_nop(void); | 419 | unsigned paravirt_patch_nop(void); |
420 | unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len); | ||
421 | unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len); | ||
391 | unsigned paravirt_patch_ignore(unsigned len); | 422 | unsigned paravirt_patch_ignore(unsigned len); |
392 | unsigned paravirt_patch_call(void *insnbuf, | 423 | unsigned paravirt_patch_call(void *insnbuf, |
393 | const void *target, u16 tgt_clobbers, | 424 | const void *target, u16 tgt_clobbers, |
@@ -479,25 +510,45 @@ int paravirt_disable_iospace(void); | |||
479 | * makes sure the incoming and outgoing types are always correct. | 510 | * makes sure the incoming and outgoing types are always correct. |
480 | */ | 511 | */ |
481 | #ifdef CONFIG_X86_32 | 512 | #ifdef CONFIG_X86_32 |
482 | #define PVOP_VCALL_ARGS unsigned long __eax, __edx, __ecx | 513 | #define PVOP_VCALL_ARGS \ |
514 | unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx | ||
483 | #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 | |||
484 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ | 521 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ |
485 | "=c" (__ecx) | 522 | "=c" (__ecx) |
486 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS | 523 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS |
524 | |||
525 | #define PVOP_VCALLEE_CLOBBERS "=a" (__eax), "=d" (__edx) | ||
526 | #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS | ||
527 | |||
487 | #define EXTRA_CLOBBERS | 528 | #define EXTRA_CLOBBERS |
488 | #define VEXTRA_CLOBBERS | 529 | #define VEXTRA_CLOBBERS |
489 | #else | 530 | #else /* CONFIG_X86_64 */ |
490 | #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 | ||
491 | #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 | |||
492 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ | 541 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ |
493 | "=S" (__esi), "=d" (__edx), \ | 542 | "=S" (__esi), "=d" (__edx), \ |
494 | "=c" (__ecx) | 543 | "=c" (__ecx) |
495 | |||
496 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) | 544 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) |
497 | 545 | ||
546 | #define PVOP_VCALLEE_CLOBBERS "=a" (__eax) | ||
547 | #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS | ||
548 | |||
498 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" | 549 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" |
499 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" | 550 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" |
500 | #endif | 551 | #endif /* CONFIG_X86_32 */ |
501 | 552 | ||
502 | #ifdef CONFIG_PARAVIRT_DEBUG | 553 | #ifdef CONFIG_PARAVIRT_DEBUG |
503 | #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) | 554 | #define PVOP_TEST_NULL(op) BUG_ON(op == NULL) |
@@ -505,10 +556,11 @@ int paravirt_disable_iospace(void); | |||
505 | #define PVOP_TEST_NULL(op) ((void)op) | 556 | #define PVOP_TEST_NULL(op) ((void)op) |
506 | #endif | 557 | #endif |
507 | 558 | ||
508 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ | 559 | #define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr, \ |
560 | pre, post, ...) \ | ||
509 | ({ \ | 561 | ({ \ |
510 | rettype __ret; \ | 562 | rettype __ret; \ |
511 | PVOP_CALL_ARGS; \ | 563 | PVOP_CALL_ARGS; \ |
512 | PVOP_TEST_NULL(op); \ | 564 | PVOP_TEST_NULL(op); \ |
513 | /* This is 32-bit specific, but is okay in 64-bit */ \ | 565 | /* This is 32-bit specific, but is okay in 64-bit */ \ |
514 | /* since this condition will never hold */ \ | 566 | /* since this condition will never hold */ \ |
@@ -516,70 +568,113 @@ int paravirt_disable_iospace(void); | |||
516 | asm volatile(pre \ | 568 | asm volatile(pre \ |
517 | paravirt_alt(PARAVIRT_CALL) \ | 569 | paravirt_alt(PARAVIRT_CALL) \ |
518 | post \ | 570 | post \ |
519 | : PVOP_CALL_CLOBBERS \ | 571 | : call_clbr \ |
520 | : paravirt_type(op), \ | 572 | : paravirt_type(op), \ |
521 | paravirt_clobber(CLBR_ANY), \ | 573 | paravirt_clobber(clbr), \ |
522 | ##__VA_ARGS__ \ | 574 | ##__VA_ARGS__ \ |
523 | : "memory", "cc" EXTRA_CLOBBERS); \ | 575 | : "memory", "cc" extra_clbr); \ |
524 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ | 576 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ |
525 | } else { \ | 577 | } else { \ |
526 | asm volatile(pre \ | 578 | asm volatile(pre \ |
527 | paravirt_alt(PARAVIRT_CALL) \ | 579 | paravirt_alt(PARAVIRT_CALL) \ |
528 | post \ | 580 | post \ |
529 | : PVOP_CALL_CLOBBERS \ | 581 | : call_clbr \ |
530 | : paravirt_type(op), \ | 582 | : paravirt_type(op), \ |
531 | paravirt_clobber(CLBR_ANY), \ | 583 | paravirt_clobber(clbr), \ |
532 | ##__VA_ARGS__ \ | 584 | ##__VA_ARGS__ \ |
533 | : "memory", "cc" EXTRA_CLOBBERS); \ | 585 | : "memory", "cc" extra_clbr); \ |
534 | __ret = (rettype)__eax; \ | 586 | __ret = (rettype)__eax; \ |
535 | } \ | 587 | } \ |
536 | __ret; \ | 588 | __ret; \ |
537 | }) | 589 | }) |
538 | #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, ...) \ | ||
539 | ({ \ | 602 | ({ \ |
540 | PVOP_VCALL_ARGS; \ | 603 | PVOP_VCALL_ARGS; \ |
541 | PVOP_TEST_NULL(op); \ | 604 | PVOP_TEST_NULL(op); \ |
542 | asm volatile(pre \ | 605 | asm volatile(pre \ |
543 | paravirt_alt(PARAVIRT_CALL) \ | 606 | paravirt_alt(PARAVIRT_CALL) \ |
544 | post \ | 607 | post \ |
545 | : PVOP_VCALL_CLOBBERS \ | 608 | : call_clbr \ |
546 | : paravirt_type(op), \ | 609 | : paravirt_type(op), \ |
547 | paravirt_clobber(CLBR_ANY), \ | 610 | paravirt_clobber(clbr), \ |
548 | ##__VA_ARGS__ \ | 611 | ##__VA_ARGS__ \ |
549 | : "memory", "cc" VEXTRA_CLOBBERS); \ | 612 | : "memory", "cc" extra_clbr); \ |
550 | }) | 613 | }) |
551 | 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 | |||
552 | #define PVOP_CALL0(rettype, op) \ | 627 | #define PVOP_CALL0(rettype, op) \ |
553 | __PVOP_CALL(rettype, op, "", "") | 628 | __PVOP_CALL(rettype, op, "", "") |
554 | #define PVOP_VCALL0(op) \ | 629 | #define PVOP_VCALL0(op) \ |
555 | __PVOP_VCALL(op, "", "") | 630 | __PVOP_VCALL(op, "", "") |
556 | 631 | ||
632 | #define PVOP_CALLEE0(rettype, op) \ | ||
633 | __PVOP_CALLEESAVE(rettype, op, "", "") | ||
634 | #define PVOP_VCALLEE0(op) \ | ||
635 | __PVOP_VCALLEESAVE(op, "", "") | ||
636 | |||
637 | |||
557 | #define PVOP_CALL1(rettype, op, arg1) \ | 638 | #define PVOP_CALL1(rettype, op, arg1) \ |
558 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1))) | 639 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) |
559 | #define PVOP_VCALL1(op, arg1) \ | 640 | #define PVOP_VCALL1(op, arg1) \ |
560 | __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 | |||
561 | 648 | ||
562 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ | 649 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ |
563 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 650 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ |
564 | "1" ((unsigned long)(arg2))) | 651 | PVOP_CALL_ARG2(arg2)) |
565 | #define PVOP_VCALL2(op, arg1, arg2) \ | 652 | #define PVOP_VCALL2(op, arg1, arg2) \ |
566 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 653 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ |
567 | "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 | |||
568 | 663 | ||
569 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ | 664 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ |
570 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 665 | __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ |
571 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) | 666 | PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) |
572 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ | 667 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ |
573 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 668 | __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ |
574 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) | 669 | PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) |
575 | 670 | ||
576 | /* 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 */ |
577 | #ifdef CONFIG_X86_32 | 672 | #ifdef CONFIG_X86_32 |
578 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 673 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
579 | __PVOP_CALL(rettype, op, \ | 674 | __PVOP_CALL(rettype, op, \ |
580 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 675 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
581 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ | 676 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
582 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 677 | PVOP_CALL_ARG3(arg3), [_arg4] "mr" ((u32)(arg4))) |
583 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | 678 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ |
584 | __PVOP_VCALL(op, \ | 679 | __PVOP_VCALL(op, \ |
585 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 680 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
@@ -587,13 +682,13 @@ int paravirt_disable_iospace(void); | |||
587 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 682 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) |
588 | #else | 683 | #else |
589 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 684 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
590 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | 685 | __PVOP_CALL(rettype, op, "", "", \ |
591 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | 686 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
592 | "3"((unsigned long)(arg4))) | 687 | PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) |
593 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | 688 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ |
594 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | 689 | __PVOP_VCALL(op, "", "", \ |
595 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | 690 | PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ |
596 | "3"((unsigned long)(arg4))) | 691 | PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) |
597 | #endif | 692 | #endif |
598 | 693 | ||
599 | static inline int paravirt_enabled(void) | 694 | static inline int paravirt_enabled(void) |
@@ -1060,13 +1155,13 @@ static inline pte_t __pte(pteval_t val) | |||
1060 | pteval_t ret; | 1155 | pteval_t ret; |
1061 | 1156 | ||
1062 | if (sizeof(pteval_t) > sizeof(long)) | 1157 | if (sizeof(pteval_t) > sizeof(long)) |
1063 | ret = PVOP_CALL2(pteval_t, | 1158 | ret = PVOP_CALLEE2(pteval_t, |
1064 | pv_mmu_ops.make_pte, | 1159 | pv_mmu_ops.make_pte, |
1065 | val, (u64)val >> 32); | 1160 | val, (u64)val >> 32); |
1066 | else | 1161 | else |
1067 | ret = PVOP_CALL1(pteval_t, | 1162 | ret = PVOP_CALLEE1(pteval_t, |
1068 | pv_mmu_ops.make_pte, | 1163 | pv_mmu_ops.make_pte, |
1069 | val); | 1164 | val); |
1070 | 1165 | ||
1071 | return (pte_t) { .pte = ret }; | 1166 | return (pte_t) { .pte = ret }; |
1072 | } | 1167 | } |
@@ -1076,11 +1171,11 @@ static inline pteval_t pte_val(pte_t pte) | |||
1076 | pteval_t ret; | 1171 | pteval_t ret; |
1077 | 1172 | ||
1078 | if (sizeof(pteval_t) > sizeof(long)) | 1173 | if (sizeof(pteval_t) > sizeof(long)) |
1079 | ret = PVOP_CALL2(pteval_t, pv_mmu_ops.pte_val, | 1174 | ret = PVOP_CALLEE2(pteval_t, pv_mmu_ops.pte_val, |
1080 | pte.pte, (u64)pte.pte >> 32); | 1175 | pte.pte, (u64)pte.pte >> 32); |
1081 | else | 1176 | else |
1082 | ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_val, | 1177 | ret = PVOP_CALLEE1(pteval_t, pv_mmu_ops.pte_val, |
1083 | pte.pte); | 1178 | pte.pte); |
1084 | 1179 | ||
1085 | return ret; | 1180 | return ret; |
1086 | } | 1181 | } |
@@ -1090,11 +1185,11 @@ static inline pgd_t __pgd(pgdval_t val) | |||
1090 | pgdval_t ret; | 1185 | pgdval_t ret; |
1091 | 1186 | ||
1092 | if (sizeof(pgdval_t) > sizeof(long)) | 1187 | if (sizeof(pgdval_t) > sizeof(long)) |
1093 | ret = PVOP_CALL2(pgdval_t, pv_mmu_ops.make_pgd, | 1188 | ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.make_pgd, |
1094 | val, (u64)val >> 32); | 1189 | val, (u64)val >> 32); |
1095 | else | 1190 | else |
1096 | ret = PVOP_CALL1(pgdval_t, pv_mmu_ops.make_pgd, | 1191 | ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.make_pgd, |
1097 | val); | 1192 | val); |
1098 | 1193 | ||
1099 | return (pgd_t) { ret }; | 1194 | return (pgd_t) { ret }; |
1100 | } | 1195 | } |
@@ -1104,11 +1199,11 @@ static inline pgdval_t pgd_val(pgd_t pgd) | |||
1104 | pgdval_t ret; | 1199 | pgdval_t ret; |
1105 | 1200 | ||
1106 | if (sizeof(pgdval_t) > sizeof(long)) | 1201 | if (sizeof(pgdval_t) > sizeof(long)) |
1107 | ret = PVOP_CALL2(pgdval_t, pv_mmu_ops.pgd_val, | 1202 | ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.pgd_val, |
1108 | pgd.pgd, (u64)pgd.pgd >> 32); | 1203 | pgd.pgd, (u64)pgd.pgd >> 32); |
1109 | else | 1204 | else |
1110 | ret = PVOP_CALL1(pgdval_t, pv_mmu_ops.pgd_val, | 1205 | ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.pgd_val, |
1111 | pgd.pgd); | 1206 | pgd.pgd); |
1112 | 1207 | ||
1113 | return ret; | 1208 | return ret; |
1114 | } | 1209 | } |
@@ -1172,11 +1267,11 @@ static inline pmd_t __pmd(pmdval_t val) | |||
1172 | pmdval_t ret; | 1267 | pmdval_t ret; |
1173 | 1268 | ||
1174 | if (sizeof(pmdval_t) > sizeof(long)) | 1269 | if (sizeof(pmdval_t) > sizeof(long)) |
1175 | ret = PVOP_CALL2(pmdval_t, pv_mmu_ops.make_pmd, | 1270 | ret = PVOP_CALLEE2(pmdval_t, pv_mmu_ops.make_pmd, |
1176 | val, (u64)val >> 32); | 1271 | val, (u64)val >> 32); |
1177 | else | 1272 | else |
1178 | ret = PVOP_CALL1(pmdval_t, pv_mmu_ops.make_pmd, | 1273 | ret = PVOP_CALLEE1(pmdval_t, pv_mmu_ops.make_pmd, |
1179 | val); | 1274 | val); |
1180 | 1275 | ||
1181 | return (pmd_t) { ret }; | 1276 | return (pmd_t) { ret }; |
1182 | } | 1277 | } |
@@ -1186,11 +1281,11 @@ static inline pmdval_t pmd_val(pmd_t pmd) | |||
1186 | pmdval_t ret; | 1281 | pmdval_t ret; |
1187 | 1282 | ||
1188 | if (sizeof(pmdval_t) > sizeof(long)) | 1283 | if (sizeof(pmdval_t) > sizeof(long)) |
1189 | ret = PVOP_CALL2(pmdval_t, pv_mmu_ops.pmd_val, | 1284 | ret = PVOP_CALLEE2(pmdval_t, pv_mmu_ops.pmd_val, |
1190 | pmd.pmd, (u64)pmd.pmd >> 32); | 1285 | pmd.pmd, (u64)pmd.pmd >> 32); |
1191 | else | 1286 | else |
1192 | ret = PVOP_CALL1(pmdval_t, pv_mmu_ops.pmd_val, | 1287 | ret = PVOP_CALLEE1(pmdval_t, pv_mmu_ops.pmd_val, |
1193 | pmd.pmd); | 1288 | pmd.pmd); |
1194 | 1289 | ||
1195 | return ret; | 1290 | return ret; |
1196 | } | 1291 | } |
@@ -1212,11 +1307,11 @@ static inline pud_t __pud(pudval_t val) | |||
1212 | pudval_t ret; | 1307 | pudval_t ret; |
1213 | 1308 | ||
1214 | if (sizeof(pudval_t) > sizeof(long)) | 1309 | if (sizeof(pudval_t) > sizeof(long)) |
1215 | ret = PVOP_CALL2(pudval_t, pv_mmu_ops.make_pud, | 1310 | ret = PVOP_CALLEE2(pudval_t, pv_mmu_ops.make_pud, |
1216 | val, (u64)val >> 32); | 1311 | val, (u64)val >> 32); |
1217 | else | 1312 | else |
1218 | ret = PVOP_CALL1(pudval_t, pv_mmu_ops.make_pud, | 1313 | ret = PVOP_CALLEE1(pudval_t, pv_mmu_ops.make_pud, |
1219 | val); | 1314 | val); |
1220 | 1315 | ||
1221 | return (pud_t) { ret }; | 1316 | return (pud_t) { ret }; |
1222 | } | 1317 | } |
@@ -1226,11 +1321,11 @@ static inline pudval_t pud_val(pud_t pud) | |||
1226 | pudval_t ret; | 1321 | pudval_t ret; |
1227 | 1322 | ||
1228 | if (sizeof(pudval_t) > sizeof(long)) | 1323 | if (sizeof(pudval_t) > sizeof(long)) |
1229 | ret = PVOP_CALL2(pudval_t, pv_mmu_ops.pud_val, | 1324 | ret = PVOP_CALLEE2(pudval_t, pv_mmu_ops.pud_val, |
1230 | pud.pud, (u64)pud.pud >> 32); | 1325 | pud.pud, (u64)pud.pud >> 32); |
1231 | else | 1326 | else |
1232 | ret = PVOP_CALL1(pudval_t, pv_mmu_ops.pud_val, | 1327 | ret = PVOP_CALLEE1(pudval_t, pv_mmu_ops.pud_val, |
1233 | pud.pud); | 1328 | pud.pud); |
1234 | 1329 | ||
1235 | return ret; | 1330 | return ret; |
1236 | } | 1331 | } |
@@ -1371,6 +1466,9 @@ static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, | |||
1371 | } | 1466 | } |
1372 | 1467 | ||
1373 | void _paravirt_nop(void); | 1468 | void _paravirt_nop(void); |
1469 | u32 _paravirt_ident_32(u32); | ||
1470 | u64 _paravirt_ident_64(u64); | ||
1471 | |||
1374 | #define paravirt_nop ((void *)_paravirt_nop) | 1472 | #define paravirt_nop ((void *)_paravirt_nop) |
1375 | 1473 | ||
1376 | #ifdef CONFIG_SMP | 1474 | #ifdef CONFIG_SMP |
@@ -1420,12 +1518,37 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1420 | __parainstructions_end[]; | 1518 | __parainstructions_end[]; |
1421 | 1519 | ||
1422 | #ifdef CONFIG_X86_32 | 1520 | #ifdef CONFIG_X86_32 |
1423 | #define PV_SAVE_REGS "pushl %%ecx; pushl %%edx;" | 1521 | #define PV_SAVE_REGS "pushl %ecx; pushl %edx;" |
1424 | #define PV_RESTORE_REGS "popl %%edx; popl %%ecx" | 1522 | #define PV_RESTORE_REGS "popl %edx; popl %ecx;" |
1523 | |||
1524 | /* save and restore all caller-save registers, except return value */ | ||
1525 | #define PV_SAVE_ALL_CALLER_REGS "pushl %ecx;" | ||
1526 | #define PV_RESTORE_ALL_CALLER_REGS "popl %ecx;" | ||
1527 | |||
1425 | #define PV_FLAGS_ARG "0" | 1528 | #define PV_FLAGS_ARG "0" |
1426 | #define PV_EXTRA_CLOBBERS | 1529 | #define PV_EXTRA_CLOBBERS |
1427 | #define PV_VEXTRA_CLOBBERS | 1530 | #define PV_VEXTRA_CLOBBERS |
1428 | #else | 1531 | #else |
1532 | /* save and restore all caller-save registers, except return value */ | ||
1533 | #define PV_SAVE_ALL_CALLER_REGS \ | ||
1534 | "push %rcx;" \ | ||
1535 | "push %rdx;" \ | ||
1536 | "push %rsi;" \ | ||
1537 | "push %rdi;" \ | ||
1538 | "push %r8;" \ | ||
1539 | "push %r9;" \ | ||
1540 | "push %r10;" \ | ||
1541 | "push %r11;" | ||
1542 | #define PV_RESTORE_ALL_CALLER_REGS \ | ||
1543 | "pop %r11;" \ | ||
1544 | "pop %r10;" \ | ||
1545 | "pop %r9;" \ | ||
1546 | "pop %r8;" \ | ||
1547 | "pop %rdi;" \ | ||
1548 | "pop %rsi;" \ | ||
1549 | "pop %rdx;" \ | ||
1550 | "pop %rcx;" | ||
1551 | |||
1429 | /* We save some registers, but all of them, that's too much. We clobber all | 1552 | /* We save some registers, but all of them, that's too much. We clobber all |
1430 | * caller saved registers but the argument parameter */ | 1553 | * caller saved registers but the argument parameter */ |
1431 | #define PV_SAVE_REGS "pushq %%rdi;" | 1554 | #define PV_SAVE_REGS "pushq %%rdi;" |
@@ -1435,52 +1558,76 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1435 | #define PV_FLAGS_ARG "D" | 1558 | #define PV_FLAGS_ARG "D" |
1436 | #endif | 1559 | #endif |
1437 | 1560 | ||
1561 | /* | ||
1562 | * Generate a thunk around a function which saves all caller-save | ||
1563 | * registers except for the return value. This allows C functions to | ||
1564 | * be called from assembler code where fewer than normal registers are | ||
1565 | * available. It may also help code generation around calls from C | ||
1566 | * code if the common case doesn't use many registers. | ||
1567 | * | ||
1568 | * When a callee is wrapped in a thunk, the caller can assume that all | ||
1569 | * arg regs and all scratch registers are preserved across the | ||
1570 | * call. The return value in rax/eax will not be saved, even for void | ||
1571 | * functions. | ||
1572 | */ | ||
1573 | #define PV_CALLEE_SAVE_REGS_THUNK(func) \ | ||
1574 | extern typeof(func) __raw_callee_save_##func; \ | ||
1575 | static void *__##func##__ __used = func; \ | ||
1576 | \ | ||
1577 | asm(".pushsection .text;" \ | ||
1578 | "__raw_callee_save_" #func ": " \ | ||
1579 | PV_SAVE_ALL_CALLER_REGS \ | ||
1580 | "call " #func ";" \ | ||
1581 | PV_RESTORE_ALL_CALLER_REGS \ | ||
1582 | "ret;" \ | ||
1583 | ".popsection") | ||
1584 | |||
1585 | /* Get a reference to a callee-save function */ | ||
1586 | #define PV_CALLEE_SAVE(func) \ | ||
1587 | ((struct paravirt_callee_save) { __raw_callee_save_##func }) | ||
1588 | |||
1589 | /* Promise that "func" already uses the right calling convention */ | ||
1590 | #define __PV_IS_CALLEE_SAVE(func) \ | ||
1591 | ((struct paravirt_callee_save) { func }) | ||
1592 | |||
1438 | static inline unsigned long __raw_local_save_flags(void) | 1593 | static inline unsigned long __raw_local_save_flags(void) |
1439 | { | 1594 | { |
1440 | unsigned long f; | 1595 | unsigned long f; |
1441 | 1596 | ||
1442 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1597 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1443 | PARAVIRT_CALL | ||
1444 | PV_RESTORE_REGS) | ||
1445 | : "=a"(f) | 1598 | : "=a"(f) |
1446 | : paravirt_type(pv_irq_ops.save_fl), | 1599 | : paravirt_type(pv_irq_ops.save_fl), |
1447 | paravirt_clobber(CLBR_EAX) | 1600 | paravirt_clobber(CLBR_EAX) |
1448 | : "memory", "cc" PV_VEXTRA_CLOBBERS); | 1601 | : "memory", "cc"); |
1449 | return f; | 1602 | return f; |
1450 | } | 1603 | } |
1451 | 1604 | ||
1452 | static inline void raw_local_irq_restore(unsigned long f) | 1605 | static inline void raw_local_irq_restore(unsigned long f) |
1453 | { | 1606 | { |
1454 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1607 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1455 | PARAVIRT_CALL | ||
1456 | PV_RESTORE_REGS) | ||
1457 | : "=a"(f) | 1608 | : "=a"(f) |
1458 | : PV_FLAGS_ARG(f), | 1609 | : PV_FLAGS_ARG(f), |
1459 | paravirt_type(pv_irq_ops.restore_fl), | 1610 | paravirt_type(pv_irq_ops.restore_fl), |
1460 | paravirt_clobber(CLBR_EAX) | 1611 | paravirt_clobber(CLBR_EAX) |
1461 | : "memory", "cc" PV_EXTRA_CLOBBERS); | 1612 | : "memory", "cc"); |
1462 | } | 1613 | } |
1463 | 1614 | ||
1464 | static inline void raw_local_irq_disable(void) | 1615 | static inline void raw_local_irq_disable(void) |
1465 | { | 1616 | { |
1466 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1617 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1467 | PARAVIRT_CALL | ||
1468 | PV_RESTORE_REGS) | ||
1469 | : | 1618 | : |
1470 | : paravirt_type(pv_irq_ops.irq_disable), | 1619 | : paravirt_type(pv_irq_ops.irq_disable), |
1471 | paravirt_clobber(CLBR_EAX) | 1620 | paravirt_clobber(CLBR_EAX) |
1472 | : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); | 1621 | : "memory", "eax", "cc"); |
1473 | } | 1622 | } |
1474 | 1623 | ||
1475 | static inline void raw_local_irq_enable(void) | 1624 | static inline void raw_local_irq_enable(void) |
1476 | { | 1625 | { |
1477 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1626 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1478 | PARAVIRT_CALL | ||
1479 | PV_RESTORE_REGS) | ||
1480 | : | 1627 | : |
1481 | : paravirt_type(pv_irq_ops.irq_enable), | 1628 | : paravirt_type(pv_irq_ops.irq_enable), |
1482 | paravirt_clobber(CLBR_EAX) | 1629 | paravirt_clobber(CLBR_EAX) |
1483 | : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); | 1630 | : "memory", "eax", "cc"); |
1484 | } | 1631 | } |
1485 | 1632 | ||
1486 | static inline unsigned long __raw_local_irq_save(void) | 1633 | static inline unsigned long __raw_local_irq_save(void) |
@@ -1523,33 +1670,49 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1523 | .popsection | 1670 | .popsection |
1524 | 1671 | ||
1525 | 1672 | ||
1673 | #define COND_PUSH(set, mask, reg) \ | ||
1674 | .if ((~(set)) & mask); push %reg; .endif | ||
1675 | #define COND_POP(set, mask, reg) \ | ||
1676 | .if ((~(set)) & mask); pop %reg; .endif | ||
1677 | |||
1526 | #ifdef CONFIG_X86_64 | 1678 | #ifdef CONFIG_X86_64 |
1527 | #define PV_SAVE_REGS \ | 1679 | |
1528 | push %rax; \ | 1680 | #define PV_SAVE_REGS(set) \ |
1529 | push %rcx; \ | 1681 | COND_PUSH(set, CLBR_RAX, rax); \ |
1530 | push %rdx; \ | 1682 | COND_PUSH(set, CLBR_RCX, rcx); \ |
1531 | push %rsi; \ | 1683 | COND_PUSH(set, CLBR_RDX, rdx); \ |
1532 | push %rdi; \ | 1684 | COND_PUSH(set, CLBR_RSI, rsi); \ |
1533 | push %r8; \ | 1685 | COND_PUSH(set, CLBR_RDI, rdi); \ |
1534 | push %r9; \ | 1686 | COND_PUSH(set, CLBR_R8, r8); \ |
1535 | push %r10; \ | 1687 | COND_PUSH(set, CLBR_R9, r9); \ |
1536 | push %r11 | 1688 | COND_PUSH(set, CLBR_R10, r10); \ |
1537 | #define PV_RESTORE_REGS \ | 1689 | COND_PUSH(set, CLBR_R11, r11) |
1538 | pop %r11; \ | 1690 | #define PV_RESTORE_REGS(set) \ |
1539 | pop %r10; \ | 1691 | COND_POP(set, CLBR_R11, r11); \ |
1540 | pop %r9; \ | 1692 | COND_POP(set, CLBR_R10, r10); \ |
1541 | pop %r8; \ | 1693 | COND_POP(set, CLBR_R9, r9); \ |
1542 | pop %rdi; \ | 1694 | COND_POP(set, CLBR_R8, r8); \ |
1543 | pop %rsi; \ | 1695 | COND_POP(set, CLBR_RDI, rdi); \ |
1544 | pop %rdx; \ | 1696 | COND_POP(set, CLBR_RSI, rsi); \ |
1545 | pop %rcx; \ | 1697 | COND_POP(set, CLBR_RDX, rdx); \ |
1546 | pop %rax | 1698 | COND_POP(set, CLBR_RCX, rcx); \ |
1699 | COND_POP(set, CLBR_RAX, rax) | ||
1700 | |||
1547 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) | 1701 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8) |
1548 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) | 1702 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8) |
1549 | #define PARA_INDIRECT(addr) *addr(%rip) | 1703 | #define PARA_INDIRECT(addr) *addr(%rip) |
1550 | #else | 1704 | #else |
1551 | #define PV_SAVE_REGS pushl %eax; pushl %edi; pushl %ecx; pushl %edx | 1705 | #define PV_SAVE_REGS(set) \ |
1552 | #define PV_RESTORE_REGS popl %edx; popl %ecx; popl %edi; popl %eax | 1706 | COND_PUSH(set, CLBR_EAX, eax); \ |
1707 | COND_PUSH(set, CLBR_EDI, edi); \ | ||
1708 | COND_PUSH(set, CLBR_ECX, ecx); \ | ||
1709 | COND_PUSH(set, CLBR_EDX, edx) | ||
1710 | #define PV_RESTORE_REGS(set) \ | ||
1711 | COND_POP(set, CLBR_EDX, edx); \ | ||
1712 | COND_POP(set, CLBR_ECX, ecx); \ | ||
1713 | COND_POP(set, CLBR_EDI, edi); \ | ||
1714 | COND_POP(set, CLBR_EAX, eax) | ||
1715 | |||
1553 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) | 1716 | #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) |
1554 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) | 1717 | #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) |
1555 | #define PARA_INDIRECT(addr) *%cs:addr | 1718 | #define PARA_INDIRECT(addr) *%cs:addr |
@@ -1561,15 +1724,15 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1561 | 1724 | ||
1562 | #define DISABLE_INTERRUPTS(clobbers) \ | 1725 | #define DISABLE_INTERRUPTS(clobbers) \ |
1563 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ | 1726 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ |
1564 | PV_SAVE_REGS; \ | 1727 | PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
1565 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ | 1728 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ |
1566 | PV_RESTORE_REGS;) \ | 1729 | PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
1567 | 1730 | ||
1568 | #define ENABLE_INTERRUPTS(clobbers) \ | 1731 | #define ENABLE_INTERRUPTS(clobbers) \ |
1569 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ | 1732 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ |
1570 | PV_SAVE_REGS; \ | 1733 | PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
1571 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ | 1734 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ |
1572 | PV_RESTORE_REGS;) | 1735 | PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
1573 | 1736 | ||
1574 | #define USERGS_SYSRET32 \ | 1737 | #define USERGS_SYSRET32 \ |
1575 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ | 1738 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ |
@@ -1599,11 +1762,15 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1599 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ | 1762 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ |
1600 | swapgs) | 1763 | swapgs) |
1601 | 1764 | ||
1765 | /* | ||
1766 | * Note: swapgs is very special, and in practise is either going to be | ||
1767 | * implemented with a single "swapgs" instruction or something very | ||
1768 | * special. Either way, we don't need to save any registers for | ||
1769 | * it. | ||
1770 | */ | ||
1602 | #define SWAPGS \ | 1771 | #define SWAPGS \ |
1603 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ | 1772 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ |
1604 | PV_SAVE_REGS; \ | 1773 | call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \ |
1605 | call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs); \ | ||
1606 | PV_RESTORE_REGS \ | ||
1607 | ) | 1774 | ) |
1608 | 1775 | ||
1609 | #define GET_CR2_INTO_RCX \ | 1776 | #define GET_CR2_INTO_RCX \ |