diff options
-rw-r--r-- | arch/x86/include/asm/paravirt.h | 126 | ||||
-rw-r--r-- | arch/x86/kernel/paravirt.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/vsmp_64.c | 12 | ||||
-rw-r--r-- | arch/x86/lguest/boot.c | 13 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 8 | ||||
-rw-r--r-- | arch/x86/xen/irq.c | 14 |
6 files changed, 132 insertions, 49 deletions
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index dcce961262bf..f9107b88631b 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
@@ -17,6 +17,10 @@ | |||
17 | #ifdef CONFIG_X86_32 | 17 | #ifdef CONFIG_X86_32 |
18 | /* CLBR_ANY should match all regs platform has. For i386, that's just it */ | 18 | /* CLBR_ANY should match all regs platform has. For i386, that's just it */ |
19 | #define CLBR_ANY ((1 << 4) - 1) | 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) | ||
23 | #define CLBR_SCRATCH (0) | ||
20 | #else | 24 | #else |
21 | #define CLBR_RAX CLBR_EAX | 25 | #define CLBR_RAX CLBR_EAX |
22 | #define CLBR_RCX CLBR_ECX | 26 | #define CLBR_RCX CLBR_ECX |
@@ -27,16 +31,19 @@ | |||
27 | #define CLBR_R9 (1 << 6) | 31 | #define CLBR_R9 (1 << 6) |
28 | #define CLBR_R10 (1 << 7) | 32 | #define CLBR_R10 (1 << 7) |
29 | #define CLBR_R11 (1 << 8) | 33 | #define CLBR_R11 (1 << 8) |
34 | |||
30 | #define CLBR_ANY ((1 << 9) - 1) | 35 | #define CLBR_ANY ((1 << 9) - 1) |
31 | 36 | ||
32 | #define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ | 37 | #define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ |
33 | CLBR_RCX | CLBR_R8 | CLBR_R9) | 38 | CLBR_RCX | CLBR_R8 | CLBR_R9) |
34 | #define CLBR_RET_REG (CLBR_RAX | CLBR_RDX) | 39 | #define CLBR_RET_REG (CLBR_RAX) |
35 | #define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) | 40 | #define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) |
36 | 41 | ||
37 | #include <asm/desc_defs.h> | 42 | #include <asm/desc_defs.h> |
38 | #endif /* X86_64 */ | 43 | #endif /* X86_64 */ |
39 | 44 | ||
45 | #define CLBR_CALLEE_SAVE ((CLBR_ARG_REGS | CLBR_SCRATCH) & ~CLBR_RET_REG) | ||
46 | |||
40 | #ifndef __ASSEMBLY__ | 47 | #ifndef __ASSEMBLY__ |
41 | #include <linux/types.h> | 48 | #include <linux/types.h> |
42 | #include <linux/cpumask.h> | 49 | #include <linux/cpumask.h> |
@@ -50,6 +57,14 @@ struct tss_struct; | |||
50 | struct mm_struct; | 57 | struct mm_struct; |
51 | struct desc_struct; | 58 | struct desc_struct; |
52 | 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 | |||
53 | /* general info */ | 68 | /* general info */ |
54 | struct pv_info { | 69 | struct pv_info { |
55 | unsigned int kernel_rpl; | 70 | unsigned int kernel_rpl; |
@@ -199,11 +214,15 @@ struct pv_irq_ops { | |||
199 | * expected to use X86_EFLAGS_IF; all other bits | 214 | * expected to use X86_EFLAGS_IF; all other bits |
200 | * returned from save_fl are undefined, and may be ignored by | 215 | * returned from save_fl are undefined, and may be ignored by |
201 | * 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. | ||
202 | */ | 220 | */ |
203 | unsigned long (*save_fl)(void); | 221 | struct paravirt_callee_save save_fl; |
204 | void (*restore_fl)(unsigned long); | 222 | struct paravirt_callee_save restore_fl; |
205 | void (*irq_disable)(void); | 223 | struct paravirt_callee_save irq_disable; |
206 | void (*irq_enable)(void); | 224 | struct paravirt_callee_save irq_enable; |
225 | |||
207 | void (*safe_halt)(void); | 226 | void (*safe_halt)(void); |
208 | void (*halt)(void); | 227 | void (*halt)(void); |
209 | 228 | ||
@@ -1437,12 +1456,37 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1437 | __parainstructions_end[]; | 1456 | __parainstructions_end[]; |
1438 | 1457 | ||
1439 | #ifdef CONFIG_X86_32 | 1458 | #ifdef CONFIG_X86_32 |
1440 | #define PV_SAVE_REGS "pushl %%ecx; pushl %%edx;" | 1459 | #define PV_SAVE_REGS "pushl %ecx; pushl %edx;" |
1441 | #define PV_RESTORE_REGS "popl %%edx; popl %%ecx" | 1460 | #define PV_RESTORE_REGS "popl %edx; popl %ecx;" |
1461 | |||
1462 | /* save and restore all caller-save registers, except return value */ | ||
1463 | #define PV_SAVE_ALL_CALLER_REGS PV_SAVE_REGS | ||
1464 | #define PV_RESTORE_ALL_CALLER_REGS PV_RESTORE_REGS | ||
1465 | |||
1442 | #define PV_FLAGS_ARG "0" | 1466 | #define PV_FLAGS_ARG "0" |
1443 | #define PV_EXTRA_CLOBBERS | 1467 | #define PV_EXTRA_CLOBBERS |
1444 | #define PV_VEXTRA_CLOBBERS | 1468 | #define PV_VEXTRA_CLOBBERS |
1445 | #else | 1469 | #else |
1470 | /* save and restore all caller-save registers, except return value */ | ||
1471 | #define PV_SAVE_ALL_CALLER_REGS \ | ||
1472 | "push %rcx;" \ | ||
1473 | "push %rdx;" \ | ||
1474 | "push %rsi;" \ | ||
1475 | "push %rdi;" \ | ||
1476 | "push %r8;" \ | ||
1477 | "push %r9;" \ | ||
1478 | "push %r10;" \ | ||
1479 | "push %r11;" | ||
1480 | #define PV_RESTORE_ALL_CALLER_REGS \ | ||
1481 | "pop %r11;" \ | ||
1482 | "pop %r10;" \ | ||
1483 | "pop %r9;" \ | ||
1484 | "pop %r8;" \ | ||
1485 | "pop %rdi;" \ | ||
1486 | "pop %rsi;" \ | ||
1487 | "pop %rdx;" \ | ||
1488 | "pop %rcx;" | ||
1489 | |||
1446 | /* We save some registers, but all of them, that's too much. We clobber all | 1490 | /* We save some registers, but all of them, that's too much. We clobber all |
1447 | * caller saved registers but the argument parameter */ | 1491 | * caller saved registers but the argument parameter */ |
1448 | #define PV_SAVE_REGS "pushq %%rdi;" | 1492 | #define PV_SAVE_REGS "pushq %%rdi;" |
@@ -1452,52 +1496,76 @@ extern struct paravirt_patch_site __parainstructions[], | |||
1452 | #define PV_FLAGS_ARG "D" | 1496 | #define PV_FLAGS_ARG "D" |
1453 | #endif | 1497 | #endif |
1454 | 1498 | ||
1499 | /* | ||
1500 | * Generate a thunk around a function which saves all caller-save | ||
1501 | * registers except for the return value. This allows C functions to | ||
1502 | * be called from assembler code where fewer than normal registers are | ||
1503 | * available. It may also help code generation around calls from C | ||
1504 | * code if the common case doesn't use many registers. | ||
1505 | * | ||
1506 | * When a callee is wrapped in a thunk, the caller can assume that all | ||
1507 | * arg regs and all scratch registers are preserved across the | ||
1508 | * call. The return value in rax/eax will not be saved, even for void | ||
1509 | * functions. | ||
1510 | */ | ||
1511 | #define PV_CALLEE_SAVE_REGS_THUNK(func) \ | ||
1512 | extern typeof(func) __raw_callee_save_##func; \ | ||
1513 | static void *__##func##__ __used = func; \ | ||
1514 | \ | ||
1515 | asm(".pushsection .text;" \ | ||
1516 | "__raw_callee_save_" #func ": " \ | ||
1517 | PV_SAVE_ALL_CALLER_REGS \ | ||
1518 | "call " #func ";" \ | ||
1519 | PV_RESTORE_ALL_CALLER_REGS \ | ||
1520 | "ret;" \ | ||
1521 | ".popsection") | ||
1522 | |||
1523 | /* Get a reference to a callee-save function */ | ||
1524 | #define PV_CALLEE_SAVE(func) \ | ||
1525 | ((struct paravirt_callee_save) { __raw_callee_save_##func }) | ||
1526 | |||
1527 | /* Promise that "func" already uses the right calling convention */ | ||
1528 | #define __PV_IS_CALLEE_SAVE(func) \ | ||
1529 | ((struct paravirt_callee_save) { func }) | ||
1530 | |||
1455 | static inline unsigned long __raw_local_save_flags(void) | 1531 | static inline unsigned long __raw_local_save_flags(void) |
1456 | { | 1532 | { |
1457 | unsigned long f; | 1533 | unsigned long f; |
1458 | 1534 | ||
1459 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1535 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1460 | PARAVIRT_CALL | ||
1461 | PV_RESTORE_REGS) | ||
1462 | : "=a"(f) | 1536 | : "=a"(f) |
1463 | : paravirt_type(pv_irq_ops.save_fl), | 1537 | : paravirt_type(pv_irq_ops.save_fl), |
1464 | paravirt_clobber(CLBR_EAX) | 1538 | paravirt_clobber(CLBR_EAX) |
1465 | : "memory", "cc" PV_VEXTRA_CLOBBERS); | 1539 | : "memory", "cc"); |
1466 | return f; | 1540 | return f; |
1467 | } | 1541 | } |
1468 | 1542 | ||
1469 | static inline void raw_local_irq_restore(unsigned long f) | 1543 | static inline void raw_local_irq_restore(unsigned long f) |
1470 | { | 1544 | { |
1471 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1545 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1472 | PARAVIRT_CALL | ||
1473 | PV_RESTORE_REGS) | ||
1474 | : "=a"(f) | 1546 | : "=a"(f) |
1475 | : PV_FLAGS_ARG(f), | 1547 | : PV_FLAGS_ARG(f), |
1476 | paravirt_type(pv_irq_ops.restore_fl), | 1548 | paravirt_type(pv_irq_ops.restore_fl), |
1477 | paravirt_clobber(CLBR_EAX) | 1549 | paravirt_clobber(CLBR_EAX) |
1478 | : "memory", "cc" PV_EXTRA_CLOBBERS); | 1550 | : "memory", "cc"); |
1479 | } | 1551 | } |
1480 | 1552 | ||
1481 | static inline void raw_local_irq_disable(void) | 1553 | static inline void raw_local_irq_disable(void) |
1482 | { | 1554 | { |
1483 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1555 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1484 | PARAVIRT_CALL | ||
1485 | PV_RESTORE_REGS) | ||
1486 | : | 1556 | : |
1487 | : paravirt_type(pv_irq_ops.irq_disable), | 1557 | : paravirt_type(pv_irq_ops.irq_disable), |
1488 | paravirt_clobber(CLBR_EAX) | 1558 | paravirt_clobber(CLBR_EAX) |
1489 | : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); | 1559 | : "memory", "eax", "cc"); |
1490 | } | 1560 | } |
1491 | 1561 | ||
1492 | static inline void raw_local_irq_enable(void) | 1562 | static inline void raw_local_irq_enable(void) |
1493 | { | 1563 | { |
1494 | asm volatile(paravirt_alt(PV_SAVE_REGS | 1564 | asm volatile(paravirt_alt(PARAVIRT_CALL) |
1495 | PARAVIRT_CALL | ||
1496 | PV_RESTORE_REGS) | ||
1497 | : | 1565 | : |
1498 | : paravirt_type(pv_irq_ops.irq_enable), | 1566 | : paravirt_type(pv_irq_ops.irq_enable), |
1499 | paravirt_clobber(CLBR_EAX) | 1567 | paravirt_clobber(CLBR_EAX) |
1500 | : "memory", "eax", "cc" PV_EXTRA_CLOBBERS); | 1568 | : "memory", "eax", "cc"); |
1501 | } | 1569 | } |
1502 | 1570 | ||
1503 | static inline unsigned long __raw_local_irq_save(void) | 1571 | static inline unsigned long __raw_local_irq_save(void) |
@@ -1541,9 +1609,9 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1541 | 1609 | ||
1542 | 1610 | ||
1543 | #define COND_PUSH(set, mask, reg) \ | 1611 | #define COND_PUSH(set, mask, reg) \ |
1544 | .if ((~set) & mask); push %reg; .endif | 1612 | .if ((~(set)) & mask); push %reg; .endif |
1545 | #define COND_POP(set, mask, reg) \ | 1613 | #define COND_POP(set, mask, reg) \ |
1546 | .if ((~set) & mask); pop %reg; .endif | 1614 | .if ((~(set)) & mask); pop %reg; .endif |
1547 | 1615 | ||
1548 | #ifdef CONFIG_X86_64 | 1616 | #ifdef CONFIG_X86_64 |
1549 | 1617 | ||
@@ -1594,15 +1662,15 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1594 | 1662 | ||
1595 | #define DISABLE_INTERRUPTS(clobbers) \ | 1663 | #define DISABLE_INTERRUPTS(clobbers) \ |
1596 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ | 1664 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ |
1597 | PV_SAVE_REGS(clobbers); \ | 1665 | PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
1598 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ | 1666 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ |
1599 | PV_RESTORE_REGS(clobbers);) | 1667 | PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
1600 | 1668 | ||
1601 | #define ENABLE_INTERRUPTS(clobbers) \ | 1669 | #define ENABLE_INTERRUPTS(clobbers) \ |
1602 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ | 1670 | PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ |
1603 | PV_SAVE_REGS(clobbers); \ | 1671 | PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
1604 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ | 1672 | call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ |
1605 | PV_RESTORE_REGS(clobbers);) | 1673 | PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
1606 | 1674 | ||
1607 | #define USERGS_SYSRET32 \ | 1675 | #define USERGS_SYSRET32 \ |
1608 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ | 1676 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32), \ |
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index dd25e2b1593b..8adb6b5aa421 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c | |||
@@ -310,10 +310,10 @@ struct pv_time_ops pv_time_ops = { | |||
310 | 310 | ||
311 | struct pv_irq_ops pv_irq_ops = { | 311 | struct pv_irq_ops pv_irq_ops = { |
312 | .init_IRQ = native_init_IRQ, | 312 | .init_IRQ = native_init_IRQ, |
313 | .save_fl = native_save_fl, | 313 | .save_fl = __PV_IS_CALLEE_SAVE(native_save_fl), |
314 | .restore_fl = native_restore_fl, | 314 | .restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl), |
315 | .irq_disable = native_irq_disable, | 315 | .irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable), |
316 | .irq_enable = native_irq_enable, | 316 | .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable), |
317 | .safe_halt = native_safe_halt, | 317 | .safe_halt = native_safe_halt, |
318 | .halt = native_halt, | 318 | .halt = native_halt, |
319 | #ifdef CONFIG_X86_64 | 319 | #ifdef CONFIG_X86_64 |
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index a688f3bfaec2..c609205df594 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c | |||
@@ -37,6 +37,7 @@ static unsigned long vsmp_save_fl(void) | |||
37 | flags &= ~X86_EFLAGS_IF; | 37 | flags &= ~X86_EFLAGS_IF; |
38 | return flags; | 38 | return flags; |
39 | } | 39 | } |
40 | PV_CALLEE_SAVE_REGS_THUNK(vsmp_save_fl); | ||
40 | 41 | ||
41 | static void vsmp_restore_fl(unsigned long flags) | 42 | static void vsmp_restore_fl(unsigned long flags) |
42 | { | 43 | { |
@@ -46,6 +47,7 @@ static void vsmp_restore_fl(unsigned long flags) | |||
46 | flags |= X86_EFLAGS_AC; | 47 | flags |= X86_EFLAGS_AC; |
47 | native_restore_fl(flags); | 48 | native_restore_fl(flags); |
48 | } | 49 | } |
50 | PV_CALLEE_SAVE_REGS_THUNK(vsmp_restore_fl); | ||
49 | 51 | ||
50 | static void vsmp_irq_disable(void) | 52 | static void vsmp_irq_disable(void) |
51 | { | 53 | { |
@@ -53,6 +55,7 @@ static void vsmp_irq_disable(void) | |||
53 | 55 | ||
54 | native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC); | 56 | native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC); |
55 | } | 57 | } |
58 | PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_disable); | ||
56 | 59 | ||
57 | static void vsmp_irq_enable(void) | 60 | static void vsmp_irq_enable(void) |
58 | { | 61 | { |
@@ -60,6 +63,7 @@ static void vsmp_irq_enable(void) | |||
60 | 63 | ||
61 | native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC)); | 64 | native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC)); |
62 | } | 65 | } |
66 | PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_enable); | ||
63 | 67 | ||
64 | static unsigned __init_or_module vsmp_patch(u8 type, u16 clobbers, void *ibuf, | 68 | static unsigned __init_or_module vsmp_patch(u8 type, u16 clobbers, void *ibuf, |
65 | unsigned long addr, unsigned len) | 69 | unsigned long addr, unsigned len) |
@@ -90,10 +94,10 @@ static void __init set_vsmp_pv_ops(void) | |||
90 | cap, ctl); | 94 | cap, ctl); |
91 | if (cap & ctl & (1 << 4)) { | 95 | if (cap & ctl & (1 << 4)) { |
92 | /* Setup irq ops and turn on vSMP IRQ fastpath handling */ | 96 | /* Setup irq ops and turn on vSMP IRQ fastpath handling */ |
93 | pv_irq_ops.irq_disable = vsmp_irq_disable; | 97 | pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable); |
94 | pv_irq_ops.irq_enable = vsmp_irq_enable; | 98 | pv_irq_ops.irq_enable = PV_CALLEE_SAVE(vsmp_irq_enable); |
95 | pv_irq_ops.save_fl = vsmp_save_fl; | 99 | pv_irq_ops.save_fl = PV_CALLEE_SAVE(vsmp_save_fl); |
96 | pv_irq_ops.restore_fl = vsmp_restore_fl; | 100 | pv_irq_ops.restore_fl = PV_CALLEE_SAVE(vsmp_restore_fl); |
97 | pv_init_ops.patch = vsmp_patch; | 101 | pv_init_ops.patch = vsmp_patch; |
98 | 102 | ||
99 | ctl &= ~(1 << 4); | 103 | ctl &= ~(1 << 4); |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 92f1c6f3e19d..19e33b6cd593 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -173,24 +173,29 @@ static unsigned long save_fl(void) | |||
173 | { | 173 | { |
174 | return lguest_data.irq_enabled; | 174 | return lguest_data.irq_enabled; |
175 | } | 175 | } |
176 | PV_CALLEE_SAVE_REGS_THUNK(save_fl); | ||
176 | 177 | ||
177 | /* restore_flags() just sets the flags back to the value given. */ | 178 | /* restore_flags() just sets the flags back to the value given. */ |
178 | static void restore_fl(unsigned long flags) | 179 | static void restore_fl(unsigned long flags) |
179 | { | 180 | { |
180 | lguest_data.irq_enabled = flags; | 181 | lguest_data.irq_enabled = flags; |
181 | } | 182 | } |
183 | PV_CALLEE_SAVE_REGS_THUNK(restore_fl); | ||
182 | 184 | ||
183 | /* Interrupts go off... */ | 185 | /* Interrupts go off... */ |
184 | static void irq_disable(void) | 186 | static void irq_disable(void) |
185 | { | 187 | { |
186 | lguest_data.irq_enabled = 0; | 188 | lguest_data.irq_enabled = 0; |
187 | } | 189 | } |
190 | PV_CALLEE_SAVE_REGS_THUNK(irq_disable); | ||
188 | 191 | ||
189 | /* Interrupts go on... */ | 192 | /* Interrupts go on... */ |
190 | static void irq_enable(void) | 193 | static void irq_enable(void) |
191 | { | 194 | { |
192 | lguest_data.irq_enabled = X86_EFLAGS_IF; | 195 | lguest_data.irq_enabled = X86_EFLAGS_IF; |
193 | } | 196 | } |
197 | PV_CALLEE_SAVE_REGS_THUNK(irq_enable); | ||
198 | |||
194 | /*:*/ | 199 | /*:*/ |
195 | /*M:003 Note that we don't check for outstanding interrupts when we re-enable | 200 | /*M:003 Note that we don't check for outstanding interrupts when we re-enable |
196 | * them (or when we unmask an interrupt). This seems to work for the moment, | 201 | * them (or when we unmask an interrupt). This seems to work for the moment, |
@@ -984,10 +989,10 @@ __init void lguest_init(void) | |||
984 | 989 | ||
985 | /* interrupt-related operations */ | 990 | /* interrupt-related operations */ |
986 | pv_irq_ops.init_IRQ = lguest_init_IRQ; | 991 | pv_irq_ops.init_IRQ = lguest_init_IRQ; |
987 | pv_irq_ops.save_fl = save_fl; | 992 | pv_irq_ops.save_fl = PV_CALLEE_SAVE(save_fl); |
988 | pv_irq_ops.restore_fl = restore_fl; | 993 | pv_irq_ops.restore_fl = PV_CALLEE_SAVE(restore_fl); |
989 | pv_irq_ops.irq_disable = irq_disable; | 994 | pv_irq_ops.irq_disable = PV_CALLEE_SAVE(irq_disable); |
990 | pv_irq_ops.irq_enable = irq_enable; | 995 | pv_irq_ops.irq_enable = PV_CALLEE_SAVE(irq_enable); |
991 | pv_irq_ops.safe_halt = lguest_safe_halt; | 996 | pv_irq_ops.safe_halt = lguest_safe_halt; |
992 | 997 | ||
993 | /* init-time operations */ | 998 | /* init-time operations */ |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0cd2a165f179..ff6d530ccc77 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -676,10 +676,10 @@ void xen_setup_vcpu_info_placement(void) | |||
676 | if (have_vcpu_info_placement) { | 676 | if (have_vcpu_info_placement) { |
677 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); | 677 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); |
678 | 678 | ||
679 | pv_irq_ops.save_fl = xen_save_fl_direct; | 679 | pv_irq_ops.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct); |
680 | pv_irq_ops.restore_fl = xen_restore_fl_direct; | 680 | pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(xen_restore_fl_direct); |
681 | pv_irq_ops.irq_disable = xen_irq_disable_direct; | 681 | pv_irq_ops.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct); |
682 | pv_irq_ops.irq_enable = xen_irq_enable_direct; | 682 | pv_irq_ops.irq_enable = __PV_IS_CALLEE_SAVE(xen_irq_enable_direct); |
683 | pv_mmu_ops.read_cr2 = xen_read_cr2_direct; | 683 | pv_mmu_ops.read_cr2 = xen_read_cr2_direct; |
684 | } | 684 | } |
685 | } | 685 | } |
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 2e8271431e1a..5a070900ad35 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c | |||
@@ -50,6 +50,7 @@ static unsigned long xen_save_fl(void) | |||
50 | */ | 50 | */ |
51 | return (-flags) & X86_EFLAGS_IF; | 51 | return (-flags) & X86_EFLAGS_IF; |
52 | } | 52 | } |
53 | PV_CALLEE_SAVE_REGS_THUNK(xen_save_fl); | ||
53 | 54 | ||
54 | static void xen_restore_fl(unsigned long flags) | 55 | static void xen_restore_fl(unsigned long flags) |
55 | { | 56 | { |
@@ -76,6 +77,7 @@ static void xen_restore_fl(unsigned long flags) | |||
76 | xen_force_evtchn_callback(); | 77 | xen_force_evtchn_callback(); |
77 | } | 78 | } |
78 | } | 79 | } |
80 | PV_CALLEE_SAVE_REGS_THUNK(xen_restore_fl); | ||
79 | 81 | ||
80 | static void xen_irq_disable(void) | 82 | static void xen_irq_disable(void) |
81 | { | 83 | { |
@@ -86,6 +88,7 @@ static void xen_irq_disable(void) | |||
86 | percpu_read(xen_vcpu)->evtchn_upcall_mask = 1; | 88 | percpu_read(xen_vcpu)->evtchn_upcall_mask = 1; |
87 | preempt_enable_no_resched(); | 89 | preempt_enable_no_resched(); |
88 | } | 90 | } |
91 | PV_CALLEE_SAVE_REGS_THUNK(xen_irq_disable); | ||
89 | 92 | ||
90 | static void xen_irq_enable(void) | 93 | static void xen_irq_enable(void) |
91 | { | 94 | { |
@@ -106,6 +109,7 @@ static void xen_irq_enable(void) | |||
106 | if (unlikely(vcpu->evtchn_upcall_pending)) | 109 | if (unlikely(vcpu->evtchn_upcall_pending)) |
107 | xen_force_evtchn_callback(); | 110 | xen_force_evtchn_callback(); |
108 | } | 111 | } |
112 | PV_CALLEE_SAVE_REGS_THUNK(xen_irq_enable); | ||
109 | 113 | ||
110 | static void xen_safe_halt(void) | 114 | static void xen_safe_halt(void) |
111 | { | 115 | { |
@@ -124,10 +128,12 @@ static void xen_halt(void) | |||
124 | 128 | ||
125 | static const struct pv_irq_ops xen_irq_ops __initdata = { | 129 | static const struct pv_irq_ops xen_irq_ops __initdata = { |
126 | .init_IRQ = __xen_init_IRQ, | 130 | .init_IRQ = __xen_init_IRQ, |
127 | .save_fl = xen_save_fl, | 131 | |
128 | .restore_fl = xen_restore_fl, | 132 | .save_fl = PV_CALLEE_SAVE(xen_save_fl), |
129 | .irq_disable = xen_irq_disable, | 133 | .restore_fl = PV_CALLEE_SAVE(xen_restore_fl), |
130 | .irq_enable = xen_irq_enable, | 134 | .irq_disable = PV_CALLEE_SAVE(xen_irq_disable), |
135 | .irq_enable = PV_CALLEE_SAVE(xen_irq_enable), | ||
136 | |||
131 | .safe_halt = xen_safe_halt, | 137 | .safe_halt = xen_safe_halt, |
132 | .halt = xen_halt, | 138 | .halt = xen_halt, |
133 | #ifdef CONFIG_X86_64 | 139 | #ifdef CONFIG_X86_64 |