<commit_before>/*
 * Performance counter x86 architecture code
 *
 *  Copyright(C) 2008 <NAME> <<EMAIL>>
 *  Copyright(C) 2008 Red Hat, Inc., <NAME>
 *
 *  For licencing details see kernel-base/COPYING
 */

#include <linux/perf_counter.h>
#include <linux/capability.h>
#include <linux/notifier.h>
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/module.h>
#include <linux/kdebug.h>
#include <linux/sched.h>

#include <asm/intel_arch_perfmon.h>
#include <asm/apic.h>

static bool perf_counters_initialized __read_mostly;

/*
 * Number of (generic) HW counters:
 */
static int nr_hw_counters __read_mostly;
static u32 perf_counter_mask __read_mostly;

/* No support for fixed function counters yet */

#define MAX_HW_COUNTERS		8

struct cpu_hw_counters {
	struct perf_counter	*counters[MAX_HW_COUNTERS];
	unsigned long		used[BITS_TO_LONGS(MAX_HW_COUNTERS)];
};

/*
 * Intel PerfMon v3. Used on Core2 and later.
 */
static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters);

const int intel_perfmon_event_map[] =
{
  [PERF_COUNT_CYCLES]			= 0x003c,
  [PERF_COUNT_INSTRUCTIONS]		= 0x00c0,
  [PERF_COUNT_CACHE_REFERENCES]		= 0x4f2e,
  [PERF_COUNT_CACHE_MISSES]		= 0x412e,
  [PERF_COUNT_BRANCH_INSTRUCTIONS]	= 0x00c4,
  [PERF_COUNT_BRANCH_MISSES]		= 0x00c5,
};

const int max_intel_perfmon_events = ARRAY_SIZE(intel_perfmon_event_map);

/*
 * Propagate counter elapsed time into the generic counter.
 * Can only be executed on the CPU where the counter is active.
 * Returns the delta events processed.
 */
static void
x86_perf_counter_update(struct perf_counter *counter,
			struct hw_perf_counter *hwc, int idx)
{
	u64 prev_raw_count, new_raw_count, delta;

	WARN_ON_ONCE(counter->state != PERF_COUNTER_STATE_ACTIVE);
	/*
	 * Careful: an NMI might modify the previous counter value.
	 *
	 * Our tactic to handle this is to first atomically read and
	 * exchange a new raw count - then add that new-prev delta
	 * count to the generic counter atomically:
	 */
again:
	prev_raw_count = atomic64_read(&hwc->prev_count);
	rdmsrl(hwc->counter_base + idx, new_raw_count);

	if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
					new_raw_count) != prev_raw_count)
		goto again;

	/*
	 * Now we have the new raw value and have updated the prev
	 * timestamp already. We can now calculate the elapsed delta
	 * (counter-)time and add that to the generic counter.
	 *
	 * Careful, not all hw sign-extends above the physical width
	 * of the count, so we do that by clipping the delta to 32 bits:
	 */
	delta = (u64)(u32)((s32)new_raw_count - (s32)prev_raw_count);
	WARN_ON_ONCE((int)delta < 0);

	atomic64_add(delta, &counter->count);
	atomic64_sub(delta, &hwc->period_left);
}

/*
 * Setup the hardware configuration for a given hw_event_type
 */
