Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186/* 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 int 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)\n", online ? "online" : "offline", strerror(errno));
return ret;}
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; enum scx_test_status status = SCX_TEST_FAIL; 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)) goto out_destroy_skel;
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; }
if (toggle_online_status(onlining ? 1 : 0)) goto out_destroy_link;
if (!SCX_TIMED_WAIT_UEI(skel, uei, 10000)) { SCX_ERR("Timed out waiting for scheduler to exit"); goto out_destroy_link; }
SCX_EQ(skel->data->uei.kind, kind); SCX_EQ(UEI_REPORT(skel, uei), code);
if (!onlining && toggle_online_status(1)) goto out_destroy_link;
status = SCX_TEST_PASS;out_destroy_link: bpf_link__destroy(link);out_destroy_skel: hotplug__destroy(skel);
return status;}
static enum scx_test_status test_hotplug_attach(void){ struct hotplug *skel; struct bpf_link *link; enum scx_test_status status = SCX_TEST_FAIL; 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 */ if (toggle_online_status(0)) goto out_destroy_skel; link = bpf_map__attach_struct_ops(skel->maps.hotplug_nocb_ops);
if (toggle_online_status(1)) goto out_destroy_link;
SCX_ASSERT(link); if (!SCX_TIMED_WAIT_UEI(skel, uei, 10000)) { SCX_ERR("Timed out waiting for scheduler to exit"); goto out_destroy_link; }
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);
status = SCX_TEST_PASS;out_destroy_link: bpf_link__destroy(link);out_destroy_skel: 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)