aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-11-21 05:06:07 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-04 12:17:00 -0500
commit2c2551ab99f9ba3c726e6a41c84ef0c7390fc546 (patch)
tree21f7fb7366c27feae8e03f30951da27ef7f9d249
parent0871420fad5844cb63cfcf85508c17bd9b15c08f (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.h3
-rw-r--r--arch/sparc64/kernel/irq.c63
-rw-r--r--arch/sparc64/kernel/ttable.S2
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);
66extern void __init init_IRQ(void); 66extern void __init init_IRQ(void);
67extern void fixup_irqs(void); 67extern void fixup_irqs(void);
68 68
69extern int register_perfctr_intr(void (*handler)(struct pt_regs *));
70extern void release_perfctr_intr(void (*handler)(struct pt_regs *));
71
69static inline void set_softint(unsigned long bits) 72static 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
778static 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. */
794static DEFINE_SPINLOCK(perf_irq_lock);
795static void *perf_irq_owner_caller; /* mostly for debugging */
796static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq;
797
798/* Invoked from level 15 PIL handler in trap table. */
799void perfctr_irq(int irq, struct pt_regs *regs)
800{
801 clear_softint(1 << irq);
802 perf_irq(regs);
803}
804
805int 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;
825out:
826 spin_unlock(&perf_irq_lock);
827
828 return ret;
829}
830EXPORT_SYMBOL_GPL(register_perfctr_intr);
831
832void 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}
839EXPORT_SYMBOL_GPL(release_perfctr_intr);
840
778#ifdef CONFIG_HOTPLUG_CPU 841#ifdef CONFIG_HOTPLUG_CPU
779void fixup_irqs(void) 842void 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)
66tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) 66tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
67tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) 67tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
68tl0_irq14: TRAP_IRQ(timer_interrupt, 14) 68tl0_irq14: TRAP_IRQ(timer_interrupt, 14)
69tl0_irq15: TRAP_IRQ(handler_irq, 15) 69tl0_irq15: TRAP_IRQ(perfctr_irq, 15)
70tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55) 70tl0_resv050: BTRAP(0x50) BTRAP(0x51) BTRAP(0x52) BTRAP(0x53) BTRAP(0x54) BTRAP(0x55)
71tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b) 71tl0_resv056: BTRAP(0x56) BTRAP(0x57) BTRAP(0x58) BTRAP(0x59) BTRAP(0x5a) BTRAP(0x5b)
72tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f) 72tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f)