blob: c05c4eff8a780ba51ac17786692bc96e8830357f [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
// A note on the distribution of code between us and the userspace driver:
// The default location for code is the userspace driver. Reasons for
// putting code here are: implementation requirement (need ring zero to write
// MSRs), stability, and performance. The device driver should do as much
// error checking as possible before calling us.
// Note that we do a lot of verification of the input configuration:
// We don't want to be compromised if the userspace driver gets compromised.
// A note on terminology: "events" vs "counters": A "counter" is an
// "event", but some events are not counters. Internally, we use the
// term "counter" when we know the event is a counter.
#include <lib/perfmon.h>
bool perfmon_supported = false;
int perfmon_active = false;
PerfmonStateBase::PerfmonStateBase(unsigned n_cpus)
: num_cpus(n_cpus) {}
PerfmonStateBase::~PerfmonStateBase() {
DEBUG_ASSERT(!atomic_load(&perfmon_active));
if (cpu_data) {
for (unsigned cpu = 0; cpu < num_cpus; ++cpu) {
auto data = &cpu_data[cpu];
data->~PerfmonCpuData();
}
// This frees the memory allocated by |memalign()|.
free(cpu_data);
}
}
bool PerfmonStateBase::AllocatePerCpuData() {
DEBUG_ASSERT(cpu_data == nullptr);
size_t space_needed = sizeof(PerfmonCpuData) * num_cpus;
auto cdata = reinterpret_cast<PerfmonCpuData*>(
memalign(alignof(PerfmonCpuData), space_needed));
if (!cdata) {
return false;
}
for (unsigned cpu = 0; cpu < num_cpus; ++cpu) {
new (&cdata[cpu]) PerfmonCpuData();
}
cpu_data = cdata;
return true;
}