at master 3.8 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (c) 2024 Meta Platforms, Inc. and affiliates. 4 * Copyright (c) 2024 David Vernet <dvernet@meta.com> 5 */ 6#include <bpf/bpf.h> 7#include <sched.h> 8#include <scx/common.h> 9#include <sys/wait.h> 10#include <unistd.h> 11 12#include "hotplug_test.h" 13#include "hotplug.bpf.skel.h" 14#include "scx_test.h" 15#include "util.h" 16 17const char *online_path = "/sys/devices/system/cpu/cpu1/online"; 18 19static bool is_cpu_online(void) 20{ 21 return file_read_long(online_path) > 0; 22} 23 24static void toggle_online_status(bool online) 25{ 26 long val = online ? 1 : 0; 27 int ret; 28 29 ret = file_write_long(online_path, val); 30 if (ret != 0) 31 fprintf(stderr, "Failed to bring CPU %s (%s)", 32 online ? "online" : "offline", strerror(errno)); 33} 34 35static enum scx_test_status setup(void **ctx) 36{ 37 if (!is_cpu_online()) 38 return SCX_TEST_SKIP; 39 40 return SCX_TEST_PASS; 41} 42 43static enum scx_test_status test_hotplug(bool onlining, bool cbs_defined) 44{ 45 struct hotplug *skel; 46 struct bpf_link *link; 47 long kind, code; 48 49 SCX_ASSERT(is_cpu_online()); 50 51 skel = hotplug__open(); 52 SCX_FAIL_IF(!skel, "Failed to open"); 53 SCX_ENUM_INIT(skel); 54 SCX_FAIL_IF(hotplug__load(skel), "Failed to load skel"); 55 56 /* Testing the offline -> online path, so go offline before starting */ 57 if (onlining) 58 toggle_online_status(0); 59 60 if (cbs_defined) { 61 kind = SCX_KIND_VAL(SCX_EXIT_UNREG_BPF); 62 code = SCX_ECODE_VAL(SCX_ECODE_ACT_RESTART) | HOTPLUG_EXIT_RSN; 63 if (onlining) 64 code |= HOTPLUG_ONLINING; 65 } else { 66 kind = SCX_KIND_VAL(SCX_EXIT_UNREG_KERN); 67 code = SCX_ECODE_VAL(SCX_ECODE_ACT_RESTART) | 68 SCX_ECODE_VAL(SCX_ECODE_RSN_HOTPLUG); 69 } 70 71 if (cbs_defined) 72 link = bpf_map__attach_struct_ops(skel->maps.hotplug_cb_ops); 73 else 74 link = bpf_map__attach_struct_ops(skel->maps.hotplug_nocb_ops); 75 76 if (!link) { 77 SCX_ERR("Failed to attach scheduler"); 78 hotplug__destroy(skel); 79 return SCX_TEST_FAIL; 80 } 81 82 toggle_online_status(onlining ? 1 : 0); 83 84 while (!UEI_EXITED(skel, uei)) 85 sched_yield(); 86 87 SCX_EQ(skel->data->uei.kind, kind); 88 SCX_EQ(UEI_REPORT(skel, uei), code); 89 90 if (!onlining) 91 toggle_online_status(1); 92 93 bpf_link__destroy(link); 94 hotplug__destroy(skel); 95 96 return SCX_TEST_PASS; 97} 98 99static enum scx_test_status test_hotplug_attach(void) 100{ 101 struct hotplug *skel; 102 struct bpf_link *link; 103 enum scx_test_status status = SCX_TEST_PASS; 104 long kind, code; 105 106 SCX_ASSERT(is_cpu_online()); 107 SCX_ASSERT(scx_hotplug_seq() > 0); 108 109 skel = SCX_OPS_OPEN(hotplug_nocb_ops, hotplug); 110 SCX_ASSERT(skel); 111 112 SCX_OPS_LOAD(skel, hotplug_nocb_ops, hotplug, uei); 113 114 /* 115 * Take the CPU offline to increment the global hotplug seq, which 116 * should cause attach to fail due to us setting the hotplug seq above 117 */ 118 toggle_online_status(0); 119 link = bpf_map__attach_struct_ops(skel->maps.hotplug_nocb_ops); 120 121 toggle_online_status(1); 122 123 SCX_ASSERT(link); 124 while (!UEI_EXITED(skel, uei)) 125 sched_yield(); 126 127 kind = SCX_KIND_VAL(SCX_EXIT_UNREG_KERN); 128 code = SCX_ECODE_VAL(SCX_ECODE_ACT_RESTART) | 129 SCX_ECODE_VAL(SCX_ECODE_RSN_HOTPLUG); 130 SCX_EQ(skel->data->uei.kind, kind); 131 SCX_EQ(UEI_REPORT(skel, uei), code); 132 133 bpf_link__destroy(link); 134 hotplug__destroy(skel); 135 136 return status; 137} 138 139static enum scx_test_status run(void *ctx) 140{ 141 142#define HP_TEST(__onlining, __cbs_defined) ({ \ 143 if (test_hotplug(__onlining, __cbs_defined) != SCX_TEST_PASS) \ 144 return SCX_TEST_FAIL; \ 145}) 146 147 HP_TEST(true, true); 148 HP_TEST(false, true); 149 HP_TEST(true, false); 150 HP_TEST(false, false); 151 152#undef HP_TEST 153 154 return test_hotplug_attach(); 155} 156 157static void cleanup(void *ctx) 158{ 159 toggle_online_status(1); 160} 161 162struct scx_test hotplug_test = { 163 .name = "hotplug", 164 .description = "Verify hotplug behavior", 165 .setup = setup, 166 .run = run, 167 .cleanup = cleanup, 168}; 169REGISTER_SCX_TEST(&hotplug_test)