static int __hw_perf_counter_init(struct perf_counter *counter)
{
	struct perf_counter_hw_event *hw_event = &counter->hw_event;
	struct hw_perf_counter *hwc = &counter->hw;

	if (unlikely(!perf_counters_initialized))
		return -EINVAL;

	/*
	 * Count user events, and generate PMC IRQs:
	 * (keep 'enabled' bit clear for now)
	 */
	hwc->config = ARCH_PERFMON_EVENTSEL_USR | ARCH_PERFMON_EVENTSEL_INT;

	/*
	 * If privileged enough, count OS events too, and allow
	 * NMI events as well:
	 */
	hwc->nmi = 0;
	if (capable(CAP_SYS_ADMIN)) {
		hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
		if (hw_event->nmi)
			hwc->nmi = 1;
	}

	hwc->config_base	= MSR_ARCH_PERFMON_EVENTSEL0;
	hwc->counter_base	= MSR_ARCH_PERFMON_PERFCTR0;

	hwc->irq_period		= hw_event->irq_period;
	/*
	 * Intel PMCs cannot be accessed sanely above 32 bit width,
	 * so we install an artificial 1<<31 period regardless of
	 * the generic counter period:
	 */
	if ((s64)hwc->irq_period <= 0 || hwc->irq_period > 0x7FFFFFFF)
		hwc->irq_period = 0x7FFFFFFF;

	atomic64_set(&hwc->period_left, hwc->irq_period);

	/*
	 * Raw event type provide the config in the event structure
	 */
	if (hw_event->raw) {
		hwc->config |= hw_event->type;
	} else {
		if (hw_event->type >= max_intel_perfmon_events)
			return -EINVAL;
		/*
		 * The generic map:
		 */
		hwc->config |= intel_perfmon_event_map[hw_event->type];
	}
	counter->wakeup_pending = 0;

	return 0;
}

void hw_perf_enable_all(void)
{
	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, perf_counter_mask, 0);
}

u64 hw_perf_save_disable(void)
{
	u64 ctrl;

	rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0);
	return ctrl;
}
EXPORT_SYMBOL_GPL(hw_perf_save_disable);

void hw_perf_restore(u64 ctrl)
{
	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, ctrl, 0);
}
EXPORT_SYMBOL_GPL(hw_perf_restore);
<commit_msg>perfcounters: fix non-intel-perfmon CPUs<commit_after>/*
 * Performance counter x86 architecture code
 *
 *  Copyright(C) 2008 <NAME> <<EMAIL>>
 *  Copyright(C) 2008 Red Hat, Inc., <NAME>
 *
 *  For licencing details see kernel-base/COPYING
 */

#include <linux/perf_counter.h>
#include <linux/capability.h>
#include <linux/notifier.h>
#include <linux/hardirq.h>
#include <linux/kprobes.h>
#include <linux/module.h>
#include <linux/kdebug.h>
#include <linux/sched.h>

#include <asm/intel_arch_perfmon.h>
#include <asm/apic.h>

static bool perf_counters_initialized __read_mostly;

/*
 * Number of (generic) HW counters:
 */
static int nr_hw_counters __read_mostly;
static u32 perf_counter_mask __read_mostly;

/* No support for fixed function counters yet */

#define MAX_HW_COUNTERS		8

struct cpu_hw_counters {
	struct perf_counter	*counters[MAX_HW_COUNTERS];
	unsigned long		used[BITS_TO_LONGS(MAX_HW_COUNTERS)];
};

/*
 * Intel PerfMon v3. Used on Core2 and later.
 */
static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters);

const int intel_perfmon_event_map[] =
{
  [PERF_COUNT_CYCLES]			= 0x003c,
  [PERF_COUNT_INSTRUCTIONS]		= 0x00c0,
  [PERF_COUNT_CACHE_REFERENCES]		= 0x4f2e,
  [PERF_COUNT_CACHE_MISSES]		= 0x412e,
  [PERF_COUNT_BRANCH_INSTRUCTIONS]	= 0x00c4,
  [PERF_COUNT_BRANCH_MISSES]		= 0x00c5,
};

const int max_intel_perfmon_events = ARRAY_SIZE(intel_perfmon_event_map);

/*
 * Propagate counter elapsed time into the generic counter.
 * Can only be executed on the CPU where the counter is active.
 * Returns the delta events processed.
 */
static void
x86_perf_counter_update(struct perf_counter *counter,
			struct hw_perf_counter *hwc, int idx)
{
	u64 prev_raw_count, new_raw_count, delta;

