From d7c3f1809b219baed6ea855be240292d51bbc10b Mon Sep 17 00:00:00 2001 From: doublefree Date: Wed, 6 Aug 2025 14:18:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B5=8B=E8=AF=95=EF=BC=8C?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E5=AF=84=E5=AD=98=E5=99=A8=E5=88=86=E9=85=8D?= =?UTF-8?q?=E5=AE=8C=E6=97=B6=E8=BF=94=E5=9B=9E=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/pcerrc.h | 1 + pmu/evt_list.cpp | 3 + pmu/perf_counter.cpp | 3 + test/test_perf/test_api.cpp | 32 +++++ test/test_perf/test_user_access.cpp | 182 ++++++++++++++++++++++++++++ 5 files changed, 221 insertions(+) create mode 100644 test/test_perf/test_user_access.cpp diff --git a/include/pcerrc.h b/include/pcerrc.h index 4151cfc..9d5f4f6 100644 --- a/include/pcerrc.h +++ b/include/pcerrc.h @@ -122,6 +122,7 @@ extern "C" { #define LIBPERF_ERR_ENABLE_USER_ACCESS_FAILED 1075 #define LIBPERF_ERR_ALLOCATE_REGISTER_FAILED 1076 #define LIBPERF_ERR_CHECK_USER_ACCESS 1077 +#define LIBPERF_ERR_COUNTER_INDEX_IS_ZERO 1078 #define UNKNOWN_ERROR 9999 diff --git a/pmu/evt_list.cpp b/pmu/evt_list.cpp index c9a5dac..7e93c0d 100644 --- a/pmu/evt_list.cpp +++ b/pmu/evt_list.cpp @@ -93,6 +93,9 @@ void KUNPENG_PMU::EvtList::AdaptErrInfo(int err, PerfEvtPtr perfEvt) pcerr::SetCustomErr(err, std::string{strerror(errno)}); } break; + case LIBPERF_ERR_COUNTER_INDEX_IS_ZERO: + pcerr::SetCustomErr(err, "There are too many open events. No registers are available."); + break; case UNKNOWN_ERROR: pcerr::SetCustomErr(err, std::string{strerror(errno)}); break; diff --git a/pmu/perf_counter.cpp b/pmu/perf_counter.cpp index b578493..cd00fc5 100644 --- a/pmu/perf_counter.cpp +++ b/pmu/perf_counter.cpp @@ -380,6 +380,9 @@ int KUNPENG_PMU::PerfCounter::Mmap() return LIBPERF_ERR_FAIL_MMAP; } this->countMmap->base = static_cast(currentMap); + if (this->countMmap->base->index == 0) { + return LIBPERF_ERR_COUNTER_INDEX_IS_ZERO; + } this->countMmap->fd = this->fd; return SUCCESS; } diff --git a/test/test_perf/test_api.cpp b/test/test_perf/test_api.cpp index a081520..e816642 100644 --- a/test/test_perf/test_api.cpp +++ b/test/test_perf/test_api.cpp @@ -14,6 +14,7 @@ ******************************************************************************/ #include #include +#include #include "util_time.h" #include "process_map.h" #include "common.h" @@ -735,3 +736,34 @@ TEST_F(TestAPI, InvalidCgroupNameListSPE) auto pd = PmuOpen(SPE_SAMPLING, &attr); ASSERT_EQ(pd, -1); } + +TEST_F(TestAPI, InvalidUserAccessAttr) +{ + if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) { + GTEST_SKIP(); + } + PmuAttr attr = {0}; + attr.enableUserAccess = 1; + char *evtList[1]; + evtList[0] = (char *)"cycles"; + attr.evtList = evtList; + attr.numEvt = 1; + int pidList[1] = {0}; + attr.pidList = pidList; + attr.numPid = 1; + int cpuList[1] = {-1}; + attr.cpuList = cpuList; + attr.numCpu = 1; + auto pd = PmuOpen(COUNTING, &attr); + ASSERT_NE(pd, -1); + PmuClose(pd); + pd = PmuOpen(SAMPLING, &attr); + ASSERT_EQ(pd, -1); + pidList[0] = 999; + pd = PmuOpen(COUNTING, &attr); + ASSERT_EQ(pd, -1); + pidList[0] = 0; + cpuList[0] = 2; + pd = PmuOpen(COUNTING, &attr); + ASSERT_EQ(pd, -1); +} diff --git a/test/test_perf/test_user_access.cpp b/test/test_perf/test_user_access.cpp new file mode 100644 index 0000000..e086e91 --- /dev/null +++ b/test/test_perf/test_user_access.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: yupan + * Create: 2025-08-04 + * Description: Unit test for counting. + ******************************************************************************/ +#include "test_common.h" +#include "common.h" +#include + +using namespace std; + +class TestUserAccessCount : public testing::Test { +public: + TestUserAccessCount() + { + attr.enableUserAccess = 1; + attr.pidList = pids; + attr.numPid = 1; + attr.cpuList = cpus; + attr.numCpu = 1; + } + +protected: + PmuAttr attr{0}; + int pids[1] = {0}; + int cpus[1] = {-1}; + std::vector events = {"branch-misses", + "bus-cycles", + "cache-misses", + "cache-references", + "cpu-cycles", + "instructions", + "stalled-cycles-backend", + "stalled-cycles-frontend", + "L1-dcache-loads", + "L1-dcache-load-misses", + "L1-icache-loads", + "L1-icache-load-misses", + "LLC-loads", + "LLC-load-misses", + "dTLB-loads", + "dTLB-load-misses", + "iTLB-loads", + "iTLB-load-misses", + "branch-loads", + "branch-load-misses", + "br_mis_pred", + "dTLB-load-misses" + "br_mis_pred_retired", + "br_pred", + "br_retired", + "br_return_retired", + "bus_access", + "bus_cycles", + "cid_write_retired", + "cpu_cycles", + "dtlb_walk", + "exc_return", + "exc_taken", + "inst_retired", + "inst_spec", + "itlb_walk", + "l1d_cache", + "l1d_cache_refill", + "l1d_cache_wb", + "l1d_tlb", + "l1d_tlb_refill", + "l1i_cache", + "l1i_cache_refill", + "l1i_tlb", + "l1i_tlb_refill", + "l2d_cache", + "l2d_cache_refill", + "l2d_cache_wb", + "l2d_tlb", + "l2d_tlb_refill", + "l2i_cache", + "l2i_cache_refill", + "l2i_tlb", + "l2i_tlb_refill", + "ll_cache", + "ll_cache_miss", + "ll_cache_miss_rd", + "ll_cache_rd", + "mem_access", + "memory_error", + "remote_access", + "remote_access_rd", + "sample_collision", + "sample_feed", + "sample_filtrate", + "sample_pop", + "stall_backend", + "stall_frontend", + "ttbr_write_retired", + "exe_stall_cycle", + "fetch_bubble", + "hit_on_prf", + "if_is_stall", + "iq_is_empty", + "l1d_cache_inval", + "l1d_cache_rd", + "l1d_cache_refill_rd", + "l1d_cache_wb_clean", + "l1d_cache_wb_victim", + "l1d_cache_wr", + "l1d_tlb_rd", + "l1d_tlb_refill_rd", + "l1d_tlb_refill_wr", + "l1d_tlb_wr", + "l1i_cache_prf", + "l1i_cache_prf_refill", + "l2d_cache_inval", + "l2d_cache_rd", + "l2d_cache_refill_rd", + "l2d_cache_wb_clean", + "l2d_cache_wb_victim", + "l2d_cache_wr", + "mem_stall_anyload", + "mem_stall_l1miss", + "mem_stall_l2miss", + "prf_req"}; +}; + +TEST_F(TestUserAccessCount, TestReadEvent) +{ + if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) { + GTEST_SKIP(); + } + attr.numEvt = 1; + char *evtList[1]; + for (int i = 0; i < events.size(); i++) { + evtList[0] = const_cast(events[i].data()); + attr.evtList = evtList; + int pd = PmuOpen(COUNTING, &attr); + if (pd == -1) { + printf("PmuOpen failed : %s\n", Perror()); + PmuClose(pd); + continue; + } + ASSERT_NE(pd, -1); + PmuEnable(pd); + PmuData *data = nullptr; + int len = PmuRead(pd, &data); + printf("==============\n"); + for (int i = 0; i < 2; i++) { + int k = 1e8; + while (k > 0) { + k--; + } + PmuDataFree(data); + len = PmuRead(pd, &data); + ASSERT_EQ(len, 1); + if (len > 0) { + for (int j = 0; j < len; j++) { + printf("event:%s pid=%d tid=%d cpu=%d groupId=%d comm=%s count=%llu countpercent=%lf\n", + data[j].evt, + data[j].pid, + data[j].tid, + data[j].cpu, + data[j].groupId, + data[j].comm, + data[j].count, + data[j].countPercent); + } + } else { + printf("%s\n", Perror()); + } + } + PmuDisable(pd); + PmuClose(pd); + } +} \ No newline at end of file -- Gitee