diff options
author | Lijun Pan <Lijun.Pan@freescale.com> | 2013-04-19 16:57:51 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-05-01 23:10:39 (GMT) |
commit | 935bd4ec8b3908db62f069575cf59e6e6aa1a1b7 (patch) | |
tree | a61b204bfe6269866d53015f75c843dbdf3f83cd | |
parent | 8e893c85f14f4cf748f23102fe8402e417bd44ca (diff) | |
download | linux-fsl-qoriq-935bd4ec8b3908db62f069575cf59e6e6aa1a1b7.tar.xz |
powerpc: add 2 additional performance counters for e6500 core
There are 6 counters in e6500 core instead of 4 in e500 core.
Correct the typos in counter enumeration.
Some of the codes are based on Priyanka Jain's patch.
e6500 core performance monitors has the following features:
- 6 performance monitor counters
- none restricted access
- 512 events supported
Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
Change-Id: Ia8a5f17087028752f2984e61c2c8abd823d27639
Reviewed-on: http://git.am.freescale.net:8181/1638
Reviewed-by: Wood Scott-B07421 <scottwood@freescale.com>
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
-rw-r--r-- | arch/powerpc/include/asm/reg_fsl_emb.h | 24 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 2 | ||||
-rw-r--r-- | arch/powerpc/oprofile/op_model_fsl_emb.c | 30 | ||||
-rw-r--r-- | arch/powerpc/perf/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/perf/core-fsl-emb.c | 24 | ||||
-rw-r--r-- | arch/powerpc/perf/e6500-pmu.c | 120 |
6 files changed, 195 insertions, 7 deletions
diff --git a/arch/powerpc/include/asm/reg_fsl_emb.h b/arch/powerpc/include/asm/reg_fsl_emb.h index 77bb71c..0e3ddf5 100644 --- a/arch/powerpc/include/asm/reg_fsl_emb.h +++ b/arch/powerpc/include/asm/reg_fsl_emb.h @@ -17,12 +17,16 @@ /* Freescale Book E Performance Monitor APU Registers */ #define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */ #define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */ -#define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */ -#define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */ +#define PMRN_PMC2 0x012 /* Performance Monitor Counter 2 */ +#define PMRN_PMC3 0x013 /* Performance Monitor Counter 3 */ +#define PMRN_PMC4 0x014 /* Performance Monitor Counter 4 */ +#define PMRN_PMC5 0x015 /* Performance Monitor Counter 5 */ #define PMRN_PMLCA0 0x090 /* PM Local Control A0 */ #define PMRN_PMLCA1 0x091 /* PM Local Control A1 */ #define PMRN_PMLCA2 0x092 /* PM Local Control A2 */ #define PMRN_PMLCA3 0x093 /* PM Local Control A3 */ +#define PMRN_PMLCA4 0x094 /* PM Local Control A4 */ +#define PMRN_PMLCA5 0x095 /* PM Local Control A5 */ #define PMLCA_FC 0x80000000 /* Freeze Counter */ #define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */ @@ -30,14 +34,18 @@ #define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */ #define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */ #define PMLCA_CE 0x04000000 /* Condition Enable */ +#define PMLCA_FGCS1 0x00000002 /* Freeze in guest state */ +#define PMLCA_FGCS0 0x00000001 /* Freeze in hypervisor state */ -#define PMLCA_EVENT_MASK 0x00ff0000 /* Event field */ +#define PMLCA_EVENT_MASK 0x01ff0000 /* Event field */ #define PMLCA_EVENT_SHIFT 16 #define PMRN_PMLCB0 0x110 /* PM Local Control B0 */ #define PMRN_PMLCB1 0x111 /* PM Local Control B1 */ #define PMRN_PMLCB2 0x112 /* PM Local Control B2 */ #define PMRN_PMLCB3 0x113 /* PM Local Control B3 */ +#define PMRN_PMLCB4 0x114 /* PM Local Control B4 */ +#define PMRN_PMLCB5 0x115 /* PM Local Control B5 */ #define PMLCB_THRESHMUL_MASK 0x0700 /* Threshold Multiple Field */ #define PMLCB_THRESHMUL_SHIFT 8 @@ -55,16 +63,22 @@ #define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */ #define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */ -#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */ -#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */ +#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 2 */ +#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 3 */ +#define PMRN_UPMC4 0x004 /* User Performance Monitor Counter 4 */ +#define PMRN_UPMC5 0x005 /* User Performance Monitor Counter 5 */ #define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */ #define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */ #define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */ #define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */ +#define PMRN_UPMLCA4 0x084 /* User PM Local Control A4 */ +#define PMRN_UPMLCA5 0x085 /* User PM Local Control A5 */ #define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */ #define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */ #define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */ #define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */ +#define PMRN_UPMLCB4 0x104 /* User PM Local Control B4 */ +#define PMRN_UPMLCB5 0x105 /* User PM Local Control B5 */ #define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 5d116d0..5f9ecfe 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -2078,7 +2078,7 @@ static struct cpu_spec __initdata cpu_specs[] = { MMU_FTR_USE_TLBILX, .icache_bsize = 64, .dcache_bsize = 64, - .num_pmcs = 4, + .num_pmcs = 6, .oprofile_cpu_type = "ppc/e6500", .oprofile_type = PPC_OPROFILE_FSL_EMB, .cpu_setup = __setup_cpu_e6500, diff --git a/arch/powerpc/oprofile/op_model_fsl_emb.c b/arch/powerpc/oprofile/op_model_fsl_emb.c index ccc1daa..2a82d3e 100644 --- a/arch/powerpc/oprofile/op_model_fsl_emb.c +++ b/arch/powerpc/oprofile/op_model_fsl_emb.c @@ -46,6 +46,12 @@ static inline u32 get_pmlca(int ctr) case 3: pmlca = mfpmr(PMRN_PMLCA3); break; + case 4: + pmlca = mfpmr(PMRN_PMLCA4); + break; + case 5: + pmlca = mfpmr(PMRN_PMLCA5); + break; default: panic("Bad ctr number\n"); } @@ -68,6 +74,12 @@ static inline void set_pmlca(int ctr, u32 pmlca) case 3: mtpmr(PMRN_PMLCA3, pmlca); break; + case 4: + mtpmr(PMRN_PMLCA4, pmlca); + break; + case 5: + mtpmr(PMRN_PMLCA5, pmlca); + break; default: panic("Bad ctr number\n"); } @@ -84,6 +96,10 @@ static inline unsigned int ctr_read(unsigned int i) return mfpmr(PMRN_PMC2); case 3: return mfpmr(PMRN_PMC3); + case 4: + return mfpmr(PMRN_PMC4); + case 5: + return mfpmr(PMRN_PMC5); default: return 0; } @@ -104,6 +120,12 @@ static inline void ctr_write(unsigned int i, unsigned int val) case 3: mtpmr(PMRN_PMC3, val); break; + case 4: + mtpmr(PMRN_PMC4, val); + break; + case 5: + mtpmr(PMRN_PMC5, val); + break; default: break; } @@ -133,6 +155,14 @@ static void init_pmc_stop(int ctr) mtpmr(PMRN_PMLCA3, pmlca); mtpmr(PMRN_PMLCB3, pmlcb); break; + case 4: + mtpmr(PMRN_PMLCA4, pmlca); + mtpmr(PMRN_PMLCB4, pmlcb); + break; + case 5: + mtpmr(PMRN_PMLCA5, pmlca); + mtpmr(PMRN_PMLCB5, pmlcb); + break; default: panic("Bad ctr number!\n"); } diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index af3fac2..06dd8d5 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile @@ -8,7 +8,7 @@ obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o obj-$(CONFIG_FSL_EMB_PERF_EVENT) += core-fsl-emb.o -obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o e6500-pmu.o obj-$(CONFIG_PPC64) += $(obj64-y) obj-$(CONFIG_PPC32) += $(obj32-y) diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c index 106c533..a81e666 100644 --- a/arch/powerpc/perf/core-fsl-emb.c +++ b/arch/powerpc/perf/core-fsl-emb.c @@ -70,6 +70,12 @@ static unsigned long read_pmc(int idx) case 3: val = mfpmr(PMRN_PMC3); break; + case 4: + val = mfpmr(PMRN_PMC4); + break; + case 5: + val = mfpmr(PMRN_PMC5); + break; default: printk(KERN_ERR "oops trying to read PMC%d\n", idx); val = 0; @@ -95,6 +101,12 @@ static void write_pmc(int idx, unsigned long val) case 3: mtpmr(PMRN_PMC3, val); break; + case 4: + mtpmr(PMRN_PMC4, val); + break; + case 5: + mtpmr(PMRN_PMC5, val); + break; default: printk(KERN_ERR "oops trying to write PMC%d\n", idx); } @@ -120,6 +132,12 @@ static void write_pmlca(int idx, unsigned long val) case 3: mtpmr(PMRN_PMLCA3, val); break; + case 4: + mtpmr(PMRN_PMLCA4, val); + break; + case 5: + mtpmr(PMRN_PMLCA5, val); + break; default: printk(KERN_ERR "oops trying to write PMLCA%d\n", idx); } @@ -145,6 +163,12 @@ static void write_pmlcb(int idx, unsigned long val) case 3: mtpmr(PMRN_PMLCB3, val); break; + case 4: + mtpmr(PMRN_PMLCB4, val); + break; + case 5: + mtpmr(PMRN_PMLCB5, val); + break; default: printk(KERN_ERR "oops trying to write PMLCB%d\n", idx); } diff --git a/arch/powerpc/perf/e6500-pmu.c b/arch/powerpc/perf/e6500-pmu.c new file mode 100644 index 0000000..795a565 --- /dev/null +++ b/arch/powerpc/perf/e6500-pmu.c @@ -0,0 +1,120 @@ +/* + * Performance counter support for e6500 family processors. + * + * Author: Lijun Pan + * Based on Priyanka Jain's code + * Based on e500-pmu.c + * Copyright 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/string.h> +#include <linux/perf_event.h> +#include <asm/reg.h> +#include <asm/cputable.h> + +/* + * Map of generic hardware event types to hardware events + * Zero if unsupported + */ +static int e6500_generic_events[] = { + [PERF_COUNT_HW_CPU_CYCLES] = 1, + [PERF_COUNT_HW_INSTRUCTIONS] = 2, + [PERF_COUNT_HW_CACHE_MISSES] = 221, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12, + [PERF_COUNT_HW_BRANCH_MISSES] = 15, +}; + +#define C(x) PERF_COUNT_HW_CACHE_##x + +/* + * Table of generalized cache-related events. + * 0 means not supported, -1 means nonsensical, other values + * are event codes. + */ +static int e6500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { + [C(L1D)] = { + /*RESULT_ACCESS RESULT_MISS */ + [C(OP_READ)] = { 27, 222 }, + [C(OP_WRITE)] = { 28, 223 }, + [C(OP_PREFETCH)] = { 29, 0 }, + }, + [C(L1I)] = { + /*RESULT_ACCESS RESULT_MISS */ + [C(OP_READ)] = { 2, 254 }, + [C(OP_WRITE)] = { -1, -1 }, + [C(OP_PREFETCH)] = { 37, 0 }, + }, + /* + * Assuming LL means L2, it's not a good match for this model. + * It does not have separate read/write events (but it does have + * separate instruction/data events). + */ + [C(LL)] = { + /*RESULT_ACCESS RESULT_MISS */ + [C(OP_READ)] = { 0, 0 }, + [C(OP_WRITE)] = { 0, 0 }, + [C(OP_PREFETCH)] = { 0, 0 }, + }, + /* + * There are data/instruction MMU misses, but that's a miss on + * the chip's internal level-one TLB which is probably not + * what the user wants. Instead, unified level-two TLB misses + * are reported here. + */ + [C(DTLB)] = { + /*RESULT_ACCESS RESULT_MISS */ + [C(OP_READ)] = { 26, 66 }, + [C(OP_WRITE)] = { -1, -1 }, + [C(OP_PREFETCH)] = { -1, -1 }, + }, + [C(BPU)] = { + /*RESULT_ACCESS RESULT_MISS */ + [C(OP_READ)] = { 12, 15 }, + [C(OP_WRITE)] = { -1, -1 }, + [C(OP_PREFETCH)] = { -1, -1 }, + }, + [C(NODE)] = { /* RESULT_ACCESS RESULT_MISS */ + [C(OP_READ)] = { -1, -1 }, + [C(OP_WRITE)] = { -1, -1 }, + [C(OP_PREFETCH)] = { -1, -1 }, + }, +}; + +static int num_events = 512; + +/* Upper half of event id is PMLCb, for threshold events */ +static u64 e6500_xlate_event(u64 event_id) +{ + u32 event_low = (u32)event_id; + if ((event_low >= num_events) || + (event_id & (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH))) + return 0; + + return FSL_EMB_EVENT_VALID; +} + +static struct fsl_emb_pmu e6500_pmu = { + .name = "e6500 family", + .n_counter = 6, + .n_restricted = 0, + .xlate_event = e6500_xlate_event, + .n_generic = ARRAY_SIZE(e6500_generic_events), + .generic_events = e6500_generic_events, + .cache_events = &e6500_cache_events, +}; + +static int init_e6500_pmu(void) +{ + if ((!cur_cpu_spec->oprofile_cpu_type) || + (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e6500"))) + return -ENODEV; + + return register_fsl_emb_pmu(&e6500_pmu); +} + +early_initcall(init_e6500_pmu); |