116f0efc3SYonghong Song // SPDX-License-Identifier: GPL-2.0 216f0efc3SYonghong Song #include <test_progs.h> 3ab8b7f0cSYonghong Song #include "test_send_signal_kern.skel.h" 416f0efc3SYonghong Song 5256eab48SAndrii Nakryiko int sigusr1_received = 0; 616f0efc3SYonghong Song 716f0efc3SYonghong Song static void sigusr1_handler(int signum) 816f0efc3SYonghong Song { 916f0efc3SYonghong Song sigusr1_received++; 1016f0efc3SYonghong Song } 1116f0efc3SYonghong Song 1286ccc384SStanislav Fomichev static void test_send_signal_common(struct perf_event_attr *attr, 13*6f6cc426SYonghong Song bool signal_thread) 1416f0efc3SYonghong Song { 15ab8b7f0cSYonghong Song struct test_send_signal_kern *skel; 1616f0efc3SYonghong Song int pipe_c2p[2], pipe_p2c[2]; 17ab8b7f0cSYonghong Song int err = -1, pmu_fd = -1; 1816f0efc3SYonghong Song char buf[256]; 1916f0efc3SYonghong Song pid_t pid; 2016f0efc3SYonghong Song 21*6f6cc426SYonghong Song if (!ASSERT_OK(pipe(pipe_c2p), "pipe_c2p")) 2286ccc384SStanislav Fomichev return; 2316f0efc3SYonghong Song 24*6f6cc426SYonghong Song if (!ASSERT_OK(pipe(pipe_p2c), "pipe_p2c")) { 2516f0efc3SYonghong Song close(pipe_c2p[0]); 2616f0efc3SYonghong Song close(pipe_c2p[1]); 2786ccc384SStanislav Fomichev return; 2816f0efc3SYonghong Song } 2916f0efc3SYonghong Song 3016f0efc3SYonghong Song pid = fork(); 31*6f6cc426SYonghong Song if (!ASSERT_GE(pid, 0, "fork")) { 3216f0efc3SYonghong Song close(pipe_c2p[0]); 3316f0efc3SYonghong Song close(pipe_c2p[1]); 3416f0efc3SYonghong Song close(pipe_p2c[0]); 3516f0efc3SYonghong Song close(pipe_p2c[1]); 3686ccc384SStanislav Fomichev return; 3716f0efc3SYonghong Song } 3816f0efc3SYonghong Song 3916f0efc3SYonghong Song if (pid == 0) { 4016f0efc3SYonghong Song /* install signal handler and notify parent */ 4116f0efc3SYonghong Song signal(SIGUSR1, sigusr1_handler); 4216f0efc3SYonghong Song 4316f0efc3SYonghong Song close(pipe_c2p[0]); /* close read */ 4416f0efc3SYonghong Song close(pipe_p2c[1]); /* close write */ 4516f0efc3SYonghong Song 4616f0efc3SYonghong Song /* notify parent signal handler is installed */ 47*6f6cc426SYonghong Song ASSERT_EQ(write(pipe_c2p[1], buf, 1), 1, "pipe_write"); 4816f0efc3SYonghong Song 4916f0efc3SYonghong Song /* make sure parent enabled bpf program to send_signal */ 50*6f6cc426SYonghong Song ASSERT_EQ(read(pipe_p2c[0], buf, 1), 1, "pipe_read"); 5116f0efc3SYonghong Song 5216f0efc3SYonghong Song /* wait a little for signal handler */ 5316f0efc3SYonghong Song sleep(1); 5416f0efc3SYonghong Song 55929e54a9SJianlin Lv buf[0] = sigusr1_received ? '2' : '0'; 56*6f6cc426SYonghong Song ASSERT_EQ(write(pipe_c2p[1], buf, 1), 1, "pipe_write"); 5716f0efc3SYonghong Song 5816f0efc3SYonghong Song /* wait for parent notification and exit */ 59*6f6cc426SYonghong Song ASSERT_EQ(read(pipe_p2c[0], buf, 1), 1, "pipe_read"); 6016f0efc3SYonghong Song 6116f0efc3SYonghong Song close(pipe_c2p[1]); 6216f0efc3SYonghong Song close(pipe_p2c[0]); 6316f0efc3SYonghong Song exit(0); 6416f0efc3SYonghong Song } 6516f0efc3SYonghong Song 6616f0efc3SYonghong Song close(pipe_c2p[1]); /* close write */ 6716f0efc3SYonghong Song close(pipe_p2c[0]); /* close read */ 6816f0efc3SYonghong Song 69ab8b7f0cSYonghong Song skel = test_send_signal_kern__open_and_load(); 70*6f6cc426SYonghong Song if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 71ab8b7f0cSYonghong Song goto skel_open_load_failure; 7216f0efc3SYonghong Song 73ab8b7f0cSYonghong Song if (!attr) { 74ab8b7f0cSYonghong Song err = test_send_signal_kern__attach(skel); 75*6f6cc426SYonghong Song if (!ASSERT_OK(err, "skel_attach")) { 76ab8b7f0cSYonghong Song err = -1; 77ab8b7f0cSYonghong Song goto destroy_skel; 78ab8b7f0cSYonghong Song } 79ab8b7f0cSYonghong Song } else { 8016f0efc3SYonghong Song pmu_fd = syscall(__NR_perf_event_open, attr, pid, -1, 8116f0efc3SYonghong Song -1 /* group id */, 0 /* flags */); 82*6f6cc426SYonghong Song if (!ASSERT_GE(pmu_fd, 0, "perf_event_open")) { 8316f0efc3SYonghong Song err = -1; 84ab8b7f0cSYonghong Song goto destroy_skel; 8516f0efc3SYonghong Song } 8616f0efc3SYonghong Song 87ab8b7f0cSYonghong Song skel->links.send_signal_perf = 88ab8b7f0cSYonghong Song bpf_program__attach_perf_event(skel->progs.send_signal_perf, pmu_fd); 89bad2e478SAndrii Nakryiko if (!ASSERT_OK_PTR(skel->links.send_signal_perf, "attach_perf_event")) 9016f0efc3SYonghong Song goto disable_pmu; 91ab8b7f0cSYonghong Song } 9216f0efc3SYonghong Song 9316f0efc3SYonghong Song /* wait until child signal handler installed */ 94*6f6cc426SYonghong Song ASSERT_EQ(read(pipe_c2p[0], buf, 1), 1, "pipe_read"); 9516f0efc3SYonghong Song 9616f0efc3SYonghong Song /* trigger the bpf send_signal */ 97ab8b7f0cSYonghong Song skel->bss->pid = pid; 98ab8b7f0cSYonghong Song skel->bss->sig = SIGUSR1; 99ab8b7f0cSYonghong Song skel->bss->signal_thread = signal_thread; 10016f0efc3SYonghong Song 10116f0efc3SYonghong Song /* notify child that bpf program can send_signal now */ 102*6f6cc426SYonghong Song ASSERT_EQ(write(pipe_p2c[1], buf, 1), 1, "pipe_write"); 10316f0efc3SYonghong Song 10416f0efc3SYonghong Song /* wait for result */ 10516f0efc3SYonghong Song err = read(pipe_c2p[0], buf, 1); 106*6f6cc426SYonghong Song if (!ASSERT_GE(err, 0, "reading pipe")) 10716f0efc3SYonghong Song goto disable_pmu; 108*6f6cc426SYonghong Song if (!ASSERT_GT(err, 0, "reading pipe error: size 0")) { 10916f0efc3SYonghong Song err = -1; 11016f0efc3SYonghong Song goto disable_pmu; 11116f0efc3SYonghong Song } 11216f0efc3SYonghong Song 113*6f6cc426SYonghong Song ASSERT_EQ(buf[0], '2', "incorrect result"); 11416f0efc3SYonghong Song 11516f0efc3SYonghong Song /* notify child safe to exit */ 116*6f6cc426SYonghong Song ASSERT_EQ(write(pipe_p2c[1], buf, 1), 1, "pipe_write"); 11716f0efc3SYonghong Song 11816f0efc3SYonghong Song disable_pmu: 11916f0efc3SYonghong Song close(pmu_fd); 120ab8b7f0cSYonghong Song destroy_skel: 121ab8b7f0cSYonghong Song test_send_signal_kern__destroy(skel); 122ab8b7f0cSYonghong Song skel_open_load_failure: 12316f0efc3SYonghong Song close(pipe_c2p[0]); 12416f0efc3SYonghong Song close(pipe_p2c[1]); 12516f0efc3SYonghong Song wait(NULL); 12616f0efc3SYonghong Song } 12716f0efc3SYonghong Song 128ab8b7f0cSYonghong Song static void test_send_signal_tracepoint(bool signal_thread) 12916f0efc3SYonghong Song { 130*6f6cc426SYonghong Song test_send_signal_common(NULL, signal_thread); 13116f0efc3SYonghong Song } 13216f0efc3SYonghong Song 133ab8b7f0cSYonghong Song static void test_send_signal_perf(bool signal_thread) 1344e59afbbSIlya Leoshkevich { 1354e59afbbSIlya Leoshkevich struct perf_event_attr attr = { 1364e59afbbSIlya Leoshkevich .sample_period = 1, 1374e59afbbSIlya Leoshkevich .type = PERF_TYPE_SOFTWARE, 1384e59afbbSIlya Leoshkevich .config = PERF_COUNT_SW_CPU_CLOCK, 1394e59afbbSIlya Leoshkevich }; 1404e59afbbSIlya Leoshkevich 141*6f6cc426SYonghong Song test_send_signal_common(&attr, signal_thread); 1424e59afbbSIlya Leoshkevich } 1434e59afbbSIlya Leoshkevich 144ab8b7f0cSYonghong Song static void test_send_signal_nmi(bool signal_thread) 14516f0efc3SYonghong Song { 14616f0efc3SYonghong Song struct perf_event_attr attr = { 14735697c12SYonghong Song .sample_period = 1, 14816f0efc3SYonghong Song .type = PERF_TYPE_HARDWARE, 14916f0efc3SYonghong Song .config = PERF_COUNT_HW_CPU_CYCLES, 15016f0efc3SYonghong Song }; 1514e59afbbSIlya Leoshkevich int pmu_fd; 15216f0efc3SYonghong Song 1534e59afbbSIlya Leoshkevich /* Some setups (e.g. virtual machines) might run with hardware 1544e59afbbSIlya Leoshkevich * perf events disabled. If this is the case, skip this test. 1554e59afbbSIlya Leoshkevich */ 1564e59afbbSIlya Leoshkevich pmu_fd = syscall(__NR_perf_event_open, &attr, 0 /* pid */, 1574e59afbbSIlya Leoshkevich -1 /* cpu */, -1 /* group_fd */, 0 /* flags */); 1584e59afbbSIlya Leoshkevich if (pmu_fd == -1) { 1594e59afbbSIlya Leoshkevich if (errno == ENOENT) { 16066bd2ec1SStanislav Fomichev printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n", 1614e59afbbSIlya Leoshkevich __func__); 162cd9c21d7SStanislav Fomichev test__skip(); 16386ccc384SStanislav Fomichev return; 1644e59afbbSIlya Leoshkevich } 1654e59afbbSIlya Leoshkevich /* Let the test fail with a more informative message */ 1664e59afbbSIlya Leoshkevich } else { 1674e59afbbSIlya Leoshkevich close(pmu_fd); 1684e59afbbSIlya Leoshkevich } 1694e59afbbSIlya Leoshkevich 170*6f6cc426SYonghong Song test_send_signal_common(&attr, signal_thread); 17116f0efc3SYonghong Song } 17216f0efc3SYonghong Song 17316f0efc3SYonghong Song void test_send_signal(void) 17416f0efc3SYonghong Song { 175b207edfeSAndrii Nakryiko if (test__start_subtest("send_signal_tracepoint")) 176ab8b7f0cSYonghong Song test_send_signal_tracepoint(false); 177b207edfeSAndrii Nakryiko if (test__start_subtest("send_signal_perf")) 178ab8b7f0cSYonghong Song test_send_signal_perf(false); 179b207edfeSAndrii Nakryiko if (test__start_subtest("send_signal_nmi")) 180ab8b7f0cSYonghong Song test_send_signal_nmi(false); 181ab8b7f0cSYonghong Song if (test__start_subtest("send_signal_tracepoint_thread")) 182ab8b7f0cSYonghong Song test_send_signal_tracepoint(true); 183ab8b7f0cSYonghong Song if (test__start_subtest("send_signal_perf_thread")) 184ab8b7f0cSYonghong Song test_send_signal_perf(true); 185ab8b7f0cSYonghong Song if (test__start_subtest("send_signal_nmi_thread")) 186ab8b7f0cSYonghong Song test_send_signal_nmi(true); 18716f0efc3SYonghong Song } 188