<commit_before>/*-
 * Copyright (c) 2003-2005,2008 <NAME>
 * Copyright (c) 2007 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by <NAME> under
 * sponsorship from the FreeBSD Foundation and Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/pmc.h>
#include <sys/pmckern.h>
#include <sys/smp.h>
#include <sys/systm.h>

#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/pmc_mdep.h>
#include <machine/specialreg.h>

/*
 * PENTIUM PRO SUPPORT
 *
 * Quirks:
 *
 * - Both PMCs are enabled by a single bit P6_EVSEL_EN in performance
 *   counter '0'.  This bit needs to be '1' if any of the two
 *   performance counters are in use.  Perf counters can also be
 *   switched off by writing zeros to their EVSEL register.
 *
 * - While the width of these counters is 40 bits, we do not appear to
 *   have a way of writing 40 bits to the counter MSRs.  A WRMSR
 *   instruction will sign extend bit 31 of the value being written to
 *   the perf counter -- a value of 0x80000000 written to an perf
 *   counter register will be sign extended to 0xFF80000000.
 *
 *   This quirk primarily affects thread-mode PMCs in counting mode, as
 *   these PMCs read and write PMC registers at every context switch.
 */

struct p6pmc_descr {
	struct pmc_descr pm_descr; /* common information */
	uint32_t	pm_pmc_msr;
	uint32_t	pm_evsel_msr;
};

static struct p6pmc_descr p6_pmcdesc[P6_NPMCS] = {

	/* TSC */
	{
		.pm_descr =
		{
			.pd_name  = "TSC",
			.pd_class = PMC_CLASS_TSC,
			.pd_caps  = PMC_CAP_READ,
			.pd_width = 64
		},
		.pm_pmc_msr   = 0x10,
		.pm_evsel_msr = ~0
	},

#define	P6_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
    PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE |	 \
    PMC_CAP_INVERT | PMC_CAP_QUALIFIER)

	/* PMC 0 */
	{
		.pm_descr =
		{
			.pd_name  ="P6-0",
			.pd_class = PMC_CLASS_P6,
			.pd_caps  = P6_PMC_CAPS,
			.pd_width = 40
		},
		.pm_pmc_msr   = P6_MSR_PERFCTR0,
		.pm_evsel_msr = P6_MSR_EVSEL0
	},

	/* PMC 1 */
	{
		.pm_descr =
		{
			.pd_name  ="P6-1",
			.pd_class = PMC_CLASS_P6,
			.pd_caps  = P6_PMC_CAPS,
			.pd_width = 40
		},
		.pm_pmc_msr   = P6_MSR_PERFCTR1,
		.pm_evsel_msr = P6_MSR_EVSEL1
	}
};

static enum pmc_cputype p6_cputype;

/*
 * P6 Event descriptor
 */

struct p6_event_descr {
	const enum pmc_event pm_event;
	uint32_t	     pm_evsel;
	uint32_t	     pm_flags;
	uint32_t	     pm_unitmask;
};

