Commit 23ba7d31 authored by Heiko Carstens's avatar Heiko Carstens
Browse files

s390/preempt: Optimize __preemp_count_add()/__preempt_count_sub()



Provide an inline assembly using alternatives to avoid the need of a
base register due to relocatable lowcore when adding or subtracting
small constants from preempt_count.

Main user is preempt_disable(), which subtracts one from
preempt_count. With this the generated code changes from

  10012c:       a7 b9 00 00             lghi    %r11,0
  100130:       eb 01 b3 a8 00 6a       asi     936(%r11),1

to something like this:

 10012c:        eb 01 03 a8 00 6a       asi     936,1

Kernel image size is reduced by 13kb (bloat-o-meter -t, defconfig, gcc15).

Reviewed-by: default avatarSven Schnelle <svens@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 6cce3609
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -84,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;
		}
	}