blob: 97e3c4aee269f6865020b17890cfffd3b9738684 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <assert.h>
#include <lib/fxl/arraysize.h>
#include <lib/fxl/logging.h>
#include "garnet/lib/cpuperf/events.h"
namespace cpuperf {
const EventDetails g_arch_event_details[] = {
#define DEF_ARCH_EVENT(symbol, event_name, id, ebx_bit, event, \
umask, flags, readable_name, description) \
[id] = {CPUPERF_MAKE_EVENT_ID(CPUPERF_GROUP_ARCH, id), #event_name, \
readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/intel-pm-events.inc>
};
const EventDetails g_fixed_event_details[] = {
#define DEF_FIXED_EVENT(symbol, event_name, id, regnum, flags, \
readable_name, description) \
[id] = {CPUPERF_MAKE_EVENT_ID(CPUPERF_GROUP_FIXED, id), #event_name, \
readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/intel-pm-events.inc>
};
const EventDetails g_skl_event_details[] = {
#define DEF_SKL_EVENT(symbol, event_name, id, event, umask, \
flags, readable_name, description) \
[id] = {CPUPERF_MAKE_EVENT_ID(CPUPERF_GROUP_MODEL, id), #event_name, \
readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/skylake-pm-events.inc>
};
const EventDetails g_skl_misc_event_details[] = {
#define DEF_MISC_SKL_EVENT(symbol, event_name, id, offset, size, \
flags, readable_name, description) \
[id] = {CPUPERF_MAKE_EVENT_ID(CPUPERF_GROUP_MISC, id), #event_name, \
readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/skylake-misc-events.inc>
};
bool EventIdToEventDetails(cpuperf_event_id_t id,
const EventDetails** out_details) {
unsigned event = CPUPERF_EVENT_ID_EVENT(id);
const EventDetails* details;
switch (CPUPERF_EVENT_ID_GROUP(id)) {
case CPUPERF_GROUP_ARCH:
details = &g_arch_event_details[event];
break;
case CPUPERF_GROUP_FIXED:
details = &g_fixed_event_details[event];
break;
case CPUPERF_GROUP_MODEL:
// TODO(dje): For now assume Skylake, Kaby Lake.
details = &g_skl_event_details[event];
break;
case CPUPERF_GROUP_MISC:
// TODO(dje): For now assume Skylake, Kaby Lake.
details = &g_skl_misc_event_details[event];
break;
default:
return false;
}
if (details->id == 0)
return false;
*out_details = details;
return true;
}
// This just uses a linear search for now.
bool LookupEventByName(const char* group_name, const char* event_name,
const EventDetails** out_details) {
const EventDetails* details;
size_t num_events;
if (strcmp(group_name, "arch") == 0) {
details = &g_arch_event_details[0];
num_events = arraysize(g_arch_event_details);
} else if (strcmp(group_name, "fixed") == 0) {
details = &g_fixed_event_details[0];
num_events = arraysize(g_fixed_event_details);
} else if (strcmp(group_name, "model") == 0) {
details = &g_skl_event_details[0];
num_events = arraysize(g_skl_event_details);
} else if (strcmp(group_name, "misc") == 0) {
details = &g_skl_misc_event_details[0];
num_events = arraysize(g_skl_misc_event_details);
} else {
return false;
}
for (size_t i = 0; i < num_events; ++i) {
if (details[i].id == 0)
continue;
if (strcmp(details[i].name, event_name) == 0) {
*out_details = &details[i];
return true;
}
}
return false;
}
size_t GetConfigEventCount(const cpuperf_config_t& config) {
size_t count;
for (count = 0; count < CPUPERF_MAX_EVENTS; ++count) {
if (config.events[count] == CPUPERF_EVENT_ID_NONE)
break;
}
return count;
}
static void AddEvents(GroupTable& gt, const char* group_name_literal,
const EventDetails* details, size_t count) {
gt.emplace_back(GroupEvents{group_name_literal, {}});
auto& v = gt.back();
for (size_t i = 0; i < count; ++i) {
if (details[i].id != CPUPERF_EVENT_ID_NONE) {
v.events.push_back(&details[i]);
}
}
}
GroupTable GetAllGroups() {
GroupTable groups;
AddEvents(groups, "arch", &g_arch_event_details[0],
arraysize(g_arch_event_details));
AddEvents(groups, "fixed", &g_fixed_event_details[0],
arraysize(g_fixed_event_details));
AddEvents(groups, "model", &g_skl_event_details[0],
arraysize(g_skl_event_details));
AddEvents(groups, "misc", &g_skl_misc_event_details[0],
arraysize(g_skl_misc_event_details));
return groups;
}
} // namespace cpuperf