Skip to content

Commit

Permalink
MIPS: Unify perf counter register definitions
Browse files Browse the repository at this point in the history
Unify definitions for MIPS performance counter register fields in
mipsregs.h rather than duplicating them in perf_events and oprofile.
This will allow future patches to use them to expose performance
counters to KVM guests.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Robert Richter <rric@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: oprofile-list@lists.sf.net
Patchwork: https://patchwork.linux-mips.org/patch/15212/
Signed-off-by: James Hogan <james.hogan@imgtec.com>
  • Loading branch information
James Hogan committed Feb 14, 2017
1 parent 573deec commit 2654294
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 59 deletions.
33 changes: 33 additions & 0 deletions arch/mips/include/asm/mipsregs.h
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,39 @@
#define MIPS_WATCHHI_W (_ULCAST_(1) << 0)
#define MIPS_WATCHHI_IRW (_ULCAST_(0x7) << 0)

/* PerfCnt control register definitions */
#define MIPS_PERFCTRL_EXL (_ULCAST_(1) << 0)
#define MIPS_PERFCTRL_K (_ULCAST_(1) << 1)
#define MIPS_PERFCTRL_S (_ULCAST_(1) << 2)
#define MIPS_PERFCTRL_U (_ULCAST_(1) << 3)
#define MIPS_PERFCTRL_IE (_ULCAST_(1) << 4)
#define MIPS_PERFCTRL_EVENT_S 5
#define MIPS_PERFCTRL_EVENT (_ULCAST_(0x3ff) << MIPS_PERFCTRL_EVENT_S)
#define MIPS_PERFCTRL_PCTD (_ULCAST_(1) << 15)
#define MIPS_PERFCTRL_EC (_ULCAST_(0x3) << 23)
#define MIPS_PERFCTRL_EC_R (_ULCAST_(0) << 23)
#define MIPS_PERFCTRL_EC_RI (_ULCAST_(1) << 23)
#define MIPS_PERFCTRL_EC_G (_ULCAST_(2) << 23)
#define MIPS_PERFCTRL_EC_GRI (_ULCAST_(3) << 23)
#define MIPS_PERFCTRL_W (_ULCAST_(1) << 30)
#define MIPS_PERFCTRL_M (_ULCAST_(1) << 31)

/* PerfCnt control register MT extensions used by MIPS cores */
#define MIPS_PERFCTRL_VPEID_S 16
#define MIPS_PERFCTRL_VPEID (_ULCAST_(0xf) << MIPS_PERFCTRL_VPEID_S)
#define MIPS_PERFCTRL_TCID_S 22
#define MIPS_PERFCTRL_TCID (_ULCAST_(0xff) << MIPS_PERFCTRL_TCID_S)
#define MIPS_PERFCTRL_MT_EN (_ULCAST_(0x3) << 20)
#define MIPS_PERFCTRL_MT_EN_ALL (_ULCAST_(0) << 20)
#define MIPS_PERFCTRL_MT_EN_VPE (_ULCAST_(1) << 20)
#define MIPS_PERFCTRL_MT_EN_TC (_ULCAST_(2) << 20)

/* PerfCnt control register MT extensions used by BMIPS5000 */
#define BRCM_PERFCTRL_TC (_ULCAST_(1) << 30)

/* PerfCnt control register MT extensions used by Netlogic XLR */
#define XLR_PERFCTRL_ALLTHREADS (_ULCAST_(1) << 13)

/* MAAR bit definitions */
#define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
#define MIPS_MAAR_ADDR_SHIFT 12
Expand Down
55 changes: 23 additions & 32 deletions arch/mips/kernel/perf_event_mipsxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,40 +101,31 @@ struct mips_pmu {

static struct mips_pmu mipspmu;

#define M_PERFCTL_EXL (1 << 0)
#define M_PERFCTL_KERNEL (1 << 1)
#define M_PERFCTL_SUPERVISOR (1 << 2)
#define M_PERFCTL_USER (1 << 3)
#define M_PERFCTL_INTERRUPT_ENABLE (1 << 4)
#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
#define M_PERFCTL_EVENT(event) (((event) << MIPS_PERFCTRL_EVENT_S) & \
MIPS_PERFCTRL_EVENT)
#define M_PERFCTL_VPEID(vpe) ((vpe) << MIPS_PERFCTRL_VPEID_S)

