// 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 "garnet/bin/cpuperf_provider/events.h"

#include <assert.h>
#include <zircon/device/cpu-trace/intel-pm.h>
#include <unordered_map>

#include "lib/fxl/logging.h"

namespace cpuperf_provider {

const EventDetails g_arch_event_details[] = {
#if IPM_API_VERSION == 0
#define DEF_ARCH_EVENT(symbol, ebx_bit, event, umask, flags, name) \
  { event, umask, flags, name },
#else
#define DEF_ARCH_EVENT(symbol, ebx_bit, event, umask, flags, name, description) \
  { event, umask, flags, name " (" description ")" },
#endif
#include <zircon/device/cpu-trace/intel-pm-events.inc>
};

const EventDetails g_skl_event_details[] = {
#if IPM_API_VERSION == 0
#define DEF_SKL_EVENT(symbol, event, umask, flags, name) \
  { event, umask, flags, name },
#include <zircon/device/cpu-trace/intel-pm-events.inc>
#else
#define DEF_SKL_EVENT(symbol, event, umask, flags, name, description) \
  { event, umask, flags, name " (" description ")" },
#include <zircon/device/cpu-trace/skylake-pm-events.inc>
#endif
};

using EventSelectMap = std::unordered_map<uint32_t, const EventDetails*>;

static EventSelectMap* g_arch_event_select_map;
static EventSelectMap* g_skl_event_select_map;

uint32_t MakeEventKey(const EventDetails& d) {
  FXL_DCHECK(d.event < (1 << IA32_PERFEVTSEL_EVENT_SELECT_LEN));
  FXL_DCHECK(d.umask < (1 << IA32_PERFEVTSEL_UMASK_LEN));
  FXL_DCHECK((d.flags & IPM_REG_FLAG_CMSK_MASK) < (1 << IA32_PERFEVTSEL_CMASK_LEN));
  uint32_t key = ((d.event << IA32_PERFEVTSEL_EVENT_SELECT_SHIFT) |
                  (d.umask << IA32_PERFEVTSEL_UMASK_SHIFT) |
                  ((d.flags & IPM_REG_FLAG_CMSK_MASK) << IA32_PERFEVTSEL_CMASK_SHIFT) |
                  (!!(d.flags & IPM_REG_FLAG_ANYT) << IA32_PERFEVTSEL_ANY_SHIFT));
  return key;
}

static void InitializeEventSelectMap(const EventDetails* details, size_t count,
                                     EventSelectMap* map) {
  for (size_t i = 0; i < count; ++i) {
    const EventDetails* d = &details[i];
    uint32_t key = MakeEventKey(*d);
    FXL_DCHECK(map->count(key) == 0);
    (*map)[key] = d;
  }
}

// Call this from main, before anything that needs to use
// |g_*_event_select_map|.
void InitializeEventSelectMaps() {
  g_arch_event_select_map = new EventSelectMap();
  InitializeEventSelectMap(g_arch_event_details, countof(g_arch_event_details),
                           g_arch_event_select_map);

  // TODO(dje): For now assume skylake/kabylake.
  g_skl_event_select_map = new EventSelectMap();
  InitializeEventSelectMap(g_skl_event_details, countof(g_skl_event_details),
                           g_skl_event_select_map);
}

bool EventSelectToEventDetails(uint64_t event_select,
                               const EventDetails** details) {
  uint32_t key = event_select & (IA32_PERFEVTSEL_EVENT_SELECT_MASK |
                                 IA32_PERFEVTSEL_UMASK_MASK |
                                 IA32_PERFEVTSEL_CMASK_MASK |
                                 IA32_PERFEVTSEL_ANY_MASK);
  if (g_arch_event_select_map->count(key)) {
    *details = (*g_arch_event_select_map)[key];
    return true;
  }

  if (g_skl_event_select_map->count(key)) {
    *details = (*g_skl_event_select_map)[key];
    return true;
  }

  return false;
}

const EventDetails* GetFixedEventDetails(int n) {
  enum {
#if IPM_API_VERSION == 0
#define DEF_ARCH_EVENT(symbol, ebx_bit, event, umask, flags, name) \
  EVENT_ ## symbol,
#else
#define DEF_ARCH_EVENT(symbol, ebx_bit, event, umask, flags, name, description) \
  EVENT_ ## symbol,
#endif
#include <zircon/device/cpu-trace/intel-pm-events.inc>
  };

  switch (n) {
    case 0:
      return &g_arch_event_details[EVENT_ARCH_INSTRUCTIONS_RETIRED];
    case 1:
      return &g_arch_event_details[EVENT_ARCH_UNHALTED_CORE_CYCLES];
    case 2:
      return &g_arch_event_details[EVENT_ARCH_UNHALTED_REFERENCE_CYCLES];
    default:
      assert(0);
      __UNREACHABLE;
  }
}

}  // namespace cpuperf_provider
