xref: /openbmc/linux/arch/sparc/kernel/pcr.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23eb8057bSDavid S. Miller /* pcr.c: Generic sparc64 performance counter infrastructure.
33eb8057bSDavid S. Miller  *
43eb8057bSDavid S. Miller  * Copyright (C) 2009 David S. Miller (davem@davemloft.net)
53eb8057bSDavid S. Miller  */
63eb8057bSDavid S. Miller #include <linux/kernel.h>
7066bcacaSPaul Gortmaker #include <linux/export.h>
83eb8057bSDavid S. Miller #include <linux/init.h>
93eb8057bSDavid S. Miller #include <linux/irq.h>
103eb8057bSDavid S. Miller 
11e360adbeSPeter Zijlstra #include <linux/irq_work.h>
129960e9e8SDavid S. Miller #include <linux/ftrace.h>
135686f9c3SDavid S. Miller 
143eb8057bSDavid S. Miller #include <asm/pil.h>
153eb8057bSDavid S. Miller #include <asm/pcr.h>
16e5553a6dSDavid S. Miller #include <asm/nmi.h>
176faaeb8eSDavid S. Miller #include <asm/asi.h>
18c2068dabSPaul Gortmaker #include <asm/spitfire.h>
193eb8057bSDavid S. Miller 
203eb8057bSDavid S. Miller /* This code is shared between various users of the performance
213eb8057bSDavid S. Miller  * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
22cdd6c482SIngo Molnar  * perf_event support layer.
233eb8057bSDavid S. Miller  */
243eb8057bSDavid S. Miller 
253eb8057bSDavid S. Miller /* Performance counter interrupts run unmasked at PIL level 15.
263eb8057bSDavid S. Miller  * Therefore we can't do things like wakeups and other work
273eb8057bSDavid S. Miller  * that expects IRQ disabling to be adhered to in locking etc.
283eb8057bSDavid S. Miller  *
293eb8057bSDavid S. Miller  * Therefore in such situations we defer the work by signalling
303eb8057bSDavid S. Miller  * a lower level cpu IRQ.
313eb8057bSDavid S. Miller  */
deferred_pcr_work_irq(int irq,struct pt_regs * regs)329960e9e8SDavid S. Miller void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs)
333eb8057bSDavid S. Miller {
345686f9c3SDavid S. Miller 	struct pt_regs *old_regs;
355686f9c3SDavid S. Miller 
363eb8057bSDavid S. Miller 	clear_softint(1 << PIL_DEFERRED_PCR_WORK);
375686f9c3SDavid S. Miller 
385686f9c3SDavid S. Miller 	old_regs = set_irq_regs(regs);
395686f9c3SDavid S. Miller 	irq_enter();
40e360adbeSPeter Zijlstra #ifdef CONFIG_IRQ_WORK
41e360adbeSPeter Zijlstra 	irq_work_run();
425686f9c3SDavid S. Miller #endif
435686f9c3SDavid S. Miller 	irq_exit();
445686f9c3SDavid S. Miller 	set_irq_regs(old_regs);
453eb8057bSDavid S. Miller }
463eb8057bSDavid S. Miller 
arch_irq_work_raise(void)47e360adbeSPeter Zijlstra void arch_irq_work_raise(void)
483eb8057bSDavid S. Miller {
493eb8057bSDavid S. Miller 	set_softint(1 << PIL_DEFERRED_PCR_WORK);
503eb8057bSDavid S. Miller }
513eb8057bSDavid S. Miller 
523eb8057bSDavid S. Miller const struct pcr_ops *pcr_ops;
533eb8057bSDavid S. Miller EXPORT_SYMBOL_GPL(pcr_ops);
543eb8057bSDavid S. Miller 
direct_pcr_read(unsigned long reg_num)550bab20baSDavid S. Miller static u64 direct_pcr_read(unsigned long reg_num)
563eb8057bSDavid S. Miller {
573eb8057bSDavid S. Miller 	u64 val;
583eb8057bSDavid S. Miller 
590bab20baSDavid S. Miller 	WARN_ON_ONCE(reg_num != 0);
6009d053c7SDavid S. Miller 	__asm__ __volatile__("rd %%pcr, %0" : "=r" (val));
613eb8057bSDavid S. Miller 	return val;
623eb8057bSDavid S. Miller }
633eb8057bSDavid S. Miller 
direct_pcr_write(unsigned long reg_num,u64 val)640bab20baSDavid S. Miller static void direct_pcr_write(unsigned long reg_num, u64 val)
653eb8057bSDavid S. Miller {
660bab20baSDavid S. Miller 	WARN_ON_ONCE(reg_num != 0);
6709d053c7SDavid S. Miller 	__asm__ __volatile__("wr %0, 0x0, %%pcr" : : "r" (val));
6809d053c7SDavid S. Miller }
6909d053c7SDavid S. Miller 
direct_pic_read(unsigned long reg_num)7009d053c7SDavid S. Miller static u64 direct_pic_read(unsigned long reg_num)
7109d053c7SDavid S. Miller {
7209d053c7SDavid S. Miller 	u64 val;
7309d053c7SDavid S. Miller 
7409d053c7SDavid S. Miller 	WARN_ON_ONCE(reg_num != 0);
7509d053c7SDavid S. Miller 	__asm__ __volatile__("rd %%pic, %0" : "=r" (val));
7609d053c7SDavid S. Miller 	return val;
7709d053c7SDavid S. Miller }
7809d053c7SDavid S. Miller 
direct_pic_write(unsigned long reg_num,u64 val)7909d053c7SDavid S. Miller static void direct_pic_write(unsigned long reg_num, u64 val)
8009d053c7SDavid S. Miller {
8109d053c7SDavid S. Miller 	WARN_ON_ONCE(reg_num != 0);
8209d053c7SDavid S. Miller 
8309d053c7SDavid S. Miller 	/* Blackbird errata workaround.  See commentary in
8409d053c7SDavid S. Miller 	 * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
8509d053c7SDavid S. Miller 	 * for more information.
8609d053c7SDavid S. Miller 	 */
8709d053c7SDavid S. Miller 	__asm__ __volatile__("ba,pt	%%xcc, 99f\n\t"
8809d053c7SDavid S. Miller 			     " nop\n\t"
8909d053c7SDavid S. Miller 			     ".align	64\n"
9009d053c7SDavid S. Miller 			  "99:wr	%0, 0x0, %%pic\n\t"
9109d053c7SDavid S. Miller 			     "rd	%%pic, %%g0" : : "r" (val));
923eb8057bSDavid S. Miller }
933eb8057bSDavid S. Miller 
direct_picl_value(unsigned int nmi_hz)9473a6b053SDavid S. Miller static u64 direct_picl_value(unsigned int nmi_hz)
9573a6b053SDavid S. Miller {
9673a6b053SDavid S. Miller 	u32 delta = local_cpu_data().clock_tick / nmi_hz;
9773a6b053SDavid S. Miller 
9873a6b053SDavid S. Miller 	return ((u64)((0 - delta) & 0xffffffff)) << 32;
9973a6b053SDavid S. Miller }
10073a6b053SDavid S. Miller 
1013eb8057bSDavid S. Miller static const struct pcr_ops direct_pcr_ops = {
10209d053c7SDavid S. Miller 	.read_pcr		= direct_pcr_read,
10309d053c7SDavid S. Miller 	.write_pcr		= direct_pcr_write,
10409d053c7SDavid S. Miller 	.read_pic		= direct_pic_read,
10509d053c7SDavid S. Miller 	.write_pic		= direct_pic_write,
10673a6b053SDavid S. Miller 	.nmi_picl_value		= direct_picl_value,
107ce4a925cSDavid S. Miller 	.pcr_nmi_enable		= (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE),
108ce4a925cSDavid S. Miller 	.pcr_nmi_disable	= PCR_PIC_PRIV,
1093eb8057bSDavid S. Miller };
1103eb8057bSDavid S. Miller 
n2_pcr_write(unsigned long reg_num,u64 val)1110bab20baSDavid S. Miller static void n2_pcr_write(unsigned long reg_num, u64 val)
1123eb8057bSDavid S. Miller {
1133eb8057bSDavid S. Miller 	unsigned long ret;
1143eb8057bSDavid S. Miller 
1150bab20baSDavid S. Miller 	WARN_ON_ONCE(reg_num != 0);
116314ff527SDavid S. Miller 	if (val & PCR_N2_HTRACE) {
1173eb8057bSDavid S. Miller 		ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
118c6fee081SDavid S. Miller 		if (ret != HV_EOK)
11909d053c7SDavid S. Miller 			direct_pcr_write(reg_num, val);
120314ff527SDavid S. Miller 	} else
12109d053c7SDavid S. Miller 		direct_pcr_write(reg_num, val);
1223eb8057bSDavid S. Miller }
1233eb8057bSDavid S. Miller 
n2_picl_value(unsigned int nmi_hz)12473a6b053SDavid S. Miller static u64 n2_picl_value(unsigned int nmi_hz)
12573a6b053SDavid S. Miller {
12673a6b053SDavid S. Miller 	u32 delta = local_cpu_data().clock_tick / (nmi_hz << 2);
12773a6b053SDavid S. Miller 
12873a6b053SDavid S. Miller 	return ((u64)((0 - delta) & 0xffffffff)) << 32;
12973a6b053SDavid S. Miller }
13073a6b053SDavid S. Miller 
1313eb8057bSDavid S. Miller static const struct pcr_ops n2_pcr_ops = {
13209d053c7SDavid S. Miller 	.read_pcr		= direct_pcr_read,
13309d053c7SDavid S. Miller 	.write_pcr		= n2_pcr_write,
13409d053c7SDavid S. Miller 	.read_pic		= direct_pic_read,
13509d053c7SDavid S. Miller 	.write_pic		= direct_pic_write,
13673a6b053SDavid S. Miller 	.nmi_picl_value		= n2_picl_value,
137ce4a925cSDavid S. Miller 	.pcr_nmi_enable		= (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE |
138ce4a925cSDavid S. Miller 				   PCR_N2_TOE_OV1 |
139ce4a925cSDavid S. Miller 				   (2 << PCR_N2_SL1_SHIFT) |
140ce4a925cSDavid S. Miller 				   (0xff << PCR_N2_MASK1_SHIFT)),
141ce4a925cSDavid S. Miller 	.pcr_nmi_disable	= PCR_PIC_PRIV,
1423eb8057bSDavid S. Miller };
1433eb8057bSDavid S. Miller 
n4_pcr_read(unsigned long reg_num)1446faaeb8eSDavid S. Miller static u64 n4_pcr_read(unsigned long reg_num)
1456faaeb8eSDavid S. Miller {
1466faaeb8eSDavid S. Miller 	unsigned long val;
1476faaeb8eSDavid S. Miller 
1486faaeb8eSDavid S. Miller 	(void) sun4v_vt_get_perfreg(reg_num, &val);
1496faaeb8eSDavid S. Miller 
1506faaeb8eSDavid S. Miller 	return val;
1516faaeb8eSDavid S. Miller }
1526faaeb8eSDavid S. Miller 
n4_pcr_write(unsigned long reg_num,u64 val)1536faaeb8eSDavid S. Miller static void n4_pcr_write(unsigned long reg_num, u64 val)
1546faaeb8eSDavid S. Miller {
1556faaeb8eSDavid S. Miller 	(void) sun4v_vt_set_perfreg(reg_num, val);
1566faaeb8eSDavid S. Miller }
1576faaeb8eSDavid S. Miller 
n4_pic_read(unsigned long reg_num)1586faaeb8eSDavid S. Miller static u64 n4_pic_read(unsigned long reg_num)
1596faaeb8eSDavid S. Miller {
1606faaeb8eSDavid S. Miller 	unsigned long val;
1616faaeb8eSDavid S. Miller 
1626faaeb8eSDavid S. Miller 	__asm__ __volatile__("ldxa [%1] %2, %0"
1636faaeb8eSDavid S. Miller 			     : "=r" (val)
1646faaeb8eSDavid S. Miller 			     : "r" (reg_num * 0x8UL), "i" (ASI_PIC));
1656faaeb8eSDavid S. Miller 
1666faaeb8eSDavid S. Miller 	return val;
1676faaeb8eSDavid S. Miller }
1686faaeb8eSDavid S. Miller 
n4_pic_write(unsigned long reg_num,u64 val)1696faaeb8eSDavid S. Miller static void n4_pic_write(unsigned long reg_num, u64 val)
1706faaeb8eSDavid S. Miller {
1716faaeb8eSDavid S. Miller 	__asm__ __volatile__("stxa %0, [%1] %2"
1726faaeb8eSDavid S. Miller 			     : /* no outputs */
1736faaeb8eSDavid S. Miller 			     : "r" (val), "r" (reg_num * 0x8UL), "i" (ASI_PIC));
1746faaeb8eSDavid S. Miller }
1756faaeb8eSDavid S. Miller 
n4_picl_value(unsigned int nmi_hz)1766faaeb8eSDavid S. Miller static u64 n4_picl_value(unsigned int nmi_hz)
1776faaeb8eSDavid S. Miller {
1786faaeb8eSDavid S. Miller 	u32 delta = local_cpu_data().clock_tick / (nmi_hz << 2);
1796faaeb8eSDavid S. Miller 
1806faaeb8eSDavid S. Miller 	return ((u64)((0 - delta) & 0xffffffff));
1816faaeb8eSDavid S. Miller }
1826faaeb8eSDavid S. Miller 
1836faaeb8eSDavid S. Miller static const struct pcr_ops n4_pcr_ops = {
1846faaeb8eSDavid S. Miller 	.read_pcr		= n4_pcr_read,
1856faaeb8eSDavid S. Miller 	.write_pcr		= n4_pcr_write,
1866faaeb8eSDavid S. Miller 	.read_pic		= n4_pic_read,
1876faaeb8eSDavid S. Miller 	.write_pic		= n4_pic_write,
1886faaeb8eSDavid S. Miller 	.nmi_picl_value		= n4_picl_value,
1896faaeb8eSDavid S. Miller 	.pcr_nmi_enable		= (PCR_N4_PICNPT | PCR_N4_STRACE |
1906faaeb8eSDavid S. Miller 				   PCR_N4_UTRACE | PCR_N4_TOE |
1916faaeb8eSDavid S. Miller 				   (26 << PCR_N4_SL_SHIFT)),
1926faaeb8eSDavid S. Miller 	.pcr_nmi_disable	= PCR_N4_PICNPT,
1936faaeb8eSDavid S. Miller };
1946faaeb8eSDavid S. Miller 
n5_pcr_read(unsigned long reg_num)19505aa1651Sbob picco static u64 n5_pcr_read(unsigned long reg_num)
19605aa1651Sbob picco {
19705aa1651Sbob picco 	unsigned long val;
19805aa1651Sbob picco 
19905aa1651Sbob picco 	(void) sun4v_t5_get_perfreg(reg_num, &val);
20005aa1651Sbob picco 
20105aa1651Sbob picco 	return val;
20205aa1651Sbob picco }
20305aa1651Sbob picco 
n5_pcr_write(unsigned long reg_num,u64 val)20405aa1651Sbob picco static void n5_pcr_write(unsigned long reg_num, u64 val)
20505aa1651Sbob picco {
20605aa1651Sbob picco 	(void) sun4v_t5_set_perfreg(reg_num, val);
20705aa1651Sbob picco }
20805aa1651Sbob picco 
20905aa1651Sbob picco static const struct pcr_ops n5_pcr_ops = {
21005aa1651Sbob picco 	.read_pcr		= n5_pcr_read,
21105aa1651Sbob picco 	.write_pcr		= n5_pcr_write,
21205aa1651Sbob picco 	.read_pic		= n4_pic_read,
21305aa1651Sbob picco 	.write_pic		= n4_pic_write,
21405aa1651Sbob picco 	.nmi_picl_value		= n4_picl_value,
21505aa1651Sbob picco 	.pcr_nmi_enable		= (PCR_N4_PICNPT | PCR_N4_STRACE |
21605aa1651Sbob picco 				   PCR_N4_UTRACE | PCR_N4_TOE |
21705aa1651Sbob picco 				   (26 << PCR_N4_SL_SHIFT)),
21805aa1651Sbob picco 	.pcr_nmi_disable	= PCR_N4_PICNPT,
21905aa1651Sbob picco };
22005aa1651Sbob picco 
m7_pcr_read(unsigned long reg_num)221b5aff55dSDavid Ahern static u64 m7_pcr_read(unsigned long reg_num)
222b5aff55dSDavid Ahern {
223b5aff55dSDavid Ahern 	unsigned long val;
224b5aff55dSDavid Ahern 
225b5aff55dSDavid Ahern 	(void) sun4v_m7_get_perfreg(reg_num, &val);
226b5aff55dSDavid Ahern 
227b5aff55dSDavid Ahern 	return val;
228b5aff55dSDavid Ahern }
229b5aff55dSDavid Ahern 
m7_pcr_write(unsigned long reg_num,u64 val)230b5aff55dSDavid Ahern static void m7_pcr_write(unsigned long reg_num, u64 val)
231b5aff55dSDavid Ahern {
232b5aff55dSDavid Ahern 	(void) sun4v_m7_set_perfreg(reg_num, val);
233b5aff55dSDavid Ahern }
234b5aff55dSDavid Ahern 
235b5aff55dSDavid Ahern static const struct pcr_ops m7_pcr_ops = {
236b5aff55dSDavid Ahern 	.read_pcr		= m7_pcr_read,
237b5aff55dSDavid Ahern 	.write_pcr		= m7_pcr_write,
238b5aff55dSDavid Ahern 	.read_pic		= n4_pic_read,
239b5aff55dSDavid Ahern 	.write_pic		= n4_pic_write,
240b5aff55dSDavid Ahern 	.nmi_picl_value		= n4_picl_value,
241b5aff55dSDavid Ahern 	.pcr_nmi_enable		= (PCR_N4_PICNPT | PCR_N4_STRACE |
242b5aff55dSDavid Ahern 				   PCR_N4_UTRACE | PCR_N4_TOE |
243b5aff55dSDavid Ahern 				   (26 << PCR_N4_SL_SHIFT)),
244b5aff55dSDavid Ahern 	.pcr_nmi_disable	= PCR_N4_PICNPT,
245b5aff55dSDavid Ahern };
24605aa1651Sbob picco 
2473eb8057bSDavid S. Miller static unsigned long perf_hsvc_group;
2483eb8057bSDavid S. Miller static unsigned long perf_hsvc_major;
2493eb8057bSDavid S. Miller static unsigned long perf_hsvc_minor;
2503eb8057bSDavid S. Miller 
register_perf_hsvc(void)2513eb8057bSDavid S. Miller static int __init register_perf_hsvc(void)
2523eb8057bSDavid S. Miller {
25305aa1651Sbob picco 	unsigned long hverror;
25405aa1651Sbob picco 
2553eb8057bSDavid S. Miller 	if (tlb_type == hypervisor) {
2563eb8057bSDavid S. Miller 		switch (sun4v_chip_type) {
2573eb8057bSDavid S. Miller 		case SUN4V_CHIP_NIAGARA1:
2583eb8057bSDavid S. Miller 			perf_hsvc_group = HV_GRP_NIAG_PERF;
2593eb8057bSDavid S. Miller 			break;
2603eb8057bSDavid S. Miller 
2613eb8057bSDavid S. Miller 		case SUN4V_CHIP_NIAGARA2:
2623eb8057bSDavid S. Miller 			perf_hsvc_group = HV_GRP_N2_CPU;
2633eb8057bSDavid S. Miller 			break;
2643eb8057bSDavid S. Miller 
2654ba991d3SDavid S. Miller 		case SUN4V_CHIP_NIAGARA3:
2664ba991d3SDavid S. Miller 			perf_hsvc_group = HV_GRP_KT_CPU;
2674ba991d3SDavid S. Miller 			break;
2684ba991d3SDavid S. Miller 
2696faaeb8eSDavid S. Miller 		case SUN4V_CHIP_NIAGARA4:
2706faaeb8eSDavid S. Miller 			perf_hsvc_group = HV_GRP_VT_CPU;
2716faaeb8eSDavid S. Miller 			break;
2726faaeb8eSDavid S. Miller 
27305aa1651Sbob picco 		case SUN4V_CHIP_NIAGARA5:
27405aa1651Sbob picco 			perf_hsvc_group = HV_GRP_T5_CPU;
27505aa1651Sbob picco 			break;
27605aa1651Sbob picco 
277b5aff55dSDavid Ahern 		case SUN4V_CHIP_SPARC_M7:
278b5aff55dSDavid Ahern 			perf_hsvc_group = HV_GRP_M7_PERF;
279b5aff55dSDavid Ahern 			break;
280b5aff55dSDavid Ahern 
2813eb8057bSDavid S. Miller 		default:
2823eb8057bSDavid S. Miller 			return -ENODEV;
2833eb8057bSDavid S. Miller 		}
2843eb8057bSDavid S. Miller 
2853eb8057bSDavid S. Miller 
2863eb8057bSDavid S. Miller 		perf_hsvc_major = 1;
2873eb8057bSDavid S. Miller 		perf_hsvc_minor = 0;
28805aa1651Sbob picco 		hverror = sun4v_hvapi_register(perf_hsvc_group,
2893eb8057bSDavid S. Miller 					       perf_hsvc_major,
29005aa1651Sbob picco 					       &perf_hsvc_minor);
29105aa1651Sbob picco 		if (hverror) {
29205aa1651Sbob picco 			pr_err("perfmon: Could not register hvapi(0x%lx).\n",
29305aa1651Sbob picco 			       hverror);
2943eb8057bSDavid S. Miller 			return -ENODEV;
2953eb8057bSDavid S. Miller 		}
2963eb8057bSDavid S. Miller 	}
2973eb8057bSDavid S. Miller 	return 0;
2983eb8057bSDavid S. Miller }
2993eb8057bSDavid S. Miller 
unregister_perf_hsvc(void)3003eb8057bSDavid S. Miller static void __init unregister_perf_hsvc(void)
3013eb8057bSDavid S. Miller {
3023eb8057bSDavid S. Miller 	if (tlb_type != hypervisor)
3033eb8057bSDavid S. Miller 		return;
3043eb8057bSDavid S. Miller 	sun4v_hvapi_unregister(perf_hsvc_group);
3053eb8057bSDavid S. Miller }
3063eb8057bSDavid S. Miller 
setup_sun4v_pcr_ops(void)3076faaeb8eSDavid S. Miller static int __init setup_sun4v_pcr_ops(void)
3086faaeb8eSDavid S. Miller {
3096faaeb8eSDavid S. Miller 	int ret = 0;
3106faaeb8eSDavid S. Miller 
3116faaeb8eSDavid S. Miller 	switch (sun4v_chip_type) {
3126faaeb8eSDavid S. Miller 	case SUN4V_CHIP_NIAGARA1:
3136faaeb8eSDavid S. Miller 	case SUN4V_CHIP_NIAGARA2:
3146faaeb8eSDavid S. Miller 	case SUN4V_CHIP_NIAGARA3:
3156faaeb8eSDavid S. Miller 		pcr_ops = &n2_pcr_ops;
3166faaeb8eSDavid S. Miller 		break;
3176faaeb8eSDavid S. Miller 
3186faaeb8eSDavid S. Miller 	case SUN4V_CHIP_NIAGARA4:
3196faaeb8eSDavid S. Miller 		pcr_ops = &n4_pcr_ops;
3206faaeb8eSDavid S. Miller 		break;
3216faaeb8eSDavid S. Miller 
32205aa1651Sbob picco 	case SUN4V_CHIP_NIAGARA5:
32305aa1651Sbob picco 		pcr_ops = &n5_pcr_ops;
32405aa1651Sbob picco 		break;
32505aa1651Sbob picco 
326b5aff55dSDavid Ahern 	case SUN4V_CHIP_SPARC_M7:
327b5aff55dSDavid Ahern 		pcr_ops = &m7_pcr_ops;
328b5aff55dSDavid Ahern 		break;
329b5aff55dSDavid Ahern 
3306faaeb8eSDavid S. Miller 	default:
3316faaeb8eSDavid S. Miller 		ret = -ENODEV;
3326faaeb8eSDavid S. Miller 		break;
3336faaeb8eSDavid S. Miller 	}
3346faaeb8eSDavid S. Miller 
3356faaeb8eSDavid S. Miller 	return ret;
3366faaeb8eSDavid S. Miller }
3376faaeb8eSDavid S. Miller 
pcr_arch_init(void)3383eb8057bSDavid S. Miller int __init pcr_arch_init(void)
3393eb8057bSDavid S. Miller {
3403eb8057bSDavid S. Miller 	int err = register_perf_hsvc();
3413eb8057bSDavid S. Miller 
3423eb8057bSDavid S. Miller 	if (err)
3433eb8057bSDavid S. Miller 		return err;
3443eb8057bSDavid S. Miller 
3453eb8057bSDavid S. Miller 	switch (tlb_type) {
3463eb8057bSDavid S. Miller 	case hypervisor:
3476faaeb8eSDavid S. Miller 		err = setup_sun4v_pcr_ops();
3486faaeb8eSDavid S. Miller 		if (err)
3496faaeb8eSDavid S. Miller 			goto out_unregister;
3503eb8057bSDavid S. Miller 		break;
3513eb8057bSDavid S. Miller 
3523eb8057bSDavid S. Miller 	case cheetah:
3533eb8057bSDavid S. Miller 	case cheetah_plus:
3543eb8057bSDavid S. Miller 		pcr_ops = &direct_pcr_ops;
3553eb8057bSDavid S. Miller 		break;
3563eb8057bSDavid S. Miller 
3571c2f61d4SDavid S. Miller 	case spitfire:
3581c2f61d4SDavid S. Miller 		/* UltraSPARC-I/II and derivatives lack a profile
3591c2f61d4SDavid S. Miller 		 * counter overflow interrupt so we can't make use of
3601c2f61d4SDavid S. Miller 		 * their hardware currently.
3611c2f61d4SDavid S. Miller 		 */
362*df561f66SGustavo A. R. Silva 		fallthrough;
3633eb8057bSDavid S. Miller 	default:
3643eb8057bSDavid S. Miller 		err = -ENODEV;
3653eb8057bSDavid S. Miller 		goto out_unregister;
3663eb8057bSDavid S. Miller 	}
3673eb8057bSDavid S. Miller 
368e5553a6dSDavid S. Miller 	return nmi_init();
3693eb8057bSDavid S. Miller 
3703eb8057bSDavid S. Miller out_unregister:
3713eb8057bSDavid S. Miller 	unregister_perf_hsvc();
3723eb8057bSDavid S. Miller 	return err;
3733eb8057bSDavid S. Miller }
374