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: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
*/
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;
}
}