* 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: Mr.Ye
* Create: 2024-04-03
* Description: event configuration query
******************************************************************************/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <functional>
#include <unordered_map>
#include <cstdarg>
#include <unistd.h>
#include <cstring>
#include <fstream>
#include "trace.h"
#include "common.h"
#include "cpu_map.h"
#include "pfm_event.h"
#include "pmu_event.h"
#include "pmu_event_list.h"
#include "pmu.h"
#include "pcerr.h"
#include "pfm.h"
#include "uncore.h"
#include "core.h"
using namespace std;
using namespace pcerr;
using namespace KUNPENG_PMU;
static constexpr int MAX_STRING_LEN = 2048;
static struct PmuEvt* GetRawEvent(const char* pmuName, int collectType)
{
const char *numStr = pmuName + 1;
char *endPtr;
__u64 config = strtol(numStr, &endPtr, 16);
if (*endPtr != '\0') {
return nullptr;
}
auto* pmuEvtPtr = new PmuEvt {0};
pmuEvtPtr->config = config;
pmuEvtPtr->name = pmuName;
pmuEvtPtr->type = PERF_TYPE_RAW;
pmuEvtPtr->pmuType = CORE_TYPE;
pmuEvtPtr->collectType = collectType;
return pmuEvtPtr;
}
static int GetSpeType(void)
{
constexpr char* speTypePath = "/sys/devices/arm_spe_0/type";
FILE *fp = fopen(speTypePath, "r");
int type;
if (!fp) {
return -1;
}
if (fscanf(fp, "%d", &type) != 1) {
if (fclose(fp) == EOF) {
return -1;
}
return -1;
}
if (fclose(fp) == EOF) {
return -1;
}
return type;
}
using EvtRetriever = std::function<struct PmuEvt*(const char*, int)>;
static const std::unordered_map<int, EvtRetriever> EvtMap{
{KUNPENG_PMU::RAW_TYPE, GetRawEvent},
{KUNPENG_PMU::CORE_TYPE, GetCoreEvent},
{KUNPENG_PMU::UNCORE_TYPE, GetUncoreEvent},
{KUNPENG_PMU::UNCORE_RAW_TYPE, GetUncoreRawEvent},
{KUNPENG_PMU::TRACE_TYPE, GetKernelTraceEvent},
};
static bool CheckEventInList(enum PmuEventType eventType, const char *pmuName)
{
unsigned numEvt;
auto eventList = PmuEventList(eventType, &numEvt, false);
if (eventList == nullptr) {
return false;
}
for (int j=0;j<numEvt;++j) {
if (strcmp(eventList[j], pmuName) == 0) {
return true;
}
}
return false;
}
static bool CheckRawEvent(const char *pmuName)
{
const char *numStr = pmuName + 1;
char *endPtr;
__u64 _ = strtol(numStr, &endPtr, 16);
if (*endPtr != '\0') {
return false;
}
return true;
}
static bool IsTraceEventFormat(const std::string evtName) {
if (evtName.find(":") != std::string::npos) {
return true;
}
return false;
}
static int GetEventType(const char *pmuName)
{
if (CheckEventInList(CORE_EVENT, pmuName)) {
return CORE_TYPE;
}
if (pmuName[0] == 'r' && CheckRawEvent(pmuName)) {
return RAW_TYPE;
}
std::string strName(pmuName);
if (CheckEventInList(UNCORE_EVENT, pmuName)) {
return UNCORE_TYPE;
}
if (CheckUncoreRawEvent(pmuName)) {
return UNCORE_RAW_TYPE;
}
if (IsTraceEventFormat(pmuName) && CheckEventInList(TRACE_EVENT, pmuName)) {
return TRACE_TYPE;
}
return -1;
}
struct PmuEvt* PfmGetPmuEvent(const char* pmuName, int collectType)
{
if (pmuName == nullptr) {
auto* evt = new PmuEvt {0};
evt->collectType = collectType;
return evt;
}
auto type = GetEventType(pmuName);
if (type == -1) {
return nullptr;
}
struct PmuEvt* evt = (EvtMap.find(type) != EvtMap.end()) ?
EvtMap.at(type)(pmuName, collectType) : nullptr;
if (evt == nullptr) {
return evt;
}
return evt;
}
struct PmuEvt* PfmGetSpeEvent(
unsigned long dataFilter, unsigned long eventFilter, unsigned long minLatency, int collectType)
{
auto* evt = new PmuEvt {0};
evt->collectType = collectType;
int type = GetSpeType();
if (type == -1) {
delete evt;
return nullptr;
}
evt->type = static_cast<unsigned long>(type);
evt->config = dataFilter;
evt->config1 = eventFilter;
evt->config2 = minLatency;
return evt;
}
void PmuEvtFree(PmuEvt *evt)
{
delete evt;
}