1*387f9dfdSAndroid Build Coastguard Worker /* 2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2017 Facebook, Inc. 3*387f9dfdSAndroid Build Coastguard Worker * 4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*387f9dfdSAndroid Build Coastguard Worker * 8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*387f9dfdSAndroid Build Coastguard Worker * 10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License. 15*387f9dfdSAndroid Build Coastguard Worker */ 16*387f9dfdSAndroid Build Coastguard Worker 17*387f9dfdSAndroid Build Coastguard Worker #include <linux/perf_event.h> 18*387f9dfdSAndroid Build Coastguard Worker #include <linux/version.h> 19*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h> 20*387f9dfdSAndroid Build Coastguard Worker #include <string> 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h" 23*387f9dfdSAndroid Build Coastguard Worker #include "catch.hpp" 24*387f9dfdSAndroid Build Coastguard Worker 25*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test read perf event", "[bpf_perf_event]") { 26*387f9dfdSAndroid Build Coastguard Worker // The basic bpf_perf_event_read is supported since Kernel 4.3. However in that 27*387f9dfdSAndroid Build Coastguard Worker // version it only supported HARDWARE and RAW events. On the other hand, our 28*387f9dfdSAndroid Build Coastguard Worker // tests running on Jenkins won't have available HARDWARE counters since they 29*387f9dfdSAndroid Build Coastguard Worker // are running on VMs. The support of other types of events such as SOFTWARE are 30*387f9dfdSAndroid Build Coastguard Worker // only added since Kernel 4.13, hence we can only run the test since that. 31*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) 32*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 33*387f9dfdSAndroid Build Coastguard Worker BPF_PERF_ARRAY(cnt, NUM_CPUS); 34*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(val, int, u64, 1); 35*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(ret, int, int, 1); 36*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(counter, int, struct bpf_perf_event_value, 1); 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker int on_sys_getuid(void *ctx) { 39*387f9dfdSAndroid Build Coastguard Worker int zero = 0; 40*387f9dfdSAndroid Build Coastguard Worker 41*387f9dfdSAndroid Build Coastguard Worker u64 v = cnt.perf_read(CUR_CPU_IDENTIFIER); 42*387f9dfdSAndroid Build Coastguard Worker if (((s64)v < 0) && ((s64)v > -256)) 43*387f9dfdSAndroid Build Coastguard Worker return 0; 44*387f9dfdSAndroid Build Coastguard Worker val.update(&zero, &v); 45*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 46*387f9dfdSAndroid Build Coastguard Worker u32 cpu = bpf_get_smp_processor_id(); 47*387f9dfdSAndroid Build Coastguard Worker struct bpf_perf_event_value c = {0}; 48*387f9dfdSAndroid Build Coastguard Worker int r = cnt.perf_counter_value(cpu, &c, sizeof(c)); 49*387f9dfdSAndroid Build Coastguard Worker ret.update(&zero, &r); 50*387f9dfdSAndroid Build Coastguard Worker counter.update(&zero, &c); 51*387f9dfdSAndroid Build Coastguard Worker #endif 52*387f9dfdSAndroid Build Coastguard Worker return 0; 53*387f9dfdSAndroid Build Coastguard Worker } 54*387f9dfdSAndroid Build Coastguard Worker )"; 55*387f9dfdSAndroid Build Coastguard Worker 56*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 57*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 58*387f9dfdSAndroid Build Coastguard Worker res = bpf.init( 59*387f9dfdSAndroid Build Coastguard Worker BPF_PROGRAM, 60*387f9dfdSAndroid Build Coastguard Worker {"-DNUM_CPUS=" + std::to_string(sysconf(_SC_NPROCESSORS_ONLN))}, {}); 61*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 62*387f9dfdSAndroid Build Coastguard Worker int pid = getpid(); 63*387f9dfdSAndroid Build Coastguard Worker res = 64*387f9dfdSAndroid Build Coastguard Worker bpf.open_perf_event("cnt", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, pid); 65*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 66*387f9dfdSAndroid Build Coastguard Worker std::string getuid_fnname = bpf.get_syscall_fnname("getuid"); 67*387f9dfdSAndroid Build Coastguard Worker res = bpf.attach_kprobe(getuid_fnname, "on_sys_getuid"); 68*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 69*387f9dfdSAndroid Build Coastguard Worker REQUIRE(getuid() >= 0); 70*387f9dfdSAndroid Build Coastguard Worker res = bpf.detach_kprobe(getuid_fnname); 71*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 72*387f9dfdSAndroid Build Coastguard Worker res = bpf.close_perf_event("cnt"); 73*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 74*387f9dfdSAndroid Build Coastguard Worker 75*387f9dfdSAndroid Build Coastguard Worker auto val = bpf.get_hash_table<int, uint64_t>("val"); 76*387f9dfdSAndroid Build Coastguard Worker REQUIRE(val[0] >= 0); 77*387f9dfdSAndroid Build Coastguard Worker #endif 78*387f9dfdSAndroid Build Coastguard Worker 79*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 80*387f9dfdSAndroid Build Coastguard Worker auto counter_table = 81*387f9dfdSAndroid Build Coastguard Worker bpf.get_hash_table<int, struct bpf_perf_event_value>("counter"); 82*387f9dfdSAndroid Build Coastguard Worker auto counter = counter_table[0]; 83*387f9dfdSAndroid Build Coastguard Worker auto ret = bpf.get_hash_table<int, int>("ret"); 84*387f9dfdSAndroid Build Coastguard Worker REQUIRE(ret[0] == 0); 85*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.counter >= 0); 86*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.enabled > 0); 87*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.running >= 0); 88*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.running <= counter.enabled); 89*387f9dfdSAndroid Build Coastguard Worker #endif 90*387f9dfdSAndroid Build Coastguard Worker } 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test attach perf event", "[bpf_perf_event]") { 93*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) 94*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 95*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(pid, int, u64, 1); 96*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(ret, int, int, 1); 97*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(counter, int, struct bpf_perf_event_value, 1); 98*387f9dfdSAndroid Build Coastguard Worker 99*387f9dfdSAndroid Build Coastguard Worker int on_event(void *ctx) { 100*387f9dfdSAndroid Build Coastguard Worker int zero = 0; 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Worker u64 p = bpf_get_current_pid_tgid(); 103*387f9dfdSAndroid Build Coastguard Worker pid.update(&zero, &p); 104*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 105*387f9dfdSAndroid Build Coastguard Worker struct bpf_perf_event_value c = {0}; 106*387f9dfdSAndroid Build Coastguard Worker int r = bpf_perf_prog_read_value(ctx, &c, sizeof(c)); 107*387f9dfdSAndroid Build Coastguard Worker ret.update(&zero, &r); 108*387f9dfdSAndroid Build Coastguard Worker counter.update(&zero, &c); 109*387f9dfdSAndroid Build Coastguard Worker #endif 110*387f9dfdSAndroid Build Coastguard Worker return 0; 111*387f9dfdSAndroid Build Coastguard Worker } 112*387f9dfdSAndroid Build Coastguard Worker )"; 113*387f9dfdSAndroid Build Coastguard Worker 114*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 115*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 116*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 117*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 118*387f9dfdSAndroid Build Coastguard Worker res = bpf.attach_perf_event(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 119*387f9dfdSAndroid Build Coastguard Worker "on_event", 0, 1000); 120*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 121*387f9dfdSAndroid Build Coastguard Worker sleep(1); 122*387f9dfdSAndroid Build Coastguard Worker res = bpf.detach_perf_event(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); 123*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 124*387f9dfdSAndroid Build Coastguard Worker 125*387f9dfdSAndroid Build Coastguard Worker auto pid = bpf.get_hash_table<int, uint64_t>("pid"); 126*387f9dfdSAndroid Build Coastguard Worker REQUIRE(pid[0] >= 0); 127*387f9dfdSAndroid Build Coastguard Worker #endif 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 130*387f9dfdSAndroid Build Coastguard Worker auto counter_table = 131*387f9dfdSAndroid Build Coastguard Worker bpf.get_hash_table<int, struct bpf_perf_event_value>("counter"); 132*387f9dfdSAndroid Build Coastguard Worker auto counter = counter_table[0]; 133*387f9dfdSAndroid Build Coastguard Worker auto ret = bpf.get_hash_table<int, int>("ret"); 134*387f9dfdSAndroid Build Coastguard Worker REQUIRE(ret[0] == 0); 135*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.counter >= 0); 136*387f9dfdSAndroid Build Coastguard Worker // the program slept one second between perf_event attachment and detachment 137*387f9dfdSAndroid Build Coastguard Worker // in the above, so the enabled counter should be 1000000000ns or 138*387f9dfdSAndroid Build Coastguard Worker // more. But in reality, most of counters (if not all) are 9xxxxxxxx, 139*387f9dfdSAndroid Build Coastguard Worker // and I also saw 7xxxxxxxx. So let us a little bit conservative here and 140*387f9dfdSAndroid Build Coastguard Worker // set 200000000 to avoie test flakiness. 141*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.enabled >= 200000000); 142*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.running >= 0); 143*387f9dfdSAndroid Build Coastguard Worker REQUIRE(counter.running <= counter.enabled); 144*387f9dfdSAndroid Build Coastguard Worker #endif 145*387f9dfdSAndroid Build Coastguard Worker } 146