From owner-svn-src-user@FreeBSD.ORG Tue Nov 11 08:04:27 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6D2F71065670; Tue, 11 Nov 2008 08:04:27 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 511508FC26; Tue, 11 Nov 2008 08:04:27 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mAB84RmR094602; Tue, 11 Nov 2008 08:04:27 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mAB84RbJ094600; Tue, 11 Nov 2008 08:04:27 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200811110804.mAB84RbJ094600@svn.freebsd.org> From: Kip Macy Date: Tue, 11 Nov 2008 08:04:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184835 - user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Nov 2008 08:04:27 -0000 Author: kmacy Date: Tue Nov 11 08:04:27 2008 New Revision: 184835 URL: http://svn.freebsd.org/changeset/base/184835 Log: Add actual ipm driver files Added: user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.c (contents, props changed) user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.h (contents, props changed) Added: user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/kmacy/HEAD_fast_multi_xmit/sys/dev/hwpmc/hwpmc_ipm.c Tue Nov 11 08:04:27 2008 (r184835) @@ -0,0 +1,1593 @@ +/*- + * Copyright (c) 2003-2005 Joseph Koshy + * Copyright (c) 2007-2008 Nokia Corporation + * All rights reserved. + * + * 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. + */ + +/* + * Add Performance Monitoring (PM) support for the processor based on Intel's + * Core Solo/Duo architecture and Intel Core microarchitecture. + * This CPUs support Intel's Architectural PM Version 1/2 functionality. + * Intel(R) 64 and IA-32 Architectures Software Developer's Manual: + * System Programming Guide: Volue 3B: Section 18.12 + * + * Intel Core Solo/Duo processors introduced architectural PM. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * I had not had so much trouble coding as giving sensible names. + * I am sticking to 'ipm' prefix (Intel Performance Monitoring). + * Where it really makes difference it will further be qualified by + * 'ipm_v1' or 'ipm_v2'. + * Bear with me. + */ + +/* + * Globals set from the initialization routine based on the + * CPU type + */ +static enum pmc_cputype ipm_cputype; +static const struct ipm_event_descr *ipm_events = NULL; +static const struct ipm_pmc_descr *ipm_pmc_desc; +static int ipm_nevents = 0; +static int ipm_npmcs = 0; + +#define IPM_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) + +#define IPM_FIXEDPMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \ + PMC_CAP_SYSTEM | PMC_CAP_READ | PMC_CAP_WRITE) + +static inline int +ipm_v2_pmc_has_overflowed(uint64_t ovf_status, int ri) +{ + return ((ri < 3) ? + (ovf_status & (0x1LL << (ri - 1))) : + (ovf_status & (0x100000000LL << (ri - 3)))); +} + + +static inline uint64_t +ipm_v2_pmc_ri_to_msr_en_bit(int ri) +{ + return ((ri < 3) ? + (0x1LL << (ri - 1)) : + (0x100000000LL << (ri - 3))); +} + +struct ipm_pmc_descr { + struct pmc_descr pm_descr; /* common information */ + uint32_t pm_pmc_msr; + uint32_t pm_evsel_msr; +}; + +static const struct ipm_pmc_descr ipm_pmc_desc_v1[IPM_NPMCS_V1] = { + /* 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 + }, + + /* PMC 0 */ + { + .pm_descr = + { + .pd_name = "IPM-PMC-1", + .pd_class = PMC_CLASS_IAP1, + .pd_caps = IPM_PMC_CAPS, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFCTR0, + .pm_evsel_msr = IPM_MSR_EVSEL0 + }, + + /* PMC 1 */ + { + .pm_descr = + { + .pd_name = "IPM-PMC-2", + .pd_class = PMC_CLASS_IAP1, + .pd_caps = IPM_PMC_CAPS, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFCTR1, + .pm_evsel_msr = IPM_MSR_EVSEL1 + }, +}; + +static const struct ipm_pmc_descr ipm_pmc_desc_v2[IPM_NPMCS_V2] = { + /* 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 + }, + + /* PMC 0 */ + { + .pm_descr = + { + .pd_name = "IPM-PMC-1", + .pd_caps = IPM_PMC_CAPS, + .pd_class = PMC_CLASS_IAP2, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFCTR0, + .pm_evsel_msr = IPM_MSR_EVSEL0 + }, + + /* PMC 1 */ + { + .pm_descr = + { + .pd_name = "IPM-PMC-2", + .pd_class = PMC_CLASS_IAP2, + .pd_caps = IPM_PMC_CAPS, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFCTR1, + .pm_evsel_msr = IPM_MSR_EVSEL1 + }, + + /* + * Following 3 fixed function performance counters are only available + * in processors supporting PM version 2 facilities + */ + /* Fixed function PMC 1 */ + { + .pm_descr = + { + .pd_name = "IPM-FIXED-PMC-1", + .pd_class = PMC_CLASS_IAF, + .pd_caps = IPM_FIXEDPMC_CAPS, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFFIXEDCTR0, + .pm_evsel_msr = IPM_MSR_PERFFIXEDCTR_CTRL + }, + + /* Fixed function PMC 2 */ + { + .pm_descr = + { + .pd_name = "IPM-FIXED-PMC-2", + .pd_class = PMC_CLASS_IAF, + .pd_caps = IPM_FIXEDPMC_CAPS, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFFIXEDCTR1, + .pm_evsel_msr = IPM_MSR_PERFFIXEDCTR_CTRL + }, + + /* Fixed function PMC 3 */ + { + .pm_descr = + { + .pd_name = "IPM-FIXED-PMC-3", + .pd_class = PMC_CLASS_IAF, + .pd_caps = IPM_FIXEDPMC_CAPS, + .pd_width = 40 + }, + .pm_pmc_msr = IPM_MSR_PERFFIXEDCTR2, + .pm_evsel_msr = IPM_MSR_PERFFIXEDCTR_CTRL + } +}; + +/* + * Event descriptors + */ +struct ipm_event_descr { + const enum pmc_event pm_event; + uint32_t pm_evsel; + uint32_t pm_umask; + uint32_t pm_umask_allowed; +}; + +/* + * Fixed function PM events. Processors based on Intel Core Microarchitecture + * have 3 fixed function PMCs. The following 3 PM events can only be + * programmed on fixed function PMCs + */ +static const struct ipm_event_descr ipm_events_fixed[] = { +#define IPM_EVDESCR(NAME, EVSEL, UMASK) \ + { \ + .pm_event = PMC_EV_IAF_##NAME, \ + .pm_evsel = (EVSEL), \ + .pm_umask = (UMASK), \ + .pm_umask_allowed = 0 \ + } + +IPM_EVDESCR(INSTRUCTIONS_RETIRED, 0xC0, 0x00), +IPM_EVDESCR(UNHALTED_CORE_CYCLES, 0x3C, 0x00), +IPM_EVDESCR(UNHALTED_REFERENCE_CYCLES, 0x3C, 0x01), + +#undef IPM_EVDESCR +}; +#define IPM_NEVENTS_FIXED 3 + +/* + * The following events can be programmed on IA32_PMC0/1 of processors based + * on Intel Core Solo/Duo processors. + */ +static const struct ipm_event_descr ipm_events_v1[] = { +#define IPM_EVDESCR(NAME, EVSEL, UMASK, ALLOW) \ + { \ + .pm_event = PMC_EV_IAP1_##NAME, \ + .pm_evsel = (EVSEL), \ + .pm_umask = (UMASK), \ + .pm_umask_allowed = (ALLOW) \ + } +IPM_EVDESCR(INSTRUCTIONS_RETIRED, 0xC0, 0x00, 0), +IPM_EVDESCR(UNHALTED_CORE_CYCLES, 0x3C, 0x00, 0), +IPM_EVDESCR(UNHALTED_REFERENCE_CYCLES, 0x3C, 0x01, 0), +IPM_EVDESCR(LLC_REFERENCE, 0x2E, 0x4F, 0), +IPM_EVDESCR(LLC_MISSES, 0x2E, 0x41, 0), +IPM_EVDESCR(BRANCH_INSTRUCTION_RETIRED, 0xC4, 0x00, 0), +IPM_EVDESCR(BRANCH_MISSES_RETIRED, 0xC5, 0x00, 0), + +IPM_EVDESCR(LD_BLOCKS, 0x03, 0x00, 0), +IPM_EVDESCR(SD_DRAINS, 0x04, 0x00, 0), +IPM_EVDESCR(MISALIGN_MEM_REF, 0x05, 0x00, 0), +IPM_EVDESCR(SEG_REG_LOADS, 0x06, 0x00, 0), +IPM_EVDESCR(SSE_PREFNTA_RET, 0x07, 0x00, 0), +IPM_EVDESCR(SSE_PREFT1_RET, 0x07, 0x01, 0), +IPM_EVDESCR(SSE_PREFT2_RET, 0x07, 0x02, 0), +IPM_EVDESCR(SSE_NTSTORES_RET, 0x07, 0x03, 0), +IPM_EVDESCR(FP_COMPS_OP_EXE, 0x10, 0x00, 0), +IPM_EVDESCR(FP_ASSIST, 0x11, 0x00, 0), +IPM_EVDESCR(MUL, 0x12, 0x00, 0), +IPM_EVDESCR(DIV, 0x13, 0x00, 0), +IPM_EVDESCR(CYCLES_DIV_BUSY, 0x14, 0x00, 0), +IPM_EVDESCR(L2_ADS, 0x21, 0xC0, 1), +IPM_EVDESCR(DBUS_BUSY, 0x22, 0xC0, 1), +IPM_EVDESCR(DBUS_BUSY_RD, 0x23, 0xC0, 1), +IPM_EVDESCR(L2_LINES_IN, 0x24, 0XF0, 1), +IPM_EVDESCR(L2_M_LINES_IN, 0x25, 0xC0, 1), +IPM_EVDESCR(L2_LINES_OUT, 0x26, 0xF0, 1), +IPM_EVDESCR(L2_M_LINES_OUT, 0x27, 0xF0, 1), +IPM_EVDESCR(L2_IFETCH, 0x28, 0xC0, 1), +IPM_EVDESCR(L2_LD, 0x29, 0xC0, 1), +IPM_EVDESCR(L2_ST, 0x2A, 0xC0, 1), +IPM_EVDESCR(L2_RQSTS, 0x2E, 0xF0, 1), +IPM_EVDESCR(L2_REJECT_CYCLES, 0x30, 0xF0, 1), +IPM_EVDESCR(L2_NO_REQUEST_CYCLES, 0x32, 0xF0, 1), +IPM_EVDESCR(EST_TRANS_ALL, 0x3A, 0x00, 0), +IPM_EVDESCR(EST_TRANS_FREQ, 0x3A, 0x10, 0), +IPM_EVDESCR(THERMAL_TRIP, 0x3B, 0xC0, 0), +IPM_EVDESCR(NONHLT_REF_CYCLES, 0x3C, 0x01, 0), +IPM_EVDESCR(SERIAL_EXECUTION_CYCLES, 0x3C, 0x02, 0), +IPM_EVDESCR(DCACHE_CACHE_LD, 0x40, 0x0F, 1), +IPM_EVDESCR(DCACHE_CACHE_ST, 0x41, 0x0F, 1), +IPM_EVDESCR(DCACHE_CACHE_LOCK, 0x42, 0x0F, 1), +IPM_EVDESCR(DATA_MEM_REF, 0x43, 0x01, 0), +IPM_EVDESCR(DATA_MEM_CACHE_REF, 0x44, 0x02, 0), +IPM_EVDESCR(DCACHE_REPL, 0x45, 0x0F, 0), +IPM_EVDESCR(DCACHE_M_REPL, 0x46, 0x00, 0), +IPM_EVDESCR(DCACHE_M_EVICT, 0x47, 0x00, 0), +IPM_EVDESCR(DCACHE_PEND_MISS, 0x48, 0x00, 0), +IPM_EVDESCR(DTLB_MISS, 0x49, 0x00, 0), +IPM_EVDESCR(SSE_PREFNTA_MISS, 0x4B, 0x00, 0), +IPM_EVDESCR(SSE_PREFT1_MISS, 0x4B, 0x01, 0), +IPM_EVDESCR(SSE_PREFT2_MISS, 0x4B, 0x02, 0), +IPM_EVDESCR(SSE_NTSTORES_MISS, 0x4B, 0x03, 0), +IPM_EVDESCR(L1_PREF_REQ, 0x4F, 0x00, 0), +IPM_EVDESCR(BUS_REQ_OUTSTANDING, 0x60, 0xE0, 1), +IPM_EVDESCR(BUS_BNR_CLOCKS, 0x61, 0x00, 0), +IPM_EVDESCR(BUS_DRDY_CLOCKS, 0x62, 0x20, 1), +IPM_EVDESCR(BUS_LOCK_CLOCKS, 0x63, 0xC0, 1), +IPM_EVDESCR(BUS_DATA_RCV, 0x64, 0x40, 0), +IPM_EVDESCR(BUS_TRANS_BRD, 0x65, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_RFO, 0x66, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_IFETCH, 0x68, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_INVAL, 0x69, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_PWR, 0x6A, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_P, 0x6B, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_IO, 0x6C, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_DEF, 0x6D, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_WB, 0x67, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_BURST, 0x6E, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_MEM, 0x6F, 0xE0, 1), +IPM_EVDESCR(BUS_TRANS_ANY, 0x70, 0xE0, 1), +IPM_EVDESCR(BUS_SNOOPS, 0x77, 0x2F, 1), +IPM_EVDESCR(DCU_SNOOP_TO_SHARE, 0x78, 0xC1, 1), +IPM_EVDESCR(BUS_NOT_IN_USE, 0x7D, 0xC0, 1), +IPM_EVDESCR(BUS_SNOOP_STALL, 0x7E, 0x00, 0), +IPM_EVDESCR(ICACHE_READS, 0x80, 0x00, 0), +IPM_EVDESCR(ICACHE_MISSES, 0x81, 0x00, 0), +IPM_EVDESCR(ITLB_MISSES, 0x85, 0x00, 0), +IPM_EVDESCR(IFU_MEM_STALL, 0x86, 0x00, 0), +IPM_EVDESCR(ILD_STALL, 0x87, 0x00, 0), +IPM_EVDESCR(BR_INST_EXEC, 0x88, 0x00, 0), +IPM_EVDESCR(BR_MISSP_EXEC, 0x89, 0x00, 0), +IPM_EVDESCR(BR_BAC_MISSP_EXEC, 0x8A, 0x00, 0), +IPM_EVDESCR(BR_CND_EXEC, 0x8B, 0x00, 0), +IPM_EVDESCR(BR_CND_MISSP_EXEC, 0x8C, 0x00, 0), +IPM_EVDESCR(BR_IND_EXEC, 0x8D, 0x00, 0), +IPM_EVDESCR(BR_IND_MISSP_EXEC, 0x8E, 0x00, 0), +IPM_EVDESCR(BR_RET_EXEC, 0x8F, 0x00, 0), +IPM_EVDESCR(BR_RET_MISSP_EXEC, 0x90, 0x00, 0), +IPM_EVDESCR(BR_RET_BAC_MISSP_EXEC, 0x91, 0x00, 0), +IPM_EVDESCR(BR_CALL_EXEC, 0x92, 0x00, 0), +IPM_EVDESCR(BR_CALL_MISSP_EXEC, 0x93, 0x00, 0), +IPM_EVDESCR(BR_IND_CALL_EXEC, 0x94, 0x00, 0), +IPM_EVDESCR(RESOURCE_STALL, 0xA2, 0x00, 0), +IPM_EVDESCR(MMX_INSTR_EXEC, 0xB0, 0x00, 0), +IPM_EVDESCR(SIMD_INT_SAT_EXEC, 0xB1, 0x00, 0), +IPM_EVDESCR(SIMD_INT_PMUL_EXEC, 0xB3, 0x01, 0), +IPM_EVDESCR(SIMD_INT_PSFT_EXEC, 0xB3, 0x02, 0), +IPM_EVDESCR(SIMD_INT_PCK_EXEC, 0xB3, 0x04, 0), +IPM_EVDESCR(SIMD_INT_UPCK_EXEC, 0xB3, 0x08, 0), +IPM_EVDESCR(SIMD_INT_PLOG_EXEC, 0xB3, 0x10, 0), +IPM_EVDESCR(SIMD_INT_PARI_EXEC, 0xB3, 0x20, 0), +IPM_EVDESCR(INSTR_RET, 0xC0, 0x00, 0), +IPM_EVDESCR(FP_COMP_INSTR_RET, 0xC1, 0x00, 0), +IPM_EVDESCR(UOPS_RET, 0xC2, 0x00, 0), +IPM_EVDESCR(SMC_DETECTED, 0xC3, 0x00, 0), +IPM_EVDESCR(BR_INSTR_RET, 0xC4, 0x00, 0), +IPM_EVDESCR(BR_MISPRED_RET, 0xC5, 0x00, 0), +IPM_EVDESCR(CYCLES_INT_MASKED, 0xC6, 0x00, 0), +IPM_EVDESCR(CYCLES_INT_PENDING_MASKED, 0xC7, 0x00, 0), +IPM_EVDESCR(HW_INT_RX, 0xC8, 0x00, 0), +IPM_EVDESCR(BR_TAKEN_RET, 0xC9, 0x00, 0), +IPM_EVDESCR(BR_MISPRED_TAKEN_RET, 0xCA, 0x00, 0), +IPM_EVDESCR(MMX_FP_TRANS, 0xCC, 0x00, 0), +IPM_EVDESCR(FP_MMX_TRANS, 0xCC, 0x01, 0), +IPM_EVDESCR(MMX_ASSIST, 0xCD, 0x00, 0), +IPM_EVDESCR(MMX_INST_RET, 0xCE, 0x00, 0), +IPM_EVDESCR(INSTR_DECODED, 0xD0, 0x00, 0), +IPM_EVDESCR(ESP_UOPS, 0xD7, 0x00, 0), +IPM_EVDESCR(SIMD_FP_SP_RET, 0xD8, 0x00, 0), +IPM_EVDESCR(SIMD_FP_SP_S_RET, 0xD8, 0x01, 0), +IPM_EVDESCR(SIMD_FP_DP_P_RET, 0xD8, 0x02, 0), +IPM_EVDESCR(SIMD_FP_DP_S_RET, 0xD8, 0x03, 0), +IPM_EVDESCR(SIMD_INT_128_RET, 0xD8, 0x04, 0), +IPM_EVDESCR(SIMD_FP_SP_P_COMP_RET, 0xD9, 0x00, 0), +IPM_EVDESCR(SIMD_FP_SP_S_COMP_RET, 0xD9, 0x01, 0), +IPM_EVDESCR(SIMD_FP_DP_P_COMP_RET, 0xD9, 0x02, 0), +IPM_EVDESCR(SIMD_FP_SP_S_COMP_RET, 0xD9, 0x03, 0), +IPM_EVDESCR(FUSED_UOPS_RET, 0xDA, 0x00, 0), +IPM_EVDESCR(FUSED_LD_UOPS_RET, 0xDA, 0x01, 0), +IPM_EVDESCR(FUSED_ST_UOPS_RET, 0xDA, 0x02, 0), +IPM_EVDESCR(UNFUSION, 0xDB, 0x00, 0), +IPM_EVDESCR(BR_INSTR_DECODED, 0xE0, 0x00, 0), +IPM_EVDESCR(BTB_MISSES, 0xE2, 0x00, 0), +IPM_EVDESCR(BR_BOGUS, 0xE4, 0x00, 0), +IPM_EVDESCR(BACLEARS, 0xE6, 0x00, 0), +IPM_EVDESCR(PREF_RQSTS_UP, 0xF0, 0x00, 0), +IPM_EVDESCR(PREF_RQSTS_DN, 0xF8, 0x00, 0), + +#undef IPM_EVDESCR +}; +#define IPM_NEVENTS_V1 (PMC_EV_IAP1_LAST - PMC_EV_IAP1_FIRST + 1) + +/* + * The following events can be programmed on IA32_PMC0/1 of processors based + * on Intel Core microarchitecture. + */ +static const struct ipm_event_descr ipm_events_v2[] = { +#define IPM_EVDESCR(NAME, EVSEL, UMASK, ALLOW) \ + { \ + .pm_event = PMC_EV_IAP2_##NAME, \ + .pm_evsel = (EVSEL), \ + .pm_umask = (UMASK), \ + .pm_umask_allowed = (ALLOW) \ + } +IPM_EVDESCR(INSTRUCTIONS_RETIRED, 0xC0, 0x00, 0), +IPM_EVDESCR(UNHALTED_CORE_CYCLES, 0x3C, 0x00, 0), +IPM_EVDESCR(UNHALTED_REFERENCE_CYCLES, 0x3C, 0x01, 0), +IPM_EVDESCR(LLC_REFERENCE, 0x2E, 0x4F, 0), +IPM_EVDESCR(LLC_MISSES, 0x2E, 0x41, 0), +IPM_EVDESCR(BRANCH_INSTRUCTION_RETIRED, 0xC4, 0x00, 0), +IPM_EVDESCR(BRANCH_MISSES_RETIRED, 0xC5, 0x00, 0), + +IPM_EVDESCR(LOAD_BLOCK_STA, 0x03, 0x02, 0), +IPM_EVDESCR(LOAD_BLOCK_STD, 0x03, 0x04, 0), +IPM_EVDESCR(LOAD_BLOCK_OVERLAP_STORE, 0x03, 0x08, 0), +IPM_EVDESCR(LOAD_BLOCK_UNTIL_RETIRE, 0x03, 0x10, 0), +IPM_EVDESCR(LOAD_BLOCK_L1D, 0x03, 0x20, 0), +IPM_EVDESCR(SB_DRAIN_CYCLES, 0x04, 0x01, 0), +IPM_EVDESCR(STORE_BLOCK_ORDER, 0x04, 0x02, 0), +IPM_EVDESCR(STORE_BLOCK_SNOOP, 0x04, 0x08, 0), +IPM_EVDESCR(MISALIGN_MEM_REF, 0x05, 0x00, 0), +IPM_EVDESCR(SEGMENT_REG_LOADS, 0x06, 0x00, 0), +IPM_EVDESCR(SSE_PRE_EXEC_NTA, 0x07, 0x00, 0), +IPM_EVDESCR(SSE_PRE_EXEC_L1, 0x07, 0x01, 0), +IPM_EVDESCR(SSE_PRE_EXEC_L2, 0x07, 0x02, 0), +IPM_EVDESCR(SSE_PRE_EXEC_STORES, 0x07, 0x03, 0), +IPM_EVDESCR(DTLB_MISSES_ANY, 0x08, 0x01, 0), +IPM_EVDESCR(DTLB_MISSES_MISS_LD, 0x08, 0x02, 0), +IPM_EVDESCR(L0_DTLB_MISSES_MISS_LD, 0x08, 0x04, 0), +IPM_EVDESCR(DTLB_MISSES_MISS_ST, 0x08, 0x08, 0), +IPM_EVDESCR(MEMORY_DISAMBIGUATION_RESET, 0x09, 0x01, 0), +IPM_EVDESCR(MEMORY_DISAMBIGUATION_SUCCESS, 0x09, 0x02, 0), +IPM_EVDESCR(PAGE_WALKS_COUNT, 0x0C, 0x01, 0), +IPM_EVDESCR(PAGE_WALKS_CYCLES, 0x0C, 0x02, 0), +IPM_EVDESCR(FP_COMP_OPS_EXE, 0x10, 0x00, 0), +IPM_EVDESCR(FP_ASSIST, 0x11, 0x00, 0), +IPM_EVDESCR(MUL, 0x12, 0x00, 0), +IPM_EVDESCR(DIV, 0x13, 0x00, 0), +IPM_EVDESCR(CYCLES_DIV_BUSY, 0x14, 0x00, 0), +IPM_EVDESCR(IDLE_DURING_DIV, 0x18, 0x00, 0), +IPM_EVDESCR(DELAYED_BYPASS_FP, 0x19, 0x00, 0), +IPM_EVDESCR(DELAYED_BYPASS_SIMD, 0x19, 0x01, 0), +IPM_EVDESCR(DELAYED_BYPASS_LOAD, 0x19, 0x02, 0), +IPM_EVDESCR(L2_ADS, 0x21, 0xC0, 1), +IPM_EVDESCR(L2_DBUS_BUSY_RD, 0x23, 0xC0, 1), +IPM_EVDESCR(L2_LINES_IN, 0x24, 0xF0, 1), +IPM_EVDESCR(L2_M_LINES_IN, 0x25, 0xC0, 1), +IPM_EVDESCR(L2_LINES_OUT, 0x26, 0xF0, 1), +IPM_EVDESCR(L2_M_LINES_OUT, 0x27, 0xF0, 1), +IPM_EVDESCR(L2_IFETCH, 0x28, 0xCF, 1), +IPM_EVDESCR(L2_LD, 0x29, 0xFF, 1), +IPM_EVDESCR(L2_ST, 0x2A, 0xCF, 1), +IPM_EVDESCR(L2_LOCK, 0x2B, 0xCF, 1), +IPM_EVDESCR(L2_RQSTS, 0x2E, 0xFF, 1), +IPM_EVDESCR(L2_RQSTS_SELF_DEMAND_I_STATE, 0x2E, 0x41, 0), +IPM_EVDESCR(L2_RQSTS_SELF_DEMAND_MESI, 0x2E, 0x4F, 0), +IPM_EVDESCR(L2_REJECT_BUSQ, 0x30, 0xFF, 1), +IPM_EVDESCR(L2_NO_REQ, 0x32, 0xC0, 1), +IPM_EVDESCR(EIST_TRANS, 0x3A, 0x00, 0), +IPM_EVDESCR(THERMAL_TRIP, 0x3B, 0xC0, 0), +IPM_EVDESCR(CPU_CLK_UNHALTED_CORE, 0x3C, 0x00, 0), +IPM_EVDESCR(CPU_CLK_UNHALTED_BUS, 0x3C, 0x01, 0), +IPM_EVDESCR(CPU_CLK_UNHALTED_NO_OTHER, 0x3C, 0x02, 0), +IPM_EVDESCR(L1D_CACHE_LD, 0x40, 0x0F, 1), +IPM_EVDESCR(L1D_CACHE_ST, 0x40, 0x0F, 1), +IPM_EVDESCR(L1D_CACHE_LOCK, 0x42, 0x0F, 1), +IPM_EVDESCR(L1D_CACHE_LOCK_DURATION, 0x42, 0x10, 0), +IPM_EVDESCR(L1D_ALL_REF, 0x43, 0x10, 0), +IPM_EVDESCR(L1D_ALL_CACHE_REF, 0x43, 0x02, 0), +IPM_EVDESCR(L1D_REPL, 0x45, 0x0F, 0), +IPM_EVDESCR(L1D_M_REPL, 0x46, 0x00, 0), +IPM_EVDESCR(L1D_M_EVICT, 0x47, 0x00, 0), +IPM_EVDESCR(L1D_PEND_MISS, 0x48, 0x00, 0), +IPM_EVDESCR(L1D_SPLIT_LOADS, 0x49, 0x01, 0), +IPM_EVDESCR(L1D_SPLIT_STORES, 0x49, 0x02, 0), +IPM_EVDESCR(SSE_PRE_MISS_NTA, 0x4B, 0x00, 0), +IPM_EVDESCR(SSE_PRE_MISS_L1, 0x4B, 0x01, 0), +IPM_EVDESCR(SSE_PRE_MISS_L2, 0x4B, 0x02, 0), +IPM_EVDESCR(LOAD_HIT_PRE, 0x4C, 0x00, 0), +IPM_EVDESCR(L1D_PREFETCH_REQUESTS, 0x4E, 0x10, 0), +IPM_EVDESCR(BUS_REQUEST_OUTSTANDING, 0x60, 0xE0, 1), +IPM_EVDESCR(BUS_BNR_DRV, 0x61, 0x20, 1), +IPM_EVDESCR(BUS_DRDY_CLOCKS, 0x62, 0x20, 1), +IPM_EVDESCR(BUS_LOCK_CLOCKS, 0x63, 0xE0, 1), +IPM_EVDESCR(BUS_DATA_RCV, 0x64, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_BRD, 0x65, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_RFO, 0x66, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_WB, 0x67, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_IFETCH, 0x68, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_INVAL, 0x69, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_PWR, 0x6A, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_P, 0x6B, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_IO, 0x6C, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_DEF, 0x6D, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_BURST, 0x6E, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_MEM, 0x6F, 0xC0, 1), +IPM_EVDESCR(BUS_TRANS_ANY, 0x70, 0xC0, 1), +IPM_EVDESCR(EXT_SNOOP, 0x77, 0xCB, 1), +IPM_EVDESCR(CMP_SNOOP, 0x78, 0xC3, 1), +IPM_EVDESCR(BUS_HIT_DRV, 0x7A, 0x20, 1), +IPM_EVDESCR(BUS_HITM_DRV, 0x7B, 0x20, 1), +IPM_EVDESCR(BUSQ_EMPTY, 0x7D, 0xC0, 1), +IPM_EVDESCR(SNOOP_STALL_DRV, 0x7E, 0xE0, 1), +IPM_EVDESCR(BUS_IO_WAIT, 0x7F, 0xC0, 1), +IPM_EVDESCR(L1I_READS, 0x80, 0x00, 0), +IPM_EVDESCR(L1I_MISSES, 0x81, 0x00, 0), +IPM_EVDESCR(ITLB_SMALL_MISS, 0x82, 0x02, 0), +IPM_EVDESCR(ITLB_LARGE_MISS, 0x82, 0x10, 0), +IPM_EVDESCR(ITLB_FLUSH, 0x82, 0x40, 0), +IPM_EVDESCR(ITLB_MISSES, 0x82, 0x12, 0), +IPM_EVDESCR(INST_QUEUE_FULL, 0x83, 0x02, 0), +IPM_EVDESCR(CYCLES_L1I_MEM_STALLED, 0x86, 0x00, 0), +IPM_EVDESCR(ILD_STALL, 0x87, 0x00, 0), +IPM_EVDESCR(BR_INST_EXEC, 0x88, 0x00, 0), +IPM_EVDESCR(BR_MISSP_EXEC, 0x89, 0x00, 0), +IPM_EVDESCR(BR_BAC_MISSP_EXEC, 0x8A, 0x00, 0), +IPM_EVDESCR(BR_CND_EXEC, 0x8B, 0x00, 0), +IPM_EVDESCR(BR_CND_MISSP_EXEC, 0x8C, 0x00, 0), +IPM_EVDESCR(BR_IND_EXEC, 0x8D, 0x00, 0), +IPM_EVDESCR(BR_IND_MISSP_EXEC, 0x8E, 0x00, 0), +IPM_EVDESCR(BR_RET_EXEC, 0x8F, 0x00, 0), +IPM_EVDESCR(BR_RET_MISSP_EXEC, 0x90, 0x00, 0), +IPM_EVDESCR(BR_RET_BAC_MISSP_EXEC, 0x91, 0x00, 0), +IPM_EVDESCR(BR_CALL_EXEC, 0x92, 0x00, 0), +IPM_EVDESCR(BR_CALL_MISSP_EXEC, 0x93, 0x00, 0), +IPM_EVDESCR(BR_IND_CALL_EXEC, 0x94, 0x00, 0), +IPM_EVDESCR(BR_TKN_BUBBLE_1, 0x97, 0x00, 0), +IPM_EVDESCR(BR_TKN_BUBBLE_2, 0x98, 0x00, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED, 0xA0, 0x00, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT0, 0xA0, 0x01, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT1, 0xA0, 0x02, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT2, 0xA0, 0x04, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT3, 0xA0, 0x08, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT4, 0xA0, 0x10, 0), +IPM_EVDESCR(RS_UOPS_DISPATCHED_PORT5, 0xA0, 0x20, 0), +IPM_EVDESCR(MACRO_INSTS_DECODED, 0xA1, 0x01, 0), +IPM_EVDESCR(MACRO_INSTS_CISC_DECODED, 0xA1, 0x08, 0), +IPM_EVDESCR(ESP_SYNCH, 0xAB, 0x01, 0), +IPM_EVDESCR(ESP_ADDITIONS, 0xAB, 0x02, 0), +IPM_EVDESCR(SIMD_UOPS_EXEC, 0xB0, 0x00, 0), +IPM_EVDESCR(SIMD_SAT_UOP_EXEC, 0xB1, 0x00, 0), +IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_MUL, 0xB3, 0x01, 0), +IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_SHIFT, 0xB3, 0x02, 0), +IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_PACK, 0xB3, 0x04, 0), +IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_UNPACK, 0xB3, 0x08, 0), +IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_LOGICAL, 0xB3, 0x10, 0), +IPM_EVDESCR(SIMD_UOP_TYPE_EXEC_ARITHMETIC, 0xB3, 0x20, 0), +IPM_EVDESCR(INST_RETIRED_ANY_P, 0xC0, 0x00, 0), +IPM_EVDESCR(INST_RETIRED_LOADS, 0xC0, 0x01, 0), +IPM_EVDESCR(INST_RETIRED_STORES, 0xC0, 0x02, 0), +IPM_EVDESCR(INST_RETIRED_OTHER, 0xC0, 0x04, 0), +IPM_EVDESCR(X87_OPS_RETIRED_FXCH, 0xC1, 0x01, 0), +IPM_EVDESCR(X87_OPS_RETIRED_ANY, 0xC1, 0xFE, 0), +IPM_EVDESCR(UOPS_RETIRED_L2_IND_BR, 0xC2, 0x01, 0), +IPM_EVDESCR(UOPS_RETIRED_STD_STA, 0xC2, 0x02, 0), +IPM_EVDESCR(UOPS_RETIRED_MACRO_FUSION, 0xC2, 0x04, 0), +IPM_EVDESCR(UOPS_RETIRED_FUSED, 0xC2, 0x07, 0), +IPM_EVDESCR(UOPS_RETIRED_NON_FUSED, 0xC2, 0x08, 0), +IPM_EVDESCR(UOPS_RETIRED_ANY, 0xC2, 0x0F, 0), +IPM_EVDESCR(MACHINE_NUKES_SMC, 0xC3, 0x01, 0), +IPM_EVDESCR(MACHINE_NUKES_MEM_ORDER, 0xC3, 0x04, 0), +IPM_EVDESCR(BR_INST_RETIRED_ANY, 0xC4, 0x00, 0), +IPM_EVDESCR(BR_INST_RETIRED_PRED_NOT_TAKEN, 0xC4, 0x01, 0), +IPM_EVDESCR(BR_INST_RETIRED_MISPRED_NOT_TAKEN, 0xC4, 0x02, 0), +IPM_EVDESCR(BR_INST_RETIRED_PRED_TAKEN, 0xC4, 0x04, 0), +IPM_EVDESCR(BR_INST_RETIRED_MISPRED_TAKEN, 0xC4, 0x08, 0), +IPM_EVDESCR(BR_INST_RETIRED_TAKEN, 0xC4, 0x0C, 0), +IPM_EVDESCR(BR_INST_RETIRED_MISPRED, 0xC5, 0x00, 0), +IPM_EVDESCR(CYCLES_INT_MASKED, 0xC6, 0x01, 0), +IPM_EVDESCR(CYCLES_INT_PENDING_AND_MASKED, 0xC6, 0x02, 0), +IPM_EVDESCR(SIMD_INST_RETIRED_PACKED_SINGLE, 0xC7, 0x01, 0), +IPM_EVDESCR(SIMD_INST_RETIRED_SCALAR_SINGLE, 0xC7, 0x02, 0), +IPM_EVDESCR(SIMD_INST_RETIRED_PACKED_DOUBLE, 0xC7, 0x04, 0), +IPM_EVDESCR(SIMD_INST_RETIRED_SCALAR_DOUBLE, 0xC7, 0x08, 0), +IPM_EVDESCR(SIMD_INST_RETIRED_VECTOR, 0xC7, 0x10, 0), +IPM_EVDESCR(SIMD_INST_RETIRED_ANY, 0xC7, 0x1F, 0), +IPM_EVDESCR(HW_INT_RCV, 0xC8, 0x00, 0), +IPM_EVDESCR(ITLB_MISS_RETIRED, 0xC9, 0x00, 0), +IPM_EVDESCR(SIMD_COMP_INST_RETIRED_PACKED_SINGLE, 0xCA, 0x01, 0), +IPM_EVDESCR(SIMD_COMP_INST_RETIRED_SCALAR_SINGLE, 0xCA, 0x02, 0), +IPM_EVDESCR(SIMD_COMP_INST_RETIRED_PACKED_DOUBLE, 0xCA, 0x04, 0), +IPM_EVDESCR(SIMD_COMP_INST_RETIRED_SCALAR_DOUBLE, 0xCA, 0x08, 0), +IPM_EVDESCR(MEM_LOAD_RETIRED_L1D_MISS, 0xCB, 0x01, 0), +IPM_EVDESCR(MEM_LOAD_RETIRED_L1D_LINE_MISS, 0xCB, 0x02, 0), +IPM_EVDESCR(MEM_LOAD_RETIRED_L2_MISS, 0xCB, 0x04, 0), +IPM_EVDESCR(MEM_LOAD_RETIRED_L2_LINE_MISS, 0xCB, 0x08, 0), +IPM_EVDESCR(MEM_LOAD_RETIRED_DTLB_MISS, 0xCB, 0x10, 0), +IPM_EVDESCR(FP_MMX_TRANS_TO_MMX, 0xCC, 0x01, 0), +IPM_EVDESCR(FP_MMX_TRANS_TO_FP, 0xCC, 0x02, 0), +IPM_EVDESCR(SIMD_ASSIST, 0xCD, 0x00, 0), +IPM_EVDESCR(SIMD_INST_RETIRED, 0xCE, 0x00, 0), +IPM_EVDESCR(SIMD_SAT_INST_RETIRED, 0xCF, 0x00, 0), +IPM_EVDESCR(RAT_STALLS_ROB_READ_PORT, 0xD2, 0x01, 0), +IPM_EVDESCR(RAT_STALLS_PARTIAL_CYCLES, 0xD2, 0x02, 0), +IPM_EVDESCR(RAT_STALLS_FLAGS, 0xD2, 0x04, 0), +IPM_EVDESCR(RAT_STALLS_FPSW, 0xD2, 0x08, 0), +IPM_EVDESCR(RAT_STALLS_ANY, 0xD2, 0x0F, 0), +IPM_EVDESCR(SEG_RENAME_STALLS_ES, 0xD4, 0x01, 0), +IPM_EVDESCR(SEG_RENAME_STALLS_DS, 0xD4, 0x02, 0), +IPM_EVDESCR(SEG_RENAME_STALLS_FS, 0xD4, 0x04, 0), +IPM_EVDESCR(SEG_RENAME_STALLS_GS, 0xD4, 0x08, 0), +IPM_EVDESCR(SEG_RENAME_STALLS_ANY, 0xD4, 0x0F, 0), +IPM_EVDESCR(SEG_REG_RENAME_ES, 0xD4, 0x01, 0), +IPM_EVDESCR(SEG_REG_RENAME_DS, 0xD5, 0x02, 0), +IPM_EVDESCR(SEG_REG_RENAME_FS, 0xD5, 0x04, 0), +IPM_EVDESCR(SEG_REG_RENAME_GS, 0xD5, 0x08, 0), +IPM_EVDESCR(SEG_REG_RENAME_ANY, 0xD5, 0x0F, 0), +IPM_EVDESCR(RESOURCE_STALLS_ROB_FULL, 0xDC, 0x01, 0), +IPM_EVDESCR(RESOURCE_STALLS_RS_FULL, 0xDC, 0x02, 0), +IPM_EVDESCR(RESOURCE_STALLS_LD_ST, 0xDC, 0x04, 0), +IPM_EVDESCR(RESOURCE_STALLS_FPCW, 0xDC, 0x08, 0), +IPM_EVDESCR(RESOURCE_STALLS_BR_MISS_CLEAR, 0xDC, 0x10, 0), +IPM_EVDESCR(RESOURCE_STALLS_ANY, 0xDC, 0x1F, 0), +IPM_EVDESCR(BR_INST_DECODED, 0xE0, 0x00, 0), +IPM_EVDESCR(BOGUS_BR, 0xE4, 0x00, 0), +IPM_EVDESCR(BACLEARS, 0xE6, 0x00, 0), +IPM_EVDESCR(PREF_RQSTS_UP, 0xF0, 0x00, 0), +IPM_EVDESCR(PREF_RQSTS_DN, 0xF8, 0x00, 0) + +#undef IPM_EVDESCR +}; +#define IPM_NEVENTS_V2 (PMC_EV_IAP2_LAST - PMC_EV_IAP2_FIRST + 1) + +/* + * Events defined here can only be programmed on the specified raw index + */ +struct ipm_ev_pmc_mapping { + const enum pmc_event pm_event; + const int pm_ri; +}; + +static const struct ipm_ev_pmc_mapping ipm_ev_pmc_mappings_v1[] = { +#define IPM_EV_PMC_MAPPING(NAME, RI) \ + { \ + .pm_event = PMC_EV_IAP1_##NAME, \ + .pm_ri = (RI), \ + } +IPM_EV_PMC_MAPPING(FP_ASSIST, 2), +IPM_EV_PMC_MAPPING(MUL, 2), +IPM_EV_PMC_MAPPING(DIV, 2), +IPM_EV_PMC_MAPPING(CYCLES_DIV_BUSY, 1), +IPM_EV_PMC_MAPPING(FP_COMP_INSTR_RET, 1), + +#undef IPM_EV_PMC_MAPPING +}; +#define IAP1_NMAPPINGS 5 + +static const struct ipm_ev_pmc_mapping ipm_ev_pmc_mappings_v2[] = { +#define IPM_EV_PMC_MAPPING(NAME, RI) \ + { \ + .pm_event = PMC_EV_IAP2_##NAME, \ + .pm_ri = (RI), \ + } +IPM_EV_PMC_MAPPING(FP_COMP_OPS_EXE, 1), +IPM_EV_PMC_MAPPING(FP_ASSIST, 2), +IPM_EV_PMC_MAPPING(MUL, 2), +IPM_EV_PMC_MAPPING(DIV, 2), +IPM_EV_PMC_MAPPING(CYCLES_DIV_BUSY, 1), +IPM_EV_PMC_MAPPING(IDLE_DURING_DIV, 1), +IPM_EV_PMC_MAPPING(DELAYED_BYPASS_FP, 2), +IPM_EV_PMC_MAPPING(DELAYED_BYPASS_SIMD, 2), +IPM_EV_PMC_MAPPING(DELAYED_BYPASS_LOAD, 2), +IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT0, 1), +IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT1, 1), +IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT2, 1), +IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT3, 1), +IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT4, 1), +IPM_EV_PMC_MAPPING(RS_UOPS_DISPATCHED_PORT5, 1), +IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L1D_MISS, 1), +IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L1D_LINE_MISS, 1), +IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L2_MISS, 1), +IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_L2_LINE_MISS, 1), +IPM_EV_PMC_MAPPING(MEM_LOAD_RETIRED_DTLB_MISS, 1), + +#undef IPM_EV_PMC_MAPPING +}; +#define IAP2_NMAPPINGS 20 + +static const struct ipm_ev_pmc_mapping *ipm_ev_pmc_mappings = NULL; +static int ipm_nmappings = 0; + +static inline int +ipm_ev_valid_for_pmc(enum pmc_event ev, int ri) +{ + int valid = 1; + int i = 0; + + for (; i < ipm_nmappings; i++) { + if (ev == ipm_ev_pmc_mappings[i].pm_event && + ri != ipm_ev_pmc_mappings[i].pm_ri) + valid = 0; + } + + return (valid); +} + + +static const struct ipm_event_descr * +ipm_find_event(enum pmc_event ev) +{ + int n; + + if (ipm_cputype == PMC_CPU_INTEL_CORE || + ipm_cputype == PMC_CPU_INTEL_CORE2 || + ipm_cputype == PMC_CPU_INTEL_ATOM) { + for (n = 0; n < IPM_NEVENTS_FIXED; n++) + if (ipm_events_fixed[n].pm_event == ev) + return (&ipm_events_fixed[n]); + } + + for (n = 0; n < ipm_nevents; n++) { + if (ipm_events[n].pm_event == ev) + return (&ipm_events[n]); + } + + return (NULL); +} + +/* + * Per-CPU data structure for Intel Core Solo/Duo class CPUs + * + * [common stuff] + * [flags for maintaining PMC start/stop state] + * [3 struct pmc_hw pointers] + * [3 struct pmc_hw structures] + */ +struct ipm_cpu { + struct pmc_cpu pc_common; + struct pmc_hw *pc_hwpmcs[IPM_NPMCS]; + struct pmc_hw pc_ipm_pmcs[IPM_NPMCS]; + uint32_t pc_state; +}; + +#define IPM_PMC_MARK_STARTED(PC,RI) do { \ + (PC)->pc_state |= (1 << ((RI)-1)); \ + } while (0) + +#define IPM_PMC_MARK_STOPPED(PC,RI) do { \ + (PC)->pc_state &= ~(1<< ((RI)-1)); \ + } while (0) + +#define IPM_PMC_STOPPED(PC,RI) (((PC)->pc_state & (1 << ((RI)-1))) == 0) +#define IPM_PMC_STARTED(PC,RI) (((PC)->pc_state & (1 << ((RI)-1))) == 1) + +static int +ipm_init(int cpu) +{ + int n; + struct ipm_cpu *pcs; + struct pmc_hw *phw; + + KASSERT(cpu >= 0 && cpu < mp_ncpus, + ("[ipm,%d] bad cpu %d", __LINE__, cpu)); + + PMCDBG(MDP,INI,0,"ipm-init cpu=%d", cpu); + + MALLOC(pcs, struct ipm_cpu *, sizeof(struct ipm_cpu), M_PMC, + M_WAITOK|M_ZERO); + + phw = pcs->pc_ipm_pmcs; + + for (n = 0; n < ipm_npmcs; n++, phw++) { + phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | + PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n); + phw->phw_pmc = NULL; + pcs->pc_hwpmcs[n] = phw; + } + + /* Mark the TSC as shareable */ + pcs->pc_hwpmcs[0]->phw_state |= PMC_PHW_FLAG_IS_SHAREABLE; + + pmc_pcpu[cpu] = (struct pmc_cpu *) pcs; + + return (0); +} + +static int +ipm_cleanup(int cpu) +{ + struct pmc_cpu *pcs; + + KASSERT(cpu >= 0 && cpu < mp_ncpus, + ("[ipm,%d] bad cpu %d", __LINE__, cpu)); + + PMCDBG(MDP,INI,0,"ipm-cleanup cpu=%d", cpu); + + if ((pcs = pmc_pcpu[cpu]) != NULL) + FREE(pcs, M_PMC); + pmc_pcpu[cpu] = NULL; + + return (0); +} + +static int +ipm_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) +{ + (void) pc; + + PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp, + pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS); + + /* allow the RDPMC instruction if needed */ + if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) + load_cr4(rcr4() | CR4_PCE); + + PMCDBG(MDP,SWI,1, "cr4=0x%x", rcr4()); + + return (0); +} + +static int +ipm_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) +{ + (void) pc; + (void) pp; /* can be NULL */ + + PMCDBG(MDP,SWO,1, "pc=%p pp=%p cr4=0x%x", pc, pp, rcr4()); + + /* always turn off the RDPMC instruction */ + load_cr4(rcr4() & ~CR4_PCE); + + return (0); +} + +static int +ipm_read_pmc(int cpu, int ri, pmc_value_t *v) +{ + struct pmc_hw *phw; + struct pmc *pm; + const struct ipm_pmc_descr *pd; + pmc_value_t tmp; + + phw = pmc_pcpu[cpu]->pc_hwpmcs[ri]; + pm = phw->phw_pmc; + pd = &ipm_pmc_desc[ri]; + + KASSERT(pm, + ("[ipm,%d] cpu %d ri %d pmc not configured", + __LINE__, cpu, ri)); + + if (pd->pm_descr.pd_class == PMC_CLASS_TSC) { + *v = rdtsc(); + return (0); + } + + tmp = rdmsr(pd->pm_pmc_msr) & IPM_PERFCTR_READ_MASK; + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + *v = IPM_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + else + *v = tmp; + + PMCDBG(MDP,REA,1, "ipm-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri, + pd->pm_pmc_msr, *v); + + return (0); +} + +static int +ipm_write_pmc(int cpu, int ri, pmc_value_t v) +{ + struct pmc_hw *phw; + struct pmc *pm; + const struct ipm_pmc_descr *pd; + uint64_t ctrl_msr; + + phw = pmc_pcpu[cpu]->pc_hwpmcs[ri]; + pm = phw->phw_pmc; + pd = &ipm_pmc_desc[ri]; + + KASSERT(pm, + ("[ipm,%d] cpu %d ri %d pmc not configured", + __LINE__, cpu, ri)); + + if (pd->pm_descr.pd_class == PMC_CLASS_TSC) + return (0); + + PMCDBG(MDP,WRI,1, "ipm-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri, + pd->pm_pmc_msr, v); + + /* + * Stop the PMC first + */ + switch (ipm_cputype) { + case PMC_CPU_INTEL_CORE: + wrmsr(pd->pm_evsel_msr, + pm->pm_md.pm_ipm.pm_ipm_evsel & (~IPM_EVSEL_EN)); + break; + + case PMC_CPU_INTEL_CORE2: + ctrl_msr = rdmsr(IPM_MSR_PERFCTR_CTRL); + ctrl_msr &= ~(ipm_v2_pmc_ri_to_msr_en_bit(ri)); + wrmsr(IPM_MSR_PERFCTR_CTRL, ctrl_msr); + break; + + default: + break; + } + + + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + v = IPM_RELOAD_COUNT_TO_PERFCTR_VALUE(v); + wrmsr(pd->pm_pmc_msr, v & IPM_PERFCTR_WRITE_MASK); + + /* + * Start the PMC + */ + switch (ipm_cputype) { + case PMC_CPU_INTEL_CORE: + wrmsr(pd->pm_evsel_msr, + pm->pm_md.pm_ipm.pm_ipm_evsel | IPM_EVSEL_EN); + break; + + case PMC_CPU_INTEL_CORE2: + ctrl_msr = rdmsr(IPM_MSR_PERFCTR_CTRL); + ctrl_msr |= ipm_v2_pmc_ri_to_msr_en_bit(ri); + wrmsr(IPM_MSR_PERFCTR_CTRL, ctrl_msr); + break; + + default: + break; + } + + return (0); +} + +static int +ipm_config_pmc(int cpu, int ri, struct pmc *pm) +{ + struct pmc_hw *phw; + + PMCDBG(MDP,CFG,1, "ipm-config cpu=%d ri=%d pm=%p", cpu, ri, pm); + + phw = pmc_pcpu[cpu]->pc_hwpmcs[ri]; + phw->phw_pmc = pm; + + return (0); +} + +/* + * Retrieve a configured PMC pointer from hardware state. + */ +static int +ipm_get_config(int cpu, int ri, struct pmc **ppm) +{ + *ppm = pmc_pcpu[cpu]->pc_hwpmcs[ri]->phw_pmc; + + return (0); +} + +static int +ipm_allocate_fixed_pmc(int cpu, int ri, uint32_t caps, + struct pmc *pm, const struct ipm_event_descr *pevent) +{ + uint32_t config, counter; + + counter = ri - 3; + + /* + * Event and fixed function counter has one to one mapping + * and the event is only valid for the counter with same + * index + */ + if ((pevent->pm_event == PMC_EV_IAF_INSTRUCTIONS_RETIRED && + counter == 0) || + (pevent->pm_event == PMC_EV_IAF_UNHALTED_CORE_CYCLES && + counter == 1) || + (pevent->pm_event == PMC_EV_IAF_UNHALTED_REFERENCE_CYCLES + && counter == 2)) { + config = 0; + } else { + return (EINVAL); + } + + if (caps & PMC_CAP_SYSTEM) + config |= IPM_FIXEDCTR_PL_OS; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***