1*39fd74dfSMykyta Yatsenko // SPDX-License-Identifier: GPL-2.0 2*39fd74dfSMykyta Yatsenko /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3*39fd74dfSMykyta Yatsenko 4*39fd74dfSMykyta Yatsenko #include <vmlinux.h> 5*39fd74dfSMykyta Yatsenko #include <string.h> 6*39fd74dfSMykyta Yatsenko #include <stdbool.h> 7*39fd74dfSMykyta Yatsenko #include <bpf/bpf_helpers.h> 8*39fd74dfSMykyta Yatsenko #include <bpf/bpf_tracing.h> 9*39fd74dfSMykyta Yatsenko #include "bpf_misc.h" 10*39fd74dfSMykyta Yatsenko #include "errno.h" 11*39fd74dfSMykyta Yatsenko 12*39fd74dfSMykyta Yatsenko char _license[] SEC("license") = "GPL"; 13*39fd74dfSMykyta Yatsenko 14*39fd74dfSMykyta Yatsenko const void *user_ptr = NULL; 15*39fd74dfSMykyta Yatsenko 16*39fd74dfSMykyta Yatsenko struct elem { 17*39fd74dfSMykyta Yatsenko char data[128]; 18*39fd74dfSMykyta Yatsenko struct bpf_task_work tw; 19*39fd74dfSMykyta Yatsenko }; 20*39fd74dfSMykyta Yatsenko 21*39fd74dfSMykyta Yatsenko struct { 22*39fd74dfSMykyta Yatsenko __uint(type, BPF_MAP_TYPE_HASH); 23*39fd74dfSMykyta Yatsenko __uint(map_flags, BPF_F_NO_PREALLOC); 24*39fd74dfSMykyta Yatsenko __uint(max_entries, 1); 25*39fd74dfSMykyta Yatsenko __type(key, int); 26*39fd74dfSMykyta Yatsenko __type(value, struct elem); 27*39fd74dfSMykyta Yatsenko } hmap SEC(".maps"); 28*39fd74dfSMykyta Yatsenko 29*39fd74dfSMykyta Yatsenko struct { 30*39fd74dfSMykyta Yatsenko __uint(type, BPF_MAP_TYPE_ARRAY); 31*39fd74dfSMykyta Yatsenko __uint(max_entries, 1); 32*39fd74dfSMykyta Yatsenko __type(key, int); 33*39fd74dfSMykyta Yatsenko __type(value, struct elem); 34*39fd74dfSMykyta Yatsenko } arrmap SEC(".maps"); 35*39fd74dfSMykyta Yatsenko 36*39fd74dfSMykyta Yatsenko struct { 37*39fd74dfSMykyta Yatsenko __uint(type, BPF_MAP_TYPE_LRU_HASH); 38*39fd74dfSMykyta Yatsenko __uint(max_entries, 1); 39*39fd74dfSMykyta Yatsenko __type(key, int); 40*39fd74dfSMykyta Yatsenko __type(value, struct elem); 41*39fd74dfSMykyta Yatsenko } lrumap SEC(".maps"); 42*39fd74dfSMykyta Yatsenko 43*39fd74dfSMykyta Yatsenko static int process_work(struct bpf_map *map, void *key, void *value) 44*39fd74dfSMykyta Yatsenko { 45*39fd74dfSMykyta Yatsenko struct elem *work = value; 46*39fd74dfSMykyta Yatsenko 47*39fd74dfSMykyta Yatsenko bpf_copy_from_user_str(work->data, sizeof(work->data), (const void *)user_ptr, 0); 48*39fd74dfSMykyta Yatsenko return 0; 49*39fd74dfSMykyta Yatsenko } 50*39fd74dfSMykyta Yatsenko 51*39fd74dfSMykyta Yatsenko int key = 0; 52*39fd74dfSMykyta Yatsenko 53*39fd74dfSMykyta Yatsenko SEC("perf_event") 54*39fd74dfSMykyta Yatsenko int oncpu_hash_map(struct pt_regs *args) 55*39fd74dfSMykyta Yatsenko { 56*39fd74dfSMykyta Yatsenko struct elem empty_work = { .data = { 0 } }; 57*39fd74dfSMykyta Yatsenko struct elem *work; 58*39fd74dfSMykyta Yatsenko struct task_struct *task; 59*39fd74dfSMykyta Yatsenko int err; 60*39fd74dfSMykyta Yatsenko 61*39fd74dfSMykyta Yatsenko task = bpf_get_current_task_btf(); 62*39fd74dfSMykyta Yatsenko err = bpf_map_update_elem(&hmap, &key, &empty_work, BPF_NOEXIST); 63*39fd74dfSMykyta Yatsenko if (err) 64*39fd74dfSMykyta Yatsenko return 0; 65*39fd74dfSMykyta Yatsenko work = bpf_map_lookup_elem(&hmap, &key); 66*39fd74dfSMykyta Yatsenko if (!work) 67*39fd74dfSMykyta Yatsenko return 0; 68*39fd74dfSMykyta Yatsenko 69*39fd74dfSMykyta Yatsenko bpf_task_work_schedule_resume(task, &work->tw, &hmap, process_work, NULL); 70*39fd74dfSMykyta Yatsenko return 0; 71*39fd74dfSMykyta Yatsenko } 72*39fd74dfSMykyta Yatsenko 73*39fd74dfSMykyta Yatsenko SEC("perf_event") 74*39fd74dfSMykyta Yatsenko int oncpu_array_map(struct pt_regs *args) 75*39fd74dfSMykyta Yatsenko { 76*39fd74dfSMykyta Yatsenko struct elem *work; 77*39fd74dfSMykyta Yatsenko struct task_struct *task; 78*39fd74dfSMykyta Yatsenko 79*39fd74dfSMykyta Yatsenko task = bpf_get_current_task_btf(); 80*39fd74dfSMykyta Yatsenko work = bpf_map_lookup_elem(&arrmap, &key); 81*39fd74dfSMykyta Yatsenko if (!work) 82*39fd74dfSMykyta Yatsenko return 0; 83*39fd74dfSMykyta Yatsenko bpf_task_work_schedule_signal(task, &work->tw, &arrmap, process_work, NULL); 84*39fd74dfSMykyta Yatsenko return 0; 85*39fd74dfSMykyta Yatsenko } 86*39fd74dfSMykyta Yatsenko 87*39fd74dfSMykyta Yatsenko SEC("perf_event") 88*39fd74dfSMykyta Yatsenko int oncpu_lru_map(struct pt_regs *args) 89*39fd74dfSMykyta Yatsenko { 90*39fd74dfSMykyta Yatsenko struct elem empty_work = { .data = { 0 } }; 91*39fd74dfSMykyta Yatsenko struct elem *work; 92*39fd74dfSMykyta Yatsenko struct task_struct *task; 93*39fd74dfSMykyta Yatsenko int err; 94*39fd74dfSMykyta Yatsenko 95*39fd74dfSMykyta Yatsenko task = bpf_get_current_task_btf(); 96*39fd74dfSMykyta Yatsenko work = bpf_map_lookup_elem(&lrumap, &key); 97*39fd74dfSMykyta Yatsenko if (work) 98*39fd74dfSMykyta Yatsenko return 0; 99*39fd74dfSMykyta Yatsenko err = bpf_map_update_elem(&lrumap, &key, &empty_work, BPF_NOEXIST); 100*39fd74dfSMykyta Yatsenko if (err) 101*39fd74dfSMykyta Yatsenko return 0; 102*39fd74dfSMykyta Yatsenko work = bpf_map_lookup_elem(&lrumap, &key); 103*39fd74dfSMykyta Yatsenko if (!work || work->data[0]) 104*39fd74dfSMykyta Yatsenko return 0; 105*39fd74dfSMykyta Yatsenko bpf_task_work_schedule_resume(task, &work->tw, &lrumap, process_work, NULL); 106*39fd74dfSMykyta Yatsenko return 0; 107*39fd74dfSMykyta Yatsenko } 108