MIPS performance event support v6
Subsystems (3)
v6 cover MIPS performance event support v6
This patchset implements the low-level logic for the Linux performance counter subsystem (Perf-events) on MIPS, which enables the collection of all sorts of HW/SW performance events based on per-CPU or per-task. For more information, please refer to tools/perf/Documentation/perf.txt.
Currently in the Oprofile module, MIPS PMUs are mainly categorized into 3 (mipsxx, loongson2 and rm9000). This patchset provides the skeleton code together with the mipsxx specific code. The other 2 (and maybe more) can be supported by adding new C files like the current perf_event_mipsxx.c.
To support mipsxx CPUs other than the implemented 24K/34K/74K/1004K, the corresponding general event map, cache event map and raw event macros need to be added. Please refer to init_hw_perf_events() for more info.
Tests were carried out on the Malta-R board. 24K/34K/74K/1004K cores and SMVP/UP kernels have been basically tested. Any more tests are welcome.
To do this, you may want to compile the tool "perf" for your MIPS platform. You can refer to the following URL:
http://www.linux-mips.org/archives/linux-mips/2010-04/msg00158.html
Please note: Before that patch is accepted, you can choose a "specific" rmb() which is suitable for your platform -- an example is provided in the description of that patch.
You also need to customize the CFLAGS and LDFLAGS in tools/perf/Makefile for your libs, includes, etc.
In case you encounter the boot failure in SMVP kernel on multi-threading CPUs, you may take a look at:
http://www.linux-mips.org/git?p=linux-mti.git;a=commitdiff;h=5460815027d802697b879644c74f0e8365254020
CHANGES:
-----------------------------
v6 - v5:
o leaving the Oprofile framework changes to another patchset.
o changing the callchain support.
o re-defining local_xchg() to pass the build (see patch #7).
o following some of David Daney's suggestions:
* CPU #if's removed from pmu.h
* Copyright info modified
* Removing the perf_irq redefinition
* 64bit counters considered
* Read/write funcs and register defs separated from event defs
* Raw event support merged into the main part
v5 - v4:
o splitting up Perf-events patches (v4 patches 1~4 are now splitted into v5 patches 1~7) for easier review.
o adding more info into the description of patches (especially how to test this patchset).
o simplifying the 2 small functions mipspmu_get_pmu_id() and mipspmu_get_max_events().
v4 - v3:
o placing the variable save_perf_irq properly (issue found by Wu Zhangjin)
o the patches 5~9 make Oprofile use Perf-events framework as backend. v3 - v2:
o adding 1004K core support.
o slightly adjusting the code structure.
o adding more comments in the code.
o fixing some small coding style issues.
v2 - v1:
o Adjusting code structure as suggested by Wu Zhangjin. With this change, hardware performance event support for loongson2 and rm9000 can be conveniently implemented by adding and including new files like perf_event_loongson2.c; Oprofile and Perf for MIPS are now sharing pmu.h; Naming changes were made to some functions.
o Fixing the generic atomic64 issue reported by David Daney. Currently, 32bit kernel is using the generic version from lib. When Ralf Baechle's common atomic64 version is ready, this may change.
o Adding raw event support. For more details, please refer to the code comments for mipsxx_pmu_map_raw_event().
o Adding new software events - PERF_COUNT_SW_ALIGNMENT_FAULTS and PERF_COUNT_SW_EMULATION_FAULTS.
o Fixing some small bugs.
o Adding new comments for the code.
o Making some code style changes.
v1:
o Using generic atomic64 operations from lib.
o SMVP/UP kernels are supported (not for SMTC).
o 24K/34K/74K cores are implemented.
o Currently working when Oprofile is _not_ available.
o Minimal software perf events are supported.
-----------------------------
Deng-Cheng Zhu (7):
MIPS/Oprofile: extract PMU defines/helper functions for sharing
MIPS: use generic atomic64 in non-64bit kernels
MIPS: add support for software performance events
MIPS: add support for hardware performance events (skeleton) MIPS/Perf-events: add callchain support
MIPS: add support for hardware performance events (mipsxx)
MIPS: define local_xchg from xchg_local to atomic_long_xchg
arch/mips/Kconfig | 11 + arch/mips/include/asm/atomic.h | 4 + arch/mips/include/asm/local.h | 2 +- arch/mips/include/asm/perf_event.h | 26 + arch/mips/include/asm/pmu.h | 299 ++++++++++++ arch/mips/kernel/Makefile | 2 + arch/mips/kernel/perf_event.c | 623 ++++++++++++++++++++++++ arch/mips/kernel/perf_event_mipsxx.c | 802 +++++++++++++++++++++++++++++++ arch/mips/kernel/traps.c | 18 +- arch/mips/kernel/unaligned.c | 5 + arch/mips/math-emu/cp1emu.c | 3 + arch/mips/mm/fault.c | 11 +- arch/mips/oprofile/op_model_loongson2.c | 18 +- arch/mips/oprofile/op_model_mipsxx.c | 147 +------ arch/mips/oprofile/op_model_rm9000.c | 16 +- 15 files changed, 1805 insertions(+), 182 deletions(-) create mode 100644 arch/mips/include/asm/perf_event.h create mode 100644 arch/mips/include/asm/pmu.h create mode 100644 arch/mips/kernel/perf_event.c create mode 100644 arch/mips/kernel/perf_event_mipsxx.c
PATCH v6 1/7 MIPS/Oprofile: extract PMU defines/helper functions for sharing
Moving performance counter/control defines/helper functions into a single header file, so that software using the MIPS PMU can share the code.
--- arch/mips/include/asm/pmu.h | 212 +++++++++++++++++++++++++++++++ arch/mips/oprofile/op_model_loongson2.c | 18 +--- arch/mips/oprofile/op_model_mipsxx.c | 147 +--------------------- arch/mips/oprofile/op_model_rm9000.c | 16 +-- 4 files changed, 217 insertions(+), 176 deletions(-) create mode 100644 arch/mips/include/asm/pmu.h
arch/mips/include/asm/pmu.h new file +212 -0
@@ -0,0 +1,212 @@ +/* +* linux/arch/mips/include/asm/pmu.h +* +* Copyright (C) 2004, 05, 06 by Ralf Baechle +* Copyright (C) 2005 by MIPS Technologies, Inc. +* Copyright (C) 2009 Lemote Inc. +* Author: Yanhua <[email protected]> +* Author: Wu Zhangjin <[email protected]> +* Copyright (C) 2010 MIPS Technologies, Inc. +* Author: Deng-Cheng Zhu (move things from Oprofile to common place) +* +* This file is shared by Oprofile and Perf. It is also shared across the +* Oprofile implementation for different MIPS CPUs. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#ifndef __MIPS_PMU_H__ +#define __MIPS_PMU_H__ + +/* Used by Perf-events */ +#define MIPS_MAX_HWEVENTS 4 + +/* mipsxx */ +#define M_CONFIG1_PC (1 << 4) + +#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_COUNTER_OVERFLOW (1UL << 31) + +#ifdef CONFIG_MIPS_MT_SMP +static int cpu_has_mipsmt_pertccounters; +#define WHAT (M_TC_EN_VPE | \ + M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id)) +/* +* FIXME: For VSMP, vpe_id() is redefined for Perf, because +* cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. WHAT is not +* redefined because Perf does not use it. +*/ +#if defined(CONFIG_HW_PERF_EVENTS ) +#define vpe_id () (cpu_has_mipsmt_pertccounters ? \ + 0 : smp_processor_id()) +#else +#define vpe_id () (cpu_has_mipsmt_pertccounters ? \ + 0 : cpu_data[smp_processor_id()].vpe_id) +#endif +/* +* The number of bits to shift to convert between counters per core and +* counters per VPE. There is no reasonable interface atm to obtain the +* number of VPEs used by Linux and in the 34K this number is fixed to two +* anyways so we hardcore a few things here for the moment. The way it's +* done here will ensure that oprofile VSMP kernel will run right on a lesser +* core like a 24K also or with maxcpus=1. +*/ +static inline unsigned int vpe_shift (void ) +{ +if (num_possible_cpus () >1 ) +return 1 ; + +return 0 ; +} +#else +#define WHAT 0 +#define vpe_id () 0 +static inline unsigned int vpe_shift (void ) +{ +return 0 ; +} +#endif + +static inline unsigned int +counters_total_to_per_cpu (unsigned int counters) +{ +return counters >>vpe_shift (); +} + +static inline unsigned int +counters_per_cpu_to_total (unsigned int counters) +{ +return counters <<vpe_shift (); +} + +#define __define_perf_accessors (r, n, np) \ + \ +static inline unsigned int r_c0_ ## r ## n(void) \ +{ \ + unsigned int cpu = vpe_id(); \ + \ + switch (cpu) { \ + case 0: \ + return read_c0_ ## r ## n(); \ + case 1: \ + return read_c0_ ## r ## np(); \ + default: \ + BUG(); \ + } \ + return 0; \ +} \ + \ +static inline void w_c0_ ## r ## n(unsigned int value) \ +{ \ + unsigned int cpu = vpe_id(); \ + \ + switch (cpu) { \ + case 0: \ + write_c0_ ## r ## n(value); \ + return; \ + case 1: \ + write_c0_ ## r ## np(value); \ + return; \ + default: \ + BUG(); \ + } \ + return; \ +} \ + +__define_perf_accessors(perfcntr, 0, 2) +__define_perf_accessors(perfcntr, 1, 3) +__define_perf_accessors(perfcntr, 2, 0) +__define_perf_accessors(perfcntr, 3, 1) + +__define_perf_accessors(perfctrl, 0, 2) +__define_perf_accessors(perfctrl, 1, 3) +__define_perf_accessors(perfctrl, 2, 0) +__define_perf_accessors(perfctrl, 3, 1) + +static inline int __n_counters (void ) +{ +if (!(read_c0_config1 () &M_CONFIG1_PC )) +return 0 ; +if (!(read_c0_perfctrl0 () &M_PERFCTL_MORE )) +return 1 ; +if (!(read_c0_perfctrl1 () &M_PERFCTL_MORE )) +return 2 ; +if (!(read_c0_perfctrl2 () &M_PERFCTL_MORE )) +return 3 ; + +return 4 ; +} + +static inline int n_counters (void ) +{ +int counters; + +switch (current_cpu_type ()) { +case CPU_R10000 : + counters =2 ; +break ; + +case CPU_R12000 : +case CPU_R14000 : + counters =4 ; +break ; + +default : + counters =__n_counters (); + } + +return counters; +} + +/* rm9000 */ +#define RM9K_COUNTER1_EVENT (event) ((event) << 0) +#define RM9K_COUNTER1_SUPERVISOR (1ULL << 7) +#define RM9K_COUNTER1_KERNEL (1ULL << 8) +#define RM9K_COUNTER1_USER (1ULL << 9) +#define RM9K_COUNTER1_ENABLE (1ULL << 10) +#define RM9K_COUNTER1_OVERFLOW (1ULL << 15) + +#define RM9K_COUNTER2_EVENT (event) ((event) << 16) +#define RM9K_COUNTER2_SUPERVISOR (1ULL << 23) +#define RM9K_COUNTER2_KERNEL (1ULL << 24) +#define RM9K_COUNTER2_USER (1ULL << 25) +#define RM9K_COUNTER2_ENABLE (1ULL << 26) +#define RM9K_COUNTER2_OVERFLOW (1ULL << 31) + +extern unsigned int rm9000_perfcount_irq; + +/* loongson2 */ +#define LOONGSON2_CPU_TYPE "mips/loongson2" + +#define LOONGSON2_PERFCNT_OVERFLOW (1ULL << 31) + +#define LOONGSON2_PERFCTRL_EXL (1UL << 0) +#define LOONGSON2_PERFCTRL_KERNEL (1UL << 1) +#define LOONGSON2_PERFCTRL_SUPERVISOR (1UL << 2) +#define LOONGSON2_PERFCTRL_USER (1UL << 3) +#define LOONGSON2_PERFCTRL_ENABLE (1UL << 4) +#define LOONGSON2_PERFCTRL_EVENT (idx, event) \ + (((event) & 0x0f) << ((idx) ? 9 : 5)) + +#define read_c0_perfctrl () __read_64bit_c0_register($24, 0) +#define write_c0_perfctrl (val) __write_64bit_c0_register($24, 0, val) +#define read_c0_perfcnt () __read_64bit_c0_register($25, 0) +#define write_c0_perfcnt (val) __write_64bit_c0_register($25, 0, val) + +#endif /* __MIPS_PMU_H__ */
arch/mips/oprofile/op_model_loongson2.c +1 -17
@@ -12,27 +12,11 @@#include <linux/init.h> #include <linux/oprofile.h> #include <linux/interrupt.h> +#include <asm/pmu.h> #include <loongson.h> /* LOONGSON2_PERFCNT_IRQ */ #include "op_impl.h" -#define LOONGSON2_CPU_TYPE "mips/loongson2" - -#define LOONGSON2_PERFCNT_OVERFLOW (1ULL << 31) - -#define LOONGSON2_PERFCTRL_EXL (1UL << 0) -#define LOONGSON2_PERFCTRL_KERNEL (1UL << 1) -#define LOONGSON2_PERFCTRL_SUPERVISOR (1UL << 2) -#define LOONGSON2_PERFCTRL_USER (1UL << 3) -#define LOONGSON2_PERFCTRL_ENABLE (1UL << 4) -#define LOONGSON2_PERFCTRL_EVENT (idx, event) \ - (((event) & 0x0f) << ((idx) ? 9 : 5)) - -#define read_c0_perfctrl () __read_64bit_c0_register($24, 0) -#define write_c0_perfctrl (val) __write_64bit_c0_register($24, 0, val) -#define read_c0_perfcnt () __read_64bit_c0_register($25, 0) -#define write_c0_perfcnt (val) __write_64bit_c0_register($25, 0, val) - static struct loongson2_register_config { unsigned int ctrl; unsigned long long reset_counter1;
arch/mips/oprofile/op_model_mipsxx.c +3 -144
168 lines not on this page · raw message
arch/mips/oprofile/op_model_rm9000.c +1 -15
@@ -9,24 +9,10 @@#include <linux/oprofile.h> #include <linux/interrupt.h> #include <linux/smp.h> +#include <asm/pmu.h> #include "op_impl.h" -#define RM9K_COUNTER1_EVENT (event) ((event) << 0) -#define RM9K_COUNTER1_SUPERVISOR (1ULL << 7) -#define RM9K_COUNTER1_KERNEL (1ULL << 8) -#define RM9K_COUNTER1_USER (1ULL << 9) -#define RM9K_COUNTER1_ENABLE (1ULL << 10) -#define RM9K_COUNTER1_OVERFLOW (1ULL << 15) - -#define RM9K_COUNTER2_EVENT (event) ((event) << 16) -#define RM9K_COUNTER2_SUPERVISOR (1ULL << 23) -#define RM9K_COUNTER2_KERNEL (1ULL << 24) -#define RM9K_COUNTER2_USER (1ULL << 25) -#define RM9K_COUNTER2_ENABLE (1ULL << 26) -#define RM9K_COUNTER2_OVERFLOW (1ULL << 31) - -extern unsigned int rm9000_perfcount_irq; static struct rm9k_register_config { unsigned int control;
Signature · 1 line
1.6.3.3
PATCH v6 2/7 MIPS: use generic atomic64 in non-64bit kernels
In reply to Deng-Cheng Zhu64bit kernel has already had its atomic64 functions. Except for that, we use the generic spinlocked version. The atomic64 types and related functions are needed for the Linux performance counter subsystem.
--- arch/mips/Kconfig | 1 + arch/mips/include/asm/atomic.h | 4 ++++ 2 files changed, 5 insertions(+), 0 deletions(-)
arch/mips/Kconfig +1 -0
@@ -11,6 +11,7 @@ config MIPS select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER select RTC_LIB if !MACH_LOONGSON + select GENERIC_ATOMIC64 if !64BIT mainmenu "Linux/MIPS Kernel Configuration"
arch/mips/include/asm/atomic.h +4 -0
@@ -782,6 +782,10 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)*/ #define atomic64_add_negative (i, v) (atomic64_add_return(i, (v)) < 0) +#else /* !CONFIG_64BIT */ + +#include <asm-generic/atomic64.h> +#endif /* CONFIG_64BIT */ /*
Signature · 1 line
1.6.3.3
Re: [PATCH v6 2/7] MIPS: use generic atomic64 in non-64bit kernels
Quoted 5 lines · Deng-Cheng Zhu
64bit kernel has already had its atomic64 functions. Except for that, we use the generic spinlocked version. The atomic64 types and related functions are needed for the Linux performance counter subsystem.
Signed-off-by Deng-Cheng Zhu<[email protected]>
I already acked this once, so you can (should) add my...
Really, this part is correct and standalone, so I think Ralf should just go ahead and merge it to his queue.
David Daney.
Quoted 32 lines
--- arch/mips/Kconfig | 1 + arch/mips/include/asm/atomic.h | 4 ++++ 2 files changed, 5 insertions(+), 0 deletions(-)arch/mips/Kconfig +1
-0@@ -11,6 +11,7 @@ config MIPS select HAVE_FTRACE_MCOUNT_RECORD select HAVE_FUNCTION_GRAPH_TRACER select RTC_LIB if !MACH_LOONGSON + select GENERIC_ATOMIC64 if !64BIT mainmenu "Linux/MIPS Kernel Configuration"arch/mips/include/asm/atomic.h +4
-0@@ -782,6 +782,10 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)*/ #define atomic64_add_negative (i, v) (atomic64_add_return(i, (v))< 0) +#else /* !CONFIG_64BIT */ + +#include <asm-generic/atomic64.h> +#endif /* CONFIG_64BIT */ /*
Ralf Baechle
AppliedRe: [PATCH v6 2/7] MIPS: use generic atomic64 in non-64bit kernels
In reply to Deng-Cheng ZhuApplied. Thanks Deng-Cheng!
Ralf
PATCH v6 3/7 MIPS: add support for software performance events
In reply to Deng-Cheng ZhuSoftware events are required as part of the measurable stuff by the Linux performance counter subsystem. Here is the list of events added by this patch:PERF_COUNT_SW_PAGE_FAULTSPERF_COUNT_SW_PAGE_FAULTS_MINPERF_COUNT_SW_PAGE_FAULTS_MAJPERF_COUNT_SW_ALIGNMENT_FAULTS PERF_COUNT_SW_EMULATION_FAULTS
--- arch/mips/Kconfig | 2 ++ arch/mips/kernel/traps.c | 18 +++++++++++++++--- arch/mips/kernel/unaligned.c | 5 +++++ arch/mips/math-emu/cp1emu.c | 3 +++ arch/mips/mm/fault.c | 11 +++++++++-- 5 files changed, 34 insertions(+), 5 deletions(-)
arch/mips/Kconfig +2 -0
@@ -4,6 +4,8 @@ config MIPS select HAVE_GENERIC_DMA_COHERENT select HAVE_IDE select HAVE_OPROFILE + select HAVE_PERF_EVENTS + select PERF_USE_VMALLOC select HAVE_ARCH_KGDB select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST
arch/mips/kernel/traps.c +15 -3
@@ -27,6 +27,7 @@#include <linux/kdebug.h> #include <linux/notifier.h> #include <linux/kdb.h> +#include <linux/perf_event.h> #include <asm/bootinfo.h> #include <asm/branch.h>
@@ -570,10 +571,16 @@ static inline int simulate_sc(struct pt_regs *regs, unsigned int opcode)*/ static int simulate_llsc (struct pt_regs *regs,unsigned int opcode) { -if ((opcode &OPCODE ) ==LL ) +if ((opcode &OPCODE ) ==LL ) { +perf_sw_event (PERF_COUNT_SW_EMULATION_FAULTS , +1 ,0 , regs,0 );return simulate_ll (regs, opcode); -if ((opcode &OPCODE ) ==SC ) + } +if ((opcode &OPCODE ) ==SC ) { +perf_sw_event (PERF_COUNT_SW_EMULATION_FAULTS , +1 ,0 , regs,0 );return simulate_sc (regs, opcode); + }return -1 ;/* Must be something else ... */ }
@@ -589,6 +596,8 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)if ((opcode &OPCODE ) ==SPEC3 && (opcode &FUNC ) ==RDHWR ) {int rd = (opcode &RD ) >>11 ;int rt = (opcode &RT ) >>16 ; +perf_sw_event (PERF_COUNT_SW_EMULATION_FAULTS , +1 ,0 , regs,0 );switch (rd) {case 0 :/* CPU number */ regs->regs[rt] =smp_processor_id ();
@@ -624,8 +633,11 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)static int simulate_sync (struct pt_regs *regs,unsigned int opcode) { -if ((opcode &OPCODE ) ==SPEC0 && (opcode &FUNC ) ==SYNC ) +if ((opcode &OPCODE ) ==SPEC0 && (opcode &FUNC ) ==SYNC ) { +perf_sw_event (PERF_COUNT_SW_EMULATION_FAULTS , +1 ,0 , regs,0 );return 0 ; + }return -1 ;/* Must be something else ... */ }
arch/mips/kernel/unaligned.c +5 -0
@@ -78,6 +78,7 @@#include <linux/smp.h> #include <linux/sched.h> #include <linux/debugfs.h> +#include <linux/perf_event.h> #include <asm/asm.h> #include <asm/branch.h> #include <asm/byteorder.h>
@@ -109,6 +110,8 @@ static void emulate_load_store_insn(struct pt_regs *regs,unsigned long value;unsigned int res; +perf_sw_event (PERF_COUNT_SW_EMULATION_FAULTS , +1 ,0 , regs,0 ); regs->regs[0 ] =0 ;/*
@@ -513,6 +516,8 @@ asmlinkage void do_ade(struct pt_regs *regs)unsigned int __user *pc;mm_segment_t seg; +perf_sw_event (PERF_COUNT_SW_ALIGNMENT_FAULTS , +1 ,0 , regs, regs->cp0_badvaddr);/* * Did we catch a fault trying to load an instruction? * Or are we running in MIPS16 mode?
arch/mips/math-emu/cp1emu.c +3 -0
@@ -37,6 +37,7 @@#include <linux/sched.h> #include <linux/module.h> #include <linux/debugfs.h> +#include <linux/perf_event.h> #include <asm/inst.h> #include <asm/bootinfo.h>
@@ -259,6 +260,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) } emul: +perf_sw_event (PERF_COUNT_SW_EMULATION_FAULTS , +1 ,0 , xcp,0 );MIPS_FPU_EMU_INC_STATS (emulated);switch (MIPSInst_OPCODE (ir)) {case ldc1_op:{
arch/mips/mm/fault.c +9 -2
@@ -17,6 +17,7 @@#include <linux/mm.h> #include <linux/smp.h> #include <linux/module.h> +#include <linux/perf_event.h> #include <asm/branch.h> #include <asm/mmu_context.h>
@@ -131,6 +132,7 @@ good_area:* the fault. */ fault =handle_mm_fault (mm, vma, address, write ?FAULT_FLAG_WRITE :0 ); +perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS ,1 ,0 , regs, address);if (unlikely (fault &VM_FAULT_ERROR )) {if (fault &VM_FAULT_OOM ) goto out_of_memory;
@@ -138,10 +140,15 @@ good_area: goto do_sigbus;BUG (); } -if (fault &VM_FAULT_MAJOR ) +if (fault &VM_FAULT_MAJOR ) { +perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS_MAJ , +1 ,0 , regs, address); tsk->maj_flt++; -else + }else { +perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS_MIN , +1 ,0 , regs, address); tsk->min_flt++; + }up_read (&mm->mmap_sem);return ;
Signature · 1 line
1.6.3.3
Re: [PATCH v6 3/7] MIPS: add support for software performance events
Quoted 10 lines · Deng-Cheng Zhu
Software events are required as part of the measurable stuff by the Linux performance counter subsystem. Here is the list of events added by this patch:
PERF_COUNT_SW_PAGE_FAULTSPERF_COUNT_SW_PAGE_FAULTS_MINPERF_COUNT_SW_PAGE_FAULTS_MAJPERF_COUNT_SW_ALIGNMENT_FAULTSPERF_COUNT_SW_EMULATION_FAULTSSigned-off-by Deng-Cheng Zhu <[email protected]>
This looks OK.
PATCH v6 4/7 MIPS: add support for hardware performance events (skeleton)
In reply to Deng-Cheng ZhuThis patch provides the skeleton of the HW perf event support. To enable this feature, we can not choose the SMTC kernel; Oprofile should be disabled; kernel performance events be selected. Then we can enable it in Kernel type menu.
Oprofile for MIPS platforms initializes irq at arch init time. Currently we do not change this logic to allow PMU reservation.
If a platform has EIC, we can use the irq base and perf counter irq offset defines for the interrupt controller in mipspmu_get_irq().
Based on this skeleton patch, the 3 different kinds of MIPS PMU, namely, mipsxx/loongson2/rm9000, can be supported by adding corresponding lower level C files at the bottom. The suggested names of these files are perf_event_mipsxx.c/perf_event_loongson2.c/perf_event_rm9000.c. So, for example, we can do this by adding "#include perf_event_mipsxx.c" at the bottom of perf_event.c.
In addition, PMUs with 64bit counters are also considered in this patch.
--- arch/mips/Kconfig | 8 + arch/mips/include/asm/perf_event.h | 26 ++ arch/mips/kernel/Makefile | 2 + arch/mips/kernel/perf_event.c | 510 ++++++++++++++++++++++++++++++++++++ 4 files changed, 546 insertions(+), 0 deletions(-) create mode 100644 arch/mips/include/asm/perf_event.h create mode 100644 arch/mips/kernel/perf_event.c
arch/mips/Kconfig +8 -0
@@ -1888,6 +1888,14 @@ config NODES_SHIFT default "6" depends on NEED_MULTIPLE_NODES +config HW_PERF_EVENTS + bool "Enable hardware performance counter support for perf events" + depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && CPU_MIPS32 + default y + help + Enable hardware performance counter support for perf events. If + disabled, perf events will use software events only. + source "mm/Kconfig" config SMP
arch/mips/include/asm/perf_event.h new file +26 -0
@@ -0,0 +1,26 @@ +/* +* linux/arch/mips/include/asm/perf_event.h +* +* Copyright (C) 2010 MIPS Technologies, Inc. +* Author: Deng-Cheng Zhu +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#ifndef __MIPS_PERF_EVENT_H__ +#define __MIPS_PERF_EVENT_H__ + +/* +* MIPS performance counters do not raise NMI upon overflow, a regular +* interrupt will be signaled. Hence we can do the pending perf event +* work at the tail of the irq handler. +*/ +static inline void +set_perf_event_pending (void ) +{ +} + +#endif /* __MIPS_PERF_EVENT_H__ */ +
arch/mips/kernel/Makefile +2 -0
@@ -101,4 +101,6 @@ obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/ +obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o + CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
arch/mips/kernel/perf_event.c new file +510 -0
510 lines not on this page · raw message
Signature · 1 line
1.6.3.3
Re: [PATCH v6 4/7] MIPS: add support for hardware performance events (skeleton)
On Wed, Jun 09, 2010 at 12:35:27PM +0800, Deng-Cheng Zhu wrote:
[...]
Quoted 11 lines
arch/mips/kernel/perf_event.c new file +11
-0+static void mipspmu_event_update (struct perf_event *event, +struct hw_perf_event *hwc, +int idx) +{ +struct cpu_hw_events *cpuc = &__get_cpu_var (cpu_hw_events); +unsigned long flags; +int shift =64 -TOTAL_BITS ; +s64 prev_raw_count, new_raw_count; +s64 delta; + +again:
arch/mips/kernel/perf_event.c line 212
Quoted 10 lines
arch/mips/kernel/perf_event.c new file +10
-0+ prev_raw_count =atomic64_read (&hwc->prev_count); +local_irq_save (flags); +/* Make the counter value be a "real" one. */ + new_raw_count = mipspmu->read_counter (idx); +if (new_raw_count & (test_bit (idx, cpuc->msbs) <<HIGHEST_BIT )) { + new_raw_count &=VALID_COUNT ; +clear_bit (idx, cpuc->msbs); + }else + new_raw_count |= (test_bit (idx, cpuc->msbs) <<HIGHEST_BIT ); +local_irq_restore (flags);
I'm probably just being stupid but I can't figure out what this snippet of code is doing. You're checking to see if the counter has overflowed, and if it has then you just clear the overflow bit? I would have expected you to reset the counter to 0.
Quoted 20 lines
arch/mips/kernel/perf_event.c new file +20
-0+if (atomic64_cmpxchg (&hwc->prev_count, prev_raw_count, + new_raw_count) != prev_raw_count) + goto again; + + delta = (new_raw_count << shift) - (prev_raw_count << shift); + delta >>= shift; + +atomic64_add (delta, &event->count); +atomic64_sub (delta, &hwc->period_left); + +return ; +} + +static void mipspmu_disable (struct perf_event *event) +{ +struct cpu_hw_events *cpuc = &__get_cpu_var (cpu_hw_events); +struct hw_perf_event *hwc = &event->hw; +int idx = hwc->idx; + +
arch/mips/kernel/perf_event.c line 243
Quoted 10 lines
arch/mips/kernel/perf_event.c new file +10
-0+WARN_ON (idx <0 || idx >= mipspmu->num_counters); + +/* We are working on a local event. */ + mipspmu->disable_event (idx); + +barrier (); + +mipspmu_event_update (event, hwc, idx); + cpuc->events[idx] =NULL ; +clear_bit (idx, cpuc->used_mask);
Shouldn't you also clear the overflow bit in ->msbs here?
Quoted 47 lines
arch/mips/kernel/perf_event.c new file +47
-0+ +perf_event_update_userpage (event); +} + +static void mipspmu_unthrottle (struct perf_event *event) +{ +struct hw_perf_event *hwc = &event->hw; + + mipspmu->enable_event (hwc, hwc->idx); +} + +static void mipspmu_read (struct perf_event *event) +{ +struct hw_perf_event *hwc = &event->hw; + +/* Don't read disabled counters! */ +if (hwc->idx <0 ) +return ; + +mipspmu_event_update (event, hwc, hwc->idx); +} + +static struct pmu pmu = { + .enable = mipspmu_enable, + .disable = mipspmu_disable, + .unthrottle = mipspmu_unthrottle, + .read = mipspmu_read, +}; + +static atomic_t active_events =ATOMIC_INIT (0 ); +static DEFINE_MUTEX (pmu_reserve_mutex); +static int mips_pmu_irq =-1 ; +static int (*save_perf_irq)(void ); + +static int mipspmu_get_irq (void ) +{ +int err; + +if (cpu_has_veic) { +/* +* Using platform specific interrupt controller defines. +*/ +#ifdef MSC01E_INT_BASE + mips_pmu_irq =MSC01E_INT_BASE +MSC01E_INT_PERFCTR ; +#endif + }else if (cp0_perfcount_irq >=0 ) { +/*
arch/mips/kernel/perf_event.c line 300
Quoted 10 lines
arch/mips/kernel/perf_event.c new file +10
-0+* Some CPUs have explicitly defined their perfcount irq. +*/ +#if defined(CONFIG_CPU_RM9000 ) + mips_pmu_irq = rm9000_perfcount_irq; +#elif defined(CONFIG_CPU_LOONGSON2 ) + mips_pmu_irq =LOONGSON2_PERFCNT_IRQ ; +#else + mips_pmu_irq =MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; +#endif + }
Having conditional code like this is a pretty sure sign that you haven't separated support for the various performance hardware properly. Have you had a look at how SH uses a registration interface to register sh_pmus? Ideally all the internals for each type of perfcounter hardware should be in their own file.
Quoted 7 lines
arch/mips/kernel/perf_event.c new file +7
-0+ +if (mips_pmu_irq >=0 ) { +/* Request my own irq handler. */ + err =request_irq (mips_pmu_irq, mipspmu->handle_irq, +IRQF_DISABLED |IRQF_NOBALANCING , +"mips_perf_pmu" ,NULL ); +if (err) {
arch/mips/kernel/perf_event.c line 317
Quoted 10 lines
arch/mips/kernel/perf_event.c new file +10
-0+pr_warning ("Unable to request IRQ%d for MIPS " +"performance counters!\n" , mips_pmu_irq); + } + }else if (cp0_perfcount_irq <0 ) { +/* +* We are sharing the irq number with the timer interrupt. +*/ + save_perf_irq = perf_irq; + perf_irq = mipspmu->handle_shared_irq; + err =0 ;
SH also has this problem that it doesn't have any sort of performance counter interrupt and so can't check for overflow. This lack of interrupt really needs to be solved generically in perf as it's a problem that effects quite a few architectures. I suspect that using a hrtimer instead of piggy-backing the timer interrupt would make the core perf guys happier. Writing support for this is on my ever-growing list of things todo. I've already started on some patches for the perf tool so that it's possible to sample counters even though there is no periodic interrupt (but that's a different problem).
Re: [PATCH v6 4/7] MIPS: add support for hardware performance events (skeleton)
2010/9/22 Matt Fleming <[email protected]>:
Quoted 4 lines
I'm probably just being stupid but I can't figure out what this snippet of code is doing. You're checking to see if the counter has overflowed, and if it has then you just clear the overflow bit? I would have expected you to reset the counter to 0.
[DC]: Maybe my original code comment for the member msbs of the struct cpu_hw_events is too simple. And here is more: Unlike the perf counters in some other architectures, a 32bit MIPS perf counter, for example, will generate an interrupt after 0x7fffffff. But we want the operation to look
like: 0x0 -> 0xffffffff -> interrupt. So there's a "pseudo" signal halfway. Please also note that the counter value will be brought back to 0 soon after it reaches 0x80000000 *each time*.
Quoted 1 line
Shouldn't you also clear the overflow bit in ->msbs here?
[DC]: See my comment above.
Quoted 5 lines
Having conditional code like this is a pretty sure sign that you haven't separated support for the various performance hardware properly. Have you had a look at how SH uses a registration interface to register
sh_pmus? Ideally all the internals for each type of perfcounter hardware should be in their own file.
[DC]: It does look ugly. It should be easy to put conditional code into perf_event_[mipsxx|loongson2|rm9000].c. I'll post a patch to fix it when the whole thing is accepted.
Quoted 9 lines
SH also has this problem that it doesn't have any sort of performance counter interrupt and so can't check for overflow. This lack of interrupt really needs to be solved generically in perf as it's a problem that effects quite a few architectures. I suspect that using a hrtimer instead of piggy-backing the timer interrupt would make the core perf guys happier. Writing support for this is on my ever-growing list of things todo. I've already started on some patches for the perf tool so that it's possible to sample counters even though there is no periodic interrupt (but that's a different problem).
[DC]: Please add me into your post list when your patches are ready :-) Finally, thanks for your time to review the code.
Deng-Cheng
Re: [PATCH v6 4/7] MIPS: add support for hardware performance events (skeleton)
Quoted 5 lines · Deng-Cheng Zhu
2010/9/22 Matt Fleming <[email protected]>:
Quoted 4 lines
I'm probably just being stupid but I can't figure out what this snippet of code is doing. You're checking to see if the counter has overflowed, and if it has then you just clear the overflow bit? I would have expected you to reset the counter to 0.
Quoted 7 lines
[DC]: Maybe my original code comment for the member msbs of the struct
cpu_hw_eventsis too simple. And here is more: Unlike the perf counters in some other architectures, a 32bit MIPS perf counter, for example, will generate an interrupt after0x7fffffff. But we want the operation to look
like:0x0->0xffffffff-> interrupt. So there's a "pseudo" signal halfway. Please also note that the counter value will be brought back to 0 soon after it reaches0x80000000*each time*.
Ah OK, thanks.
Quoted 8 lines
Quoted 5 lines
Having conditional code like this is a pretty sure sign that you haven't separated support for the various performance hardware properly. Have you had a look at how SH uses a registration interface to register
sh_pmus? Ideally all the internals for each type of perfcounter hardware should be in their own file.[DC]: It does look ugly. It should be easy to put conditional code into perf_event_[mipsxx|loongson2|rm9000].c. I'll post a patch to fix it when the whole thing is accepted.
The potential problem with doing a cleanup patch after this series has been merged is that it will modify most of the code in this patch series - essentially rewriting it. I don't have a strong opinion either way but Ralf may.
Quoted 11 lines
Quoted 9 lines
SH also has this problem that it doesn't have any sort of performance counter interrupt and so can't check for overflow. This lack of interrupt really needs to be solved generically in perf as it's a problem that effects quite a few architectures. I suspect that using a hrtimer instead of piggy-backing the timer interrupt would make the core perf guys happier. Writing support for this is on my ever-growing list of things todo. I've already started on some patches for the perf tool so that it's possible to sample counters even though there is no periodic interrupt (but that's a different problem).
[DC]: Please add me into your post list when your patches are ready :-) Finally, thanks for your time to review the code.
Sure, I will do. No problem!
Re: [PATCH v6 4/7] MIPS: add support for hardware performance events (skeleton)
2010/9/24 Matt Fleming <[email protected]>:
Quoted 4 lines
The potential problem with doing a cleanup patch after this series has been merged is that it will modify most of the code in this patch series - essentially rewriting it. I don't have a strong opinion either way but Ralf may.
[DC]: No, the situation is not that serious. The mips_pmu registration mechanism had already been implemented. You may take a look at the bottom of perf_event_mipsxx.c (patch #6). The ugly conditional code (mips_pmu_irq) could be fixed easily, I suppose.
Deng-Cheng
PATCH v6 5/7 MIPS/Perf-events: add callchain support
In reply to Deng-Cheng ZhuThis patch adds callchain support for MIPS Perf-events. For more info on this feature, please refer to tools/perf/Documentation/perf-report.txt and tools/perf/design.txt.
Currently userspace callchain data is not recorded, because we do not have a safe way to do this.
--- arch/mips/kernel/perf_event.c | 108 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 107 insertions(+), 1 deletions(-)
arch/mips/kernel/perf_event.c +107 -1
@@ -6,7 +6,8 @@* * This code is based on the implementation for ARM, which is in turn * based on the sparc64 perf event code and the x86 code. Performance -* counter access is based on the MIPS Oprofile code. +* counter access is based on the MIPS Oprofile code. And the callchain +* support references the code of MIPS stacktrace.c. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -508,3 +509,108 @@ handle_associated_event(struct cpu_hw_events *cpuc, mipspmu->disable_event (idx); } +/* Callchain handling code. */ +static inline void +callchain_store (struct perf_callchain_entry *entry, +u64 ip) +{ +if (entry->nr <PERF_MAX_STACK_DEPTH ) + entry->ip[entry->nr++] = ip; +} + +/* +* Leave userspace callchain empty for now. When we find a way to trace +* the user stack callchains, we add here. +*/ +static void +perf_callchain_user (struct pt_regs *regs, +struct perf_callchain_entry *entry) +{ +} + +static void save_raw_perf_callchain (struct perf_callchain_entry *entry, +unsigned long reg29) +{ +unsigned long *sp = (unsigned long *)reg29; +unsigned long addr; + +while (!kstack_end (sp)) { + addr = *sp++; +if (__kernel_text_address (addr)) { +callchain_store (entry, addr); +if (entry->nr >=PERF_MAX_STACK_DEPTH ) +break ; + } + } +} + +static void +perf_callchain_kernel (struct pt_regs *regs, +struct perf_callchain_entry *entry) +{ +unsigned long sp = regs->regs[29 ]; +#ifdef CONFIG_KALLSYMS +unsigned long ra = regs->regs[31 ]; +unsigned long pc = regs->cp0_epc; + +callchain_store (entry,PERF_CONTEXT_KERNEL ); +if (raw_show_trace || !__kernel_text_address (pc)) { +unsigned long stack_page = + (unsigned long )task_stack_page (current); +if (stack_page && sp >= stack_page && + sp <= stack_page +THREAD_SIZE -32 ) +save_raw_perf_callchain (entry, sp); +return ; + } +do { +callchain_store (entry, pc); +if (entry->nr >=PERF_MAX_STACK_DEPTH ) +break ; + pc =unwind_stack (current, &sp, pc, &ra); + }while (pc); +#else +callchain_store (entry,PERF_CONTEXT_KERNEL ); +save_raw_perf_callchain (entry, sp); +#endif +} + +static void +perf_do_callchain (struct pt_regs *regs, +struct perf_callchain_entry *entry) +{ +int is_user; + +if (!regs) +return ; + + is_user =user_mode (regs); + +if (!current || !current->pid) +return ; + +if (is_user && current->state !=TASK_RUNNING ) +return ; + +if (!is_user) { +perf_callchain_kernel (regs, entry); +if (current->mm) + regs =task_pt_regs (current); +else + regs =NULL ; + } +if (regs) +perf_callchain_user (regs, entry); +} + +static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); + +struct perf_callchain_entry * +perf_callchain (struct pt_regs *regs) +{ +struct perf_callchain_entry *entry = &__get_cpu_var (pmc_irq_entry); + + entry->nr =0 ; +perf_do_callchain (regs, entry); +return entry; +} +
Signature · 1 line
1.6.3.3
PATCH v6 6/7 MIPS: add support for hardware performance events (mipsxx)
In reply to Deng-Cheng ZhuThis patch adds the mipsxx Perf-event support based on the skeleton. Generic hardware events and cache events are now fully implemented for the 24K/34K/74K/1004K cores. To support other cores in mipsxx (such as R10000/SB1), the generic hardware event tables and cache event tables need to be filled out. To support other CPUs which have different PMU than mipsxx, such as RM9000 and LOONGSON2, the additional files perf_event_$cpu.c need to be created.
Raw event is an important part of Perf-events. It helps the user collect performance data for events that are not listed as the generic hardware events and cache events but ARE supported by the CPU's PMU.
This patch also adds this feature for mipsxx 24K/34K/74K/1004K. For how to use it, please refer to processor core software user's manual and the comments for mipsxx_pmu_map_raw_event() for more details.
Please note that this is a "precise" implementation, which means the kernel will check whether the requested raw events are supported by this CPU and which hardware counters can be assigned for them.
To test the functionality of Perf-event, you may want to compile the tool "perf" for your MIPS platform. You can refer to the following URL:
http://www.linux-mips.org/archives/linux-mips/2010-04/msg00158.html
Please note: Before that patch is accepted, you can choose a "specific" rmb() which is suitable for your platform -- an example is provided in the description of that patch.
You also need to customize the CFLAGS and LDFLAGS in tools/perf/Makefile for your libs, includes, etc.
In case you encounter the boot failure in SMVP kernel on multi-threading CPUs, you may take a look at:
http://www.linux-mips.org/git?p=linux-mti.git;a=commitdiff;h=5460815027d802697b879644c74f0e8365254020
--- arch/mips/include/asm/pmu.h | 87 ++++ arch/mips/kernel/perf_event.c | 7 + arch/mips/kernel/perf_event_mipsxx.c | 802 ++++++++++++++++++++++++++++++++++ 3 files changed, 896 insertions(+), 0 deletions(-) create mode 100644 arch/mips/kernel/perf_event_mipsxx.c
arch/mips/include/asm/pmu.h +87 -0
@@ -41,6 +41,19 @@#define M_PERFCTL_WIDE (1UL << 30)#define M_PERFCTL_MORE (1UL << 31) +#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \ + M_PERFCTL_KERNEL | \ + M_PERFCTL_USER | \ + M_PERFCTL_SUPERVISOR | \ + M_PERFCTL_INTERRUPT_ENABLE) + +#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 +#define M_COUNTER_OVERFLOW (1UL << 31)#ifdef CONFIG_MIPS_MT_SMP
@@ -174,6 +187,80 @@ static inline int n_counters(void)return counters; } +static inline u64 +mipsxx_pmu_read_counter (unsigned int idx) +{ +switch (idx) { +case 0 : +return r_c0_perfcntr0 (); +case 1 : +return r_c0_perfcntr1 (); +case 2 : +return r_c0_perfcntr2 (); +case 3 : +return r_c0_perfcntr3 (); +default : +WARN_ONCE (1 ,"Invalid performance counter number (%d)\n" , idx); +return 0 ; + } +} + +static inline void +mipsxx_pmu_write_counter (unsigned int idx,u64 val) +{ +switch (idx) { +case 0 : +w_c0_perfcntr0 (val); +return ; +case 1 : +w_c0_perfcntr1 (val); +return ; +case 2 : +w_c0_perfcntr2 (val); +return ; +case 3 : +w_c0_perfcntr3 (val); +return ; + } +} + +static inline unsigned int +mipsxx_pmu_read_control (unsigned int idx) +{ +switch (idx) { +case 0 : +return r_c0_perfctrl0 (); +case 1 : +return r_c0_perfctrl1 (); +case 2 : +return r_c0_perfctrl2 (); +case 3 : +return r_c0_perfctrl3 (); +default : +WARN_ONCE (1 ,"Invalid performance counter number (%d)\n" , idx); +return 0 ; + } +} + +static inline void +mipsxx_pmu_write_control (unsigned int idx,unsigned int val) +{ +switch (idx) { +case 0 : +w_c0_perfctrl0 (val); +return ; +case 1 : +w_c0_perfctrl1 (val); +return ; +case 2 : +w_c0_perfctrl2 (val); +return ; +case 3 : +w_c0_perfctrl3 (val); +return ; + } +} +/* rm9000 */ #define RM9K_COUNTER1_EVENT (event) ((event) << 0)#define RM9K_COUNTER1_SUPERVISOR (1ULL << 7)
arch/mips/kernel/perf_event.c +7 -0
@@ -87,6 +87,9 @@ struct mips_perf_event {#endif }; +static struct mips_perf_event raw_event; +static DEFINE_MUTEX (raw_event_mutex); +#define UNSUPPORTED_PERF_EVENT_ID 0xffffffff#define C (x) PERF_COUNT_HW_CACHE_##x
@@ -102,6 +105,7 @@ struct mips_pmu {void (*write_counter)(unsigned int idx,u64 val);void (*enable_event)(struct hw_perf_event *evt,int idx);void (*disable_event)(int idx); +const struct mips_perf_event *(*map_raw_event)(u64 config);const struct mips_perf_event (*general_event_map)[PERF_COUNT_HW_MAX ];const struct mips_perf_event (*cache_event_map) [PERF_COUNT_HW_CACHE_MAX ]
@@ -430,6 +434,7 @@ static int validate_group(struct perf_event *event)* mipsxx/rm9000/loongson2 have different performance counters, they have * specific low-level init routines. */ +static void reset_counters (void *arg);static int __hw_perf_event_init (struct perf_event *event);static void hw_perf_event_destroy (struct perf_event *event)
@@ -509,6 +514,8 @@ handle_associated_event(struct cpu_hw_events *cpuc, mipspmu->disable_event (idx); } +#include "perf_event_mipsxx.c" +/* Callchain handling code. */ static inline void callchain_store(struct perf_callchain_entry *entry,
arch/mips/kernel/perf_event_mipsxx.c new file +802 -0
802 lines not on this page · raw message
Signature · 1 line
1.6.3.3
PATCH v6 7/7 MIPS: define local_xchg from xchg_local to atomic_long_xchg
In reply to Deng-Cheng ZhuPerf-events is now using local_t helper functions internally. There is a use of local_xchg(). On MIPS, this is defined to xchg_local() which is missing in asm/system.h. This patch re-defines local_xchg() in asm/local.h to atomic_long_xchg(). Then Perf-events can pass the build.
--- arch/mips/include/asm/local.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/mips/include/asm/local.h +1 -1
@@ -117,7 +117,7 @@ static __inline__ long local_sub_return(long i, local_t * l)#define local_cmpxchg (l, o, n) \ ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) -#define local_xchg (l, n) (xchg_local(&((l)->a.counter), (n))) +#define local_xchg (l, n) atomic_long_xchg((&(l)->a), (n))/** * local_add_unless - add unless the number is a given value
Signature · 1 line
1.6.3.3
Re: [PATCH v6 7/7] MIPS: define local_xchg from xchg_local to atomic_long_xchg
Quoted 6 lines · Deng-Cheng Zhu
Perf-events is now using
local_thelper functions internally. There is a use oflocal_xchg(). On MIPS, this is defined toxchg_local()which is missing inasm/system.h. This patch re-defineslocal_xchg()inasm/local.htoatomic_long_xchg(). Then Perf-events can pass the build.Signed-off-by Deng-Cheng Zhu <[email protected]>
Is this a separate issue from the rest of this patch series? In any event, it's probably worth moving this earlier in the patch series so as not to break bisect.
Re: [PATCH v6 7/7] MIPS: define local_xchg from xchg_local to atomic_long_xchg
Yes, it's here only to pass the compiling (coz the Perf core had evolved since the v5 of this patchset). Since the file it touches is stand-alone, it can be applied earlier than the rest (like the patch #2).
Deng-Cheng
2010/9/22 Matt Fleming <[email protected]>:
Quoted 12 lines · Deng-Cheng Zhu
Quoted 6 lines
Perf-events is now using
local_thelper functions internally. There is a use oflocal_xchg(). On MIPS, this is defined toxchg_local()which is missing inasm/system.h. This patch re-defineslocal_xchg()inasm/local.htoatomic_long_xchg(). Then Perf-events can pass the build.Signed-off-by Deng-Cheng Zhu <[email protected]>Is this a separate issue from the rest of this patch series? In any event, it's probably worth moving this earlier in the patch series so as not to break bisect.