Merge "bpfprogs: Add bpf kswapd wake/sleep progs for LMKD" into main
diff --git a/libmemevents/bpfprogs/bpfMemEvents.c b/libmemevents/bpfprogs/bpfMemEvents.c
index f74e4c1..acac056 100644
--- a/libmemevents/bpfprogs/bpfMemEvents.c
+++ b/libmemevents/bpfprogs/bpfMemEvents.c
@@ -77,5 +77,35 @@
     return 0;
 }
 
+DEFINE_BPF_PROG("tracepoint/vmscan/mm_vmscan_kswapd_wake/lmkd", AID_ROOT, AID_SYSTEM,
+                tp_lmkd_kswapd_wake)
+(struct kswapd_wake_args* args) {
+    struct mem_event_t* data = bpf_lmkd_rb_reserve();
+    if (data == NULL) return 1;
+
+    data->type = MEM_EVENT_KSWAPD_WAKE;
+    data->event_data.kswapd_wake.node_id = args->nid;
+    data->event_data.kswapd_wake.zone_id = args->zid;
+    data->event_data.kswapd_wake.alloc_order = args->order;
+
+    bpf_lmkd_rb_submit(data);
+
+    return 0;
+}
+
+DEFINE_BPF_PROG("tracepoint/vmscan/mm_vmscan_kswapd_sleep/lmkd", AID_ROOT, AID_SYSTEM,
+                tp_lmkd_kswapd_sleep)
+(struct kswapd_sleep_args* args) {
+    struct mem_event_t* data = bpf_lmkd_rb_reserve();
+    if (data == NULL) return 1;
+
+    data->type = MEM_EVENT_KSWAPD_SLEEP;
+    data->event_data.kswapd_wake.node_id = args->nid;
+
+    bpf_lmkd_rb_submit(data);
+
+    return 0;
+}
+
 // bpf_probe_read_str is GPL only symbol
 LICENSE("GPL");
diff --git a/libmemevents/bpfprogs/bpfMemEventsTest.c b/libmemevents/bpfprogs/bpfMemEventsTest.c
index ea7013e..1d7bfb9 100644
--- a/libmemevents/bpfprogs/bpfMemEventsTest.c
+++ b/libmemevents/bpfprogs/bpfMemEventsTest.c
@@ -96,5 +96,37 @@
     return 0;
 }
 
+DEFINE_BPF_PROG_KVER("skfilter/kswapd_wake", AID_ROOT, AID_ROOT, tp_memevents_test_kswapd_wake,
+                     KVER(5, 8, 0))
+(void* unused_ctx) {
+    struct mem_event_t* data = bpf_rb_reserve();
+    if (data == NULL) return 1;
+
+    data->type = MEM_EVENT_KSWAPD_WAKE;
+    data->event_data.kswapd_wake.node_id = mocked_kswapd_wake_event.event_data.kswapd_wake.node_id;
+    data->event_data.kswapd_wake.zone_id = mocked_kswapd_wake_event.event_data.kswapd_wake.zone_id;
+    data->event_data.kswapd_wake.alloc_order =
+            mocked_kswapd_wake_event.event_data.kswapd_wake.alloc_order;
+
+    bpf_rb_submit(data);
+
+    return 0;
+}
+
+DEFINE_BPF_PROG_KVER("skfilter/kswapd_sleep", AID_ROOT, AID_ROOT, tp_memevents_test_kswapd_sleep,
+                     KVER(5, 8, 0))
+(void* unused_ctx) {
+    struct mem_event_t* data = bpf_rb_reserve();
+    if (data == NULL) return 1;
+
+    data->type = MEM_EVENT_KSWAPD_SLEEP;
+    data->event_data.kswapd_sleep.node_id =
+            mocked_kswapd_sleep_event.event_data.kswapd_sleep.node_id;
+
+    bpf_rb_submit(data);
+
+    return 0;
+}
+
 // bpf_probe_read_str is GPL only symbol
 LICENSE("GPL");
diff --git a/libmemevents/include/memevents/bpf_types.h b/libmemevents/include/memevents/bpf_types.h
index 7d0514d..9bdb4ab 100644
--- a/libmemevents/include/memevents/bpf_types.h
+++ b/libmemevents/include/memevents/bpf_types.h
@@ -28,9 +28,11 @@
 #define MEM_EVENT_BASE MEM_EVENT_OOM_KILL
 #define MEM_EVENT_DIRECT_RECLAIM_BEGIN 1
 #define MEM_EVENT_DIRECT_RECLAIM_END 2
+#define MEM_EVENT_KSWAPD_WAKE 3
+#define MEM_EVENT_KSWAPD_SLEEP 4
 
 // This always comes after the last valid event type
-#define NR_MEM_EVENTS 3
+#define NR_MEM_EVENTS 5
 
 /* BPF-Rb Paths */
 #define MEM_EVENTS_AMS_RB "/sys/fs/bpf/map_bpfMemEvents_ams_rb"
