mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
Merge branch 'preempt'
Heiko Carstens says: ==================== The option to select PREEMPT_NONE will go away for all architectures which support PREEMPT_LAZY [1]. Until now all distributions provide kernels built with PREEMPT_NONE enabled for s390. In particular this means that all preempt_disable() / preempt_enable() pairs are optimized away during compile time. With PREEMPT_LAZY this is not the case. Switching to PREEMPT_LAZY leads to a kernel image size increase of ~218kb (defconfig, gcc15). s390 provides optimized preempt primitives, however there is still room for improvement. Since support for relocatable lowcore was added access to preempt_count in lowcore requires an extra call of get_lowcore(), which generates an extra instruction. Also all instructions have to use a base register which is not zero to access preempt_count. Address this by adding a couple of inline assemblies with alternatives. This generates better code and reduces the size of a PREEMPT_LAZY built kernel image by ~58kb. [1] https://lore.kernel.org/all/20251219101502.GB1132199@noisy.programming.kicks-ass.net/ ==================== Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
commit
86302ddf20
|
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_ASM_FLAG_OUTPUT_BROKEN))
|
||||
|
||||
#define __HAVE_ASM_FLAG_OUTPUTS__
|
||||
#define __HAVE_ASM_FLAG_OUTPUTS__ 1
|
||||
|
||||
#define CC_IPM(sym)
|
||||
#define CC_OUT(sym, var) "=@cc" (var)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@
|
|||
#include <asm/cmpxchg.h>
|
||||
#include <asm/march.h>
|
||||
|
||||
/* We use the MSB mostly because its available */
|
||||
/*
|
||||
* Use MSB so it is possible to read preempt_count with LLGT which
|
||||
* reads the least significant 31 bits with a single instruction.
|
||||
*/
|
||||
#define PREEMPT_NEED_RESCHED 0x80000000
|
||||
|
||||
/*
|
||||
|
|
@ -23,7 +26,20 @@
|
|||
*/
|
||||
static __always_inline int preempt_count(void)
|
||||
{
|
||||
return READ_ONCE(get_lowcore()->preempt_count) & ~PREEMPT_NEED_RESCHED;
|
||||
unsigned long lc_preempt, count;
|
||||
|
||||
BUILD_BUG_ON(sizeof_field(struct lowcore, preempt_count) != sizeof(int));
|
||||
lc_preempt = offsetof(struct lowcore, preempt_count);
|
||||
/* READ_ONCE(get_lowcore()->preempt_count) & ~PREEMPT_NEED_RESCHED */
|
||||
asm_inline(
|
||||
ALTERNATIVE("llgt %[count],%[offzero](%%r0)\n",
|
||||
"llgt %[count],%[offalt](%%r0)\n",
|
||||
ALT_FEATURE(MFEATURE_LOWCORE))
|
||||
: [count] "=d" (count)
|
||||
: [offzero] "i" (lc_preempt),
|
||||
[offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS),
|
||||
"m" (((struct lowcore *)0)->preempt_count));
|
||||
return count;
|
||||
}
|
||||
|
||||
static __always_inline void preempt_count_set(int pc)
|
||||
|
|
@ -68,7 +84,17 @@ static __always_inline void __preempt_count_add(int val)
|
|||
*/
|
||||
if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) {
|
||||
if (__builtin_constant_p(val) && (val >= -128) && (val <= 127)) {
|
||||
__atomic_add_const(val, &get_lowcore()->preempt_count);
|
||||
unsigned long lc_preempt;
|
||||
|
||||
lc_preempt = offsetof(struct lowcore, preempt_count);
|
||||
asm_inline(
|
||||
ALTERNATIVE("asi %[offzero](%%r0),%[val]\n",
|
||||
"asi %[offalt](%%r0),%[val]\n",
|
||||
ALT_FEATURE(MFEATURE_LOWCORE))
|
||||
: "+m" (((struct lowcore *)0)->preempt_count)
|
||||
: [offzero] "i" (lc_preempt), [val] "i" (val),
|
||||
[offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS)
|
||||
: "cc");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -87,7 +113,22 @@ static __always_inline void __preempt_count_sub(int val)
|
|||
*/
|
||||
static __always_inline bool __preempt_count_dec_and_test(void)
|
||||
{
|
||||
#ifdef __HAVE_ASM_FLAG_OUTPUTS__
|
||||
unsigned long lc_preempt;
|
||||
int cc;
|
||||
|
||||
lc_preempt = offsetof(struct lowcore, preempt_count);
|
||||
asm_inline(
|
||||
ALTERNATIVE("alsi %[offzero](%%r0),%[val]\n",
|
||||
"alsi %[offalt](%%r0),%[val]\n",
|
||||
ALT_FEATURE(MFEATURE_LOWCORE))
|
||||
: "=@cc" (cc), "+m" (((struct lowcore *)0)->preempt_count)
|
||||
: [offzero] "i" (lc_preempt), [val] "i" (-1),
|
||||
[offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS));
|
||||
return (cc == 0) || (cc == 2);
|
||||
#else
|
||||
return __atomic_add_const_and_test(-1, &get_lowcore()->preempt_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user