#ifdef CONFIG_CPU_BMIPS5000
#define M_PERFCTL_MT_EN(filter) 0
#else /* !CONFIG_CPU_BMIPS5000 */
#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
#define M_PERFCTL_MT_EN(filter) (filter)
#endif /* CONFIG_CPU_BMIPS5000 */

#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
#define M_PERFCTL_WIDE (1 << 30)
#define M_PERFCTL_MORE (1 << 31)
#define M_PERFCTL_TC (1 << 30)
#define M_TC_EN_ALL M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_ALL)
#define M_TC_EN_VPE M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_VPE)
#define M_TC_EN_TC M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_TC)

#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \
M_PERFCTL_KERNEL | \
M_PERFCTL_USER | \
M_PERFCTL_SUPERVISOR | \
M_PERFCTL_INTERRUPT_ENABLE)
#define M_PERFCTL_COUNT_EVENT_WHENEVER (MIPS_PERFCTRL_EXL | \
MIPS_PERFCTRL_K | \
MIPS_PERFCTRL_U | \
MIPS_PERFCTRL_S | \
MIPS_PERFCTRL_IE)

#ifdef CONFIG_MIPS_MT_SMP
#define M_PERFCTL_CONFIG_MASK 0x3fff801f
#else
#define M_PERFCTL_CONFIG_MASK 0x1f
#endif
#define M_PERFCTL_EVENT_MASK 0xfe0


