Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sparc64: Move generic PCR support code to seperate file.

It all lives in the oprofile support code currently and we will need
to share this stuff with NMI watchdog and perf_counter support.

Signed-off-by: David S. Miller <davem@davemloft.net>

+177 -108
+30
arch/sparc/include/asm/pcr.h
··· 1 + #ifndef __PCR_H 2 + #define __PCR_H 3 + 4 + struct pcr_ops { 5 + u64 (*read)(void); 6 + void (*write)(u64); 7 + }; 8 + extern const struct pcr_ops *pcr_ops; 9 + 10 + extern void deferred_pcr_work_irq(int irq, struct pt_regs *regs); 11 + extern void schedule_deferred_pcr_work(void); 12 + 13 + #define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ 14 + #define PCR_STRACE 0x00000002 /* Trace supervisor events */ 15 + #define PCR_UTRACE 0x00000004 /* Trace user events */ 16 + #define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ 17 + #define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ 18 + #define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ 19 + #define PCR_N2_MASK0 0x00003fc0 20 + #define PCR_N2_MASK0_SHIFT 6 21 + #define PCR_N2_SL0 0x0003c000 22 + #define PCR_N2_SL0_SHIFT 14 23 + #define PCR_N2_OV0 0x00040000 24 + #define PCR_N2_MASK1 0x07f80000 25 + #define PCR_N2_MASK1_SHIFT 19 26 + #define PCR_N2_SL1 0x78000000 27 + #define PCR_N2_SL1_SHIFT 27 28 + #define PCR_N2_OV1 0x80000000 29 + 30 + #endif /* __PCR_H */
+1
arch/sparc/include/asm/pil.h
··· 23 23 #define PIL_SMP_CTX_NEW_VERSION 4 24 24 #define PIL_DEVICE_IRQ 5 25 25 #define PIL_SMP_CALL_FUNC_SNGL 6 26 + #define PIL_DEFERRED_PCR_WORK 7 26 27 #define PIL_NORMAL_MAX 14 27 28 #define PIL_NMI 15 28 29
+1
arch/sparc/kernel/Makefile
··· 52 52 obj-$(CONFIG_SPARC64) += hvapi.o 53 53 obj-$(CONFIG_SPARC64) += sstate.o 54 54 obj-$(CONFIG_SPARC64) += mdesc.o 55 + obj-$(CONFIG_SPARC64) += pcr.o 55 56 56 57 # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation 57 58 obj-$(CONFIG_SPARC32) += devres.o
+140
arch/sparc/kernel/pcr.c
··· 1 + /* pcr.c: Generic sparc64 performance counter infrastructure. 2 + * 3 + * Copyright (C) 2009 David S. Miller (davem@davemloft.net) 4 + */ 5 + #include <linux/kernel.h> 6 + #include <linux/module.h> 7 + #include <linux/init.h> 8 + #include <linux/irq.h> 9 + 10 + #include <asm/pil.h> 11 + #include <asm/pcr.h> 12 + 13 + /* This code is shared between various users of the performance 14 + * counters. Users will be oprofile, pseudo-NMI watchdog, and the 15 + * perf_counter support layer. 16 + */ 17 + 18 + /* Performance counter interrupts run unmasked at PIL level 15. 19 + * Therefore we can't do things like wakeups and other work 20 + * that expects IRQ disabling to be adhered to in locking etc. 21 + * 22 + * Therefore in such situations we defer the work by signalling 23 + * a lower level cpu IRQ. 24 + */ 25 + void deferred_pcr_work_irq(int irq, struct pt_regs *regs) 26 + { 27 + clear_softint(1 << PIL_DEFERRED_PCR_WORK); 28 + } 29 + 30 + void schedule_deferred_pcr_work(void) 31 + { 32 + set_softint(1 << PIL_DEFERRED_PCR_WORK); 33 + } 34 + 35 + const struct pcr_ops *pcr_ops; 36 + EXPORT_SYMBOL_GPL(pcr_ops); 37 + 38 + static u64 direct_pcr_read(void) 39 + { 40 + u64 val; 41 + 42 + read_pcr(val); 43 + return val; 44 + } 45 + 46 + static void direct_pcr_write(u64 val) 47 + { 48 + write_pcr(val); 49 + } 50 + 51 + static const struct pcr_ops direct_pcr_ops = { 52 + .read = direct_pcr_read, 53 + .write = direct_pcr_write, 54 + }; 55 + 56 + static void n2_pcr_write(u64 val) 57 + { 58 + unsigned long ret; 59 + 60 + ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); 61 + if (val != HV_EOK) 62 + write_pcr(val); 63 + } 64 + 65 + static const struct pcr_ops n2_pcr_ops = { 66 + .read = direct_pcr_read, 67 + .write = n2_pcr_write, 68 + }; 69 + 70 + static unsigned long perf_hsvc_group; 71 + static unsigned long perf_hsvc_major; 72 + static unsigned long perf_hsvc_minor; 73 + 74 + static int __init register_perf_hsvc(void) 75 + { 76 + if (tlb_type == hypervisor) { 77 + switch (sun4v_chip_type) { 78 + case SUN4V_CHIP_NIAGARA1: 79 + perf_hsvc_group = HV_GRP_NIAG_PERF; 80 + break; 81 + 82 + case SUN4V_CHIP_NIAGARA2: 83 + perf_hsvc_group = HV_GRP_N2_CPU; 84 + break; 85 + 86 + default: 87 + return -ENODEV; 88 + } 89 + 90 + 91 + perf_hsvc_major = 1; 92 + perf_hsvc_minor = 0; 93 + if (sun4v_hvapi_register(perf_hsvc_group, 94 + perf_hsvc_major, 95 + &perf_hsvc_minor)) { 96 + printk("perfmon: Could not register hvapi.\n"); 97 + return -ENODEV; 98 + } 99 + } 100 + return 0; 101 + } 102 + 103 + static void __init unregister_perf_hsvc(void) 104 + { 105 + if (tlb_type != hypervisor) 106 + return; 107 + sun4v_hvapi_unregister(perf_hsvc_group); 108 + } 109 + 110 + int __init pcr_arch_init(void) 111 + { 112 + int err = register_perf_hsvc(); 113 + 114 + if (err) 115 + return err; 116 + 117 + switch (tlb_type) { 118 + case hypervisor: 119 + pcr_ops = &n2_pcr_ops; 120 + break; 121 + 122 + case spitfire: 123 + case cheetah: 124 + case cheetah_plus: 125 + pcr_ops = &direct_pcr_ops; 126 + break; 127 + 128 + default: 129 + err = -ENODEV; 130 + goto out_unregister; 131 + } 132 + 133 + return 0; 134 + 135 + out_unregister: 136 + unregister_perf_hsvc(); 137 + return err; 138 + } 139 + 140 + arch_initcall(pcr_arch_init);
+2 -1
arch/sparc/kernel/ttable.S
··· 63 63 #else 64 64 tl0_irq6: BTRAP(0x46) 65 65 #endif 66 - tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) 66 + tl0_irq7: TRAP_IRQ(deferred_pcr_work_irq, 7) 67 + tl0_irq8: BTRAP(0x48) BTRAP(0x49) 67 68 tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) 68 69 tl0_irq14: TRAP_IRQ(timer_interrupt, 14) 69 70 tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15)
+3 -107
arch/sparc/oprofile/init.c
··· 17 17 #include <asm/spitfire.h> 18 18 #include <asm/cpudata.h> 19 19 #include <asm/irq.h> 20 + #include <asm/pcr.h> 20 21 21 22 static int nmi_enabled; 22 - 23 - struct pcr_ops { 24 - u64 (*read)(void); 25 - void (*write)(u64); 26 - }; 27 - static const struct pcr_ops *pcr_ops; 28 - 29 - static u64 direct_pcr_read(void) 30 - { 31 - u64 val; 32 - 33 - read_pcr(val); 34 - return val; 35 - } 36 - 37 - static void direct_pcr_write(u64 val) 38 - { 39 - write_pcr(val); 40 - } 41 - 42 - static const struct pcr_ops direct_pcr_ops = { 43 - .read = direct_pcr_read, 44 - .write = direct_pcr_write, 45 - }; 46 - 47 - static void n2_pcr_write(u64 val) 48 - { 49 - unsigned long ret; 50 - 51 - ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); 52 - if (val != HV_EOK) 53 - write_pcr(val); 54 - } 55 - 56 - static const struct pcr_ops n2_pcr_ops = { 57 - .read = direct_pcr_read, 58 - .write = n2_pcr_write, 59 - }; 60 23 61 24 /* In order to commonize as much of the implementation as 62 25 * possible, we use PICH as our counter. Mostly this is ··· 33 70 return ((u64)((0 - delta) & 0xffffffff)) << 32; 34 71 } 35 72 36 - #define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ 37 - #define PCR_STRACE 0x00000002 /* Trace supervisor events */ 38 - #define PCR_UTRACE 0x00000004 /* Trace user events */ 39 - #define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ 40 - #define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ 41 - #define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ 42 - #define PCR_N2_MASK0 0x00003fc0 43 - #define PCR_N2_MASK0_SHIFT 6 44 - #define PCR_N2_SL0 0x0003c000 45 - #define PCR_N2_SL0_SHIFT 14 46 - #define PCR_N2_OV0 0x00040000 47 - #define PCR_N2_MASK1 0x07f80000 48 - #define PCR_N2_MASK1_SHIFT 19 49 - #define PCR_N2_SL1 0x78000000 50 - #define PCR_N2_SL1_SHIFT 27 51 - #define PCR_N2_OV1 0x80000000 52 - 53 73 #define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) 54 74 #define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ 55 75 PCR_N2_TOE_OV1 | \ 56 76 (2 << PCR_N2_SL1_SHIFT) | \ 57 77 (0xff << PCR_N2_MASK1_SHIFT)) 58 78 59 - static u64 pcr_enable = PCR_SUN4U_ENABLE; 79 + static u64 pcr_enable; 60 80 61 81 static void nmi_handler(struct pt_regs *regs) 62 82 { ··· 99 153 synchronize_sched(); 100 154 } 101 155 102 - static unsigned long perf_hsvc_group; 103 - static unsigned long perf_hsvc_major; 104 - static unsigned long perf_hsvc_minor; 105 - 106 - static int __init register_perf_hsvc(void) 107 - { 108 - if (tlb_type == hypervisor) { 109 - switch (sun4v_chip_type) { 110 - case SUN4V_CHIP_NIAGARA1: 111 - perf_hsvc_group = HV_GRP_NIAG_PERF; 112 - break; 113 - 114 - case SUN4V_CHIP_NIAGARA2: 115 - perf_hsvc_group = HV_GRP_N2_CPU; 116 - break; 117 - 118 - default: 119 - return -ENODEV; 120 - } 121 - 122 - 123 - perf_hsvc_major = 1; 124 - perf_hsvc_minor = 0; 125 - if (sun4v_hvapi_register(perf_hsvc_group, 126 - perf_hsvc_major, 127 - &perf_hsvc_minor)) { 128 - printk("perfmon: Could not register N2 hvapi.\n"); 129 - return -ENODEV; 130 - } 131 - } 132 - return 0; 133 - } 134 - 135 - static void unregister_perf_hsvc(void) 136 - { 137 - if (tlb_type != hypervisor) 138 - return; 139 - sun4v_hvapi_unregister(perf_hsvc_group); 140 - } 141 - 142 156 static int oprofile_nmi_init(struct oprofile_operations *ops) 143 157 { 144 - int err = register_perf_hsvc(); 145 - 146 - if (err) 147 - return err; 148 - 149 158 switch (tlb_type) { 150 159 case hypervisor: 151 - pcr_ops = &n2_pcr_ops; 152 160 pcr_enable = PCR_N2_ENABLE; 153 161 break; 154 162 155 163 case cheetah: 156 164 case cheetah_plus: 157 - pcr_ops = &direct_pcr_ops; 165 + pcr_enable = PCR_SUN4U_ENABLE; 158 166 break; 159 167 160 168 default: ··· 141 241 return ret; 142 242 } 143 243 144 - 145 244 void oprofile_arch_exit(void) 146 245 { 147 - #ifdef CONFIG_SPARC64 148 - unregister_perf_hsvc(); 149 - #endif 150 246 }