MIPS: perf: Add hardware perf events support for Loongson-3
authorHuacai Chen <chenhc@lemote.com>
Sun, 29 Mar 2015 02:54:08 +0000 (10:54 +0800)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 1 Apr 2015 15:22:17 +0000 (17:22 +0200)
This patch enable hardware performance counter support for Loongson-3's
perf events.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/9618/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/Kconfig
arch/mips/kernel/perf_event_mipsxx.c

index 6dca06527d2d7c52cf9c1154ecb503473c88b131..b018062b9d3e00155d99f9600571b8e4e3e68626 100644 (file)
@@ -2390,7 +2390,7 @@ config NODES_SHIFT
 
 config HW_PERF_EVENTS
        bool "Enable hardware performance counter support for perf events"
-       depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP)
+       depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
        default y
        help
          Enable hardware performance counter support for perf events. If
index 192e7f59245e5b403ed31d75d83b08ccf75c17c3..cc1b6fadf08989a8048a6dc304a9f58f1c29228e 100644 (file)
@@ -825,6 +825,13 @@ static const struct mips_perf_event mipsxxcore_event_map2
        [PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T },
 };
 
+static const struct mips_perf_event loongson3_event_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN },
+       [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, CNTR_ODD },
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x01, CNTR_EVEN },
+       [PERF_COUNT_HW_BRANCH_MISSES] = { 0x01, CNTR_ODD },
+};
+
 static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = {
        [PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
        [PERF_COUNT_HW_INSTRUCTIONS] = { 0x03, CNTR_ALL },
@@ -1008,6 +1015,61 @@ static const struct mips_perf_event mipsxxcore_cache_map2
 },
 };
 
+static const struct mips_perf_event loongson3_cache_map
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+       /*
+        * Like some other architectures (e.g. ARM), the performance
+        * counters don't differentiate between read and write
+        * accesses/misses, so this isn't strictly correct, but it's the
+        * best we can do. Writes and reads get combined.
+        */
+       [C(OP_READ)] = {
+               [C(RESULT_MISS)]        = { 0x04, CNTR_ODD },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_MISS)]        = { 0x04, CNTR_ODD },
+       },
+},
+[C(L1I)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_MISS)]        = { 0x04, CNTR_EVEN },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_MISS)]        = { 0x04, CNTR_EVEN },
+       },
+},
+[C(DTLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_MISS)]        = { 0x09, CNTR_ODD },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_MISS)]        = { 0x09, CNTR_ODD },
+       },
+},
+[C(ITLB)] = {
+       [C(OP_READ)] = {
+               [C(RESULT_MISS)]        = { 0x0c, CNTR_ODD },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_MISS)]        = { 0x0c, CNTR_ODD },
+       },
+},
+[C(BPU)] = {
+       /* Using the same code for *HW_BRANCH* */
+       [C(OP_READ)] = {
+               [C(RESULT_ACCESS)]      = { 0x02, CNTR_EVEN },
+               [C(RESULT_MISS)]        = { 0x02, CNTR_ODD },
+       },
+       [C(OP_WRITE)] = {
+               [C(RESULT_ACCESS)]      = { 0x02, CNTR_EVEN },
+               [C(RESULT_MISS)]        = { 0x02, CNTR_ODD },
+       },
+},
+};
+
 /* BMIPS5000 */
 static const struct mips_perf_event bmips5000_cache_map
                                [PERF_COUNT_HW_CACHE_MAX]
@@ -1542,6 +1604,10 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
                else
                        raw_event.cntr_mask =
                                raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
+               break;
+       case CPU_LOONGSON3:
+               raw_event.cntr_mask = raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
+       break;
        }
 
        raw_event.event_id = base_id;
@@ -1671,6 +1737,11 @@ init_hw_perf_events(void)
                mipspmu.general_event_map = &mipsxxcore_event_map;
                mipspmu.cache_event_map = &mipsxxcore_cache_map;
                break;
+       case CPU_LOONGSON3:
+               mipspmu.name = "mips/loongson3";
+               mipspmu.general_event_map = &loongson3_event_map;
+               mipspmu.cache_event_map = &loongson3_cache_map;
+               break;
        case CPU_CAVIUM_OCTEON:
        case CPU_CAVIUM_OCTEON_PLUS:
        case CPU_CAVIUM_OCTEON2: