162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2021, Oracle and/or its affiliates. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "vmlinux.h" 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 762306a36Sopenharmony_ci#include <bpf/bpf_tracing.h> 862306a36Sopenharmony_ci#include <bpf/bpf_core_read.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciunsigned int exception_triggered; 1362306a36Sopenharmony_ciint test_pid; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* TRACE_EVENT(task_newtask, 1662306a36Sopenharmony_ci * TP_PROTO(struct task_struct *p, u64 clone_flags) 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ciSEC("tp_btf/task_newtask") 1962306a36Sopenharmony_ciint BPF_PROG(trace_task_newtask, struct task_struct *task, u64 clone_flags) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci int pid = bpf_get_current_pid_tgid() >> 32; 2262306a36Sopenharmony_ci struct callback_head *work; 2362306a36Sopenharmony_ci void *func; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if (test_pid != pid) 2662306a36Sopenharmony_ci return 0; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci /* To verify we hit an exception we dereference task->task_works->func. 2962306a36Sopenharmony_ci * If task work has been added, 3062306a36Sopenharmony_ci * - task->task_works is non-NULL; and 3162306a36Sopenharmony_ci * - task->task_works->func is non-NULL also (the callback function 3262306a36Sopenharmony_ci * must be specified for the task work. 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * However, for a newly-created task, task->task_works is NULLed, 3562306a36Sopenharmony_ci * so we know the exception handler triggered if task_works is 3662306a36Sopenharmony_ci * NULL and func is NULL. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci work = task->task_works; 3962306a36Sopenharmony_ci func = work->func; 4062306a36Sopenharmony_ci /* Currently verifier will fail for `btf_ptr |= btf_ptr` * instruction. 4162306a36Sopenharmony_ci * To workaround the issue, use barrier_var() and rewrite as below to 4262306a36Sopenharmony_ci * prevent compiler from generating verifier-unfriendly code. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci barrier_var(work); 4562306a36Sopenharmony_ci if (work) 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci barrier_var(func); 4862306a36Sopenharmony_ci if (func) 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci exception_triggered++; 5162306a36Sopenharmony_ci return 0; 5262306a36Sopenharmony_ci} 53