Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
Peter Zijlstra (Intel) | f233f7f | 2015-04-24 14:56:38 -0400 | [diff] [blame] | 2 | #ifndef __ASM_QSPINLOCK_PARAVIRT_H |
| 3 | #define __ASM_QSPINLOCK_PARAVIRT_H |
| 4 | |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 5 | /* |
| 6 | * For x86-64, PV_CALLEE_SAVE_REGS_THUNK() saves and restores 8 64-bit |
| 7 | * registers. For i386, however, only 1 32-bit register needs to be saved |
| 8 | * and restored. So an optimized version of __pv_queued_spin_unlock() is |
| 9 | * hand-coded for 64-bit, but it isn't worthwhile to do it for 32-bit. |
| 10 | */ |
| 11 | #ifdef CONFIG_64BIT |
| 12 | |
| 13 | PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath); |
| 14 | #define __pv_queued_spin_unlock __pv_queued_spin_unlock |
| 15 | #define PV_UNLOCK "__raw_callee_save___pv_queued_spin_unlock" |
| 16 | #define PV_UNLOCK_SLOWPATH "__raw_callee_save___pv_queued_spin_unlock_slowpath" |
| 17 | |
| 18 | /* |
| 19 | * Optimized assembly version of __raw_callee_save___pv_queued_spin_unlock |
| 20 | * which combines the registers saving trunk and the body of the following |
| 21 | * C code: |
| 22 | * |
| 23 | * void __pv_queued_spin_unlock(struct qspinlock *lock) |
| 24 | * { |
Will Deacon | 625e88b | 2018-04-26 11:34:16 +0100 | [diff] [blame] | 25 | * u8 lockval = cmpxchg(&lock->locked, _Q_LOCKED_VAL, 0); |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 26 | * |
| 27 | * if (likely(lockval == _Q_LOCKED_VAL)) |
| 28 | * return; |
| 29 | * pv_queued_spin_unlock_slowpath(lock, lockval); |
| 30 | * } |
| 31 | * |
| 32 | * For x86-64, |
| 33 | * rdi = lock (first argument) |
| 34 | * rsi = lockval (second argument) |
| 35 | * rdx = internal variable (set to 0) |
| 36 | */ |
| 37 | asm (".pushsection .text;" |
| 38 | ".globl " PV_UNLOCK ";" |
Josh Poimboeuf | 16df4ff | 2016-01-21 16:49:32 -0600 | [diff] [blame] | 39 | ".type " PV_UNLOCK ", @function;" |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 40 | ".align 4,0x90;" |
| 41 | PV_UNLOCK ": " |
Josh Poimboeuf | 16df4ff | 2016-01-21 16:49:32 -0600 | [diff] [blame] | 42 | FRAME_BEGIN |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 43 | "push %rdx;" |
| 44 | "mov $0x1,%eax;" |
| 45 | "xor %edx,%edx;" |
Waiman Long | c0dc373 | 2018-07-17 16:16:00 -0400 | [diff] [blame^] | 46 | LOCK_PREFIX "cmpxchg %dl,(%rdi);" |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 47 | "cmp $0x1,%al;" |
| 48 | "jne .slowpath;" |
| 49 | "pop %rdx;" |
Josh Poimboeuf | 16df4ff | 2016-01-21 16:49:32 -0600 | [diff] [blame] | 50 | FRAME_END |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 51 | "ret;" |
| 52 | ".slowpath: " |
| 53 | "push %rsi;" |
| 54 | "movzbl %al,%esi;" |
| 55 | "call " PV_UNLOCK_SLOWPATH ";" |
| 56 | "pop %rsi;" |
| 57 | "pop %rdx;" |
Josh Poimboeuf | 16df4ff | 2016-01-21 16:49:32 -0600 | [diff] [blame] | 58 | FRAME_END |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 59 | "ret;" |
| 60 | ".size " PV_UNLOCK ", .-" PV_UNLOCK ";" |
| 61 | ".popsection"); |
| 62 | |
| 63 | #else /* CONFIG_64BIT */ |
| 64 | |
| 65 | extern void __pv_queued_spin_unlock(struct qspinlock *lock); |
Peter Zijlstra (Intel) | f233f7f | 2015-04-24 14:56:38 -0400 | [diff] [blame] | 66 | PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock); |
| 67 | |
Waiman Long | d780453 | 2015-11-09 19:09:24 -0500 | [diff] [blame] | 68 | #endif /* CONFIG_64BIT */ |
Peter Zijlstra (Intel) | f233f7f | 2015-04-24 14:56:38 -0400 | [diff] [blame] | 69 | #endif |