xref: /illumos-gate/usr/src/uts/sun4v/cpu/niagara.c (revision 07e2e5e8f3dc2fda396ec1f2107273b48f3d974f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/systm.h>
31 #include <sys/archsystm.h>
32 #include <sys/machparam.h>
33 #include <sys/machsystm.h>
34 #include <sys/cpu.h>
35 #include <sys/elf_SPARC.h>
36 #include <vm/hat_sfmmu.h>
37 #include <vm/page.h>
38 #include <sys/cpuvar.h>
39 #include <sys/async.h>
40 #include <sys/cmn_err.h>
41 #include <sys/debug.h>
42 #include <sys/dditypes.h>
43 #include <sys/sunddi.h>
44 #include <sys/cpu_module.h>
45 #include <sys/prom_debug.h>
46 #include <sys/vmsystm.h>
47 #include <sys/prom_plat.h>
48 #include <sys/sysmacros.h>
49 #include <sys/intreg.h>
50 #include <sys/machtrap.h>
51 #include <sys/ontrap.h>
52 #include <sys/ivintr.h>
53 #include <sys/atomic.h>
54 #include <sys/panic.h>
55 #include <sys/dtrace.h>
56 #include <sys/simulate.h>
57 #include <sys/fault.h>
58 
59 #define	S_VAC_SIZE	MMU_PAGESIZE /* XXXQ? */
60 
61 /*
62  * Maximum number of contexts
63  */
64 #define	MAX_NCTXS	(1 << 13)
65 
66 uint_t root_phys_addr_lo_mask = 0xffffffffU;
67 
68 #ifdef NIAGARA_CHK_VERSION
69 static uint64_t	cpu_ver;			/* Niagara CPU version reg */
70 
71 /* Niagara CPU version register */
72 #define	VER_MASK_MAJOR_SHIFT	28
73 #define	VER_MASK_MAJOR_MASK	0xf
74 
75 extern uint64_t	va_to_pa(void *);
76 extern uint64_t	ni_getver();			/* HV code to get %hver */
77 extern uint64_t	niagara_getver(uint64_t ni_getver_ra, uint64_t *cpu_version);
78 
79 #endif	/* NIAGARA_CHK_VERSION */
80 
81 void
82 cpu_setup(void)
83 {
84 	extern int at_flags;
85 	extern int disable_delay_tlb_flush, delay_tlb_flush;
86 	extern int mmu_exported_pagesize_mask;
87 	extern int get_cpu_pagesizes(void);
88 	extern int cpc_has_overflow_intr;
89 
90 	cache |= (CACHE_PTAG | CACHE_IOCOHERENT);
91 	at_flags = EF_SPARC_SUN_US3 | EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
92 
93 	/*
94 	 * Use the maximum number of contexts available for Spitfire unless
95 	 * it has been tuned for debugging.
96 	 * We are checking against 0 here since this value can be patched
97 	 * while booting.  It can not be patched via /etc/system since it
98 	 * will be patched too late and thus cause the system to panic.
99 	 */
100 	if (nctxs == 0)
101 		nctxs = MAX_NCTXS;
102 
103 	if (use_page_coloring) {
104 		do_pg_coloring = 1;
105 		if (use_virtual_coloring)
106 			do_virtual_coloring = 1;
107 	}
108 	/*
109 	 * Initalize supported page sizes information before the PD.
110 	 * If no information is available, then initialize the
111 	 * mmu_exported_pagesize_mask to a reasonable value for that processor.
112 	 */
113 	mmu_exported_pagesize_mask = get_cpu_pagesizes();
114 	if (mmu_exported_pagesize_mask <= 0) {
115 		mmu_exported_pagesize_mask = (1 << TTE8K) | (1 << TTE64K) |
116 		    (1 << TTE4M) | (1 << TTE256M);
117 	}
118 
119 	/*
120 	 * Tune pp_slots to use up to 1/8th of the tlb entries.
121 	 */
122 	pp_slots = MIN(8, MAXPP_SLOTS);
123 
124 	/*
125 	 * Block stores invalidate all pages of the d$ so pagecopy
126 	 * et. al. do not need virtual translations with virtual
127 	 * coloring taken into consideration.
128 	 */
129 	pp_consistent_coloring = 0;
130 	isa_list =
131 	    "sparcv9 sparcv8plus sparcv8 sparcv8-fsmuld sparcv7 "
132 	    "sparc sparcv9+vis sparcv9+vis2 sparcv8plus+vis sparcv8plus+vis2";
133 
134 	cpu_hwcap_flags |= AV_SPARC_ASI_BLK_INIT;
135 
136 	/*
137 	 * Niagara supports a 48-bit subset of the full 64-bit virtual
138 	 * address space. Virtual addresses between 0x0000800000000000
139 	 * and 0xffff.7fff.ffff.ffff inclusive lie within a "VA Hole"
140 	 * and must never be mapped. In addition, software must not use
141 	 * pages within 4GB of the VA hole as instruction pages to
142 	 * avoid problems with prefetching into the VA hole.
143 	 *
144 	 * VA hole information should be obtained from the machine
145 	 * description.
146 	 */
147 	hole_start = (caddr_t)(0x800000000000ul - (1ul << 32));
148 	hole_end = (caddr_t)(0xffff800000000000ul + (1ul << 32));
149 
150 	/*
151 	 * The kpm mapping window.
152 	 * kpm_size:
153 	 *	The size of a single kpm range.
154 	 *	The overall size will be: kpm_size * vac_colors.
155 	 * kpm_vbase:
156 	 *	The virtual start address of the kpm range within the kernel
157 	 *	virtual address space. kpm_vbase has to be kpm_size aligned.
158 	 */
159 	kpm_size = (size_t)(2ull * 1024 * 1024 * 1024 * 1024); /* 2TB */
160 	kpm_size_shift = 41;
161 	kpm_vbase = (caddr_t)0xfffffa0000000000ull; /* 16EB - 6TB */
162 
163 	/*
164 	 * The traptrace code uses either %tick or %stick for
165 	 * timestamping.  We have %stick so we can use it.
166 	 */
167 	traptrace_use_stick = 1;
168 
169 	/*
170 	 * sun4v provides demap_all
171 	 */
172 	if (!disable_delay_tlb_flush)
173 		delay_tlb_flush = 1;
174 	/*
175 	 * Niagara has a performance counter overflow interrupt
176 	 */
177 	cpc_has_overflow_intr = 1;
178 }
179 
180 #define	MB	 * 1024 * 1024
181 /*
182  * Set the magic constants of the implementation.
183  */
184 void
185 cpu_fiximp(struct cpu_node *cpunode)
186 {
187 	extern int vac_size, vac_shift;
188 	extern uint_t vac_mask;
189 	int i, a;
190 
191 	/*
192 	 * The assumption here is that fillsysinfo will eventually
193 	 * have code to fill this info in from the PD.
194 	 * We hard code this for niagara now.
195 	 * Once the PD access library is done this code
196 	 * might need to be changed to get the info from the PD
197 	 */
198 	if (cpunode->ecache_size == 0)
199 		cpunode->ecache_size = 3 MB;
200 	if (cpunode->ecache_linesize == 0)
201 		cpunode->ecache_linesize = 64;
202 	if (cpunode->ecache_associativity == 0)
203 		cpunode->ecache_associativity = 12;
204 
205 	cpunode->ecache_setsize =
206 	    cpunode->ecache_size / cpunode->ecache_associativity;
207 
208 	if (ecache_setsize == 0)
209 		ecache_setsize = cpunode->ecache_setsize;
210 	if (ecache_alignsize == 0)
211 		ecache_alignsize = cpunode->ecache_linesize;
212 
213 	vac_size = S_VAC_SIZE;
214 	vac_mask = MMU_PAGEMASK & (vac_size - 1);
215 	i = 0; a = vac_size;
216 	while (a >>= 1)
217 		++i;
218 	vac_shift = i;
219 	shm_alignment = vac_size;
220 	vac = 0;
221 }
222 
223 static int niagara_cpucnt;
224 
225 void
226 cpu_init_private(struct cpu *cp)
227 {
228 	extern int niagara_kstat_init(void);
229 
230 #ifdef NIAGARA_CHK_VERSION
231 	/*
232 	 * Prevent booting on a Niagara 1.x processor as it is no longer
233 	 * supported.
234 	 *
235 	 * This is a temporary hack until everyone has switched to the
236 	 * firmware which prevents booting on a Niagara 1.x processor.
237 	 */
238 	if (niagara_getver(va_to_pa((void *)ni_getver), &cpu_ver) == H_EOK &&
239 	    ((cpu_ver >> VER_MASK_MAJOR_SHIFT) & VER_MASK_MAJOR_MASK) <= 1)
240 		cmn_err(CE_PANIC, "CPU%d: Niagara 1.x no longer supported.",
241 		    cp->cpu_id);
242 #endif	/* NIAGARA_CHK_VERSION */
243 
244 	/*
245 	 * This code change assumes that the virtual cpu ids are identical
246 	 * to the physical cpu ids which is true for ontario but not for
247 	 * niagara in general.
248 	 * This is a temporary fix which will later be modified to obtain
249 	 * the execution unit sharing information from MD table.
250 	 */
251 	cp->cpu_m.cpu_ipipe = (id_t)(cp->cpu_id / 4);
252 
253 	ASSERT(MUTEX_HELD(&cpu_lock));
254 	if (niagara_cpucnt++ == 0) {
255 		(void) niagara_kstat_init();
256 	}
257 }
258 
259 void
260 cpu_uninit_private(struct cpu *cp)
261 {
262 	extern int niagara_kstat_fini(void);
263 
264 	ASSERT(MUTEX_HELD(&cpu_lock));
265 	if (--niagara_cpucnt == 0) {
266 		(void) niagara_kstat_fini();
267 	}
268 }
269 
270 /*
271  * On Niagara, any flush will cause all preceding stores to be
272  * synchronized wrt the i$, regardless of address or ASI.  In fact,
273  * the address is ignored, so we always flush address 0.
274  */
275 void
276 dtrace_flush_sec(uintptr_t addr)
277 {
278 	doflush(0);
279 }
280 
281 #define	IS_FLOAT(i) (((i) & 0x1000000) != 0)
282 #define	IS_IBIT_SET(x)	(x & 0x2000)
283 #define	IS_VIS1(op, op3)(op == 2 && op3 == 0x36)
284 #define	IS_PARTIAL_OR_SHORT_FLOAT_LD_ST(op, op3, asi)		\
285 		(op == 3 && (op3 == IOP_V8_LDDFA ||		\
286 		op3 == IOP_V8_STDFA) &&	asi > ASI_SNFL)
287 int
288 vis1_partial_support(struct regs *rp, k_siginfo_t *siginfo, uint_t *fault)
289 {
290 	char *badaddr;
291 	int instr;
292 	uint_t	optype, op3, asi;
293 	uint_t	rd, ignor;
294 
295 	ASSERT(USERMODE(rp->r_tstate));
296 
297 	instr = fetch_user_instr((caddr_t)rp->r_pc);
298 
299 	rd = (instr >> 25) & 0x1f;
300 	optype = (instr >> 30) & 0x3;
301 	op3 = (instr >> 19) & 0x3f;
302 	ignor = (instr >> 5) & 0xff;
303 	if (IS_IBIT_SET(instr)) {
304 		asi = (uint32_t)((rp->r_tstate >> TSTATE_ASI_SHIFT) &
305 		    TSTATE_ASI_MASK);
306 	} else {
307 		asi = ignor;
308 	}
309 
310 	if (!IS_VIS1(optype, op3) &&
311 	    !IS_PARTIAL_OR_SHORT_FLOAT_LD_ST(optype, op3, asi)) {
312 		return (-1);
313 	}
314 	switch (simulate_unimp(rp, &badaddr)) {
315 	case SIMU_RETRY:
316 		break;	/* regs are already set up */
317 		/*NOTREACHED*/
318 
319 	case SIMU_SUCCESS:
320 		/*
321 		 * skip the successfully
322 		 * simulated instruction
323 		 */
324 		rp->r_pc = rp->r_npc;
325 		rp->r_npc += 4;
326 		break;
327 		/*NOTREACHED*/
328 
329 	case SIMU_FAULT:
330 		siginfo->si_signo = SIGSEGV;
331 		siginfo->si_code = SEGV_MAPERR;
332 		siginfo->si_addr = badaddr;
333 		*fault = FLTBOUNDS;
334 		break;
335 
336 	case SIMU_DZERO:
337 		siginfo->si_signo = SIGFPE;
338 		siginfo->si_code = FPE_INTDIV;
339 		siginfo->si_addr = (caddr_t)rp->r_pc;
340 		*fault = FLTIZDIV;
341 		break;
342 
343 	case SIMU_UNALIGN:
344 		siginfo->si_signo = SIGBUS;
345 		siginfo->si_code = BUS_ADRALN;
346 		siginfo->si_addr = badaddr;
347 		*fault = FLTACCESS;
348 		break;
349 
350 	case SIMU_ILLEGAL:
351 	default:
352 		siginfo->si_signo = SIGILL;
353 		op3 = (instr >> 19) & 0x3F;
354 		if ((IS_FLOAT(instr) && (op3 == IOP_V8_STQFA) ||
355 		    (op3 == IOP_V8_STDFA)))
356 			siginfo->si_code = ILL_ILLADR;
357 		else
358 			siginfo->si_code = ILL_ILLOPC;
359 		siginfo->si_addr = (caddr_t)rp->r_pc;
360 		*fault = FLTILL;
361 		break;
362 	}
363 	return (0);
364 }
365