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