From f06e7aa47f3cad55c5737eb87280e90e25882d60 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 7 May 2018 17:28:28 +0800 Subject: MIPS: Convert update_persistent_clock() to update_persistent_clock64() Since struct timespec is not y2038 safe on 32bit machines, this patch converts update_persistent_clock() to update_persistent_clock64() using struct timespec64. The rtc_mips_set_time() and rtc_mips_set_mmss() interfaces were using 'unsigned long' type that is not y2038 safe on 32bit machines, moreover there is only one platform implementing rtc_mips_set_time() and two platforms implementing rtc_mips_set_mmss(), so we can just make them each implement update_persistent_clock64() directly, to get that helper out of the common mips code by removing rtc_mips_set_time() and rtc_mips_set_mmss() interfaces. Signed-off-by: Baolin Wang Acked-by: Arnd Bergmann Cc: Ralf Baechle Cc: Huacai Chen Cc: Paul Burton Cc: linux-mips@linux-mips.org Signed-off-by: James Hogan --- arch/mips/kernel/time.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index a6ebc8135112..bfe02ded25d1 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -34,21 +34,6 @@ DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); -int __weak rtc_mips_set_time(unsigned long sec) -{ - return -ENODEV; -} - -int __weak rtc_mips_set_mmss(unsigned long nowtime) -{ - return rtc_mips_set_time(nowtime); -} - -int update_persistent_clock(struct timespec now) -{ - return rtc_mips_set_mmss(now.tv_sec); -} - static int null_perf_irq(void) { return 0; -- cgit v1.2.3 From aae22f16022600bae990ec4c2f2cb997c7393216 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 10 May 2018 17:59:00 +0100 Subject: MIPS: VPE: Fix spelling mistake: "uneeded" -> "unneeded" Trivial fix to spelling mistake in pr_warn message text. Signed-off-by: Colin Ian King Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Cc: kernel-janitors@vger.kernel.org Signed-off-by: James Hogan --- arch/mips/kernel/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 544ea21bfef9..0bef238d2c0c 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -872,7 +872,7 @@ static ssize_t vpe_write(struct file *file, const char __user *buffer, return -ENODEV; if ((count + v->len) > v->plen) { - pr_warn("VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); + pr_warn("VPE loader: elf size too big. Perhaps strip unneeded symbols\n"); return -ENOMEM; } -- cgit v1.2.3 From 8270ab48e67333f760b3bef507c1524c7a06c699 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 20 Apr 2018 11:23:03 +0100 Subject: MIPS: Probe for MIPS MT perf counters per TC Processors implementing the MIPS MT ASE may have performance counters implemented per core or per TC. Processors implemented by MIPS Technologies signify presence per TC through a bit in the implementation specific Config7 register. Currently the code which probes for their presence blindly reads a magic number corresponding to this bit, despite it potentially having a different meaning in the CPU implementation. Since CPU features are generally detected by cpu-probe.c, perform the detection here instead. Introduce cpu_set_mt_per_tc_perf which checks the bit in config7 and call it from MIPS CPUs known to implement this bit and the MT ASE, specifically, the 34K, 1004K and interAptiv. Once the presence of the per-tc counter is indicated in cpu_data, tests for it can be updated to use this flag. Suggested-by: James Hogan Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: Florian Fainelli Cc: Matt Redfearn Cc: Paul Burton Cc: Maciej W. Rozycki Cc: linux-mips@linux-mips.org> Patchwork: https://patchwork.linux-mips.org/patch/19136/ Signed-off-by: James Hogan --- arch/mips/kernel/cpu-probe.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 6b07b739f914..b2509c19cfb5 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -414,6 +414,14 @@ static int __init ftlb_disable(char *s) __setup("noftlb", ftlb_disable); +/* + * Check if the CPU has per tc perf counters + */ +static inline void cpu_set_mt_per_tc_perf(struct cpuinfo_mips *c) +{ + if (read_c0_config7() & MTI_CONF7_PTC) + c->options |= MIPS_CPU_MT_PER_TC_PERF_COUNTERS; +} static inline void check_errata(void) { @@ -1572,6 +1580,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_34K; c->writecombine = _CACHE_UNCACHED; __cpu_name[cpu] = "MIPS 34Kc"; + cpu_set_mt_per_tc_perf(c); break; case PRID_IMP_74K: c->cputype = CPU_74K; @@ -1592,6 +1601,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_1004K; c->writecombine = _CACHE_UNCACHED; __cpu_name[cpu] = "MIPS 1004Kc"; + cpu_set_mt_per_tc_perf(c); break; case PRID_IMP_1074K: c->cputype = CPU_1074K; @@ -1601,10 +1611,12 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) case PRID_IMP_INTERAPTIV_UP: c->cputype = CPU_INTERAPTIV; __cpu_name[cpu] = "MIPS interAptiv"; + cpu_set_mt_per_tc_perf(c); break; case PRID_IMP_INTERAPTIV_MP: c->cputype = CPU_INTERAPTIV; __cpu_name[cpu] = "MIPS interAptiv (multi)"; + cpu_set_mt_per_tc_perf(c); break; case PRID_IMP_PROAPTIV_UP: c->cputype = CPU_PROAPTIV; -- cgit v1.2.3 From 800fb71281ca2ed5c8a7299e10ebc0de2f61cdda Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 20 Apr 2018 11:23:04 +0100 Subject: MIPS: perf: More robustly probe for the presence of per-tc counters The presence of per TC performance counters is now detected by cpu-probe.c and indicated by MIPS_CPU_MT_PER_TC_PERF_COUNTERS in cpu_data. Switch detection of the feature to use this new flag rather than blindly testing the implementation specific config7 register with a magic number. Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: Florian Fainelli Cc: Maciej W. Rozycki Cc: Paul Burton Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Robert Richter Cc: linux-mips@linux-mips.org Cc: oprofile-list@lists.sf.net Patchwork: https://patchwork.linux-mips.org/patch/19142/ Signed-off-by: James Hogan --- arch/mips/kernel/perf_event_mipsxx.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index ee73550f0b9a..458015da7149 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -129,8 +129,6 @@ static struct mips_pmu mipspmu; #ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS -static int cpu_has_mipsmt_pertccounters; - static DEFINE_RWLOCK(pmuint_rwlock); #if defined(CONFIG_CPU_BMIPS5000) @@ -1723,7 +1721,6 @@ init_hw_perf_events(void) } #ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS - cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19); if (!cpu_has_mipsmt_pertccounters) counters = counters_total_to_per_cpu(counters); #endif -- cgit v1.2.3 From 840a8b55effdc9a98b115f84b8bbb6a2f5d05226 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 20 Apr 2018 11:23:05 +0100 Subject: MIPS: perf: Use correct VPE ID when setting up VPE tracing There are a couple of FIXME's in the perf code which state that cpu_data[event->cpu].vpe_id reports 0 for both CPUs. This is no longer the case, since the vpe_id is used extensively by SMP CPS. VPE local counting gets around this by using smp_processor_id() instead. As it happens this does work correctly to count events on the right VPE, but relies on 2 assumptions: a) Always having 2 VPEs / core. b) The hardware only paying attention to the least significant bit of the PERFCTL.VPEID field. If either of these assumptions change then the incorrect VPEs events will be counted. Fix this by replacing smp_processor_id() with cpu_vpe_id(¤t_cpu_data), in the vpe_id() macro, and pass vpe_id() to M_PERFCTL_VPEID() when setting up PERFCTL.VPEID. The FIXME's can also be removed since they no longer apply. Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/19137/ Signed-off-by: James Hogan --- arch/mips/kernel/perf_event_mipsxx.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 458015da7149..11d1b2268fdd 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -135,12 +135,8 @@ static DEFINE_RWLOCK(pmuint_rwlock); #define vpe_id() (cpu_has_mipsmt_pertccounters ? \ 0 : (smp_processor_id() & MIPS_CPUID_TO_COUNTER_MASK)) #else -/* - * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because - * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. - */ #define vpe_id() (cpu_has_mipsmt_pertccounters ? \ - 0 : smp_processor_id()) + 0 : cpu_vpe_id(¤t_cpu_data)) #endif /* Copied from op_model_mipsxx.c */ @@ -1277,11 +1273,7 @@ static void check_and_calc_range(struct perf_event *event, */ hwc->config_base |= M_TC_EN_ALL; } else { - /* - * FIXME: cpu_data[event->cpu].vpe_id reports 0 - * for both CPUs. - */ - hwc->config_base |= M_PERFCTL_VPEID(event->cpu); + hwc->config_base |= M_PERFCTL_VPEID(vpe_id()); hwc->config_base |= M_TC_EN_VPE; } } else -- cgit v1.2.3 From 84002c88599d6b537e54b003f763215be2075243 Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Fri, 20 Apr 2018 11:23:06 +0100 Subject: MIPS: perf: Fix perf with MT counting other threads When perf is used in non-system mode, i.e. without specifying CPUs to count on, check_and_calc_range falls into the case when it sets M_TC_EN_ALL in the counter config_base. This has the impact of always counting for all of the threads in a core, even when the user has not requested it. For example this can be seen with a test program which executes 30002 instructions and 10000 branches running on one VPE and a busy load on the other VPE in the core. Without this commit, the expected count is not returned: taskset 4 dd if=/dev/zero of=/dev/null count=100000 & taskset 8 perf stat -e instructions:u,branches:u ./test_prog Performance counter stats for './test_prog': 103235 instructions:u 17015 branches:u In order to fix this, remove check_and_calc_range entirely and perform all of the logic in mipsxx_pmu_enable_event. Since mipsxx_pmu_enable_event now requires the range of the event, ensure that it is set by mipspmu_perf_event_encode in the same circumstances as before (i.e. #ifdef CONFIG_MIPS_MT_SMP && num_possible_cpus() > 1). The logic of mipsxx_pmu_enable_event now becomes: If the CPU is a BMIPS5000, then use the special vpe_id() implementation to select which VPE to count. If the counter has a range greater than a single VPE, i.e. it is a core-wide counter, then ensure that the counter is set up to count events from all TCs (though, since this is true by definition, is this necessary? Just enabling a core-wide counter in the per-VPE case appears experimentally to return the same counts. This is left in for now as the logic was present before). If the event is set up to count a particular CPU (i.e. system mode), then the VPE ID of that CPU is used for the counter. Otherwise, the event should be counted on the CPU scheduling this thread (this was the critical bit missing from the previous implementation) so the VPE ID of this CPU is used for the counter. With this commit, the same test as before returns the counts expected: taskset 4 dd if=/dev/zero of=/dev/null count=100000 & taskset 8 perf stat -e instructions:u,branches:u ./test_prog Performance counter stats for './test_prog': 30002 instructions:u 10000 branches:u Signed-off-by: Matt Redfearn Cc: Ralf Baechle Cc: Florian Fainelli Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/19138/ Signed-off-by: James Hogan --- arch/mips/kernel/perf_event_mipsxx.c | 78 ++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 11d1b2268fdd..413863508f6f 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -323,7 +323,11 @@ static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc, static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) { + struct perf_event *event = container_of(evt, struct perf_event, hw); struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); +#ifdef CONFIG_MIPS_MT_SMP + unsigned int range = evt->event_base >> 24; +#endif /* CONFIG_MIPS_MT_SMP */ WARN_ON(idx < 0 || idx >= mipspmu.num_counters); @@ -331,11 +335,37 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx) (evt->config_base & M_PERFCTL_CONFIG_MASK) | /* Make sure interrupt enabled. */ MIPS_PERFCTRL_IE; - if (IS_ENABLED(CONFIG_CPU_BMIPS5000)) + +#ifdef CONFIG_CPU_BMIPS5000 + { /* enable the counter for the calling thread */ cpuc->saved_ctrl[idx] |= (1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC; + } +#else +#ifdef CONFIG_MIPS_MT_SMP + if (range > V) { + /* The counter is processor wide. Set it up to count all TCs. */ + pr_debug("Enabling perf counter for all TCs\n"); + cpuc->saved_ctrl[idx] |= M_TC_EN_ALL; + } else +#endif /* CONFIG_MIPS_MT_SMP */ + { + unsigned int cpu, ctrl; + /* + * Set up the counter for a particular CPU when event->cpu is + * a valid CPU number. Otherwise set up the counter for the CPU + * scheduling this thread. + */ + cpu = (event->cpu >= 0) ? event->cpu : smp_processor_id(); + + ctrl = M_PERFCTL_VPEID(cpu_vpe_id(&cpu_data[cpu])); + ctrl |= M_TC_EN_VPE; + cpuc->saved_ctrl[idx] |= ctrl; + pr_debug("Enabling perf counter for CPU%d\n", cpu); + } +#endif /* CONFIG_CPU_BMIPS5000 */ /* * We do not actually let the counter run. Leave it until start(). */ @@ -649,13 +679,14 @@ static unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev) * event_id. */ #ifdef CONFIG_MIPS_MT_SMP - return ((unsigned int)pev->range << 24) | - (pev->cntr_mask & 0xffff00) | - (pev->event_id & 0xff); -#else - return (pev->cntr_mask & 0xffff00) | - (pev->event_id & 0xff); -#endif + if (num_possible_cpus() > 1) + return ((unsigned int)pev->range << 24) | + (pev->cntr_mask & 0xffff00) | + (pev->event_id & 0xff); + else +#endif /* CONFIG_MIPS_MT_SMP */ + return ((pev->cntr_mask & 0xffff00) | + (pev->event_id & 0xff)); } static const struct mips_perf_event *mipspmu_map_general_event(int idx) @@ -1259,33 +1290,6 @@ static const struct mips_perf_event xlp_cache_map }, }; -#ifdef CONFIG_MIPS_MT_SMP -static void check_and_calc_range(struct perf_event *event, - const struct mips_perf_event *pev) -{ - struct hw_perf_event *hwc = &event->hw; - - if (event->cpu >= 0) { - if (pev->range > V) { - /* - * The user selected an event that is processor - * wide, while expecting it to be VPE wide. - */ - hwc->config_base |= M_TC_EN_ALL; - } else { - hwc->config_base |= M_PERFCTL_VPEID(vpe_id()); - hwc->config_base |= M_TC_EN_VPE; - } - } else - hwc->config_base |= M_TC_EN_ALL; -} -#else -static void check_and_calc_range(struct perf_event *event, - const struct mips_perf_event *pev) -{ -} -#endif - static int __hw_perf_event_init(struct perf_event *event) { struct perf_event_attr *attr = &event->attr; @@ -1321,10 +1325,6 @@ static int __hw_perf_event_init(struct perf_event *event) */ hwc->config_base = MIPS_PERFCTRL_IE; - /* Calculate range bits and validate it. */ - if (num_possible_cpus() > 1) - check_and_calc_range(event, pev); - hwc->event_base = mipspmu_perf_event_encode(pev); if (PERF_TYPE_RAW == event->attr.type) mutex_unlock(&raw_event_mutex); -- cgit v1.2.3 From d1157b1074343fa3e21c083277fc4eae162ff1e4 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 15 May 2018 23:03:09 +0100 Subject: MIPS: ptrace: Make FPU context layout comments match reality Correct comments across ptrace(2) handlers about an FPU register context layout discrepancy between MIPS I and later ISAs, which was fixed with `linux-mips.org' (LMO) commit 42533948caac ("Major pile of FP emulator changes."), the fix corrected with LMO commit 849fa7a50dff ("R3k FPU ptrace() handling fixes."), and then broken and fixed over and over again, until last time fixed with commit 80cbfad79096 ("MIPS: Correct MIPS I FP context layout"). NB running the GDB test suite for the relevant ABI/ISA and watching out for regressions is advisable when poking around ptrace(2). Signed-off-by: Maciej W. Rozycki Cc: Ralf Baechle Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/19326/ Signed-off-by: James Hogan --- arch/mips/kernel/ptrace.c | 4 ++-- arch/mips/kernel/ptrace32.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/mips/kernel') diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 0b23b1ad99e6..1098ca8b50e9 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -797,7 +797,7 @@ long arch_ptrace(struct task_struct *child, long request, /* * The odd registers are actually the high * order bits of the values stored in the even - * registers - unless we're using r2k_switch.S. + * registers. */ tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE], addr & 1); @@ -892,7 +892,7 @@ long arch_ptrace(struct task_struct *child, long request, /* * The odd registers are actually the high * order bits of the values stored in the even - * registers - unless we're using r2k_switch.S. + * registers. */ set_fpr32(&fregs[(addr & ~1) - FPR_BASE], addr & 1, data); diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 2b9260f92ccd..c6fc496430e9 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -103,7 +103,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, /* * The odd registers are actually the high * order bits of the values stored in the even - * registers - unless we're using r2k_switch.S. + * registers. */ tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE], addr & 1); @@ -216,7 +216,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, /* * The odd registers are actually the high * order bits of the values stored in the even - * registers - unless we're using r2k_switch.S. + * registers. */ set_fpr32(&fregs[(addr & ~1) - FPR_BASE], addr & 1, data); -- cgit v1.2.3