|
@@ -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:
|