xref: /titanic_54/usr/src/uts/sun4v/cpu/niagara2.c (revision 4496171313bed39e96f21bc2f9faf2868e267ae3)
1*44961713Sgirish /*
2*44961713Sgirish  * CDDL HEADER START
3*44961713Sgirish  *
4*44961713Sgirish  * The contents of this file are subject to the terms of the
5*44961713Sgirish  * Common Development and Distribution License (the "License").
6*44961713Sgirish  * You may not use this file except in compliance with the License.
7*44961713Sgirish  *
8*44961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*44961713Sgirish  * or http://www.opensolaris.org/os/licensing.
10*44961713Sgirish  * See the License for the specific language governing permissions
11*44961713Sgirish  * and limitations under the License.
12*44961713Sgirish  *
13*44961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
14*44961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*44961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
16*44961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
17*44961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
18*44961713Sgirish  *
19*44961713Sgirish  * CDDL HEADER END
20*44961713Sgirish  */
21*44961713Sgirish /*
22*44961713Sgirish  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*44961713Sgirish  * Use is subject to license terms.
24*44961713Sgirish  */
25*44961713Sgirish 
26*44961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*44961713Sgirish 
28*44961713Sgirish #include <sys/types.h>
29*44961713Sgirish #include <sys/systm.h>
30*44961713Sgirish #include <sys/archsystm.h>
31*44961713Sgirish #include <sys/machparam.h>
32*44961713Sgirish #include <sys/machsystm.h>
33*44961713Sgirish #include <sys/cpu.h>
34*44961713Sgirish #include <sys/elf_SPARC.h>
35*44961713Sgirish #include <vm/hat_sfmmu.h>
36*44961713Sgirish #include <vm/page.h>
37*44961713Sgirish #include <sys/cpuvar.h>
38*44961713Sgirish #include <sys/async.h>
39*44961713Sgirish #include <sys/cmn_err.h>
40*44961713Sgirish #include <sys/debug.h>
41*44961713Sgirish #include <sys/dditypes.h>
42*44961713Sgirish #include <sys/sunddi.h>
43*44961713Sgirish #include <sys/cpu_module.h>
44*44961713Sgirish #include <sys/prom_debug.h>
45*44961713Sgirish #include <sys/vmsystm.h>
46*44961713Sgirish #include <sys/prom_plat.h>
47*44961713Sgirish #include <sys/sysmacros.h>
48*44961713Sgirish #include <sys/intreg.h>
49*44961713Sgirish #include <sys/machtrap.h>
50*44961713Sgirish #include <sys/ontrap.h>
51*44961713Sgirish #include <sys/ivintr.h>
52*44961713Sgirish #include <sys/atomic.h>
53*44961713Sgirish #include <sys/panic.h>
54*44961713Sgirish #include <sys/dtrace.h>
55*44961713Sgirish #include <sys/simulate.h>
56*44961713Sgirish #include <sys/fault.h>
57*44961713Sgirish #include <sys/niagara2regs.h>
58*44961713Sgirish #include <sys/hsvc.h>
59*44961713Sgirish #include <sys/trapstat.h>
60*44961713Sgirish 
61*44961713Sgirish uint_t root_phys_addr_lo_mask = 0xffffffffU;
62*44961713Sgirish char cpu_module_name[] = "SUNW,UltraSPARC-T2";
63*44961713Sgirish 
64*44961713Sgirish /*
65*44961713Sgirish  * Hypervisor services information for the NIAGARA2 CPU module
66*44961713Sgirish  */
67*44961713Sgirish static boolean_t niagara2_hsvc_available = B_TRUE;
68*44961713Sgirish static uint64_t niagara2_sup_minor;		/* Supported minor number */
69*44961713Sgirish static hsvc_info_t niagara2_hsvc = {
70*44961713Sgirish 	HSVC_REV_1, NULL, HSVC_GROUP_NIAGARA2_CPU, NIAGARA2_HSVC_MAJOR,
71*44961713Sgirish 	NIAGARA2_HSVC_MINOR, cpu_module_name
72*44961713Sgirish };
73*44961713Sgirish 
74*44961713Sgirish void
75*44961713Sgirish cpu_setup(void)
76*44961713Sgirish {
77*44961713Sgirish 	extern int mmu_exported_pagesize_mask;
78*44961713Sgirish 	extern int cpc_has_overflow_intr;
79*44961713Sgirish 	int status;
80*44961713Sgirish 
81*44961713Sgirish 	/*
82*44961713Sgirish 	 * Negotiate the API version for Niagara2 specific hypervisor
83*44961713Sgirish 	 * services.
84*44961713Sgirish 	 */
85*44961713Sgirish 	status = hsvc_register(&niagara2_hsvc, &niagara2_sup_minor);
86*44961713Sgirish 	if (status != 0) {
87*44961713Sgirish 		cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
88*44961713Sgirish 		    "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d",
89*44961713Sgirish 		    niagara2_hsvc.hsvc_modname, niagara2_hsvc.hsvc_group,
90*44961713Sgirish 		    niagara2_hsvc.hsvc_major, niagara2_hsvc.hsvc_minor, status);
91*44961713Sgirish 		niagara2_hsvc_available = B_FALSE;
92*44961713Sgirish 	}
93*44961713Sgirish 
94*44961713Sgirish 	/*
95*44961713Sgirish 	 * The setup common to all CPU modules is done in cpu_setup_common
96*44961713Sgirish 	 * routine.
97*44961713Sgirish 	 */
98*44961713Sgirish 	cpu_setup_common(NULL);
99*44961713Sgirish 
100*44961713Sgirish 	cache |= (CACHE_PTAG | CACHE_IOCOHERENT);
101*44961713Sgirish 
102*44961713Sgirish 	if ((mmu_exported_pagesize_mask &
103*44961713Sgirish 	    DEFAULT_SUN4V_MMU_PAGESIZE_MASK) !=
104*44961713Sgirish 	    DEFAULT_SUN4V_MMU_PAGESIZE_MASK)
105*44961713Sgirish 		cmn_err(CE_PANIC, "machine description"
106*44961713Sgirish 		    " does not have required sun4v page sizes"
107*44961713Sgirish 		    " 8K, 64K and 4M: MD mask is 0x%x",
108*44961713Sgirish 		    mmu_exported_pagesize_mask);
109*44961713Sgirish 
110*44961713Sgirish 	cpu_hwcap_flags = AV_SPARC_VIS | AV_SPARC_VIS2 | AV_SPARC_ASI_BLK_INIT;
111*44961713Sgirish 
112*44961713Sgirish 	/*
113*44961713Sgirish 	 * Niagara2 supports a 48-bit subset of the full 64-bit virtual
114*44961713Sgirish 	 * address space. Virtual addresses between 0x0000800000000000
115*44961713Sgirish 	 * and 0xffff.7fff.ffff.ffff inclusive lie within a "VA Hole"
116*44961713Sgirish 	 * and must never be mapped. In addition, software must not use
117*44961713Sgirish 	 * pages within 4GB of the VA hole as instruction pages to
118*44961713Sgirish 	 * avoid problems with prefetching into the VA hole.
119*44961713Sgirish 	 */
120*44961713Sgirish 	hole_start = (caddr_t)((1ull << (va_bits - 1)) - (1ull << 32));
121*44961713Sgirish 	hole_end = (caddr_t)((0ull - (1ull << (va_bits - 1))) + (1ull << 32));
122*44961713Sgirish 
123*44961713Sgirish 	/*
124*44961713Sgirish 	 * Niagara2 has a performance counter overflow interrupt
125*44961713Sgirish 	 */
126*44961713Sgirish 	cpc_has_overflow_intr = 1;
127*44961713Sgirish }
128*44961713Sgirish 
129*44961713Sgirish /*
130*44961713Sgirish  * Set the magic constants of the implementation.
131*44961713Sgirish  */
132*44961713Sgirish void
133*44961713Sgirish cpu_fiximp(struct cpu_node *cpunode)
134*44961713Sgirish {
135*44961713Sgirish 	/*
136*44961713Sgirish 	 * The Cache node is optional in MD. Therefore in case "Cache"
137*44961713Sgirish 	 * node does not exists in MD, set the default L2 cache associativity,
138*44961713Sgirish 	 * size, linesize.
139*44961713Sgirish 	 */
140*44961713Sgirish 	if (cpunode->ecache_size == 0)
141*44961713Sgirish 		cpunode->ecache_size = L2CACHE_SIZE;
142*44961713Sgirish 	if (cpunode->ecache_linesize == 0)
143*44961713Sgirish 		cpunode->ecache_linesize = L2CACHE_LINESIZE;
144*44961713Sgirish 	if (cpunode->ecache_associativity == 0)
145*44961713Sgirish 		cpunode->ecache_associativity = L2CACHE_ASSOCIATIVITY;
146*44961713Sgirish }
147*44961713Sgirish 
148*44961713Sgirish static int niagara2_cpucnt;
149*44961713Sgirish 
150*44961713Sgirish void
151*44961713Sgirish cpu_init_private(struct cpu *cp)
152*44961713Sgirish {
153*44961713Sgirish 	extern int niagara_kstat_init(void);
154*44961713Sgirish 
155*44961713Sgirish 	/*
156*44961713Sgirish 	 * The cpu_ipipe field is initialized based on the execution
157*44961713Sgirish 	 * unit sharing information from the MD. It defaults to the
158*44961713Sgirish 	 * virtual CPU id in the absence of such information.
159*44961713Sgirish 	 */
160*44961713Sgirish 	cp->cpu_m.cpu_ipipe = cpunodes[cp->cpu_id].exec_unit_mapping;
161*44961713Sgirish 	if (cp->cpu_m.cpu_ipipe == NO_EU_MAPPING_FOUND)
162*44961713Sgirish 		cp->cpu_m.cpu_ipipe = (id_t)(cp->cpu_id);
163*44961713Sgirish 
164*44961713Sgirish 	ASSERT(MUTEX_HELD(&cpu_lock));
165*44961713Sgirish 	if ((niagara2_cpucnt++ == 0) && (niagara2_hsvc_available == B_TRUE))
166*44961713Sgirish 		(void) niagara_kstat_init();
167*44961713Sgirish }
168*44961713Sgirish 
169*44961713Sgirish /*ARGSUSED*/
170*44961713Sgirish void
171*44961713Sgirish cpu_uninit_private(struct cpu *cp)
172*44961713Sgirish {
173*44961713Sgirish 	extern int niagara_kstat_fini(void);
174*44961713Sgirish 
175*44961713Sgirish 	ASSERT(MUTEX_HELD(&cpu_lock));
176*44961713Sgirish 	if ((--niagara2_cpucnt == 0) && (niagara2_hsvc_available == B_TRUE))
177*44961713Sgirish 		(void) niagara_kstat_fini();
178*44961713Sgirish }
179*44961713Sgirish 
180*44961713Sgirish /*
181*44961713Sgirish  * On Niagara2, any flush will cause all preceding stores to be
182*44961713Sgirish  * synchronized wrt the i$, regardless of address or ASI.  In fact,
183*44961713Sgirish  * the address is ignored, so we always flush address 0.
184*44961713Sgirish  */
185*44961713Sgirish /*ARGSUSED*/
186*44961713Sgirish void
187*44961713Sgirish dtrace_flush_sec(uintptr_t addr)
188*44961713Sgirish {
189*44961713Sgirish 	doflush(0);
190*44961713Sgirish }
191*44961713Sgirish 
192*44961713Sgirish /*
193*44961713Sgirish  * Trapstat support for Niagara2 processor
194*44961713Sgirish  * The Niagara2 provides HWTW support for TSB lookup and with HWTW
195*44961713Sgirish  * enabled no TSB hit information will be available. Therefore setting
196*44961713Sgirish  * the time spent in TLB miss handler for TSB hits to 0.
197*44961713Sgirish  */
198*44961713Sgirish int
199*44961713Sgirish cpu_trapstat_conf(int cmd)
200*44961713Sgirish {
201*44961713Sgirish 	int status = 0;
202*44961713Sgirish 
203*44961713Sgirish 	switch (cmd) {
204*44961713Sgirish 	case CPU_TSTATCONF_INIT:
205*44961713Sgirish 	case CPU_TSTATCONF_FINI:
206*44961713Sgirish 	case CPU_TSTATCONF_ENABLE:
207*44961713Sgirish 	case CPU_TSTATCONF_DISABLE:
208*44961713Sgirish 		break;
209*44961713Sgirish 	default:
210*44961713Sgirish 		status = EINVAL;
211*44961713Sgirish 		break;
212*44961713Sgirish 	}
213*44961713Sgirish 	return (status);
214*44961713Sgirish }
215*44961713Sgirish 
216*44961713Sgirish void
217*44961713Sgirish cpu_trapstat_data(void *buf, uint_t tstat_pgszs)
218*44961713Sgirish {
219*44961713Sgirish 	tstat_pgszdata_t	*tstatp = (tstat_pgszdata_t *)buf;
220*44961713Sgirish 	int	i;
221*44961713Sgirish 
222*44961713Sgirish 	for (i = 0; i < tstat_pgszs; i++, tstatp++) {
223*44961713Sgirish 		tstatp->tpgsz_kernel.tmode_itlb.ttlb_tlb.tmiss_count = 0;
224*44961713Sgirish 		tstatp->tpgsz_kernel.tmode_itlb.ttlb_tlb.tmiss_time = 0;
225*44961713Sgirish 		tstatp->tpgsz_user.tmode_itlb.ttlb_tlb.tmiss_count = 0;
226*44961713Sgirish 		tstatp->tpgsz_user.tmode_itlb.ttlb_tlb.tmiss_time = 0;
227*44961713Sgirish 		tstatp->tpgsz_kernel.tmode_dtlb.ttlb_tlb.tmiss_count = 0;
228*44961713Sgirish 		tstatp->tpgsz_kernel.tmode_dtlb.ttlb_tlb.tmiss_time = 0;
229*44961713Sgirish 		tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_count = 0;
230*44961713Sgirish 		tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_time = 0;
231*44961713Sgirish 	}
232*44961713Sgirish }
233