* [PATCH 1/2] s390: Introduce bpf_get_lowcore() kfunc
2026-02-17 16:05 [PATCH 0/2] bpf/s390: Implement get_preempt_count() Ilya Leoshkevich
@ 2026-02-17 16:05 ` Ilya Leoshkevich
2026-02-17 16:05 ` [PATCH 2/2] bpf/s390: Implement get_preempt_count() Ilya Leoshkevich
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Ilya Leoshkevich @ 2026-02-17 16:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
Cc: bpf, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Ilya Leoshkevich
Implementing BPF version of preempt_count() requires accessing lowcore
from BPF. Since lowcore can be relocated, open-coding
(struct lowcore *)0 does not work, so add a kfunc.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
arch/s390/kernel/Makefile | 2 ++
arch/s390/kernel/bpf.c | 12 ++++++++++++
kernel/bpf/helpers.c | 3 +++
tools/testing/selftests/bpf/bpf_experimental.h | 4 ++++
4 files changed, 21 insertions(+)
create mode 100644 arch/s390/kernel/bpf.c
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 42c83d60d6fae..b522c6649fccb 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -80,5 +80,7 @@ obj-$(CONFIG_PERF_EVENTS) += perf_pai.o
obj-$(CONFIG_TRACEPOINTS) += trace.o
+obj-$(CONFIG_BPF_SYSCALL) += bpf.o
+
# vdso
obj-y += vdso/
diff --git a/arch/s390/kernel/bpf.c b/arch/s390/kernel/bpf.c
new file mode 100644
index 0000000000000..713337fae6263
--- /dev/null
+++ b/arch/s390/kernel/bpf.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <asm/lowcore.h>
+#include <linux/btf.h>
+
+__bpf_kfunc_start_defs();
+
+__bpf_kfunc struct lowcore *bpf_get_lowcore(void)
+{
+ return get_lowcore();
+}
+
+__bpf_kfunc_end_defs();
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 7ac32798eb041..8c1023da3855d 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -4578,6 +4578,9 @@ BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE)
BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE)
#endif
#endif
+#ifdef CONFIG_S390
+BTF_ID_FLAGS(func, bpf_get_lowcore)
+#endif
BTF_KFUNCS_END(generic_btf_ids)
static const struct btf_kfunc_id_set generic_kfunc_set = {
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 9df77e59d4f5d..4453ad27b2ef7 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -627,6 +627,10 @@ struct task_struct___preempt_rt {
int softirq_disable_cnt;
} __attribute__((preserve_access_index));
+#ifdef bpf_target_s390
+extern struct lowcore *bpf_get_lowcore(void) __weak __ksym;
+#endif
+
static inline int get_preempt_count(void)
{
#if defined(bpf_target_x86)
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 2/2] bpf/s390: Implement get_preempt_count()
2026-02-17 16:05 [PATCH 0/2] bpf/s390: Implement get_preempt_count() Ilya Leoshkevich
2026-02-17 16:05 ` [PATCH 1/2] s390: Introduce bpf_get_lowcore() kfunc Ilya Leoshkevich
@ 2026-02-17 16:05 ` Ilya Leoshkevich
2026-02-17 17:55 ` [PATCH 0/2] " Vasily Gorbik
2026-03-03 16:40 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 8+ messages in thread
From: Ilya Leoshkevich @ 2026-02-17 16:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko
Cc: bpf, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
Ilya Leoshkevich
exe_ctx test fails on s390, because get_preempt_count() is not
implemented and its fallback path always returns 0. Implement it
using the new bpf_get_lowcore() kfunc.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
tools/testing/selftests/bpf/bpf_experimental.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 4453ad27b2ef7..44466acf80838 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -651,6 +651,8 @@ static inline int get_preempt_count(void)
return bpf_get_current_task_btf()->thread_info.preempt.count;
#elif defined(bpf_target_powerpc)
return bpf_get_current_task_btf()->thread_info.preempt_count;
+#elif defined(bpf_target_s390)
+ return bpf_get_lowcore()->preempt_count;
#endif
return 0;
}
@@ -660,6 +662,7 @@ static inline int get_preempt_count(void)
* * x86
* * arm64
* * powerpc64
+ * * s390x
*/
static inline int bpf_in_interrupt(void)
{
@@ -680,6 +683,7 @@ static inline int bpf_in_interrupt(void)
* * x86
* * arm64
* * powerpc64
+ * * s390x
*/
static inline int bpf_in_nmi(void)
{
@@ -691,6 +695,7 @@ static inline int bpf_in_nmi(void)
* * x86
* * arm64
* * powerpc64
+ * * s390x
*/
static inline int bpf_in_hardirq(void)
{
@@ -702,6 +707,7 @@ static inline int bpf_in_hardirq(void)
* * x86
* * arm64
* * powerpc64
+ * * s390x
*/
static inline int bpf_in_serving_softirq(void)
{
@@ -721,6 +727,7 @@ static inline int bpf_in_serving_softirq(void)
* * x86
* * arm64
* * powerpc64
+ * * s390x
*/
static inline int bpf_in_task(void)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 0/2] bpf/s390: Implement get_preempt_count()
2026-02-17 16:05 [PATCH 0/2] bpf/s390: Implement get_preempt_count() Ilya Leoshkevich
2026-02-17 16:05 ` [PATCH 1/2] s390: Introduce bpf_get_lowcore() kfunc Ilya Leoshkevich
2026-02-17 16:05 ` [PATCH 2/2] bpf/s390: Implement get_preempt_count() Ilya Leoshkevich
@ 2026-02-17 17:55 ` Vasily Gorbik
2026-02-17 19:32 ` Alexei Starovoitov
2026-03-03 16:40 ` patchwork-bot+netdevbpf
3 siblings, 1 reply; 8+ messages in thread
From: Vasily Gorbik @ 2026-02-17 17:55 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
Heiko Carstens, Alexander Gordeev
On Tue, Feb 17, 2026 at 05:05:07PM +0100, Ilya Leoshkevich wrote:
> Hi,
>
> This series adds get_preempt_count() BPF implementation for s390.
> On s390 preempt_count lives in lowcore: a per-cpu data structure
> mapped at virtual address 0 or 0x70000 depending on the kernel
> command line.
>
> Patch 1 adds a kfunc to obtain lowcore address.
> Patch 2 is the implementation that delegates to it.
Hi Ilya,
do we really want to expose bpf_get_lowcore() (full lowcore) to BPF just
to implement get_preempt_count()?
Could we instead provide a narrow kfunc/helper that returns preempt_count
and keep lowcore details internal?
Thanks
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] bpf/s390: Implement get_preempt_count()
2026-02-17 17:55 ` [PATCH 0/2] " Vasily Gorbik
@ 2026-02-17 19:32 ` Alexei Starovoitov
2026-02-17 23:34 ` Ilya Leoshkevich
0 siblings, 1 reply; 8+ messages in thread
From: Alexei Starovoitov @ 2026-02-17 19:32 UTC (permalink / raw)
To: Vasily Gorbik
Cc: Ilya Leoshkevich, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, bpf, Heiko Carstens, Alexander Gordeev
On Tue, Feb 17, 2026 at 9:55 AM Vasily Gorbik <gor@linux.ibm.com> wrote:
>
> On Tue, Feb 17, 2026 at 05:05:07PM +0100, Ilya Leoshkevich wrote:
> > Hi,
> >
> > This series adds get_preempt_count() BPF implementation for s390.
> > On s390 preempt_count lives in lowcore: a per-cpu data structure
> > mapped at virtual address 0 or 0x70000 depending on the kernel
> > command line.
> >
> > Patch 1 adds a kfunc to obtain lowcore address.
> > Patch 2 is the implementation that delegates to it.
>
> Hi Ilya,
>
> do we really want to expose bpf_get_lowcore() (full lowcore) to BPF just
> to implement get_preempt_count()?
I think there are no other options. For this and other cases.
Like to inline bpf_get_smp_processor_id(), current_task, etc.
arch/s390/kernel/bpf.c is a good place for such arch specific kfunc.
I cannot really tell by looking at the implementation of get_lowcore(),
but can this kfunc be marked as KF_FASTCALL to further improve performance?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] bpf/s390: Implement get_preempt_count()
2026-02-17 19:32 ` Alexei Starovoitov
@ 2026-02-17 23:34 ` Ilya Leoshkevich
2026-02-18 0:18 ` Alexei Starovoitov
0 siblings, 1 reply; 8+ messages in thread
From: Ilya Leoshkevich @ 2026-02-17 23:34 UTC (permalink / raw)
To: Alexei Starovoitov, Vasily Gorbik
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
Heiko Carstens, Alexander Gordeev
On 2/17/26 20:32, Alexei Starovoitov wrote:
> On Tue, Feb 17, 2026 at 9:55 AM Vasily Gorbik <gor@linux.ibm.com> wrote:
>> On Tue, Feb 17, 2026 at 05:05:07PM +0100, Ilya Leoshkevich wrote:
>>> Hi,
>>>
>>> This series adds get_preempt_count() BPF implementation for s390.
>>> On s390 preempt_count lives in lowcore: a per-cpu data structure
>>> mapped at virtual address 0 or 0x70000 depending on the kernel
>>> command line.
>>>
>>> Patch 1 adds a kfunc to obtain lowcore address.
>>> Patch 2 is the implementation that delegates to it.
>> Hi Ilya,
>>
>> do we really want to expose bpf_get_lowcore() (full lowcore) to BPF just
>> to implement get_preempt_count()?
> I think there are no other options. For this and other cases.
> Like to inline bpf_get_smp_processor_id(), current_task, etc.
>
> arch/s390/kernel/bpf.c is a good place for such arch specific kfunc.
>
> I cannot really tell by looking at the implementation of get_lowcore(),
> but can this kfunc be marked as KF_FASTCALL to further improve performance?
I think so.
KF_FASTCALL will require inlining in the JIT, right?
Then bpf_get_preempt_count() might be a little bit better, because
inlined bpf_get_lowcore() followed by preempt_count access will look
like this:
LGFI %r2,0x70000
LY %r2,preempt_count(%r2)
and inlined bpf_s390_get_preempt_count() will be one instruction shorter:
LY %r2,0x70000+preempt_count
Do you think it is worth the while pursuing this?
If yes, would it make sense to add an implementation delegating to
preempt_count() to BPF common code and use it only for s390 for now?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] bpf/s390: Implement get_preempt_count()
2026-02-17 23:34 ` Ilya Leoshkevich
@ 2026-02-18 0:18 ` Alexei Starovoitov
0 siblings, 0 replies; 8+ messages in thread
From: Alexei Starovoitov @ 2026-02-18 0:18 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: Vasily Gorbik, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, bpf, Heiko Carstens, Alexander Gordeev
On Tue, Feb 17, 2026 at 3:34 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
>
> On 2/17/26 20:32, Alexei Starovoitov wrote:
> > On Tue, Feb 17, 2026 at 9:55 AM Vasily Gorbik <gor@linux.ibm.com> wrote:
> >> On Tue, Feb 17, 2026 at 05:05:07PM +0100, Ilya Leoshkevich wrote:
> >>> Hi,
> >>>
> >>> This series adds get_preempt_count() BPF implementation for s390.
> >>> On s390 preempt_count lives in lowcore: a per-cpu data structure
> >>> mapped at virtual address 0 or 0x70000 depending on the kernel
> >>> command line.
> >>>
> >>> Patch 1 adds a kfunc to obtain lowcore address.
> >>> Patch 2 is the implementation that delegates to it.
> >> Hi Ilya,
> >>
> >> do we really want to expose bpf_get_lowcore() (full lowcore) to BPF just
> >> to implement get_preempt_count()?
> > I think there are no other options. For this and other cases.
> > Like to inline bpf_get_smp_processor_id(), current_task, etc.
> >
> > arch/s390/kernel/bpf.c is a good place for such arch specific kfunc.
> >
> > I cannot really tell by looking at the implementation of get_lowcore(),
> > but can this kfunc be marked as KF_FASTCALL to further improve performance?
>
>
> I think so.
>
> KF_FASTCALL will require inlining in the JIT, right?
Not really. Just that the binary code has to conform to fastcall
semantics. Like in this case the get_lowcore() is always_inline and
its body is written in asm, so bpf_get_lowcore() kfunc
seems to fit the pattern. It's a leaf function and doesn't
scratch s390 cpu registers that are equivalent to bpf's r1-r5.
It only updates bpf's r0.
> Then bpf_get_preempt_count() might be a little bit better, because
> inlined bpf_get_lowcore() followed by preempt_count access will look
> like this:
>
> LGFI %r2,0x70000
it doesn't have to be inlined. It can stay as a call to kfunc.
> LY %r2,preempt_count(%r2)
>
> and inlined bpf_s390_get_preempt_count() will be one instruction shorter:
>
> LY %r2,0x70000+preempt_count
>
> Do you think it is worth the while pursuing this?
>
> If yes, would it make sense to add an implementation delegating to
> preempt_count() to BPF common code and use it only for s390 for now?
Let's not over optimize.
bpf_get_lowcore() seems to be a more generic approach and
a bunch of s390 accessors can use it.
get_preempt_count() can call it from bpf prog as your patch did.
Then later s390 JIT can call into that kfunc when it inlines
bpf_get_current_task() helper.
I think you're saying s390 JIT can inline bpf_get_current_task()
more efficiently as 'LY %r2,0x70000+..' ?
And complicate the JIT with MFEATURE_LOWCORE detection, etc?
We're actually thinking of moving the other direction.
Use in-kernel arch specific disassembler to parse compiled kfunc-s
and inline them in JIT instead of emitting binary opcodes.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] bpf/s390: Implement get_preempt_count()
2026-02-17 16:05 [PATCH 0/2] bpf/s390: Implement get_preempt_count() Ilya Leoshkevich
` (2 preceding siblings ...)
2026-02-17 17:55 ` [PATCH 0/2] " Vasily Gorbik
@ 2026-03-03 16:40 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-03 16:40 UTC (permalink / raw)
To: Ilya Leoshkevich; +Cc: ast, daniel, andrii, bpf, hca, gor, agordeev
Hello:
This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Tue, 17 Feb 2026 17:05:07 +0100 you wrote:
> Hi,
>
> This series adds get_preempt_count() BPF implementation for s390.
> On s390 preempt_count lives in lowcore: a per-cpu data structure
> mapped at virtual address 0 or 0x70000 depending on the kernel
> command line.
>
> [...]
Here is the summary with links:
- [1/2] s390: Introduce bpf_get_lowcore() kfunc
https://git.kernel.org/bpf/bpf-next/c/6fe54677bcc2
- [2/2] bpf/s390: Implement get_preempt_count()
https://git.kernel.org/bpf/bpf-next/c/0f87614c4dbd
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 8+ messages in thread