diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index b9ec6ee21c941..e09c70b4eaea1 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -4252,6 +4252,47 @@ __bpf_kfunc int bpf_task_work_schedule_resume(struct task_struct *task, struct b return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_RESUME); } +/** + * bpf_in_nmi_context - Check whether we are serving NMI + * + * Return: true if we are serving NMI + */ +__bpf_kfunc bool bpf_in_nmi_context(void) +{ + return in_nmi(); +} + +/** + * bpf_in_hardirq_context - Check whether we are serving hard irq + * + * Return: true if we are serving hard irq + */ +__bpf_kfunc bool bpf_in_hardirq_context(void) +{ + return in_hardirq(); +} + +/** + * bpf_in_softirq_context - Check whether we are serving soft irq + * + * Return: true if we are serving soft irq + */ +__bpf_kfunc bool bpf_in_softirq_context(void) +{ + /* in_softirq() has been deprecated */ + return in_serving_softirq(); +} + +/** + * bpf_in_task_context - Check whether we are in task context + * + * Return: true if we are in task context + */ +__bpf_kfunc bool bpf_in_task_context(void) +{ + return in_task(); +} + __bpf_kfunc_end_defs(); static void bpf_task_work_cancel_scheduled(struct irq_work *irq_work) @@ -4429,6 +4470,10 @@ BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU) BTF_ID_FLAGS(func, bpf_stream_vprintk, KF_TRUSTED_ARGS) BTF_ID_FLAGS(func, bpf_task_work_schedule_signal, KF_TRUSTED_ARGS) BTF_ID_FLAGS(func, bpf_task_work_schedule_resume, KF_TRUSTED_ARGS) +BTF_ID_FLAGS(func, bpf_in_softirq_context) +BTF_ID_FLAGS(func, bpf_in_hardirq_context) +BTF_ID_FLAGS(func, bpf_in_task_context) +BTF_ID_FLAGS(func, bpf_in_nmi_context) BTF_KFUNCS_END(common_btf_ids) static const struct btf_kfunc_id_set common_kfunc_set = { diff --git a/tools/testing/selftests/bpf/prog_tests/context.c b/tools/testing/selftests/bpf/prog_tests/context.c new file mode 100644 index 0000000000000..f09d24069941b --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/context.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include "context_prog.skel.h" + +void test_context(void) +{ + struct context_prog *skel = NULL; + + skel = context_prog__open_and_load(); + if (!ASSERT_OK_PTR(skel, "loading prog fail")) + return; + + context_prog__attach(skel); + getuid(); + sleep(5); + + if (!ASSERT_EQ(1, skel->bss->in_hardirq, "hardirq not triggered")) + goto out; + if (!ASSERT_EQ(1, skel->bss->in_softriq, "softirq not triggered")) + goto out; + if (!ASSERT_EQ(1, skel->bss->in_task, "task context not triggered")) + goto out; +out: + context_prog__destroy(skel); +} + +void test_bpf_context(void) +{ + if (test__start_subtest("context")) + test_context(); +} diff --git a/tools/testing/selftests/bpf/progs/context_prog.c b/tools/testing/selftests/bpf/progs/context_prog.c new file mode 100644 index 0000000000000..81e21f684a843 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/context_prog.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include "bpf_misc.h" +#include "bpf_experimental.h" + +int in_hardirq = 0; +int in_softriq = 0; +int in_task = 0; + +SEC("tp/irq/irq_handler_entry") +int trace_irq_handler_entry(const void *ctx) +{ + in_hardirq = bpf_in_hardirq_context(); + return 0; +} + +SEC("tp/irq/softirq_entry") +int trace_softirq_entry(const void *ctx) +{ + in_softriq = bpf_in_softirq_context(); + return 0; +} + +SEC("tp/syscalls/sys_enter_getuid") +int trace_syscall(const void *ctx) +{ + in_task = bpf_in_task_context(); + return 0; +} + +char _license[] SEC("license") = "GPL";