Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 1 | /* |
| 2 | * x86-64 rwsem wrappers |
| 3 | * |
| 4 | * This interfaces the inline asm code to the slow-path |
| 5 | * C routines. We need to save the call-clobbered regs |
| 6 | * that the asm does not mark as clobbered, and move the |
| 7 | * argument from %rax to %rdi. |
| 8 | * |
| 9 | * NOTE! We don't need to save %rax, because the functions |
| 10 | * will always return the semaphore pointer in %rax (which |
| 11 | * is also the input argument to these helpers) |
| 12 | * |
| 13 | * The following can clobber %rdx because the asm clobbers it: |
| 14 | * call_rwsem_down_write_failed |
| 15 | * call_rwsem_wake |
| 16 | * but %rdi, %rsi, %rcx, %r8-r11 always need saving. |
| 17 | */ |
| 18 | |
| 19 | #include <linux/linkage.h> |
| 20 | #include <asm/rwlock.h> |
| 21 | #include <asm/alternative-asm.h> |
| 22 | #include <asm/frame.h> |
| 23 | #include <asm/dwarf2.h> |
| 24 | |
| 25 | #define save_common_regs \ |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 26 | pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \ |
| 27 | pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \ |
| 28 | pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \ |
| 29 | pushq_cfi %r8; CFI_REL_OFFSET r8, 0; \ |
| 30 | pushq_cfi %r9; CFI_REL_OFFSET r9, 0; \ |
| 31 | pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \ |
| 32 | pushq_cfi %r11; CFI_REL_OFFSET r11, 0 |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 33 | |
| 34 | #define restore_common_regs \ |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 35 | popq_cfi %r11; CFI_RESTORE r11; \ |
| 36 | popq_cfi %r10; CFI_RESTORE r10; \ |
| 37 | popq_cfi %r9; CFI_RESTORE r9; \ |
| 38 | popq_cfi %r8; CFI_RESTORE r8; \ |
| 39 | popq_cfi %rcx; CFI_RESTORE rcx; \ |
| 40 | popq_cfi %rsi; CFI_RESTORE rsi; \ |
| 41 | popq_cfi %rdi; CFI_RESTORE rdi |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 42 | |
| 43 | /* Fix up special calling conventions */ |
| 44 | ENTRY(call_rwsem_down_read_failed) |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 45 | CFI_STARTPROC |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 46 | save_common_regs |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 47 | pushq_cfi %rdx |
| 48 | CFI_REL_OFFSET rdx, 0 |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 49 | movq %rax,%rdi |
| 50 | call rwsem_down_read_failed |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 51 | popq_cfi %rdx |
| 52 | CFI_RESTORE rdx |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 53 | restore_common_regs |
| 54 | ret |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 55 | CFI_ENDPROC |
| 56 | ENDPROC(call_rwsem_down_read_failed) |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 57 | |
| 58 | ENTRY(call_rwsem_down_write_failed) |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 59 | CFI_STARTPROC |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 60 | save_common_regs |
| 61 | movq %rax,%rdi |
| 62 | call rwsem_down_write_failed |
| 63 | restore_common_regs |
| 64 | ret |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 65 | CFI_ENDPROC |
| 66 | ENDPROC(call_rwsem_down_write_failed) |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 67 | |
| 68 | ENTRY(call_rwsem_wake) |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 69 | CFI_STARTPROC |
David Howells | a66f637 | 2010-05-04 13:42:53 +0100 | [diff] [blame] | 70 | decl %edx /* do nothing if still outstanding active readers */ |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 71 | jnz 1f |
| 72 | save_common_regs |
| 73 | movq %rax,%rdi |
| 74 | call rwsem_wake |
| 75 | restore_common_regs |
| 76 | 1: ret |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 77 | CFI_ENDPROC |
| 78 | ENDPROC(call_rwsem_wake) |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 79 | |
| 80 | /* Fix up special calling conventions */ |
| 81 | ENTRY(call_rwsem_downgrade_wake) |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 82 | CFI_STARTPROC |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 83 | save_common_regs |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 84 | pushq_cfi %rdx |
| 85 | CFI_REL_OFFSET rdx, 0 |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 86 | movq %rax,%rdi |
| 87 | call rwsem_downgrade_wake |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 88 | popq_cfi %rdx |
| 89 | CFI_RESTORE rdx |
Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 90 | restore_common_regs |
| 91 | ret |
Jan Beulich | 39f2205 | 2011-02-28 15:31:59 +0000 | [diff] [blame] | 92 | CFI_ENDPROC |
| 93 | ENDPROC(call_rwsem_downgrade_wake) |