s390/bitops: optimize set_bit() for constant values
Since zEC12 we have the interlocked-access facility 2 which allows to use the instructions ni/oi/xi to update a single byte in storage with compare-and-swap semantics. So change set_bit(), clear_bit() and change_bit() to generate such code instead of a compare-and-swap loop (or using the load-and-* instruction family), if possible. This reduces the text segment by yet another 8KB (defconfig). Alternatively the long displacement variants niy/oiy/xiy could have been used, but the extended displacement field is usually not needed and therefore would only increase the size of the text segment again. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
370b0b5f77
commit
4ae803253e
|
@ -151,6 +151,18 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
|
||||||
unsigned long *addr = __bitops_word(nr, ptr);
|
unsigned long *addr = __bitops_word(nr, ptr);
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
|
||||||
|
if (__builtin_constant_p(nr)) {
|
||||||
|
unsigned char *caddr = __bitops_byte(nr, ptr);
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"oi %0,%b1\n"
|
||||||
|
: "+Q" (*caddr)
|
||||||
|
: "i" (1 << (nr & 7))
|
||||||
|
: "cc");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
mask = 1UL << (nr & (BITS_PER_LONG - 1));
|
mask = 1UL << (nr & (BITS_PER_LONG - 1));
|
||||||
__BITOPS_LOOP(addr, mask, __BITOPS_OR);
|
__BITOPS_LOOP(addr, mask, __BITOPS_OR);
|
||||||
}
|
}
|
||||||
|
@ -160,6 +172,18 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
|
||||||
unsigned long *addr = __bitops_word(nr, ptr);
|
unsigned long *addr = __bitops_word(nr, ptr);
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
|
||||||
|
if (__builtin_constant_p(nr)) {
|
||||||
|
unsigned char *caddr = __bitops_byte(nr, ptr);
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"ni %0,%b1\n"
|
||||||
|
: "+Q" (*caddr)
|
||||||
|
: "i" (~(1 << (nr & 7)))
|
||||||
|
: "cc");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
|
mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
|
||||||
__BITOPS_LOOP(addr, mask, __BITOPS_AND);
|
__BITOPS_LOOP(addr, mask, __BITOPS_AND);
|
||||||
}
|
}
|
||||||
|
@ -169,6 +193,18 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
|
||||||
unsigned long *addr = __bitops_word(nr, ptr);
|
unsigned long *addr = __bitops_word(nr, ptr);
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
|
||||||
|
if (__builtin_constant_p(nr)) {
|
||||||
|
unsigned char *caddr = __bitops_byte(nr, ptr);
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"xi %0,%b1\n"
|
||||||
|
: "+Q" (*caddr)
|
||||||
|
: "i" (1 << (nr & 7))
|
||||||
|
: "cc");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
mask = 1UL << (nr & (BITS_PER_LONG - 1));
|
mask = 1UL << (nr & (BITS_PER_LONG - 1));
|
||||||
__BITOPS_LOOP(addr, mask, __BITOPS_XOR);
|
__BITOPS_LOOP(addr, mask, __BITOPS_XOR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,7 +437,7 @@ ENTRY(startup_kdump)
|
||||||
|
|
||||||
#if defined(CONFIG_64BIT)
|
#if defined(CONFIG_64BIT)
|
||||||
#if defined(CONFIG_MARCH_ZEC12)
|
#if defined(CONFIG_MARCH_ZEC12)
|
||||||
.long 3, 0xc100efe3, 0xf46ce000, 0x00400000
|
.long 3, 0xc100efe3, 0xf46ce800, 0x00400000
|
||||||
#elif defined(CONFIG_MARCH_Z196)
|
#elif defined(CONFIG_MARCH_Z196)
|
||||||
.long 2, 0xc100efe3, 0xf46c0000
|
.long 2, 0xc100efe3, 0xf46c0000
|
||||||
#elif defined(CONFIG_MARCH_Z10)
|
#elif defined(CONFIG_MARCH_Z10)
|
||||||
|
|
Loading…
Reference in New Issue