| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
- * Copyright (c) 2024 David Vernet <dvernet@meta.com>
- */
- #include <bpf/bpf.h>
- #include <sched.h>
- #include <scx/common.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include "hotplug_test.h"
- #include "hotplug.bpf.skel.h"
- #include "scx_test.h"
- #include "util.h"
- const char *online_path = "/sys/devices/system/cpu/cpu1/online";
- static bool is_cpu_online(void)
- {
- return file_read_long(online_path) > 0;
- }
- static void toggle_online_status(bool online)
- {
- long val = online ? 1 : 0;
- int ret;
- ret = file_write_long(online_path, val);
- if (ret != 0)
- fprintf(stderr, "Failed to bring CPU %s (%s)",
- online ? "online" : "offline", strerror(errno));
- }
- static enum scx_test_status setup(void **ctx)
- {
- if (!is_cpu_online())
- return SCX_TEST_SKIP;
- return SCX_TEST_PASS;
- }
- static enum scx_test_status test_hotplug(bool onlining, bool cbs_defined)
- {
- struct hotplug *skel;
- struct bpf_link *link;
- long kind, code;
- SCX_ASSERT(is_cpu_online());
- skel = hotplug__open();
- SCX_FAIL_IF(!skel, "Failed to open");
- SCX_ENUM_INIT(skel);
- SCX_FAIL_IF(hotplug__load(skel), "Failed to load skel");
- /* Testing the offline -> online path, so go offline before starting */
- if (onlining)
- toggle_online_status(0);
- if (cbs_defined) {
- kind = SCX_KIND_VAL(SCX_EXIT_UNREG_BPF);
- code = SCX_ECODE_VAL(SCX_ECODE_ACT_RESTART) | HOTPLUG_EXIT_RSN;
- if (onlining)
- code |= HOTPLUG_ONLINING;
- } else {
- kind = SCX_KIND_VAL(SCX_EXIT_UNREG_KERN);
- code = SCX_ECODE_VAL(SCX_ECODE_ACT_RESTART) |
- SCX_ECODE_VAL(SCX_ECODE_RSN_HOTPLUG);
- }
- if (cbs_defined)
- link = bpf_map__attach_struct_ops(skel->maps.hotplug_cb_ops);
- else
- link = bpf_map__attach_struct_ops(skel->maps.hotplug_nocb_ops);
- if (!link) {
- SCX_ERR("Failed to attach scheduler");
- hotplug__destroy(skel);
- return SCX_TEST_FAIL;
- }
- toggle_online_status(onlining ? 1 : 0);
- while (!UEI_EXITED(skel, uei))
- sched_yield();
- SCX_EQ(skel->data->uei.kind, kind);
- SCX_EQ(UEI_REPORT(skel, uei), code);
- if (!onlining)
- toggle_online_status(1);
- bpf_link__destroy(link);
- hotplug__destroy(skel);
- return SCX_TEST_PASS;
- }
- static enum scx_test_status test_hotplug_attach(void)
- {
- struct hotplug *skel;
- struct bpf_link *link;
- enum scx_test_status status = SCX_TEST_PASS;
- long kind, code;
- SCX_ASSERT(is_cpu_online());
- SCX_ASSERT(scx_hotplug_seq() > 0);
- skel = SCX_OPS_OPEN(hotplug_nocb_ops, hotplug);
- SCX_ASSERT(skel);
- SCX_OPS_LOAD(skel, hotplug_nocb_ops, hotplug, uei);
- /*
- * Take the CPU offline to increment the global hotplug seq, which
- * should cause attach to fail due to us setting the hotplug seq above
- */
- toggle_online_status(0);
- link = bpf_map__attach_struct_ops(skel->maps.hotplug_nocb_ops);
- toggle_online_status(1);
- SCX_ASSERT(link);
- while (!UEI_EXITED(skel, uei))
- sched_yield();
- kind = SCX_KIND_VAL(SCX_EXIT_UNREG_KERN);
- code = SCX_ECODE_VAL(SCX_ECODE_ACT_RESTART) |
- SCX_ECODE_VAL(SCX_ECODE_RSN_HOTPLUG);
- SCX_EQ(skel->data->uei.kind, kind);
- SCX_EQ(UEI_REPORT(skel, uei), code);
- bpf_link__destroy(link);
- hotplug__destroy(skel);
- return status;
- }
- static enum scx_test_status run(void *ctx)
- {
- #define HP_TEST(__onlining, __cbs_defined) ({ \
- if (test_hotplug(__onlining, __cbs_defined) != SCX_TEST_PASS) \
- return SCX_TEST_FAIL; \
- })
- HP_TEST(true, true);
- HP_TEST(false, true);
- HP_TEST(true, false);
- HP_TEST(false, false);
- #undef HP_TEST
- return test_hotplug_attach();
- }
- static void cleanup(void *ctx)
- {
- toggle_online_status(1);
- }
- struct scx_test hotplug_test = {
- .name = "hotplug",
- .description = "Verify hotplug behavior",
- .setup = setup,
- .run = run,
- .cleanup = cleanup,
- };
- REGISTER_SCX_TEST(&hotplug_test)
|