Support hardware perf counters on xtensa
Subsystems (2)
Max Filippov
maintainercover Support hardware perf counters on xtensa
Hello,
this series adds support for hardware performance counters in counting and sampling modes as well as for page fault counting. It reorganizes stack stracing code to share it between old oprofile and new perf interfaces, and improves kernel stack traces both for builtin debug functions and for gdb.
Max Filippov (8):
xtensa: clean up Kconfig dependencies for custom cores
xtensa: keep exception/interrupt stack continuous
xtensa: move oprofile stack tracing to stacktrace.c
xtensa: select PERF_USE_VMALLOC for cache-aliasing configurations
xtensa: add profiling IRQ type to xtensa_irq_map
xtensa: count software page fault perf events
xtensa: implement counting and sampling perf events perf tools: xtensa: add DWARF register names
arch/xtensa/Kconfig | 22 +- arch/xtensa/include/asm/stacktrace.h | 8 + arch/xtensa/kernel/Makefile | 1 + arch/xtensa/kernel/entry.S | 60 +++-- arch/xtensa/kernel/irq.c | 6 + arch/xtensa/kernel/perf_event.c | 450 +++++++++++++++++++++++++++++++ arch/xtensa/kernel/stacktrace.c | 167 +++++++++++- arch/xtensa/mm/fault.c | 7 + arch/xtensa/oprofile/backtrace.c | 158 +---------- tools/perf/arch/xtensa/Build | 1 + tools/perf/arch/xtensa/Makefile | 3 + tools/perf/arch/xtensa/util/Build | 1 + tools/perf/arch/xtensa/util/dwarf-regs.c | 25 ++ 13 files changed, 725 insertions(+), 184 deletions(-) create mode 100644 arch/xtensa/kernel/perf_event.c create mode 100644 tools/perf/arch/xtensa/Build create mode 100644 tools/perf/arch/xtensa/Makefile create mode 100644 tools/perf/arch/xtensa/util/Build create mode 100644 tools/perf/arch/xtensa/util/dwarf-regs.c
Signature · 1 line
1.8.1.4
Max Filippov
maintainerPATCH 1/8 xtensa: clean up Kconfig dependencies for custom cores
--- arch/xtensa/Kconfig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
arch/xtensa/Kconfig +3 -8
@@ -61,9 +61,7 @@ config TRACE_IRQFLAGS_SUPPORT def_bool y config MMU - bool - default n if !XTENSA_VARIANT_CUSTOM - default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM + def_bool n config VARIANT_IRQ_SWITCH def_bool n
@@ -71,9 +69,6 @@ config VARIANT_IRQ_SWITCH config HAVE_XTENSA_GPIO32 def_bool n -config MAY_HAVE_SMP - def_bool n - menu "Processor type and features" choice
@@ -100,7 +95,6 @@ config XTENSA_VARIANT_DC233C config XTENSA_VARIANT_CUSTOM bool "Custom Xtensa processor configuration" - select MAY_HAVE_SMP select HAVE_XTENSA_GPIO32 help Select this variant to use a custom Xtensa processor configuration.
@@ -126,6 +120,7 @@ config XTENSA_VARIANT_MMU bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)" depends on XTENSA_VARIANT_CUSTOM default y + select MMU help Build a Conventional Kernel with full MMU support, ie: it supports a TLB with auto-loading, page protection.
@@ -143,7 +138,7 @@ source "kernel/Kconfig.preempt" config HAVE_SMP bool "System Supports SMP (MX)" - depends on MAY_HAVE_SMP + depends on XTENSA_VARIANT_CUSTOM select XTENSA_MX help This option is use to indicate that the system-on-a-chip (SOC)
Signature · 1 line
1.8.1.4
Re: [PATCH 1/8] xtensa: clean up Kconfig dependencies for custom cores
arch/xtensa/Kconfig config TRACE_IRQFLAGS_SUPPORT · line 64
Quoted 8 lines · Max Filippov
arch/xtensa/Kconfig +1
-3config MMU - bool - default n if !XTENSA_VARIANT_CUSTOM - default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM + def_bool n
Doesn't
config MMU
bool
(ie, drop the 'n' default) work just as well?
Paul Bolle
Max Filippov
maintainerPATCH 2/8 xtensa: keep exception/interrupt stack continuous
In reply to Max FilippovRestore original a0 in the kernel exception stack frame. This way it looks like the frame that got interrupt/exception did alloca (copy a0 and a1 potentially spilled under old stack to the new location as well) to save registers and then did a call to handler. The point where interrupt/exception was taken is not in the stack chain, only in pt_regs (call4 from that address can be simulated to keep it in the stack trace).
--- arch/xtensa/kernel/entry.S | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 25 deletions(-)
arch/xtensa/kernel/entry.S +35 -25
@@ -218,7 +218,7 @@ _user_exception: /* We are back to the original stack pointer (a1) */ 2: /* Now, jump to the common exception handler. */ - + movi a0, 0 # terminate user stack trace with 0 j common_exception ENDPROC(user_exception)
@@ -264,6 +264,19 @@ ENTRY(kernel_exception) .globl _kernel_exception _kernel_exception: + /* Copy spill slots of a0 and a1 to imitate movsp + * in order to keep exception stack continuous + */ + l32i a0, a1, PT_AREG1 + addi a2, a1, -16 + addi a0, a0, -16 + l32i a3, a0, 0 + l32i a0, a0, 4 + s32i a3, a2, 0 + s32i a0, a2, 4 + + l32i a0, a1, PT_AREG0 # restore saved a0 + /* Save SAR and turn off single stepping */ movi a2, 0
@@ -338,52 +351,50 @@ common_exception: xsr a2, lcount s32i a2, a1, PT_LCOUNT - /* It is now save to restore the EXC_TABLE_FIXUP variable. */ + /* It is now safe to restore the EXC_TABLE_FIXUP variable. */ - rsr a0, exccause movi a3, 0 rsr a2, excsave1 - s32i a0, a1, PT_EXCCAUSE s32i a3, a2, EXC_TABLE_FIXUP - /* All unrecoverable states are saved on stack, now, and a1 is valid, - * so we can allow exceptions and interrupts (*) again. - * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) + /* Save remaining unrecoverable states (exccause, ps) on stack. + * Now we can allow exceptions again. In case we've got an interrupt + * PS.INTLEVEL is set to LOCKLEVEL disabling furhter interrupts, + * otherwise it's left unchanged. * - * (*) We only allow interrupts if they were previously enabled and - * we're not handling an IRQ + * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) */ rsr a3, ps - addi a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT - movi a2, LOCKLEVEL + movi a2, (1 << PS_WOE_BIT) extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH - # a3 = PS.INTLEVEL - moveqz a3, a2, a0 # a3 = LOCKLEVEL iff interrupt - movi a2, 1 << PS_WOE_BIT or a3, a3, a2 - rsr a0, exccause - xsr a3, ps + rsr a2, exccause + bnei a2, EXCCAUSE_LEVEL1_INTERRUPT, 1f + movi a3, (1 << PS_WOE_BIT) | LOCKLEVEL +1: + xsr a3, ps + s32i a2, a1, PT_EXCCAUSE s32i a3, a1, PT_PS # save ps /* Save lbeg, lend */ - rsr a2, lbeg + rsr a4, lbeg rsr a3, lend - s32i a2, a1, PT_LBEG + s32i a4, a1, PT_LBEG s32i a3, a1, PT_LEND /* Save SCOMPARE1 */ #if XCHAL_HAVE_S32C1I - rsr a2, scompare1 - s32i a2, a1, PT_SCOMPARE1 + rsr a3, scompare1 + s32i a3, a1, PT_SCOMPARE1 #endif /* Save optional registers. */ - save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT + save_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT #ifdef CONFIG_TRACE_IRQFLAGS l32i a4, a1, PT_DEPC
@@ -391,8 +402,7 @@ common_exception: * while PS.EXCM was set, i.e. interrupts disabled. */ bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f - l32i a4, a1, PT_EXCCAUSE - bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f + bnei a2, EXCCAUSE_LEVEL1_INTERRUPT, 1f /* We came here with an interrupt means interrupts were enabled * and we've just disabled them. */
@@ -407,8 +417,8 @@ common_exception: rsr a4, excsave1 mov a6, a1 # pass stack frame - mov a7, a0 # pass EXCCAUSE - addx4 a4, a0, a4 + mov a7, a2 # pass EXCCAUSE + addx4 a4, a2, a4 l32i a4, a4, EXC_TABLE_DEFAULT # load handler /* Call the second-level handler */
Signature · 1 line
1.8.1.4
Chris Zankel
maintainerRe: [PATCH 2/8] xtensa: keep exception/interrupt stack continuous
Hi Max,
Not such a big fan about these changes as they introduce additional load and stores and a branch.
Copy spill area:
- is this only for debugging? Could the debugger identify the 'kernel exception' frame and handle it appropriately?
- if we need it for debugging/perf, maybe move these line under a kernel option (could be enabled by default)
- since we know the kernel stack frame size, why can't we just load from that offset (instead of the l32i and add). Also, can't we use s32e (need to look up the spec again).
Branch:
- is there any logical change in the code or are these only to avoid using a0?
- if for a0, couldn't we load a0 just before the 'xsr a3, ps' and keep the code as before?
Thanks,
-Chris
Quoted 140 lines · Max Filippov
Restore original a0 in the kernel exception stack frame. This way it looks like the frame that got interrupt/exception did alloca (copy a0 and a1 potentially spilled under old stack to the new location as well) to save registers and then did a call to handler. The point where interrupt/exception was taken is not in the stack chain, only in
pt_regs(call4 from that address can be simulated to keep it in the stack trace).Signed-off-by Max Filippov <[email protected]>--- arch/xtensa/kernel/entry.S | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 25 deletions(-)arch/xtensa/kernel/entry.S +35
-26@@ -218,7 +218,7 @@ _user_exception: /* We are back to the original stack pointer (a1) */ 2: /* Now, jump to the common exception handler. */ - + movi a0, 0 # terminate user stack trace with 0 j common_exception ENDPROC(user_exception)@@ -264,6 +264,19 @@ ENTRY(kernel_exception) .globl _kernel_exception _kernel_exception: + /* Copy spill slots of a0 and a1 to imitate movsp + * in order to keep exception stack continuous + */ + l32i a0, a1, PT_AREG1 + addi a2, a1, -16 + addi a0, a0, -16 + l32i a3, a0, 0 + l32i a0, a0, 4 + s32i a3, a2, 0 + s32i a0, a2, 4 + + l32i a0, a1, PT_AREG0 # restore saved a0 + /* Save SAR and turn off single stepping */ movi a2, 0@@ -338,52 +351,50 @@ common_exception: xsr a2, lcount s32i a2, a1, PT_LCOUNT - /* It is now save to restore the EXC_TABLE_FIXUP variable. */ + /* It is now safe to restore the EXC_TABLE_FIXUP variable. */ - rsr a0, exccause movi a3, 0 rsr a2, excsave1 - s32i a0, a1, PT_EXCCAUSE s32i a3, a2, EXC_TABLE_FIXUP - /* All unrecoverable states are saved on stack, now, and a1 is valid, - * so we can allow exceptions and interrupts (*) again. - * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) + /* Save remaining unrecoverable states (exccause, ps) on stack. + * Now we can allow exceptions again. In case we've got an interrupt + * PS.INTLEVEL is set to LOCKLEVEL disabling furhter interrupts, + * otherwise it's left unchanged. * - * (*) We only allow interrupts if they were previously enabled and - * we're not handling an IRQ + * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) */ rsr a3, ps - addi a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT - movi a2, LOCKLEVEL + movi a2, (1 << PS_WOE_BIT) extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH - # a3 = PS.INTLEVEL - moveqz a3, a2, a0 # a3 = LOCKLEVEL iff interrupt - movi a2, 1 << PS_WOE_BIT or a3, a3, a2 - rsr a0, exccause - xsr a3, ps + rsr a2, exccause + bnei a2, EXCCAUSE_LEVEL1_INTERRUPT, 1f + movi a3, (1 << PS_WOE_BIT) | LOCKLEVEL +1: + xsr a3, ps + s32i a2, a1, PT_EXCCAUSE s32i a3, a1, PT_PS # save ps /* Save lbeg, lend */ - rsr a2, lbeg + rsr a4, lbeg rsr a3, lend - s32i a2, a1, PT_LBEG + s32i a4, a1, PT_LBEG s32i a3, a1, PT_LEND /* Save SCOMPARE1 */ #if XCHAL_HAVE_S32C1I - rsr a2, scompare1 - s32i a2, a1, PT_SCOMPARE1 + rsr a3, scompare1 + s32i a3, a1, PT_SCOMPARE1 #endif /* Save optional registers. */ - save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT + save_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT #ifdef CONFIG_TRACE_IRQFLAGS l32i a4, a1, PT_DEPC@@ -391,8 +402,7 @@ common_exception: * while PS.EXCM was set, i.e. interrupts disabled. */ bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f - l32i a4, a1, PT_EXCCAUSE - bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f + bnei a2, EXCCAUSE_LEVEL1_INTERRUPT, 1f /* We came here with an interrupt means interrupts were enabled * and we've just disabled them. */@@ -407,8 +417,8 @@ common_exception: rsr a4, excsave1 mov a6, a1 # pass stack frame - mov a7, a0 # pass EXCCAUSE - addx4 a4, a0, a4 + mov a7, a2 # pass EXCCAUSE + addx4 a4, a2, a4 l32i a4, a4, EXC_TABLE_DEFAULT # load handler /* Call the second-level handler */ --1.8.1.4
Max Filippov
maintainerRe: [PATCH 2/8] xtensa: keep exception/interrupt stack continuous
Hi Chris,
Quoted 6 lines · Chris Zankel
Not such a big fan about these changes as they introduce additional load and stores and a branch.
Copy spill area:
- is this only for debugging? Could the debugger identify the 'kernel exception' frame and handle it appropriately?
For the debugger and all in-kernel stack tracers: perf, ftrace, oprofile. I'm not sure how the kernel exception frame can be identified, especially for the nested kernel re-entries.
Quoted 2 lines
- if we need it for debugging/perf, maybe move these line under a kernel option (could be enabled by default)
Ok.
Quoted 3 lines
- since we know the kernel stack frame size, why can't we just load from that offset (instead of the l32i and add). Also, can't we use s32e (need to look up the spec again).
Oh, right, l32e and s32e make perfect sense here, I thought about it, but somehow I was under impression we could get here from userspace and CRING would be wrong for the kernel stack. We obviously can't.
Quoted 2 lines
Branch:
- is there any logical change in the code or are these only to avoid using a0?
Yes.
Quoted 2 lines
- if for a0, couldn't we load a0 just before the 'xsr a3, ps' and keep the code as before?
Sure.
Signature · 2 lines
Thanks. -- Max
Max Filippov
maintainerRe: [PATCH 2/8] xtensa: keep exception/interrupt stack continuous
Quoted 4 lines · Max Filippov
Quoted 2 lines
Branch:
- is there any logical change in the code or are these only to avoid using a0?Yes.
Meant the latter.
Signature · 2 lines
Thanks. -- Max
Max Filippov
maintainerPATCH 3/8 xtensa: move oprofile stack tracing to stacktrace.c
In reply to Max FilippovOld oprofile interface will share user stack tracing with new perf interface. Move oprofile user/kernel stack tracing to stacktrace.c to make it possible.
--- arch/xtensa/include/asm/stacktrace.h | 8 ++ arch/xtensa/kernel/stacktrace.c | 167 ++++++++++++++++++++++++++++++++++- arch/xtensa/oprofile/backtrace.c | 158 ++------------------------------- 3 files changed, 182 insertions(+), 151 deletions(-)
arch/xtensa/include/asm/stacktrace.h +8 -0
@@ -33,4 +33,12 @@ void walk_stackframe(unsigned long *sp,int (*fn)(struct stackframe *frame,void *data), void *data); +void xtensa_backtrace_kernel (struct pt_regs *regs,unsigned int depth, +int (*kfn)(struct stackframe *frame,void *data), +int (*ufn)(struct stackframe *frame,void *data), +void *data); +void xtensa_backtrace_user (struct pt_regs *regs,unsigned int depth, +int (*ufn)(struct stackframe *frame,void *data), +void *data); +#endif /* _XTENSA_STACKTRACE_H */
arch/xtensa/kernel/stacktrace.c +166 -1
183 lines not on this page · raw message
arch/xtensa/oprofile/backtrace.c +8 -150
176 lines not on this page · raw message
Signature · 1 line
1.8.1.4
Max Filippov
maintainerPATCH 4/8 xtensa: select PERF_USE_VMALLOC for cache-aliasing configurations
In reply to Max Filippov--- arch/xtensa/Kconfig | 1 + 1 file changed, 1 insertion(+)
arch/xtensa/Kconfig +1 -0
@@ -20,6 +20,7 @@ config XTENSA select HAVE_PERF_EVENTS select IRQ_DOMAIN select MODULES_USE_ELF_RELA + select PERF_USE_VMALLOC select VIRT_TO_BUS help Xtensa processors are 32-bit RISC machines designed by Tensilica
Signature · 1 line
1.8.1.4
Max Filippov
maintainerPATCH 5/8 xtensa: add profiling IRQ type to xtensa_irq_map
In reply to Max Filippov--- arch/xtensa/kernel/irq.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/xtensa/kernel/irq.c +6 -0
@@ -106,6 +106,12 @@ int xtensa_irq_map(struct irq_domain *d, unsigned int irq,irq_set_chip_and_handler_name (irq, irq_chip, handle_percpu_irq,"timer" );irq_clear_status_flags (irq,IRQ_LEVEL ); +#ifdef XCHAL_INTTYPE_MASK_PROFILING + }else if (mask &XCHAL_INTTYPE_MASK_PROFILING ) { +irq_set_chip_and_handler_name (irq, irq_chip, + handle_percpu_irq,"profiling" ); +irq_set_status_flags (irq,IRQ_LEVEL ); +#endif }else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */ /* XCHAL_INTTYPE_MASK_NMI */ irq_set_chip_and_handler_name(irq, irq_chip,
Signature · 1 line
1.8.1.4
Max Filippov
maintainerPATCH 6/8 xtensa: count software page fault perf events
In reply to Max Filippov--- arch/xtensa/mm/fault.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/xtensa/mm/fault.c +7 -0
@@ -15,6 +15,7 @@#include <linux/mm.h> #include <linux/module.h> #include <linux/hardirq.h> +#include <linux/perf_event.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h> #include <asm/hardirq.h>
@@ -142,6 +143,12 @@ good_area: }up_read (&mm->mmap_sem); +perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS ,1 , regs, address); +if (flags &VM_FAULT_MAJOR ) +perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS_MAJ ,1 , regs, address); +else if (flags &VM_FAULT_MINOR ) +perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS_MIN ,1 , regs, address); +return ;/* Something tried to access memory that isn't in our memory map..
Signature · 1 line
1.8.1.4
Max Filippov
maintainerPATCH 7/8 xtensa: implement counting and sampling perf events
In reply to Max FilippovXtensa Performance Monitor Module has up to 8 32 bit wide performance counters. Each counter may be enabled independently and can count any single type of hardware performance events. Event counting may be enabled and disabled globally (per PMM).
Each counter has status register with bits indicating if the counter has been overflown and may be programmed to raise profiling IRQ on overflow. This IRQ is used to rewind counters and allow for counting more than 2^32 samples for counting events and to report samples for sampling events.
For more details see Tensilica Debug User's Guide, chapter 8 "Performance monitor module".
--- arch/xtensa/Kconfig | 10 + arch/xtensa/kernel/Makefile | 1 + arch/xtensa/kernel/perf_event.c | 450 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 461 insertions(+) create mode 100644 arch/xtensa/kernel/perf_event.c
arch/xtensa/Kconfig +10 -0
@@ -126,6 +126,16 @@ config XTENSA_VARIANT_MMU Build a Conventional Kernel with full MMU support, ie: it supports a TLB with auto-loading, page protection. +config XTENSA_VARIANT_HAVE_PERF_EVENTS + bool "Core variant has Performance Monitor Module" + depends on XTENSA_VARIANT_CUSTOM + default n + help + Enable if core variant has Performance Monitor Module with + External Registers Interface. + + If unsure, say N. + config XTENSA_UNALIGNED_USER bool "Unaligned memory access in use space" help
arch/xtensa/kernel/Makefile +1 -0
@@ -13,6 +13,7 @@ obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o obj-$(CONFIG_FUNCTION_TRACER) += mcount.o obj-$(CONFIG_SMP) += smp.o mxhead.o +obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o AFLAGS_head.o += -mtext-section-literals
arch/xtensa/kernel/perf_event.c new file +450 -0
450 lines not on this page · raw message
Signature · 1 line
1.8.1.4
Peter Zijlstra
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
Quoted 21 lines · Max Filippov
arch/xtensa/kernel/perf_event.c new file +21
-0+static int xtensa_pmu_event_init (struct perf_event *event) +{ +int ret; + +switch (event->attr.type) { +case PERF_TYPE_HARDWARE : +if (event->attr.config >=ARRAY_SIZE (xtensa_hw_ctl) || + xtensa_hw_ctl[event->attr.config] ==0 ) +return -ENOENT ; + event->hw.config = xtensa_hw_ctl[event->attr.config]; +return 0 ; + +case PERF_TYPE_HW_CACHE : + ret =xtensa_pmu_cache_event (event->attr.config); +if (ret <0 ) +return ret; + event->hw.config = ret; +return 0 ; + +case PERF_TYPE_RAW : +/* Not 'previous counter' select */
arch/xtensa/kernel/perf_event.c line 231
Quoted 10 lines
arch/xtensa/kernel/perf_event.c new file +10
-0+if ((event->attr.config &XTENSA_PMU_PMCTRL_SELECT ) == + (1 <<XTENSA_PMU_PMCTRL_SELECT_SHIFT )) +return -ENOENT ; + event->hw.config = (event->attr.config & + (XTENSA_PMU_PMCTRL_KRNLCNT | +XTENSA_PMU_PMCTRL_TRACELEVEL | +XTENSA_PMU_PMCTRL_SELECT | +XTENSA_PMU_PMCTRL_MASK )) | +XTENSA_PMU_PMCTRL_INTEN ; +return 0 ;
Since this PMU implements TYPE_HARDWARE/TYPE_HW_CACHE/TYPE_RAW, returning -ENOENT for those is wrong.
If the configuration is invalid, return -EINVAL.
Quoted 5 lines
arch/xtensa/kernel/perf_event.c new file +5
-0+ +default : +return -ENOENT ; + } +}
Max Filippov
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
Quoted 4 lines · Peter Zijlstra
Since this PMU implements TYPE_HARDWARE/TYPE_HW_CACHE/TYPE_RAW, returning
-ENOENTfor those is wrong.If the configuration is invalid, return
-EINVAL.
Ok.
Signature · 2 lines
Thanks. -- Max
Peter Zijlstra
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
In reply to Max Filippovarch/xtensa/kernel/perf_event.c line 436
Quoted 4 lines · Max Filippov
arch/xtensa/kernel/perf_event.c new file +4
-0+static int __init xtensa_pmu_init (void ) +{ +int ret; +int irq =irq_create_mapping (NULL ,XCHAL_PROFILING_INTERRUPT );
Does this platform have interrupt priorities which you can partially mask in order to create NMI like behaviour?
Max Filippov
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
Quoted 8 lines · Peter Zijlstra
arch/xtensa/kernel/perf_event.c line 436
Quoted 4 lines · Max Filippov
arch/xtensa/kernel/perf_event.c new file +4
-0+static int __init xtensa_pmu_init (void ) +{ +int ret; +int irq =irq_create_mapping (NULL ,XCHAL_PROFILING_INTERRUPT );Does this platform have interrupt priorities which you can partially mask in order to create NMI like behaviour?
Not sure what you mean by "NMI like".
Interrupt priorities are fixed in the current xtensa architecture, and we can in theory
mask certain level and below, but practically we always mask all low- and medium-
level interrupts.
Also we currently can't have handlers for high priority interrupts written in C.
Signature · 2 lines
Thanks. -- Max
Peter Zijlstra
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
Quoted 11 lines · Max Filippov
Quoted 8 lines · Peter Zijlstra
arch/xtensa/kernel/perf_event.c line 436
Quoted 4 lines · Max Filippov
arch/xtensa/kernel/perf_event.c new file +4
-0+static int __init xtensa_pmu_init (void ) +{ +int ret; +int irq =irq_create_mapping (NULL ,XCHAL_PROFILING_INTERRUPT );Does this platform have interrupt priorities which you can partially mask in order to create NMI like behaviour?
Not sure what you mean by "NMI like".
There's a number of archs where we implement NMIs by having local_irq_disable() only disable part of the interrupt priority range and making sure all 'normal' IRQs are mapped in that priority range.
We then map our NMI handlers to a priority above the 'normal' range, such that these interrupts can indeed happen when interrupts are 'disabled.
See for example:
b4f4372f96e0 ("sparc64: Make %pil level 15 a pseudo-NMI.") 0c25e9e6cbe7 ("sparc64: Adjust __raw_local_irq_save() to cooperate in NMIs.") c011f80ba091 ("sparc64: Add some more commentary to __raw_local_irq_save()")
Quoted 5 lines
Interrupt priorities are fixed in the current xtensa architecture, and we can in theory mask certain level and below, but practically we always mask all low- and medium- level interrupts.
Also we currently can't have handlers for high priority interrupts written in C.
Why not? Surely this can be cured with an assembly stub?
The advantage of having NMIs is that profiling information for the kernel becomes much more useful. Without this local_irq_enable() will be a very 'hot' function.
Max Filippov
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
Quoted 21 lines · Peter Zijlstra
Quoted 11 lines · Max Filippov
Quoted 8 lines · Peter Zijlstra
arch/xtensa/kernel/perf_event.c line 436
Quoted 4 lines · Max Filippov
arch/xtensa/kernel/perf_event.c new file +4
-0+static int __init xtensa_pmu_init (void ) +{ +int ret; +int irq =irq_create_mapping (NULL ,XCHAL_PROFILING_INTERRUPT );Does this platform have interrupt priorities which you can partially mask in order to create NMI like behaviour?
Not sure what you mean by "NMI like".
There's a number of archs where we implement NMIs by having
local_irq_disable()only disable part of the interrupt priority range and making sure all 'normal' IRQs are mapped in that priority range.We then map our NMI handlers to a priority above the 'normal' range, such that these interrupts can indeed happen when interrupts are 'disabled.
Quoted 5 lines
See for example:
b4f4372f96e0("sparc64: Make %pil level 15 a pseudo-NMI.")0c25e9e6cbe7("sparc64: Adjust__raw_local_irq_save()to cooperate in NMIs.")c011f80ba091("sparc64: Add some more commentary to__raw_local_irq_save()")
Ok, I see. I guess I can change IRQ disabling logic to not mask perf IRQ in case it's configured as the only interrupt on its level and it's the highest medium-level IRQ.
Quoted 7 lines
Quoted 5 lines
Interrupt priorities are fixed in the current xtensa architecture, and we can in theory mask certain level and below, but practically we always mask all low- and medium- level interrupts.
Also we currently can't have handlers for high priority interrupts written in C.
Why not? Surely this can be cured with an assembly stub?
IIUC that was a deliberate architecture design choice and working around it penalizes all interrupt handlers. But let me take another close look.
Quoted 3 lines
The advantage of having NMIs is that profiling information for the kernel becomes much more useful. Without this
local_irq_enable()will be a very 'hot' function.
I haven't noticed that in my testing.
Signature · 2 lines
Thanks. -- Max
Chris Zankel
maintainerRe: [PATCH 7/8] xtensa: implement counting and sampling perf events
Hi Max,
We could probably still use NMI with a separate stack. However, for exception handling while in NMI, we might have to implement something similar to x86_64 (https://lwn.net/Articles/484932/).
Cheers!
-Chris
Quoted 52 lines · Max Filippov
Quoted 21 lines · Peter Zijlstra
Quoted 11 lines · Max Filippov
Quoted 8 lines · Peter Zijlstra
arch/xtensa/kernel/perf_event.c line 436
Quoted 4 lines · Max Filippov
arch/xtensa/kernel/perf_event.c new file +4
-0+static int __init xtensa_pmu_init (void ) +{ +int ret; +int irq =irq_create_mapping (NULL ,XCHAL_PROFILING_INTERRUPT );Does this platform have interrupt priorities which you can partially mask in order to create NMI like behaviour?
Not sure what you mean by "NMI like".
There's a number of archs where we implement NMIs by having
local_irq_disable()only disable part of the interrupt priority range and making sure all 'normal' IRQs are mapped in that priority range.We then map our NMI handlers to a priority above the 'normal' range, such that these interrupts can indeed happen when interrupts are 'disabled.
Quoted 5 lines
See for example:
b4f4372f96e0("sparc64: Make %pil level 15 a pseudo-NMI.")0c25e9e6cbe7("sparc64: Adjust__raw_local_irq_save()to cooperate in NMIs.")c011f80ba091("sparc64: Add some more commentary to__raw_local_irq_save()")Ok, I see. I guess I can change IRQ disabling logic to not mask perf IRQ in case it's configured as the only interrupt on its level and it's the highest medium-level IRQ.
Quoted 7 lines
Quoted 5 lines
Interrupt priorities are fixed in the current xtensa architecture, and we can in theory mask certain level and below, but practically we always mask all low- and medium- level interrupts.
Also we currently can't have handlers for high priority interrupts written in C.
Why not? Surely this can be cured with an assembly stub?
IIUC that was a deliberate architecture design choice and working around it penalizes all interrupt handlers. But let me take another close look.
Quoted 3 lines
The advantage of having NMIs is that profiling information for the kernel becomes much more useful. Without this
local_irq_enable()will be a very 'hot' function.I haven't noticed that in my testing.
--
Thanks.
-- Max
Max Filippov
maintainerPATCH 8/8 perf tools: xtensa: add DWARF register names
In reply to Max Filippov--- tools/perf/arch/xtensa/Build | 1 + tools/perf/arch/xtensa/Makefile | 3 +++ tools/perf/arch/xtensa/util/Build | 1 + tools/perf/arch/xtensa/util/dwarf-regs.c | 25 +++++++++++++++++++++++++ 4 files changed, 30 insertions(+) create mode 100644 tools/perf/arch/xtensa/Build create mode 100644 tools/perf/arch/xtensa/Makefile create mode 100644 tools/perf/arch/xtensa/util/Build create mode 100644 tools/perf/arch/xtensa/util/dwarf-regs.c
tools/perf/arch/xtensa/Build new file +1 -0
@@ -0,0 +1 @@ +libperf-y += util/
tools/perf/arch/xtensa/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +ifndef NO_DWARF +PERF_HAVE_DWARF_REGS := 1 +endif
tools/perf/arch/xtensa/util/Build new file +1 -0
@@ -0,0 +1 @@ +libperf-$(CONFIG_DWARF) += dwarf-regs.o
tools/perf/arch/xtensa/util/dwarf-regs.c new file +25 -0
@@ -0,0 +1,25 @@ +/* +* Mapping of DWARF debug register numbers into register names. +* +* Copyright (c) 2015 Cadence Design Systems Inc. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version +* 2 of the License, or (at your option) any later version. +*/ + +#include <stddef.h> +#include <dwarf-regs.h> + +#define XTENSA_MAX_REGS 16 + +const char *xtensa_regs_table[XTENSA_MAX_REGS ] = { +"a0" ,"a1" ,"a2" ,"a3" ,"a4" ,"a5" ,"a6" ,"a7" , +"a8" ,"a9" ,"a10" ,"a11" ,"a12" ,"a13" ,"a14" ,"a15" , +}; + +const char *get_arch_regstr (unsigned int n) +{ +return n <XTENSA_MAX_REGS ? xtensa_regs_table[n] :NULL ; +}
Signature · 1 line
1.8.1.4