static const struct p6_event_descr p6_events[] = {

#define	P6_EVDESCR(NAME, EVSEL, FLAGS, UMASK)	\
	{					\
		.pm_event = PMC_EV_P6_##NAME,	\
		.pm_evsel = (EVSEL),		\
		.pm_flags = (FLAGS),		\
		.pm_unitmask = (UMASK)		\
	}

#define	P6F_P6		(1 << PMC_CPU_INTEL_P6)
#define	P6F_CL		(1 << PMC_CPU_INTEL_CL)
#define	P6F_PII		(1 << PMC_CPU_INTEL_PII)
#define	P6F_PIII	(1 << PMC_CPU_INTEL_PIII)
#define	P6F_PM		(1 << PMC_CPU_INTEL_PM)
#define	P6F_CTR0	0x0001
#define	P6F_CTR1	0x0002
#define	P6F_ALL_CPUS	(P6F_P6 | P6F_PII | P6F_CL | P6F_PIII | P6F_PM)
#define	P6F_ALL_CTRS	(P6F_CTR0 | P6F_CTR1)
#define	P6F_ALL		(P6F_ALL_CPUS | P6F_ALL_CTRS)

#define	P6_EVENT_VALID_FOR_CPU(P,CPU)	((P)->pm_flags & (1 << (CPU)))
#define	P6_EVENT_VALID_FOR_CTR(P,CTR)	((P)->pm_flags & (1 << (CTR)))

P6_EVDESCR(DATA_MEM_REFS,		0x43, P6F_ALL, 0x00),
P6_EVDESCR(DCU_LINES_IN,		0x45, P6F_ALL, 0x00),
P6_EVDESCR(DCU_M_LINES_IN,		0x46, P6F_ALL, 0x00),
P6_EVDESCR(DCU_M_LINES_OUT,		0x47, P6F_ALL, 0x00),
P6_EVDESCR(DCU_MISS_OUTSTANDING,	0x47, P6F_ALL, 0x00),
P6_EVDESCR(IFU_FETCH,			0x80, P6F_ALL, 0x00),
P6_EVDESCR(IFU_FETCH_MISS,		0x81, P6F_ALL, 0x00),
P6_EVDESCR(ITLB_MISS,			0x85, P6F_ALL, 0x00),
P6_EVDESCR(IFU_MEM_STALL,		0x86, P6F_ALL, 0x00),
P6_EVDESCR(ILD_STALL,			0x87, P6F_ALL, 0x00),
P6_EVDESCR(L2_IFETCH,			0x28, P6F_ALL, 0x0F),
P6_EVDESCR(L2_LD,			0x29, P6F_ALL, 0x0F),
P6_EVDESCR(L2_ST,			0x2A, P6F_ALL, 0x0F),
P6_EVDESCR(L2_LINES_IN,			0x24, P6F_ALL, 0x0F),
P6_EVDESCR(L2_LINES_OUT,		0x26, P6F_ALL, 0x0F),
P6_EVDESCR(L2_M_LINES_INM,		0x25, P6F_ALL, 0x00),
P6_EVDESCR(L2_M_LINES_OUTM,		0x27, P6F_ALL, 0x0F),
P6_EVDESCR(L2_RQSTS,			0x2E, P6F_ALL, 0x0F),
P6_EVDESCR(L2_ADS,			0x21, P6F_ALL, 0x00),
P6_EVDESCR(L2_DBUS_BUSY,		0x22, P6F_ALL, 0x00),
P6_EVDESCR(L2_DBUS_BUSY_RD,		0x23, P6F_ALL, 0x00),
P6_EVDESCR(BUS_DRDY_CLOCKS,		0x62, P6F_ALL, 0x20),
P6_EVDESCR(BUS_LOCK_CLOCKS,		0x63, P6F_ALL, 0x20),
P6_EVDESCR(BUS_REQ_OUTSTANDING,		0x60, P6F_ALL, 0x00),
P6_EVDESCR(BUS_TRAN_BRD,		0x65, P6F_ALL, 0x20),<commit_msg>Rework pmc-dependent flag handling.<commit_after>/*-
 * Copyright (c) 2003-2005,2008 <NAME>
 * Copyright (c) 2007 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by <NAME> under
 * sponsorship from the FreeBSD Foundation and Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/pmc.h>
#include <sys/pmckern.h>
#include <sys/smp.h>
#include <sys/systm.h>

#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/pmc_mdep.h>
#include <machine/specialreg.h>

/*
 * PENTIUM PRO SUPPORT
 *
 * Quirks:
 *
 * - Both PMCs are enabled by a single bit P6_EVSEL_EN in performance
 *   counter '0'.  This bit needs to be '1' if any of the two
 *   performance counters are in use.  Perf counters can also be
 *   switched off by writing zeros to their EVSEL register.
 *
 * - While the width of these counters is 40 bits, we do not appear to
 *   have a way of writing 40 bits to the counter MSRs.  A WRMSR
 *   instruction will sign extend bit 31 of the value being written to
 *   the perf counter -- a value of 0x80000000 written to an perf
 *   counter register will be sign extended to 0xFF80000000.
 *
 *   This quirk primarily affects thread-mode PMCs in counting mode, as
 *   these PMCs read and write PMC registers at every context switch.
 */

struct p6pmc_descr {
	struct pmc_descr pm_descr; /* common information */
	uint32_t	pm_pmc_msr;
	uint32_t	pm_evsel_msr;
};

static struct p6pmc_descr p6_pmcdesc[P6_NPMCS] = {

	/* TSC */
	{
		.pm_descr =
		{
			.pd_name  = "TSC",
			.pd_class = PMC_CLASS_TSC,
			.pd_caps  = PMC_CAP_READ,
			.pd_width = 64
		},
		.pm_pmc_msr   = 0x10,
		.pm_evsel_msr = ~0
	},

#define	P6_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
    PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE |	 \
    PMC_CAP_INVERT | PMC_CAP_QUALIFIER)

	/* PMC 0 */
	{
		.pm_descr =
		{
			.pd_name  ="P6-0",
			.pd_class = PMC_CLASS_P6,
			.pd_caps  = P6_PMC_CAPS,
			.pd_width = 40
		},
		.pm_pmc_msr   = P6_MSR_PERFCTR0,
		.pm_evsel_msr = P6_MSR_EVSEL0
	},

	/* PMC 1 */
	{
		.pm_descr =
		{
			.pd_name  ="P6-1",
			.pd_class = PMC_CLASS_P6,
			.pd_caps  = P6_PMC_CAPS,
			.pd_width = 40
		},
		.pm_pmc_msr   = P6_MSR_PERFCTR1,
		.pm_evsel_msr = P6_MSR_EVSEL1
	}
};

static enum pmc_cputype p6_cputype;

