| 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 \ | 
|  | 26 | pushq %rdi; \ | 
|  | 27 | pushq %rsi; \ | 
|  | 28 | pushq %rcx; \ | 
|  | 29 | pushq %r8; \ | 
|  | 30 | pushq %r9; \ | 
|  | 31 | pushq %r10; \ | 
|  | 32 | pushq %r11 | 
|  | 33 |  | 
|  | 34 | #define restore_common_regs \ | 
|  | 35 | popq %r11; \ | 
|  | 36 | popq %r10; \ | 
|  | 37 | popq %r9; \ | 
|  | 38 | popq %r8; \ | 
|  | 39 | popq %rcx; \ | 
|  | 40 | popq %rsi; \ | 
|  | 41 | popq %rdi | 
|  | 42 |  | 
|  | 43 | /* Fix up special calling conventions */ | 
|  | 44 | ENTRY(call_rwsem_down_read_failed) | 
|  | 45 | save_common_regs | 
|  | 46 | pushq %rdx | 
|  | 47 | movq %rax,%rdi | 
|  | 48 | call rwsem_down_read_failed | 
|  | 49 | popq %rdx | 
|  | 50 | restore_common_regs | 
|  | 51 | ret | 
|  | 52 | ENDPROC(call_rwsem_down_read_failed) | 
|  | 53 |  | 
|  | 54 | ENTRY(call_rwsem_down_write_failed) | 
|  | 55 | save_common_regs | 
|  | 56 | movq %rax,%rdi | 
|  | 57 | call rwsem_down_write_failed | 
|  | 58 | restore_common_regs | 
|  | 59 | ret | 
|  | 60 | ENDPROC(call_rwsem_down_write_failed) | 
|  | 61 |  | 
|  | 62 | ENTRY(call_rwsem_wake) | 
| David Howells | a66f637 | 2010-05-04 13:42:53 +0100 | [diff] [blame] | 63 | decl %edx	/* do nothing if still outstanding active readers */ | 
| Linus Torvalds | bafaecd | 2010-01-12 18:16:42 -0800 | [diff] [blame] | 64 | jnz 1f | 
|  | 65 | save_common_regs | 
|  | 66 | movq %rax,%rdi | 
|  | 67 | call rwsem_wake | 
|  | 68 | restore_common_regs | 
|  | 69 | 1:	ret | 
|  | 70 | ENDPROC(call_rwsem_wake) | 
|  | 71 |  | 
|  | 72 | /* Fix up special calling conventions */ | 
|  | 73 | ENTRY(call_rwsem_downgrade_wake) | 
|  | 74 | save_common_regs | 
|  | 75 | pushq %rdx | 
|  | 76 | movq %rax,%rdi | 
|  | 77 | call rwsem_downgrade_wake | 
|  | 78 | popq %rdx | 
|  | 79 | restore_common_regs | 
|  | 80 | ret | 
|  | 81 | ENDPROC(call_rwsem_downgrade_wake) |