mirror of
https://github.com/torvalds/linux.git
synced 2025-04-12 06:49:52 +00:00
s390/spinlock: Implement SPINLOCK_LOCKVAL with inline assembly
Implement SPINLOCK_LOCKVAL with an inline assembly, which makes use of the ALTERNATIVE macro, to read spinlock_lockval from lowcore. Provide an alternative instruction with a different offset in case lowcore is relocated. This replaces sequences of two instructions with one instruction. Before: 10602a: a7 78 00 00 lhi %r7,0 10602e: a5 8e 00 00 llilh %r8,0 106032: 58 d0 83 ac l %r13,940(%r8) 106036: ba 7d b5 80 cs %r7,%r13,1408(%r11) After: 10602a: a7 88 00 00 lhi %r8,0 10602e: e3 70 03 ac 00 58 ly %r7,940 106034: ba 87 b5 80 cs %r8,%r7,1408(%r11) Kernel image size change: add/remove: 756/750 grow/shrink: 646/3435 up/down: 30778/-46326 (-15548) Acked-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
4797e9b506
commit
b46525437e
@ -16,7 +16,23 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/alternative.h>
|
||||
|
||||
#define SPINLOCK_LOCKVAL (get_lowcore()->spinlock_lockval)
|
||||
static __always_inline unsigned int spinlock_lockval(void)
|
||||
{
|
||||
unsigned long lc_lockval;
|
||||
unsigned int lockval;
|
||||
|
||||
BUILD_BUG_ON(sizeof_field(struct lowcore, spinlock_lockval) != sizeof(lockval));
|
||||
lc_lockval = offsetof(struct lowcore, spinlock_lockval);
|
||||
asm_inline(
|
||||
ALTERNATIVE(" ly %[lockval],%[offzero](%%r0)\n",
|
||||
" ly %[lockval],%[offalt](%%r0)\n",
|
||||
ALT_FEATURE(MFEATURE_LOWCORE))
|
||||
: [lockval] "=d" (lockval)
|
||||
: [offzero] "i" (lc_lockval),
|
||||
[offalt] "i" (lc_lockval + LOWCORE_ALT_ADDRESS),
|
||||
"m" (((struct lowcore *)0)->spinlock_lockval));
|
||||
return lockval;
|
||||
}
|
||||
|
||||
extern int spin_retry;
|
||||
|
||||
@ -60,7 +76,7 @@ static inline int arch_spin_trylock_once(arch_spinlock_t *lp)
|
||||
int old = 0;
|
||||
|
||||
barrier();
|
||||
return likely(arch_try_cmpxchg(&lp->lock, &old, SPINLOCK_LOCKVAL));
|
||||
return likely(arch_try_cmpxchg(&lp->lock, &old, spinlock_lockval()));
|
||||
}
|
||||
|
||||
static inline void arch_spin_lock(arch_spinlock_t *lp)
|
||||
|
@ -160,7 +160,7 @@ static inline void arch_spin_lock_queued(arch_spinlock_t *lp)
|
||||
|
||||
ix = get_lowcore()->spinlock_index++;
|
||||
barrier();
|
||||
lockval = SPINLOCK_LOCKVAL; /* cpu + 1 */
|
||||
lockval = spinlock_lockval(); /* cpu + 1 */
|
||||
node = this_cpu_ptr(&spin_wait[ix]);
|
||||
node->prev = node->next = NULL;
|
||||
node_id = node->node_id;
|
||||
@ -251,7 +251,7 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp)
|
||||
{
|
||||
int lockval, old, new, owner, count;
|
||||
|
||||
lockval = SPINLOCK_LOCKVAL; /* cpu + 1 */
|
||||
lockval = spinlock_lockval(); /* cpu + 1 */
|
||||
|
||||
/* Pass the virtual CPU to the lock holder if it is not running */
|
||||
owner = arch_spin_yield_target(READ_ONCE(lp->lock), NULL);
|
||||
@ -290,7 +290,7 @@ EXPORT_SYMBOL(arch_spin_lock_wait);
|
||||
|
||||
int arch_spin_trylock_retry(arch_spinlock_t *lp)
|
||||
{
|
||||
int cpu = SPINLOCK_LOCKVAL;
|
||||
int cpu = spinlock_lockval();
|
||||
int owner, count;
|
||||
|
||||
for (count = spin_retry; count > 0; count--) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user