/*
 * P6 Event descriptor
 *
 * The 'pm_flags' field has the following structure:
 * - The upper 4 bits are used to track which counter an event is valid on.
 * - The lower bits form a bitmask of flags indicating support for the event
 *   on a given CPU.
 */

struct p6_event_descr {
	const enum pmc_event pm_event;
	uint32_t	     pm_evsel;
	uint32_t	     pm_flags;
	uint32_t	     pm_unitmask;
};

#define	P6F_CTR(C)	(1 << (28 + (C)))
#define	P6F_CTR0	P6F_CTR(0)
#define	P6F_CTR1	P6F_CTR(1)
#define	P6F(CPU)	(1 << ((CPU) - PMC_CPU_INTEL_P6))
#define	_P6F(C)		P6F(PMC_CPU_INTEL_##C)
#define	P6F_P6		_P6F(P6)
#define	P6F_CL		_P6F(CL)
#define	P6F_PII		_P6F(PII)
#define	P6F_PIII	_P6F(PIII)
#define	P6F_PM		_P6F(PM)
#define	P6F_ALL_CPUS	(P6F_P6 | P6F_PII | P6F_CL | P6F_PIII | P6F_PM)
#define	P6F_ALL_CTRS	(P6F_CTR0 | P6F_CTR1)
#define	P6F_ALL		(P6F_ALL_CPUS | P6F_ALL_CTRS)

#define	P6_EVENT_VALID_FOR_CPU(P,CPU)	((P)->pm_flags & P6F(CPU))
#define	P6_EVENT_VALID_FOR_CTR(P,CTR)	((P)->pm_flags & P6F_CTR(CTR))

static const struct p6_event_descr p6_events[] = {

#define	P6_EVDESCR(NAME, EVSEL, FLAGS, UMASK)	\
	{					\
		.pm_event = PMC_EV_P6_##NAME,	\
		.pm_evsel = (EVSEL),		\
		.pm_flags = (FLAGS),		\
		.pm_unitmask = (UMASK)		\
	}

P6_EVDESCR(DATA_MEM_REFS,		0x43, P6F_ALL, 0x00),
P6_EVDESCR(DCU_LINES_IN,		0x45, P6F_ALL, 0x00),
P6_EVDESCR(DCU_M_LINES_IN,		0x46, P6F_ALL, 0x00),
P6_EVDESCR(DCU_M_LINES_OUT,		0x47, P6F_ALL, 0x00),
P6_EVDESCR(DCU_MISS_OUTSTANDING,	0x47, P6F_ALL, 0x00),
P6_EVDESCR(IFU_FETCH,			0x80, P6F_ALL, 0x00),
P6_EVDESCR(IFU_FETCH_MISS,		0x81, P6F_ALL, 0x00),
P6_EVDESCR(ITLB_MISS,			0x85, P6F_ALL, 0x00),
P6_EVDESCR(IFU_MEM_STALL,		0x86, P6F_ALL, 0x00),
P6_EVDESCR(ILD_STALL,			0x87, P6F_ALL, 0x00),
P6_EVDESCR(L2_IFETCH,			0x28, P6F_ALL, 0x0F),
P6_EVDESCR(L2_LD,			0x29, P6F_ALL, 0x0F),
P6_EVDESCR(L2_ST,			0x2A, P6F_ALL, 0x0F),
P6_EVDESCR(L2_LINES_IN,			0x24, P6F_ALL, 0x0F),
P6_EVDESCR(L2_LINES_OUT,		0x26, P6F_ALL, 0x0F),
P6_EVDESCR(L2_M_LINES_INM,		0x25, P6F_ALL, 0x00),
P6_EVDESCR(L2_M_LINES_OUTM,		0x27, P6F_ALL, 0x0F),
P6_EVDESCR(L2_RQSTS,			0x2E, P6F_ALL, 0x0F),
P6_EVDESCR(L2_ADS,			0x21, P6F_ALL, 0x00),
P6_EVDESCR(L2_DBUS_BUSY,		0x22, P6F_ALL, 0x00),
P6_EVDESCR(L2_DBUS_BUSY_RD,		0x23, P6F_ALL, 0x00),
P6_EVDESCR(BUS_DRDY_CLOCKS,		0x62, P6F_ALL, 0x20),
P6_EVDESCR(BUS_LOCK_CLOCKS,		0x63, P6F_ALL, 0x20),
P6_EVDESCR(BUS_REQ_OUTSTANDING,		0x60, P6F_ALL, 0x00),
P6_EVDESCR(BUS_TRAN_BRD,		0x65, P6F_ALL, 0x20),
{'fraction_non_alphanumeric': 0.10143962719480736, 'fraction_numerical': 0.05725222601314804, 'mean_word_length': 4.15793991416309, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 37, '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': '5688356', 'n_tokens_mistral': 5872, 'n_tokens_neox': 5352, 'n_words': 1297}