diff options
-rw-r--r-- | lib/libpmc/libpmc.c | 42 | ||||
-rw-r--r-- | sys/conf/files.powerpc | 1 | ||||
-rw-r--r-- | sys/dev/hwpmc/hwpmc_mpc7xxx.c | 29 | ||||
-rw-r--r-- | sys/dev/hwpmc/hwpmc_powerpc.c | 11 | ||||
-rw-r--r-- | sys/dev/hwpmc/hwpmc_powerpc.h | 2 | ||||
-rw-r--r-- | sys/dev/hwpmc/hwpmc_ppc970.c | 689 | ||||
-rw-r--r-- | sys/dev/hwpmc/pmc_events.h | 57 | ||||
-rw-r--r-- | sys/powerpc/include/pmc_mdep.h | 1 | ||||
-rw-r--r-- | sys/powerpc/include/spr.h | 36 | ||||
-rw-r--r-- | sys/sys/pmc.h | 2 |
10 files changed, 828 insertions, 42 deletions
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c index 74956a9..209ae56 100644 --- a/lib/libpmc/libpmc.c +++ b/lib/libpmc/libpmc.c @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> +#include <sys/param.h> #include <sys/module.h> #include <sys/pmc.h> #include <sys/syscall.h> @@ -85,7 +86,7 @@ static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec, struct pmc_op_pmcallocate *_pmc_config); #if defined(__powerpc__) -static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec, +static int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec, struct pmc_op_pmcallocate *_pmc_config); #endif /* __powerpc__ */ @@ -156,6 +157,7 @@ PMC_CLASSDEP_TABLE(mips24k, MIPS24K); PMC_CLASSDEP_TABLE(octeon, OCTEON); PMC_CLASSDEP_TABLE(ucf, UCF); PMC_CLASSDEP_TABLE(ppc7450, PPC7450); +PMC_CLASSDEP_TABLE(ppc970, PPC970); static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT]; @@ -262,6 +264,7 @@ PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE); PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K); PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON); PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450); +PMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970); PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT); static const struct pmc_event_descr tsc_event_table[] = @@ -322,7 +325,8 @@ PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips); PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips); #endif /* __mips__ */ #if defined(__powerpc__) -PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450); +PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc); +PMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc); #endif static struct pmc_class_descr soft_class_table_descr = @@ -2404,13 +2408,19 @@ static struct pmc_event_alias ppc7450_aliases[] = { EV_ALIAS(NULL, NULL) }; -#define PPC7450_KW_OS "os" -#define PPC7450_KW_USR "usr" -#define PPC7450_KW_ANYTHREAD "anythread" +static struct pmc_event_alias ppc970_aliases[] = { + EV_ALIAS("instructions", "INSTR_COMPLETED"), + EV_ALIAS("cycles", "CYCLES"), + EV_ALIAS(NULL, NULL) +}; + +#define POWERPC_KW_OS "os" +#define POWERPC_KW_USR "usr" +#define POWERPC_KW_ANYTHREAD "anythread" static int -ppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, - struct pmc_op_pmcallocate *pmc_config __unused) +powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, + struct pmc_op_pmcallocate *pmc_config __unused) { char *p; @@ -2419,11 +2429,11 @@ ppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); while ((p = strsep(&ctrspec, ",")) != NULL) { - if (KWMATCH(p, PPC7450_KW_OS)) + if (KWMATCH(p, POWERPC_KW_OS)) pmc_config->pm_caps |= PMC_CAP_SYSTEM; - else if (KWMATCH(p, PPC7450_KW_USR)) + else if (KWMATCH(p, POWERPC_KW_USR)) pmc_config->pm_caps |= PMC_CAP_USER; - else if (KWMATCH(p, PPC7450_KW_ANYTHREAD)) + else if (KWMATCH(p, POWERPC_KW_ANYTHREAD)) pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM); else return (-1); @@ -2431,6 +2441,7 @@ ppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused, return (0); } + #endif /* __powerpc__ */ @@ -2830,6 +2841,10 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, ev = ppc7450_event_table; count = PMC_EVENT_TABLE_SIZE(ppc7450); break; + case PMC_CLASS_PPC970: + ev = ppc970_event_table; + count = PMC_EVENT_TABLE_SIZE(ppc970); + break; case PMC_CLASS_SOFT: ev = soft_event_table; count = soft_event_info.pm_nevent; @@ -3100,6 +3115,10 @@ pmc_init(void) PMC_MDEP_INIT(ppc7450); pmc_class_table[n] = &ppc7450_class_table_descr; break; + case PMC_CPU_PPC_970: + PMC_MDEP_INIT(ppc970); + pmc_class_table[n] = &ppc970_class_table_descr; + break; #endif default: /* @@ -3270,6 +3289,9 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) } else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) { ev = ppc7450_event_table; evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450); + } else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) { + ev = ppc970_event_table; + evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970); } else if (pe == PMC_EV_TSC_TSC) { ev = tsc_event_table; evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 2f63ff9..6a823de 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -31,6 +31,7 @@ dev/fb/fb.c optional sc dev/fdt/fdt_powerpc.c optional fdt dev/hwpmc/hwpmc_powerpc.c optional hwpmc dev/hwpmc/hwpmc_mpc7xxx.c optional hwpmc +dev/hwpmc/hwpmc_ppc970.c optional hwpmc dev/iicbus/ad7417.c optional ad7417 powermac dev/iicbus/ds1631.c optional ds1631 powermac dev/iicbus/ds1775.c optional ds1775 powermac diff --git a/sys/dev/hwpmc/hwpmc_mpc7xxx.c b/sys/dev/hwpmc/hwpmc_mpc7xxx.c index 93b5c74..8394e12 100644 --- a/sys/dev/hwpmc/hwpmc_mpc7xxx.c +++ b/sys/dev/hwpmc/hwpmc_mpc7xxx.c @@ -69,10 +69,10 @@ __FBSDID("$FreeBSD$"); * specifically). */ -struct powerpc_event_code_map { +struct mpc7xxx_event_code_map { enum pmc_event pe_ev; /* enum value */ uint8_t pe_counter_mask; /* Which counter this can be counted in. */ - uint8_t pe_code; /* numeric code */ + uint8_t pe_code; /* numeric code */ }; #define PPC_PMC_MASK1 0 @@ -85,7 +85,7 @@ struct powerpc_event_code_map { #define PMC_POWERPC_EVENT(id, mask, number) \ { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number } -static struct powerpc_event_code_map powerpc_event_codes[] = { +static struct mpc7xxx_event_code_map mpc7xxx_event_codes[] = { PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1), PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2), PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3), @@ -311,8 +311,8 @@ static struct powerpc_event_code_map powerpc_event_codes[] = { PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57) }; -const size_t powerpc_event_codes_size = - sizeof(powerpc_event_codes) / sizeof(powerpc_event_codes[0]); +const size_t mpc7xxx_event_codes_size = + sizeof(mpc7xxx_event_codes) / sizeof(mpc7xxx_event_codes[0]); static pmc_value_t mpc7xxx_pmcn_read(unsigned int pmc) @@ -565,6 +565,7 @@ mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu) M_WAITOK|M_ZERO); pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * MPC7XXX_MAX_PMCS, M_PMC, M_WAITOK|M_ZERO); + pac->pc_class = PMC_CLASS_PPC7450; pc = pmc_pcpu[cpu]; first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450].pcd_ri; KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); @@ -611,14 +612,14 @@ mpc7xxx_allocate_pmc(int cpu, int ri, struct pmc *pm, caps = a->pm_caps; pe = a->pm_ev; - for (i = 0; i < powerpc_event_codes_size; i++) { - if (powerpc_event_codes[i].pe_ev == pe) { - config = powerpc_event_codes[i].pe_code; - counter = powerpc_event_codes[i].pe_counter_mask; + for (i = 0; i < mpc7xxx_event_codes_size; i++) { + if (mpc7xxx_event_codes[i].pe_ev == pe) { + config = mpc7xxx_event_codes[i].pe_code; + counter = mpc7xxx_event_codes[i].pe_counter_mask; break; } } - if (i == powerpc_event_codes_size) + if (i == mpc7xxx_event_codes_size) return (EINVAL); if ((counter & (1 << ri)) == 0) @@ -724,6 +725,8 @@ pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) { struct pmc_classdep *pcd; + pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450; + pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450]; pcd->pcd_caps = POWERPC_PMC_CAPS; pcd->pcd_class = PMC_CLASS_PPC7450; @@ -735,6 +738,8 @@ pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) pcd->pcd_config_pmc = mpc7xxx_config_pmc; pcd->pcd_pcpu_fini = mpc7xxx_pcpu_fini; pcd->pcd_pcpu_init = mpc7xxx_pcpu_init; + pcd->pcd_describe = powerpc_describe; + pcd->pcd_get_config = powerpc_get_config; pcd->pcd_read_pmc = mpc7xxx_read_pmc; pcd->pcd_release_pmc = mpc7xxx_release_pmc; pcd->pcd_start_pmc = mpc7xxx_start_pmc; @@ -742,7 +747,7 @@ pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep) pcd->pcd_write_pmc = mpc7xxx_write_pmc; pmc_mdep->pmd_npmc += MPC7XXX_MAX_PMCS; - pmc_mdep->pmd_intr = mpc7xxx_intr; + pmc_mdep->pmd_intr = mpc7xxx_intr; - return 0; + return (0); } diff --git a/sys/dev/hwpmc/hwpmc_powerpc.c b/sys/dev/hwpmc/hwpmc_powerpc.c index 8da54c2..0efae5e 100644 --- a/sys/dev/hwpmc/hwpmc_powerpc.c +++ b/sys/dev/hwpmc/hwpmc_powerpc.c @@ -96,7 +96,7 @@ powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) if ((error = copystr(powerpc_name, pi->pm_name, PMC_NAME_MAX, NULL)) != 0) return error; - pi->pm_class = PMC_CLASS_PPC7450; + pi->pm_class = powerpc_pcpu[cpu]->pc_class; if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { pi->pm_enabled = TRUE; *ppmc = phw->phw_pmc; @@ -133,8 +133,6 @@ pmc_md_initialize() /* Just one class */ pmc_mdep = pmc_mdep_alloc(1); - pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450; - vers = mfpvr() >> 16; pmc_mdep->pmd_switch_in = powerpc_switch_in; @@ -151,6 +149,8 @@ pmc_md_initialize() case IBM970: case IBM970FX: case IBM970MP: + error = pmc_ppc970_initialize(pmc_mdep); + break; default: error = -1; break; @@ -159,7 +159,6 @@ pmc_md_initialize() if (error != 0) { pmc_mdep_free(pmc_mdep); pmc_mdep = NULL; - return NULL; } return (pmc_mdep); @@ -168,7 +167,9 @@ pmc_md_initialize() void pmc_md_finalize(struct pmc_mdep *md) { - free(md, M_PMC); + + free(powerpc_pcpu, M_PMC); + powerpc_pcpu = NULL; } int diff --git a/sys/dev/hwpmc/hwpmc_powerpc.h b/sys/dev/hwpmc/hwpmc_powerpc.h index a9b54f4..8f0b8ce 100644 --- a/sys/dev/hwpmc/hwpmc_powerpc.h +++ b/sys/dev/hwpmc/hwpmc_powerpc.h @@ -46,11 +46,13 @@ struct powerpc_cpu { struct pmc_hw *pc_ppcpmcs; + enum pmc_class pc_class; }; extern struct powerpc_cpu **powerpc_pcpu; extern int pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep); +extern int pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep); extern int powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc); extern int powerpc_get_config(int cpu, int ri, struct pmc **ppm); diff --git a/sys/dev/hwpmc/hwpmc_ppc970.c b/sys/dev/hwpmc/hwpmc_ppc970.c new file mode 100644 index 0000000..0d73508 --- /dev/null +++ b/sys/dev/hwpmc/hwpmc_ppc970.c @@ -0,0 +1,689 @@ +/*- + * Copyright (c) 2013 Justin Hibbits + * 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. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/pmc.h> +#include <sys/pmckern.h> +#include <sys/systm.h> + +#include <machine/pmc_mdep.h> +#include <machine/spr.h> +#include <machine/cpu.h> + +#include "hwpmc_powerpc.h" + +#define PPC970_MAX_PMCS 8 + +/* MMCR0, PMC1 is 8 bytes in, PMC2 is 1 byte in. */ +#define PPC970_SET_MMCR0_PMCSEL(r, x, i) \ + ((r & ~(0x1f << (7 * (1 - i) + 1))) | (x << (7 * (1 - i) + 1))) +/* MMCR1 has 6 PMC*SEL items (PMC3->PMC8), in sequence. */ +#define PPC970_SET_MMCR1_PMCSEL(r, x, i) \ + ((r & ~(0x1f << (5 * (7 - i) + 2))) | (x << (5 * (7 - i) + 2))) + +#define PPC970_PMC_HAS_OVERFLOWED(x) (ppc970_pmcn_read(x) & (0x1 << 31)) + +/* How PMC works on PPC970: + * + * Any PMC can count a direct event. Indirect events are handled specially. + * Direct events: As published. + * + * Encoding 00 000 -- Add byte lane bit counters + * MMCR1[24:31] -- select bit matching PMC being an adder. + * Bus events: + * PMCxSEL: 1x -- select from byte lane: 10 == lower lane (0/1), 11 == upper + * lane (2/3). + * PMCxSEL[2:4] -- bit in the byte lane selected. + * + * PMC[1,2,5,6] == lane 0/lane 2 + * PMC[3,4,7,8] == lane 1,3 + * + * + * Lanes: + * Lane 0 -- TTM0(FPU,ISU,IFU,VPU) + * TTM1(IDU,ISU,STS) + * LSU0 byte 0 + * LSU1 byte 0 + * Lane 1 -- TTM0 + * TTM1 + * LSU0 byte 1 + * LSU1 byte 1 + * Lane 2 -- TTM0 + * TTM1 + * LSU0 byte 2 + * LSU1 byte 2 or byte 6 + * Lane 3 -- TTM0 + * TTM1 + * LSU0 byte 3 + * LSU1 byte 3 or byte 7 + * + * Adders: + * Add byte lane for PMC (above), bit 0+4, 1+5, 2+6, 3+7 + */ + +struct pmc_ppc970_event { + enum pmc_event pe_event; + uint32_t pe_flags; +#define PMC_PPC970_FLAG_PMCS 0x000000ff +#define PMC_PPC970_FLAG_PMC1 0x01 +#define PMC_PPC970_FLAG_PMC2 0x02 +#define PMC_PPC970_FLAG_PMC3 0x04 +#define PMC_PPC970_FLAG_PMC4 0x08 +#define PMC_PPC970_FLAG_PMC5 0x10 +#define PMC_PPC970_FLAG_PMC6 0x20 +#define PMC_PPC970_FLAG_PMC7 0x40 +#define PMC_PPC970_FLAG_PMC8 0x80 + uint32_t pe_code; +}; + +static struct pmc_ppc970_event ppc970_event_codes[] = { + {PMC_EV_PPC970_INSTR_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMCS, + .pe_code = 0x09 + }, + {PMC_EV_PPC970_MARKED_GROUP_DISPATCH, + .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_MARKED_STORE_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_code = 0x03 + }, + {PMC_EV_PPC970_GCT_EMPTY, + .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_code = 0x04 + }, + {PMC_EV_PPC970_RUN_CYCLES, + .pe_flags = PMC_PPC970_FLAG_PMC1, + .pe_code = 0x05 + }, + {PMC_EV_PPC970_OVERFLOW, + .pe_flags = PMC_PPC970_FLAG_PMCS, + .pe_code = 0x0a + }, + {PMC_EV_PPC970_CYCLES, + .pe_flags = PMC_PPC970_FLAG_PMCS, + .pe_code = 0x0f + }, + {PMC_EV_PPC970_THRESHOLD_TIMEOUT, + .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_GROUP_DISPATCH, + .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_BR_MARKED_INSTR_FINISH, + .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_code = 0x5 + }, + {PMC_EV_PPC970_GCT_EMPTY_BY_SRQ_FULL, + .pe_flags = PMC_PPC970_FLAG_PMC2, + .pe_code = 0xb + }, + {PMC_EV_PPC970_STOP_COMPLETION, + .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_code = 0x1 + }, + {PMC_EV_PPC970_LSU_EMPTY, + .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_MARKED_STORE_WITH_INTR, + .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_CYCLES_IN_SUPER, + .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_VPU_MARKED_INSTR_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMC3, + .pe_code = 0x5 + }, + {PMC_EV_PPC970_FXU0_IDLE_FXU1_BUSY, + .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_SRQ_EMPTY, + .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_MARKED_GROUP_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_CR_MARKED_INSTR_FINISH, + .pe_flags = PMC_PPC970_FLAG_PMC4, + .pe_code = 0x5 + }, + {PMC_EV_PPC970_DISPATCH_SUCCESS, + .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_code = 0x1 + }, + {PMC_EV_PPC970_FXU0_IDLE_FXU1_IDLE, + .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_ONE_PLUS_INSTR_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_GROUP_MARKED_IDU, + .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_MARKED_GROUP_COMPLETE_TIMEOUT, + .pe_flags = PMC_PPC970_FLAG_PMC5, + .pe_code = 0x5 + }, + {PMC_EV_PPC970_FXU0_BUSY_FXU1_BUSY, + .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_MARKED_STORE_SENT_TO_STS, + .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_FXU_MARKED_INSTR_FINISHED, + .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_MARKED_GROUP_ISSUED, + .pe_flags = PMC_PPC970_FLAG_PMC6, + .pe_code = 0x5 + }, + {PMC_EV_PPC970_FXU0_BUSY_FXU1_IDLE, + .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_GROUP_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_FPU_MARKED_INSTR_COMPLETED, + .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_MARKED_INSTR_FINISH_ANY_UNIT, + .pe_flags = PMC_PPC970_FLAG_PMC7, + .pe_code = 0x5 + }, + {PMC_EV_PPC970_EXTERNAL_INTERRUPT, + .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_code = 0x2 + }, + {PMC_EV_PPC970_GROUP_DISPATCH_REJECT, + .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_code = 0x3 + }, + {PMC_EV_PPC970_LSU_MARKED_INSTR_FINISH, + .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_code = 0x4 + }, + {PMC_EV_PPC970_TIMEBASE_EVENT, + .pe_flags = PMC_PPC970_FLAG_PMC8, + .pe_code = 0x5 + }, +#if 0 + {PMC_EV_PPC970_LSU_COMPLETION_STALL, }, + {PMC_EV_PPC970_FXU_COMPLETION_STALL, }, + {PMC_EV_PPC970_DCACHE_MISS_COMPLETION_STALL, }, + {PMC_EV_PPC970_FPU_COMPLETION_STALL, }, + {PMC_EV_PPC970_FXU_LONG_INSTR_COMPLETION_STALL, }, + {PMC_EV_PPC970_REJECT_COMPLETION_STALL, }, + {PMC_EV_PPC970_FPU_LONG_INSTR_COMPLETION_STALL, }, + {PMC_EV_PPC970_GCT_EMPTY_BY_ICACHE_MISS, }, + {PMC_EV_PPC970_REJECT_COMPLETION_STALL_ERAT_MISS, }, + {PMC_EV_PPC970_GCT_EMPTY_BY_BRANCH_MISS_PREDICT, }, +#endif +}; +static size_t ppc970_event_codes_size = nitems(ppc970_event_codes); + +static pmc_value_t +ppc970_pmcn_read(unsigned int pmc) +{ + pmc_value_t val; + + switch (pmc) { + case 0: + val = mfspr(SPR_970PMC1); + break; + case 1: + val = mfspr(SPR_970PMC2); + break; + case 2: + val = mfspr(SPR_970PMC3); + break; + case 3: + val = mfspr(SPR_970PMC4); + break; + case 4: + val = mfspr(SPR_970PMC5); + break; + case 5: + val = mfspr(SPR_970PMC6); + break; + case 6: + val = mfspr(SPR_970PMC7); + break; + case 7: + val = mfspr(SPR_970PMC8); + break; + default: + panic("Invalid PMC number: %d\n", pmc); + } + + return (val); +} + +static void +ppc970_pmcn_write(unsigned int pmc, uint32_t val) +{ + switch (pmc) { + case 0: + mtspr(SPR_970PMC1, val); + break; + case 1: + mtspr(SPR_970PMC2, val); + break; + case 2: + mtspr(SPR_970PMC3, val); + break; + case 3: + mtspr(SPR_970PMC4, val); + break; + case 4: + mtspr(SPR_970PMC5, val); + break; + case 5: + mtspr(SPR_970PMC6, val); + break; + case 6: + mtspr(SPR_970PMC7, val); + break; + case 7: + mtspr(SPR_970PMC8, val); + break; + default: + panic("Invalid PMC number: %d\n", pmc); + } +} + +static int +ppc970_config_pmc(int cpu, int ri, struct pmc *pm) +{ + struct pmc_hw *phw; + + PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + + KASSERT(pm == NULL || phw->phw_pmc == NULL, + ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", + __LINE__, pm, phw->phw_pmc)); + + phw->phw_pmc = pm; + + return 0; +} + +static int +ppc970_set_pmc(int cpu, int ri, int config) +{ + struct pmc *pm; + struct pmc_hw *phw; + register_t pmc_mmcr; + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + pm = phw->phw_pmc; + + /* + * Disable the PMCs. + */ + switch (ri) { + case 0: + case 1: + pmc_mmcr = mfspr(SPR_970MMCR0); + pmc_mmcr = PPC970_SET_MMCR0_PMCSEL(pmc_mmcr, config, ri); + mtspr(SPR_970MMCR0, pmc_mmcr); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + pmc_mmcr = mfspr(SPR_970MMCR1); + pmc_mmcr = PPC970_SET_MMCR1_PMCSEL(pmc_mmcr, config, ri); + mtspr(SPR_970MMCR1, pmc_mmcr); + break; + } + return 0; +} + +static int +ppc970_start_pmc(int cpu, int ri) +{ + struct pmc *pm; + struct pmc_hw *phw; + register_t pmc_mmcr; + uint32_t config; + int error; + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + pm = phw->phw_pmc; + config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; + + error = ppc970_set_pmc(cpu, ri, config); + + /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which + * are Freeze flags. + */ + config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; + + pmc_mmcr = mfspr(SPR_970MMCR0); + pmc_mmcr &= ~SPR_MMCR0_FC; + pmc_mmcr |= config; + mtspr(SPR_970MMCR0, pmc_mmcr); + + return 0; +} + +static int +ppc970_stop_pmc(int cpu, int ri) +{ + return ppc970_set_pmc(cpu, ri, PMC970N_NONE); +} + +static int +ppc970_read_pmc(int cpu, int ri, pmc_value_t *v) +{ + struct pmc *pm; + pmc_value_t tmp; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, + ("[powerpc,%d] illegal row index %d", __LINE__, ri)); + + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + KASSERT(pm, + ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, + ri)); + + tmp = ppc970_pmcn_read(ri); + PMCDBG(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); + else + *v = tmp; + + return 0; +} + +static int +ppc970_write_pmc(int cpu, int ri, pmc_value_t v) +{ + struct pmc *pm; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; + + if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) + v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); + + PMCDBG(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); + + ppc970_pmcn_write(ri, v); + + return 0; +} + +static int +ppc970_intr(int cpu, struct trapframe *tf) +{ + struct pmc *pm; + struct powerpc_cpu *pac; + pmc_value_t v; + uint32_t config; + int i, error, retval; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); + + PMCDBG(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, + TRAPF_USERMODE(tf)); + + retval = 0; + + pac = powerpc_pcpu[cpu]; + + /* + * look for all PMCs that have interrupted: + * - look for a running, sampling PMC which has overflowed + * and which has a valid 'struct pmc' association + * + * If found, we call a helper to process the interrupt. + */ + + config = mfspr(SPR_970MMCR0); + mtspr(SPR_970MMCR0, config | SPR_MMCR0_FC); + for (i = 0; i < PPC970_MAX_PMCS; i++) { + if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || + !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { + continue; + } + + if (!PPC970_PMC_HAS_OVERFLOWED(i)) + continue; + + retval = 1; /* Found an interrupting PMC. */ + + if (pm->pm_state != PMC_STATE_RUNNING) + continue; + + /* Stop the PMC, reload count. */ + v = pm->pm_sc.pm_reloadcount; + + ppc970_pmcn_write(i, v); + + /* Restart the counter if logging succeeded. */ + error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, + TRAPF_USERMODE(tf)); + mtspr(SPR_970MMCR0, config); + if (error != 0) + ppc970_stop_pmc(cpu, i); + atomic_add_int(retval ? &pmc_stats.pm_intr_processed : + &pmc_stats.pm_intr_ignored, 1); + + } + + /* Re-enable PERF exceptions. */ + mtspr(SPR_970MMCR0, mfspr(SPR_970MMCR0) | SPR_MMCR0_PMXE); + + return (retval); +} + +static int +ppc970_pcpu_init(struct pmc_mdep *md, int cpu) +{ + struct pmc_cpu *pc; + struct powerpc_cpu *pac; + struct pmc_hw *phw; + int first_ri, i; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); + PMCDBG(MDP,INI,1,"powerpc-init cpu=%d", cpu); + + powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, + M_WAITOK|M_ZERO); + pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * PPC970_MAX_PMCS, + M_PMC, M_WAITOK|M_ZERO); + pac->pc_class = PMC_CLASS_PPC970; + + pc = pmc_pcpu[cpu]; + first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC970].pcd_ri; + KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); + + for (i = 0, phw = pac->pc_ppcpmcs; i < PPC970_MAX_PMCS; i++, phw++) { + phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | + PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); + phw->phw_pmc = NULL; + pc->pc_hwpmcs[i + first_ri] = phw; + } + + /* Clear the MMCRs, and set FC, to disable all PMCs. */ + /* 970 PMC is not counted when set to 0x08 */ + mtspr(SPR_970MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | + SPR_MMCR0_PMCNCE | SPR_970MMCR0_PMC1SEL(0x8) | SPR_970MMCR0_PMC2SEL(0x8)); + mtspr(SPR_970MMCR1, 0x4218420); + + return 0; +} + +static int +ppc970_pcpu_fini(struct pmc_mdep *md, int cpu) +{ + register_t mmcr0 = mfspr(SPR_MMCR0); + + mmcr0 |= SPR_MMCR0_FC; + mmcr0 &= ~SPR_MMCR0_PMXE; + mtspr(SPR_MMCR0, mmcr0); + free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); + free(powerpc_pcpu[cpu], M_PMC); + return 0; +} + +static int +ppc970_allocate_pmc(int cpu, int ri, struct pmc *pm, + const struct pmc_op_pmcallocate *a) +{ + enum pmc_event pe; + uint32_t caps, config = 0, counter = 0; + int i; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, + ("[powerpc,%d] illegal row index %d", __LINE__, ri)); + + caps = a->pm_caps; + + pe = a->pm_ev; + + if (pe < PMC_EV_PPC970_FIRST || pe > PMC_EV_PPC970_LAST) + return (EINVAL); + + for (i = 0; i < ppc970_event_codes_size; i++) { + if (ppc970_event_codes[i].pe_event == pe) { + config = ppc970_event_codes[i].pe_code; + counter = ppc970_event_codes[i].pe_flags; + break; + } + } + if (i == ppc970_event_codes_size) + return (EINVAL); + + if ((counter & (1 << ri)) == 0) + return (EINVAL); + + if (caps & PMC_CAP_SYSTEM) + config |= POWERPC_PMC_KERNEL_ENABLE; + if (caps & PMC_CAP_USER) + config |= POWERPC_PMC_USER_ENABLE; + if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) + config |= POWERPC_PMC_ENABLE; + + pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; + + PMCDBG(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); + + return 0; +} + +static int +ppc970_release_pmc(int cpu, int ri, struct pmc *pmc) +{ + struct pmc_hw *phw; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, + ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); + + phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; + KASSERT(phw->phw_pmc == NULL, + ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); + + return 0; +} + +int +pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep) +{ + struct pmc_classdep *pcd; + + pmc_mdep->pmd_cputype = PMC_CPU_PPC_970; + + pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC970]; + pcd->pcd_caps = POWERPC_PMC_CAPS; + pcd->pcd_class = PMC_CLASS_PPC970; + pcd->pcd_num = PPC970_MAX_PMCS; + pcd->pcd_ri = pmc_mdep->pmd_npmc; + pcd->pcd_width = 32; + + pcd->pcd_allocate_pmc = ppc970_allocate_pmc; + pcd->pcd_config_pmc = ppc970_config_pmc; + pcd->pcd_pcpu_fini = ppc970_pcpu_fini; + pcd->pcd_pcpu_init = ppc970_pcpu_init; + pcd->pcd_describe = powerpc_describe; + pcd->pcd_get_config = powerpc_get_config; + pcd->pcd_read_pmc = ppc970_read_pmc; + pcd->pcd_release_pmc = ppc970_release_pmc; + pcd->pcd_start_pmc = ppc970_start_pmc; + pcd->pcd_stop_pmc = ppc970_stop_pmc; + pcd->pcd_write_pmc = ppc970_write_pmc; + + pmc_mdep->pmd_npmc += PPC970_MAX_PMCS; + pmc_mdep->pmd_intr = ppc970_intr; + + return (0); +} diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h index ac933fe..a17b132 100644 --- a/sys/dev/hwpmc/pmc_events.h +++ b/sys/dev/hwpmc/pmc_events.h @@ -4749,6 +4749,61 @@ __PMC_EV_ALIAS("IMPC_C0H_TRK_REQUEST.ALL", UCP_EVENT_84H_01H) #define PMC_EV_PPC7450_FIRST PMC_EV_PPC7450_CYCLE #define PMC_EV_PPC7450_LAST PMC_EV_PPC7450_PREFETCH_ENGINE_FULL +#define __PMC_EV_PPC970() \ + __PMC_EV(PPC970, INSTR_COMPLETED) \ + __PMC_EV(PPC970, MARKED_GROUP_DISPATCH) \ + __PMC_EV(PPC970, MARKED_STORE_COMPLETED) \ + __PMC_EV(PPC970, GCT_EMPTY) \ + __PMC_EV(PPC970, RUN_CYCLES) \ + __PMC_EV(PPC970, OVERFLOW) \ + __PMC_EV(PPC970, CYCLES) \ + __PMC_EV(PPC970, THRESHOLD_TIMEOUT) \ + __PMC_EV(PPC970, GROUP_DISPATCH) \ + __PMC_EV(PPC970, BR_MARKED_INSTR_FINISH) \ + __PMC_EV(PPC970, GCT_EMPTY_BY_SRQ_FULL) \ + __PMC_EV(PPC970, STOP_COMPLETION) \ + __PMC_EV(PPC970, LSU_EMPTY) \ + __PMC_EV(PPC970, MARKED_STORE_WITH_INTR) \ + __PMC_EV(PPC970, CYCLES_IN_SUPER) \ + __PMC_EV(PPC970, VPU_MARKED_INSTR_COMPLETED) \ + __PMC_EV(PPC970, FXU0_IDLE_FXU1_BUSY) \ + __PMC_EV(PPC970, SRQ_EMPTY) \ + __PMC_EV(PPC970, MARKED_GROUP_COMPLETED) \ + __PMC_EV(PPC970, CR_MARKED_INSTR_FINISH) \ + __PMC_EV(PPC970, DISPATCH_SUCCESS) \ + __PMC_EV(PPC970, FXU0_IDLE_FXU1_IDLE) \ + __PMC_EV(PPC970, ONE_PLUS_INSTR_COMPLETED) \ + __PMC_EV(PPC970, GROUP_MARKED_IDU) \ + __PMC_EV(PPC970, MARKED_GROUP_COMPLETE_TIMEOUT) \ + __PMC_EV(PPC970, FXU0_BUSY_FXU1_BUSY) \ + __PMC_EV(PPC970, MARKED_STORE_SENT_TO_STS) \ + __PMC_EV(PPC970, FXU_MARKED_INSTR_FINISHED) \ + __PMC_EV(PPC970, MARKED_GROUP_ISSUED) \ + __PMC_EV(PPC970, FXU0_BUSY_FXU1_IDLE) \ + __PMC_EV(PPC970, GROUP_COMPLETED) \ + __PMC_EV(PPC970, FPU_MARKED_INSTR_COMPLETED) \ + __PMC_EV(PPC970, MARKED_INSTR_FINISH_ANY_UNIT) \ + __PMC_EV(PPC970, EXTERNAL_INTERRUPT) \ + __PMC_EV(PPC970, GROUP_DISPATCH_REJECT) \ + __PMC_EV(PPC970, LSU_MARKED_INSTR_FINISH) \ + __PMC_EV(PPC970, TIMEBASE_EVENT) \ + __PMC_EV(PPC970, LSU_COMPLETION_STALL) \ + __PMC_EV(PPC970, FXU_COMPLETION_STALL) \ + __PMC_EV(PPC970, DCACHE_MISS_COMPLETION_STALL) \ + __PMC_EV(PPC970, FPU_COMPLETION_STALL) \ + __PMC_EV(PPC970, FXU_LONG_INSTR_COMPLETION_STALL) \ + __PMC_EV(PPC970, REJECT_COMPLETION_STALL) \ + __PMC_EV(PPC970, FPU_LONG_INSTR_COMPLETION_STALL) \ + __PMC_EV(PPC970, GCT_EMPTY_BY_ICACHE_MISS) \ + __PMC_EV(PPC970, REJECT_COMPLETION_STALL_ERAT_MISS) \ + __PMC_EV(PPC970, GCT_EMPTY_BY_BRANCH_MISS_PREDICT) \ + __PMC_EV(PPC970, BUS_HIGH) \ + __PMC_EV(PPC970, BUS_LOW) \ + __PMC_EV(PPC970, ADDER) + + +#define PMC_EV_PPC970_FIRST PMC_EV_PPC970_INSTR_COMPLETED +#define PMC_EV_PPC970_LAST PMC_EV_PPC970_ADDER /* * All known PMC events. * @@ -4799,6 +4854,8 @@ __PMC_EV_ALIAS("IMPC_C0H_TRK_REQUEST.ALL", UCP_EVENT_84H_01H) __PMC_EV_UCP() \ __PMC_EV_BLOCK(PPC7450, 0x13000) \ __PMC_EV_PPC7450() \ + __PMC_EV_BLOCK(PPC970, 0x13100) \ + __PMC_EV_PPC970() \ #define PMC_EVENT_FIRST PMC_EV_TSC_TSC #define PMC_EVENT_LAST PMC_EV_SOFT_LAST diff --git a/sys/powerpc/include/pmc_mdep.h b/sys/powerpc/include/pmc_mdep.h index a0f2062..87dc76c 100644 --- a/sys/powerpc/include/pmc_mdep.h +++ b/sys/powerpc/include/pmc_mdep.h @@ -7,6 +7,7 @@ #ifndef _MACHINE_PMC_MDEP_H_ #define _MACHINE_PMC_MDEP_H_ +#define PMC_MDEP_CLASS_INDEX_CPU 1 #define PMC_MDEP_CLASS_INDEX_PPC7450 1 #define PMC_MDEP_CLASS_INDEX_PPC970 1 diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h index f275069..b9fb3c1 100644 --- a/sys/powerpc/include/spr.h +++ b/sys/powerpc/include/spr.h @@ -294,6 +294,27 @@ #define M_CASID 0x0000000f /* Current AS Id */ #define SPR_MD_AP 0x31a /* ..8 DMMU access protection */ #define SPR_MD_EPN 0x31b /* ..8 DMMU effective number */ + +#define SPR_970MMCR0 0x31b /* ... Monitor Mode Control Register 0 (PPC 970) */ +#define SPR_970MMCR0_PMC1SEL(x) ((x) << 8) /* PMC1 selector (970) */ +#define SPR_970MMCR0_PMC2SEL(x) ((x) << 1) /* PMC2 selector (970) */ +#define SPR_970MMCR1 0x31e /* ... Monitor Mode Control Register 1 (PPC 970) */ +#define SPR_970MMCR1_PMC3SEL(x) (((x) & 0x1f) << 27) /* PMC 3 selector */ +#define SPR_970MMCR1_PMC4SEL(x) (((x) & 0x1f) << 22) /* PMC 4 selector */ +#define SPR_970MMCR1_PMC5SEL(x) (((x) & 0x1f) << 17) /* PMC 5 selector */ +#define SPR_970MMCR1_PMC6SEL(x) (((x) & 0x1f) << 12) /* PMC 6 selector */ +#define SPR_970MMCR1_PMC7SEL(x) (((x) & 0x1f) << 7) /* PMC 7 selector */ +#define SPR_970MMCR1_PMC8SEL(x) (((x) & 0x1f) << 2) /* PMC 8 selector */ +#define SPR_970MMCRA 0x312 /* ... Monitor Mode Control Register 2 (PPC 970) */ +#define SPR_970PMC1 0x313 /* ... PMC 1 */ +#define SPR_970PMC2 0x314 /* ... PMC 2 */ +#define SPR_970PMC3 0x315 /* ... PMC 3 */ +#define SPR_970PMC4 0x316 /* ... PMC 4 */ +#define SPR_970PMC5 0x317 /* ... PMC 5 */ +#define SPR_970PMC6 0x318 /* ... PMC 6 */ +#define SPR_970PMC7 0x319 /* ... PMC 7 */ +#define SPR_970PMC8 0x31a /* ... PMC 8 */ + #define SPR_M_TWB 0x31c /* ..8 MMU tablewalk base */ #define M_TWB_L1TB 0xfffff000 /* level-1 translation base */ #define M_TWB_L1INDX 0x00000ffc /* level-1 index */ @@ -323,19 +344,6 @@ #define SPR_DVC1 0x3b6 /* 4.. Data Value Compare 1 */ #define SPR_DVC2 0x3b7 /* 4.. Data Value Compare 2 */ #define SPR_MMCR0 0x3b8 /* .6. Monitor Mode Control Register 0 */ - -#define SPR_970MMCR0 0x31b /* ... Monitor Mode Control Register 0 (PPC 970) */ -#define SPR_970MMCR1 0x31e /* ... Monitor Mode Control Register 1 (PPC 970) */ -#define SPR_970MMCRA 0x312 /* ... Monitor Mode Control Register 2 (PPC 970) */ -#define SPR_970PMC1 0x313 /* ... PMC 1 */ -#define SPR_970PMC2 0x314 /* ... PMC 2 */ -#define SPR_970PMC3 0x315 /* ... PMC 3 */ -#define SPR_970PMC4 0x316 /* ... PMC 4 */ -#define SPR_970PMC5 0x317 /* ... PMC 5 */ -#define SPR_970PMC6 0x318 /* ... PMC 6 */ -#define SPR_970PMC7 0x319 /* ... PMC 7 */ -#define SPR_970PMC8 0x31a /* ... PMC 8 */ - #define SPR_MMCR0_FC 0x80000000 /* Freeze counters */ #define SPR_MMCR0_FCS 0x40000000 /* Freeze counters in supervisor mode */ #define SPR_MMCR0_FCP 0x20000000 /* Freeze counters in user mode */ @@ -354,8 +362,6 @@ #define SPR_MMCR0_TRIGGER 0x00002000 /* Trigger */ #define SPR_MMCR0_PMC1SEL(x) (((x) & 0x3f) << 6) /* PMC1 selector */ #define SPR_MMCR0_PMC2SEL(x) (((x) & 0x3f) << 0) /* PMC2 selector */ -#define SPR_970MMCR0_PMC1SEL(x) ((x) << 8) /* PMC1 selector (970) */ -#define SPR_970MMCR0_PMC2SEL(x) ((x) << 1) /* PMC2 selector (970) */ #define SPR_SGR 0x3b9 /* 4.. Storage Guarded Register */ #define SPR_PMC1 0x3b9 /* .6. Performance Counter Register 1 */ #define SPR_DCWR 0x3ba /* 4.. Data Cache Write-through Register */ diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index e5a9c45..de397c8 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -95,6 +95,7 @@ __PMC_CPU(MIPS_24K, 0x200, "MIPS 24K") \ __PMC_CPU(MIPS_OCTEON, 0x201, "Cavium Octeon") \ __PMC_CPU(PPC_7450, 0x300, "PowerPC MPC7450") \ + __PMC_CPU(PPC_970, 0x380, "IBM PowerPC 970") \ __PMC_CPU(GENERIC, 0x400, "Generic") enum pmc_cputype { @@ -125,6 +126,7 @@ enum pmc_cputype { __PMC_CLASS(MIPS24K) /* MIPS 24K */ \ __PMC_CLASS(OCTEON) /* Cavium Octeon */ \ __PMC_CLASS(PPC7450) /* Motorola MPC7450 class */ \ + __PMC_CLASS(PPC970) /* IBM PowerPC 970 class */ \ __PMC_CLASS(SOFT) /* Software events */ enum pmc_class { |