File Index
Files and directories
Sign in
FILE

hotplug.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/sched_ext/hotplug.c C
  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)
~/ Read-only file preview.