blob: 6c722b539794a0abb0071dc9c1dd0b5e9d5a5da3 [file] [log] [blame]
// Copyright 2019 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.
// This file contains Intel events.
// When needed separate files will describe non-Intel x64 events.
#include <iterator>
#include <cpuid.h>
#include "src/performance/lib/perfmon/event-registry.h"
#include "src/performance/lib/perfmon/events.h"
namespace perfmon {
namespace {
enum class Microarch {
kSkylake,
kGoldmont,
kUnknown
};
bool is_intel() {
uint32_t a, b, c, d;
__get_cpuid(0, &a, &b, &c, &d);
return (b == signature_INTEL_ebx) &&
(d == signature_INTEL_edx) &&
(c == signature_INTEL_ecx);
}
Microarch microarch() {
uint32_t a, b, c, d;
__get_cpuid(1, &a, &b, &c, &d);
uint32_t family = ((a >> 8) & 0xf) | ((a >> 16) & 0xff0);
uint32_t model = ((a >> 4) & 0xf) | ((a >> 12) & 0xf0);
if (family != 0x6) {
return Microarch::kUnknown;
}
switch (model) {
case 0x4E: // Skylake-Y, -U
case 0x5E: // Skylake-DT, -H, -S
case 0x8E: // Kabylake-Y, -U; Whiskey Lake-U; Amber Lake-Y; Comet Lake-U
case 0x9E: // Kabylake-DT, -H, -S, -X; Coffee Lake-S, -H, -E; Comet Lake-S, -H
case 0x55: // Skylake-SP, Cascade Lake-SP
return Microarch::kSkylake;
case 0x5C: // Apollo Lake
return Microarch::kGoldmont;
default:
return Microarch::kUnknown;
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc99-designator"
const EventDetails g_fixed_event_details[] = {
#define DEF_FIXED_EVENT(symbol, event_name, id, regnum, flags, readable_name, description) \
[id] = {MakeEventId(kGroupFixed, id), #event_name, readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/intel-pm-events.inc>
};
const size_t g_num_fixed_event_details = std::size(g_fixed_event_details);
const EventDetails g_arch_event_details[] = {
#define DEF_ARCH_EVENT(symbol, event_name, id, ebx_bit, event, umask, flags, readable_name, \
description) \
[id] = {MakeEventId(kGroupArch, id), #event_name, readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/intel-pm-events.inc>
};
const size_t g_num_arch_event_details = std::size(g_arch_event_details);
const EventDetails g_skl_event_details[] = {
#define DEF_SKL_EVENT(symbol, event_name, id, event, umask, flags, readable_name, description) \
[id] = {MakeEventId(kGroupModel, id), #event_name, readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/skylake-pm-events.inc>
};
const size_t g_num_skl_event_details = std::size(g_skl_event_details);
const EventDetails g_skl_misc_event_details[] = {
#define DEF_MISC_SKL_EVENT(symbol, event_name, id, offset, size, flags, readable_name, \
description) \
[id] = {MakeEventId(kGroupMisc, id), #event_name, readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/skylake-misc-events.inc>
};
const size_t g_num_skl_misc_event_details = std::size(g_skl_misc_event_details);
const EventDetails g_glm_event_details[] = {
#define DEF_GLM_EVENT(symbol, event_name, id, event, umask, flags, readable_name, description) \
[id] = {MakeEventId(kGroupModel, id), #event_name, readable_name, description},
#include <lib/zircon-internal/device/cpu-trace/goldmont-pm-events.inc>
};
const size_t g_num_glm_event_details = std::size(g_glm_event_details);
#pragma GCC diagnostic pop
// Register all events for Intel Skylake.
void RegisterIntelSkylakeEvents(internal::EventRegistry* registry) {
// TODO(dje): Clear table first (start over).
registry->RegisterEvents("skylake", "fixed", g_fixed_event_details, g_num_fixed_event_details);
registry->RegisterEvents("skylake", "arch", g_arch_event_details, g_num_arch_event_details);
registry->RegisterEvents("skylake", "model", g_skl_event_details, g_num_skl_event_details);
registry->RegisterEvents("skylake", "misc", g_skl_misc_event_details,
g_num_skl_misc_event_details);
}
void RegisterIntelGoldmontEvents(internal::EventRegistry* registry) {
registry->RegisterEvents("goldmont", "fixed", g_fixed_event_details, g_num_fixed_event_details);
registry->RegisterEvents("goldmont", "arch", g_arch_event_details, g_num_arch_event_details);
registry->RegisterEvents("goldmont", "model", g_glm_event_details, g_num_glm_event_details);
}
} // namespace
namespace internal {
void RegisterAllIntelModelEvents(internal::EventRegistry* registry) {
if (!is_intel()) {
return;
}
switch (microarch()) {
case Microarch::kSkylake:
RegisterIntelSkylakeEvents(registry);
break;
case Microarch::kGoldmont:
RegisterIntelGoldmontEvents(registry);
break;
case Microarch::kUnknown:
break;
}
}
} // namespace internal
} // namespace perfmon