	WARN_ON_ONCE(counter->state != PERF_COUNTER_STATE_ACTIVE);
	/*
	 * Careful: an NMI might modify the previous counter value.
	 *
	 * Our tactic to handle this is to first atomically read and
	 * exchange a new raw count - then add that new-prev delta
	 * count to the generic counter atomically:
	 */
again:
	prev_raw_count = atomic64_read(&hwc->prev_count);
	rdmsrl(hwc->counter_base + idx, new_raw_count);

	if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
					new_raw_count) != prev_raw_count)
		goto again;

	/*
	 * Now we have the new raw value and have updated the prev
	 * timestamp already. We can now calculate the elapsed delta
	 * (counter-)time and add that to the generic counter.
	 *
	 * Careful, not all hw sign-extends above the physical width
	 * of the count, so we do that by clipping the delta to 32 bits:
	 */
	delta = (u64)(u32)((s32)new_raw_count - (s32)prev_raw_count);
	WARN_ON_ONCE((int)delta < 0);

	atomic64_add(delta, &counter->count);
	atomic64_sub(delta, &hwc->period_left);
}

/*
 * Setup the hardware configuration for a given hw_event_type
 */
static int __hw_perf_counter_init(struct perf_counter *counter)
{
	struct perf_counter_hw_event *hw_event = &counter->hw_event;
	struct hw_perf_counter *hwc = &counter->hw;

	if (unlikely(!perf_counters_initialized))
		return -EINVAL;

	/*
	 * Count user events, and generate PMC IRQs:
	 * (keep 'enabled' bit clear for now)
	 */
	hwc->config = ARCH_PERFMON_EVENTSEL_USR | ARCH_PERFMON_EVENTSEL_INT;

	/*
	 * If privileged enough, count OS events too, and allow
	 * NMI events as well:
	 */
	hwc->nmi = 0;
	if (capable(CAP_SYS_ADMIN)) {
		hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
		if (hw_event->nmi)
			hwc->nmi = 1;
	}

	hwc->config_base	= MSR_ARCH_PERFMON_EVENTSEL0;
	hwc->counter_base	= MSR_ARCH_PERFMON_PERFCTR0;

	hwc->irq_period		= hw_event->irq_period;
	/*
	 * Intel PMCs cannot be accessed sanely above 32 bit width,
	 * so we install an artificial 1<<31 period regardless of
	 * the generic counter period:
	 */
	if ((s64)hwc->irq_period <= 0 || hwc->irq_period > 0x7FFFFFFF)
		hwc->irq_period = 0x7FFFFFFF;

	atomic64_set(&hwc->period_left, hwc->irq_period);

	/*
	 * Raw event type provide the config in the event structure
	 */
	if (hw_event->raw) {
		hwc->config |= hw_event->type;
	} else {
		if (hw_event->type >= max_intel_perfmon_events)
			return -EINVAL;
		/*
		 * The generic map:
		 */
		hwc->config |= intel_perfmon_event_map[hw_event->type];
	}
	counter->wakeup_pending = 0;

	return 0;
}

void hw_perf_enable_all(void)
{
	if (unlikely(!perf_counters_initialized))
		return;

	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, perf_counter_mask, 0);
}

u64 hw_perf_save_disable(void)
{
	u64 ctrl;

	if (unlikely(!perf_counters_initialized))
		return 0;

	rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0, 0);

	return ctrl;
}
EXPORT_SYMBOL_GPL(hw_perf_save_disable);

void hw_perf_restore(u64 ctrl)
{
	if (unlikely(!perf_counters_initialized))
		return;

	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, ctrl, 0);
}
EXPORT_SYMBOL_GPL(hw_perf_restore);

{'fraction_non_alphanumeric': 0.10692159794915616, 'fraction_numerical': 0.0195471053193762, 'mean_word_length': 4.650573325286663, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6324973', 'n_tokens_mistral': 3779, 'n_tokens_neox': 3519, 'n_words': 841}