@@ -44,6 +46,10 @@
     "/sys/fs/bpf/prog_bpfMemEvents_tracepoint_vmscan_mm_vmscan_direct_reclaim_begin_lmkd"
 #define MEM_EVENTS_LMKD_VMSCAN_DR_END_TP \
     "/sys/fs/bpf/prog_bpfMemEvents_tracepoint_vmscan_mm_vmscan_direct_reclaim_end_lmkd"
+#define MEM_EVENTS_LMKD_VMSCAN_KSWAPD_WAKE_TP \
+    "/sys/fs/bpf/prog_bpfMemEvents_tracepoint_vmscan_mm_vmscan_kswapd_wake_lmkd"
+#define MEM_EVENTS_LMKD_VMSCAN_KSWAPD_SLEEP_TP \
+    "/sys/fs/bpf/prog_bpfMemEvents_tracepoint_vmscan_mm_vmscan_kswapd_sleep_lmkd"
 #define MEM_EVENTS_TEST_OOM_MARK_VICTIM_TP \
     "/sys/fs/bpf/prog_bpfMemEventsTest_tracepoint_oom_mark_victim"
 
@@ -59,6 +65,16 @@
             uint32_t uid;
             char process_name[MEM_EVENT_PROC_NAME_LEN];
         } oom_kill;
+
+        struct KswapdWake {
+            uint32_t node_id;
+            uint32_t zone_id;
+            uint32_t alloc_order;
+        } kswapd_wake;
+
+        struct KswapdSleep {
+            uint32_t node_id;
+        } kswapd_sleep;
     } event_data;
 };
 
@@ -81,4 +97,18 @@
     char __ignore[16];
 };
 
+struct kswapd_wake_args {
+    uint64_t __ignore;
+    /* Actual fields start at offset 8 */
+    uint32_t nid;
+    uint32_t zid;
+    uint32_t order;
+};
+
+struct kswapd_sleep_args {
+    uint64_t __ignore;
+    /* Actual fields start at offset 8 */
+    uint32_t nid;
+};
+
 #endif /* MEM_EVENTS_BPF_TYES_H_ */
diff --git a/libmemevents/include/memevents/memevents_test.h b/libmemevents/include/memevents/memevents_test.h
index 7b6638b..c07477a 100644
--- a/libmemevents/include/memevents/memevents_test.h
+++ b/libmemevents/include/memevents/memevents_test.h
@@ -27,6 +27,8 @@
     "/sys/fs/bpf/prog_bpfMemEventsTest_skfilter_direct_reclaim_begin"
 #define MEM_EVENTS_TEST_DIRECT_RECLAIM_END_TP \
     "/sys/fs/bpf/prog_bpfMemEventsTest_skfilter_direct_reclaim_end"
+#define MEM_EVENTS_TEST_KSWAPD_WAKE_TP "/sys/fs/bpf/prog_bpfMemEventsTest_skfilter_kswapd_wake"
+#define MEM_EVENTS_TEST_KSWAPD_SLEEP_TP "/sys/fs/bpf/prog_bpfMemEventsTest_skfilter_kswapd_sleep"
 
 // clang-format off
 const struct mem_event_t mocked_oom_event = {
@@ -38,6 +40,20 @@
         .timestamp_ms = 1,
         .oom_score_adj = 999,
 }};
+
+const struct mem_event_t mocked_kswapd_wake_event = {
+     .type = MEM_EVENT_KSWAPD_WAKE,
+     .event_data.kswapd_wake = {
+        .node_id = 1,
+        .zone_id = 0,
+        .alloc_order = 2,
+}};
+
+const struct mem_event_t mocked_kswapd_sleep_event = {
+     .type = MEM_EVENT_KSWAPD_SLEEP,
+     .event_data.kswapd_sleep = {
+        .node_id = 3,
+}};
 // clang-format on
 
 #endif /* MEM_EVENTS_TEST_H_ */
\ No newline at end of file
diff --git a/libmemevents/memevents_test.cpp b/libmemevents/memevents_test.cpp
index b846e38..c8a78d0 100644
--- a/libmemevents/memevents_test.cpp
+++ b/libmemevents/memevents_test.cpp
@@ -50,7 +50,8 @@
         MEM_EVENTS_AMS_RB, MEM_EVENTS_LMKD_RB, MEM_EVENTS_TEST_RB};
 static const std::string testBpfSkfilterProgPaths[NR_MEM_EVENTS] = {
         MEM_EVENTS_TEST_OOM_KILL_TP, MEM_EVENTS_TEST_DIRECT_RECLAIM_START_TP,
-        MEM_EVENTS_TEST_DIRECT_RECLAIM_END_TP};
+        MEM_EVENTS_TEST_DIRECT_RECLAIM_END_TP, MEM_EVENTS_TEST_KSWAPD_WAKE_TP,
+        MEM_EVENTS_TEST_KSWAPD_SLEEP_TP};
 static const std::filesystem::path sysrq_trigger_path = "proc/sysrq-trigger";
 
 /*