diff options
author | David S. Miller <davem@davemloft.net> | 2008-11-21 05:06:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-04 12:17:00 -0500 |
commit | 2c2551ab99f9ba3c726e6a41c84ef0c7390fc546 (patch) | |
tree | 21f7fb7366c27feae8e03f30951da27ef7f9d249 | |
parent | 0871420fad5844cb63cfcf85508c17bd9b15c08f (diff) |
sparc64: Add interface for registering a performance counter IRQ handler.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/include/asm/irq_64.h | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/irq.c | 63 | ||||
-rw-r--r-- | arch/sparc64/kernel/ttable.S | 2 |
3 files changed, 67 insertions, 1 deletions
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index 71673eca3660..d47d4a1955a9 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h | |||
@@ -66,6 +66,9 @@ extern void virt_irq_free(unsigned int virt_irq); | |||
66 | extern void __init init_IRQ(void); | 66 | extern void __init init_IRQ(void); |
67 | extern void fixup_irqs(void); | 67 | extern void fixup_irqs(void); |
68 | 68 | ||
69 | extern int register_perfctr_intr(void (*handler)(struct pt_regs *)); | ||
70 | extern void release_perfctr_intr(void (*handler)(struct pt_regs *)); | ||
71 | |||
69 | static inline void set_softint(unsigned long bits) | 72 | static inline void set_softint(unsigned long bits) |
70 | { | 73 | { |
71 | __asm__ __volatile__("wr %0, 0x0, %%set_softint" | 74 | __asm__ __volatile__("wr %0, 0x0, %%set_softint" |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 52fc836f464d..a3ea2bcb95de 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -775,6 +775,69 @@ void do_softirq(void) | |||
775 | local_irq_restore(flags); | 775 | local_irq_restore(flags); |
776 | } | 776 | } |
777 | 777 | ||
778 | static void unhandled_perf_irq(struct pt_regs *regs) | ||
779 | { | ||
780 | unsigned long pcr, pic; | ||
781 | |||
782 | read_pcr(pcr); | ||
783 | read_pic(pic); | ||
784 | |||
785 | write_pcr(0); | ||
786 | |||
787 | printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n", | ||
788 | smp_processor_id()); | ||
789 | printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n", | ||
790 | smp_processor_id(), pcr, pic); | ||
791 | } | ||
792 | |||
793 | /* Almost a direct copy of the powerpc PMC code. */ | ||
794 | static DEFINE_SPINLOCK(perf_irq_lock); | ||
795 | static void *perf_irq_owner_caller; /* mostly for debugging */ | ||
796 | static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq; | ||
797 | |||
798 | /* Invoked from level 15 PIL handler in trap table. */ | ||
799 | void perfctr_irq(int irq, struct pt_regs *regs) | ||
800 | { | ||
801 | clear_softint(1 << irq); | ||
802 | perf_irq(regs); | ||
803 | } | ||
804 | |||
805 | int register_perfctr_intr(void (*handler)(struct pt_regs *)) | ||
806 | { | ||
807 | int ret; | ||
808 | |||
809 | if (!handler) | ||
810 | return -EINVAL; | ||
811 | |||
812 | spin_lock(&perf_irq_lock); | ||
813 | if (perf_irq != unhandled_perf_irq) { | ||
814 | printk(KERN_WARNING "register_perfctr_intr: " | ||
815 | "perf IRQ busy (reserved by caller %p)\n", | ||
816 | perf_irq_owner_caller); | ||
817 | ret = -EBUSY; | ||
818 | goto out; | ||
819 | } | ||
820 | |||
821 | perf_irq_owner_caller = __builtin_return_address(0); | ||
822 | perf_irq = handler; | ||
823 | |||
824 | ret = 0; | ||
825 | out: | ||
826 | spin_unlock(&perf_irq_lock); | ||
827 | |||
828 | return ret; | ||
829 | } | ||
830 | EXPORT_SYMBOL_GPL(register_perfctr_intr); | ||
831 | |||
832 | void release_perfctr_intr(void (*handler)(struct pt_regs *)) | ||
833 | { | ||
834 | spin_lock(&perf_irq_lock); | ||
835 | perf_irq_owner_caller = NULL; | ||
836 | perf_irq = unhandled_perf_irq; | ||
837 | spin_unlock(&perf_irq_lock); | ||
838 | } | ||
839 | EXPORT_SYMBOL_GPL(release_perfctr_intr); | ||
840 | |||
778 | #ifdef CONFIG_HOTPLUG_CPU | 841 | #ifdef CONFIG_HOTPLUG_CPU |
779 | void fixup_irqs(void) | 842 | void fixup_irqs(void) |
780 | { | 843 | { |
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 1ade3d6fb7fc..2a31ffa4c28d 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S | |||
@@ -66,7 +66,7 @@ tl0_irq6: BTRAP(0x46) | |||
66 | tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) | 66 | tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) |
67 | tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) | 67 | tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) |
68 | tl0_irq14: TRAP_IRQ(timer_interrupt, 14) | 68 | tl0_irq14: TRAP_IRQ(timer_interrupt, 14) |
69 | tl0_irq15: TRAP_IRQ(handler_irq, 15) | 69 | tl0_irq15: TRAP_IRQ(perfctr_irq, 15) |
70 | tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) | 70 | tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) |
71 | tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) | 71 | tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) |
72 | tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f) | 72 | tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f) |