#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
Expand Down Expand Up @@ -345,11 +336,11 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
(evt->config_base & M_PERFCTL_CONFIG_MASK) |
/* Make sure interrupt enabled. */
M_PERFCTL_INTERRUPT_ENABLE;
MIPS_PERFCTRL_IE;
if (IS_ENABLED(CONFIG_CPU_BMIPS5000))
/* enable the counter for the calling thread */
cpuc->saved_ctrl[idx] |=
(1 << (12 + vpe_id())) | M_PERFCTL_TC;
(1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC;

/*
* We do not actually let the counter run. Leave it until start().
Expand Down Expand Up @@ -754,11 +745,11 @@ static int __n_counters(void)
{
if (!cpu_has_perf)
return 0;
if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M))
return 1;
if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M))
return 2;
if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M))
return 3;

return 4;
Expand Down Expand Up @@ -1339,7 +1330,7 @@ static int __hw_perf_event_init(struct perf_event *event)
* We allow max flexibility on how each individual counter shared
* by the single CPU operates (the mode exclusion and the range).
*/
hwc->config_base = M_PERFCTL_INTERRUPT_ENABLE;
hwc->config_base = MIPS_PERFCTRL_IE;

/* Calculate range bits and validate it. */
if (num_possible_cpus() > 1)
Expand All @@ -1350,14 +1341,14 @@ static int __hw_perf_event_init(struct perf_event *event)
mutex_unlock(&raw_event_mutex);

if (!attr->exclude_user)
hwc->config_base |= M_PERFCTL_USER;
hwc->config_base |= MIPS_PERFCTRL_U;
if (!attr->exclude_kernel) {
hwc->config_base |= M_PERFCTL_KERNEL;
hwc->config_base |= MIPS_PERFCTRL_K;
/* MIPS kernel mode: KSU == 00b || EXL == 1 || ERL == 1 */
hwc->config_base |= M_PERFCTL_EXL;
hwc->config_base |= MIPS_PERFCTRL_EXL;
}
if (!attr->exclude_hv)
hwc->config_base |= M_PERFCTL_SUPERVISOR;
hwc->config_base |= MIPS_PERFCTRL_S;

hwc->config_base &= M_PERFCTL_CONFIG_MASK;
/*
Expand Down Expand Up @@ -1830,7 +1821,7 @@ init_hw_perf_events(void)
mipspmu.num_counters = counters;
mipspmu.irq = irq;

if (read_c0_perfctrl0() & M_PERFCTL_WIDE) {
if (read_c0_perfctrl0() & MIPS_PERFCTRL_W) {
mipspmu.max_period = (1ULL << 63) - 1;
mipspmu.valid_count = (1ULL << 63) - 1;
mipspmu.overflow = 1ULL << 63;
Expand Down
40 changes: 13 additions & 27 deletions arch/mips/oprofile/op_model_mipsxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,12 @@

#include "op_impl.h"

#define M_PERFCTL_EXL (1UL << 0)
#define M_PERFCTL_KERNEL (1UL << 1)
#define M_PERFCTL_SUPERVISOR (1UL << 2)
#define M_PERFCTL_USER (1UL << 3)
#define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4)
#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
#define M_PERFCTL_WIDE (1UL << 30)
#define M_PERFCTL_MORE (1UL << 31)
#define M_PERFCTL_EVENT(event) (((event) << MIPS_PERFCTRL_EVENT_S) & \
MIPS_PERFCTRL_EVENT)
#define M_PERFCTL_VPEID(vpe) ((vpe) << MIPS_PERFCTRL_VPEID_S)

#define M_COUNTER_OVERFLOW (1UL << 31)

/* Netlogic XLR specific, count events in all threads in a core */
#define M_PERFCTL_COUNT_ALL_THREADS (1UL << 13)

static int (*save_perf_irq)(void);
static int perfcount_irq;

Expand All @@ -51,7 +37,7 @@ static int perfcount_irq;

#ifdef CONFIG_MIPS_MT_SMP
static int cpu_has_mipsmt_pertccounters;
#define WHAT (M_TC_EN_VPE | \
#define WHAT (MIPS_PERFCTRL_MT_EN_VPE | \
M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id))
#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
0 : cpu_data[smp_processor_id()].vpe_id)
Expand Down Expand Up @@ -161,15 +147,15 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
continue;

reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) |
M_PERFCTL_INTERRUPT_ENABLE;
MIPS_PERFCTRL_IE;
if (ctr[i].kernel)
reg.control[i] |= M_PERFCTL_KERNEL;
reg.control[i] |= MIPS_PERFCTRL_K;
if (ctr[i].user)
reg.control[i] |= M_PERFCTL_USER;
reg.control[i] |= MIPS_PERFCTRL_U;
if (ctr[i].exl)
reg.control[i] |= M_PERFCTL_EXL;
reg.control[i] |= MIPS_PERFCTRL_EXL;
if (boot_cpu_type() == CPU_XLR)
reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
reg.control[i] |= XLR_PERFCTRL_ALLTHREADS;
reg.counter[i] = 0x80000000 - ctr[i].count;
}
}
Expand Down Expand Up @@ -254,7 +240,7 @@ static int mipsxx_perfcount_handler(void)
case n + 1: \
control = r_c0_perfctrl ## n(); \
counter = r_c0_perfcntr ## n(); \
if ((control & M_PERFCTL_INTERRUPT_ENABLE) && \
if ((control & MIPS_PERFCTRL_IE) && \
(counter & M_COUNTER_OVERFLOW)) { \
oprofile_add_sample(get_irq_regs(), n); \
w_c0_perfcntr ## n(reg.counter[n]); \
Expand All @@ -273,11 +259,11 @@ static inline int __n_counters(void)
{
if (!cpu_has_perf)
return 0;
if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M))
return 1;
if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M))
return 2;
if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M))
return 3;

return 4;
Expand Down

0 comments on commit 2654294

Please sign in to comment.