···5252obj-$(CONFIG_SPARC64) += hvapi.o5353obj-$(CONFIG_SPARC64) += sstate.o5454obj-$(CONFIG_SPARC64) += mdesc.o5555+obj-$(CONFIG_SPARC64) += pcr.o55565657# sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation5758obj-$(CONFIG_SPARC32) += devres.o
+140
arch/sparc/kernel/pcr.c
···11+/* pcr.c: Generic sparc64 performance counter infrastructure.22+ *33+ * Copyright (C) 2009 David S. Miller (davem@davemloft.net)44+ */55+#include <linux/kernel.h>66+#include <linux/module.h>77+#include <linux/init.h>88+#include <linux/irq.h>99+1010+#include <asm/pil.h>1111+#include <asm/pcr.h>1212+1313+/* This code is shared between various users of the performance1414+ * counters. Users will be oprofile, pseudo-NMI watchdog, and the1515+ * perf_counter support layer.1616+ */1717+1818+/* Performance counter interrupts run unmasked at PIL level 15.1919+ * Therefore we can't do things like wakeups and other work2020+ * that expects IRQ disabling to be adhered to in locking etc.2121+ *2222+ * Therefore in such situations we defer the work by signalling2323+ * a lower level cpu IRQ.2424+ */2525+void deferred_pcr_work_irq(int irq, struct pt_regs *regs)2626+{2727+ clear_softint(1 << PIL_DEFERRED_PCR_WORK);2828+}2929+3030+void schedule_deferred_pcr_work(void)3131+{3232+ set_softint(1 << PIL_DEFERRED_PCR_WORK);3333+}3434+3535+const struct pcr_ops *pcr_ops;3636+EXPORT_SYMBOL_GPL(pcr_ops);3737+3838+static u64 direct_pcr_read(void)3939+{4040+ u64 val;4141+4242+ read_pcr(val);4343+ return val;4444+}4545+4646+static void direct_pcr_write(u64 val)4747+{4848+ write_pcr(val);4949+}5050+5151+static const struct pcr_ops direct_pcr_ops = {5252+ .read = direct_pcr_read,5353+ .write = direct_pcr_write,5454+};5555+5656+static void n2_pcr_write(u64 val)5757+{5858+ unsigned long ret;5959+6060+ ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);6161+ if (val != HV_EOK)6262+ write_pcr(val);6363+}6464+6565+static const struct pcr_ops n2_pcr_ops = {6666+ .read = direct_pcr_read,6767+ .write = n2_pcr_write,6868+};6969+7070+static unsigned long perf_hsvc_group;7171+static unsigned long perf_hsvc_major;7272+static unsigned long perf_hsvc_minor;7373+7474+static int __init register_perf_hsvc(void)7575+{7676+ if (tlb_type == hypervisor) {7777+ switch (sun4v_chip_type) {7878+ case SUN4V_CHIP_NIAGARA1:7979+ perf_hsvc_group = HV_GRP_NIAG_PERF;8080+ break;8181+8282+ case SUN4V_CHIP_NIAGARA2:8383+ perf_hsvc_group = HV_GRP_N2_CPU;8484+ break;8585+8686+ default:8787+ return -ENODEV;8888+ }8989+9090+9191+ perf_hsvc_major = 1;9292+ perf_hsvc_minor = 0;9393+ if (sun4v_hvapi_register(perf_hsvc_group,9494+ perf_hsvc_major,9595+ &perf_hsvc_minor)) {9696+ printk("perfmon: Could not register hvapi.\n");9797+ return -ENODEV;9898+ }9999+ }100100+ return 0;101101+}102102+103103+static void __init unregister_perf_hsvc(void)104104+{105105+ if (tlb_type != hypervisor)106106+ return;107107+ sun4v_hvapi_unregister(perf_hsvc_group);108108+}109109+110110+int __init pcr_arch_init(void)111111+{112112+ int err = register_perf_hsvc();113113+114114+ if (err)115115+ return err;116116+117117+ switch (tlb_type) {118118+ case hypervisor:119119+ pcr_ops = &n2_pcr_ops;120120+ break;121121+122122+ case spitfire:123123+ case cheetah:124124+ case cheetah_plus:125125+ pcr_ops = &direct_pcr_ops;126126+ break;127127+128128+ default:129129+ err = -ENODEV;130130+ goto out_unregister;131131+ }132132+133133+ return 0;134134+135135+out_unregister:136136+ unregister_perf_hsvc();137137+ return err;138138+}139139+140140+arch_initcall(pcr_arch_init);