xref: /netbsd-src/sys/arch/sparc64/sparc64/cpu.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /*	$NetBSD: cpu.c,v 1.110 2014/04/15 12:22:49 macallan Exp $ */
2 
3 /*
4  * Copyright (c) 1996
5  *	The President and Fellows of Harvard College. All rights reserved.
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This software was developed by the Computer Systems Engineering group
10  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11  * contributed to Berkeley.
12  *
13  * All advertising materials mentioning features or use of this software
14  * must display the following acknowledgement:
15  *	This product includes software developed by Harvard University.
16  *	This product includes software developed by the University of
17  *	California, Lawrence Berkeley Laboratory.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  *
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer.
25  * 2. Redistributions in binary form must reproduce the above copyright
26  *    notice, this list of conditions and the following disclaimer in the
27  *    documentation and/or other materials provided with the distribution.
28  * 3. All advertising materials mentioning features or use of this software
29  *    must display the following acknowledgement:
30  *	This product includes software developed by Aaron Brown and
31  *	Harvard University.
32  *	This product includes software developed by the University of
33  *	California, Berkeley and its contributors.
34  * 4. Neither the name of the University nor the names of its contributors
35  *    may be used to endorse or promote products derived from this software
36  *    without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  *
50  *	@(#)cpu.c	8.5 (Berkeley) 11/23/93
51  *
52  */
53 
54 #include <sys/cdefs.h>
55 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.110 2014/04/15 12:22:49 macallan Exp $");
56 
57 #include "opt_multiprocessor.h"
58 
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/device.h>
62 #include <sys/kernel.h>
63 #include <sys/reboot.h>
64 #include <sys/cpu.h>
65 
66 #include <uvm/uvm.h>
67 
68 #include <machine/autoconf.h>
69 #include <machine/cpu.h>
70 #include <machine/reg.h>
71 #include <machine/trap.h>
72 #include <machine/pmap.h>
73 #include <machine/sparc64.h>
74 #include <machine/openfirm.h>
75 
76 #include <sparc64/sparc64/cache.h>
77 #ifdef SUN4V
78 #include <sparc64/hypervisor.h>
79 #endif
80 
81 int ecache_min_line_size;
82 
83 /* Linked list of all CPUs in system. */
84 #if defined(MULTIPROCESSOR)
85 int sparc_ncpus = 0;
86 #endif
87 struct cpu_info *cpus = NULL;
88 
89 volatile sparc64_cpuset_t cpus_active;/* set of active cpus */
90 struct cpu_bootargs *cpu_args;	/* allocated very early in pmap_bootstrap. */
91 struct pool_cache *fpstate_cache;
92 
93 static struct cpu_info *alloc_cpuinfo(u_int);
94 
95 /* The following are used externally (sysctl_hw). */
96 char	machine[] = MACHINE;		/* from <machine/param.h> */
97 char	machine_arch[] = MACHINE_ARCH;	/* from <machine/param.h> */
98 
99 /* These are used in locore.s, and are maximums */
100 int	dcache_line_size;
101 int	dcache_size;
102 int	icache_line_size;
103 int	icache_size;
104 
105 #ifdef MULTIPROCESSOR
106 static const char *ipi_evcnt_names[IPI_EVCNT_NUM] = IPI_EVCNT_NAMES;
107 #endif
108 
109 static void cpu_reset_fpustate(void);
110 
111 volatile int sync_tick = 0;
112 
113 /* The CPU configuration driver. */
114 void cpu_attach(device_t, device_t, void *);
115 int cpu_match(device_t, cfdata_t, void *);
116 
117 CFATTACH_DECL_NEW(cpu, 0, cpu_match, cpu_attach, NULL, NULL);
118 
119 static int
120 upaid_from_node(u_int cpu_node)
121 {
122 	int portid;
123 
124 	if (OF_getprop(cpu_node, "upa-portid", &portid, sizeof(portid)) <= 0 &&
125 	    OF_getprop(cpu_node, "portid", &portid, sizeof(portid)) <= 0)
126 		panic("cpu node w/o upa-portid");
127 
128 	return portid;
129 }
130 
131 struct cpu_info *
132 alloc_cpuinfo(u_int cpu_node)
133 {
134 	paddr_t pa0, pa;
135 	vaddr_t va, va0;
136 	vsize_t sz = 8 * PAGE_SIZE;
137 	int portid;
138 	struct cpu_info *cpi, *ci;
139 	extern paddr_t cpu0paddr;
140 
141 	/*
142 	 * Check for UPAID in the cpus list.
143 	 */
144 	portid = upaid_from_node(cpu_node);
145 
146 	for (cpi = cpus; cpi != NULL; cpi = cpi->ci_next)
147 		if (cpi->ci_cpuid == portid)
148 			return cpi;
149 
150 	/* Allocate the aligned VA and determine the size. */
151 	va = uvm_km_alloc(kernel_map, sz, 8 * PAGE_SIZE, UVM_KMF_VAONLY);
152 	if (!va)
153 		panic("alloc_cpuinfo: no virtual space");
154 	va0 = va;
155 
156 	pa0 = cpu0paddr;
157 	cpu0paddr += sz;
158 
159 	for (pa = pa0; pa < cpu0paddr; pa += PAGE_SIZE, va += PAGE_SIZE)
160 		pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
161 
162 	pmap_update(pmap_kernel());
163 
164 	cpi = (struct cpu_info *)(va0 + CPUINFO_VA - INTSTACK);
165 
166 	memset((void *)va0, 0, sz);
167 
168 	/*
169 	 * Initialize cpuinfo structure.
170 	 *
171 	 * Arrange pcb, idle stack and interrupt stack in the same
172 	 * way as is done for the boot CPU in pmap.c.
173 	 */
174 	cpi->ci_next = NULL;
175 	cpi->ci_curlwp = NULL;
176 	cpi->ci_cpuid = portid;
177 	cpi->ci_fplwp = NULL;
178 	cpi->ci_eintstack = NULL;
179 	cpi->ci_spinup = NULL;
180 	cpi->ci_paddr = pa0;
181 	cpi->ci_self = cpi;
182 #ifdef SUN4V
183 	if (CPU_ISSUN4V)
184 		cpi->ci_mmfsa = pa0;
185 #endif
186 	cpi->ci_node = cpu_node;
187 	cpi->ci_idepth = -1;
188 	memset(cpi->ci_intrpending, -1, sizeof(cpi->ci_intrpending));
189 
190 	/*
191 	 * Finally, add itself to the list of active cpus.
192 	 */
193 	for (ci = cpus; ci->ci_next != NULL; ci = ci->ci_next)
194 		;
195 #ifdef MULTIPROCESSOR
196 	ci->ci_next = cpi;
197 #endif
198 	return (cpi);
199 }
200 
201 int
202 cpu_match(device_t parent, cfdata_t cf, void *aux)
203 {
204 	struct mainbus_attach_args *ma = aux;
205 
206 	if (strcmp(cf->cf_name, ma->ma_name) != 0)
207 		return 0;
208 
209 	/*
210 	 * If we are going to only attach a single cpu, make sure
211 	 * to pick the one we are running on right now.
212 	 */
213 	if (upaid_from_node(ma->ma_node) != CPU_UPAID) {
214 #ifdef MULTIPROCESSOR
215 		if (boothowto & RB_MD1)
216 #endif
217 			return 0;
218 	}
219 
220 	return 1;
221 }
222 
223 static void
224 cpu_reset_fpustate(void)
225 {
226 	struct fpstate64 *fpstate;
227 	struct fpstate64 fps[2];
228 
229 	/* This needs to be 64-byte aligned */
230 	fpstate = ALIGNFPSTATE(&fps[1]);
231 
232 	/*
233 	 * Get the FSR and clear any exceptions.  If we do not unload
234 	 * the queue here and it is left over from a previous crash, we
235 	 * will panic in the first loadfpstate(), due to a sequence error,
236 	 * so we need to dump the whole state anyway.
237 	 */
238 	fpstate->fs_fsr = 7 << FSR_VER_SHIFT;	/* 7 is reserved for "none" */
239 	savefpstate(fpstate);
240 }
241 
242 /*
243  * Attach the CPU.
244  * Discover interesting goop about the virtual address cache
245  * (slightly funny place to do it, but this is where it is to be found).
246  */
247 void
248 cpu_attach(device_t parent, device_t dev, void *aux)
249 {
250 	int node;
251 	long clk, sclk = 0;
252 	struct mainbus_attach_args *ma = aux;
253 	struct cpu_info *ci;
254 	const char *sep;
255 	register int i, l;
256 	int bigcache, cachesize;
257 	char buf[100];
258 	int 	totalsize = 0;
259 	int 	linesize, dcachesize, icachesize;
260 
261 	/* tell them what we have */
262 	node = ma->ma_node;
263 
264 	/*
265 	 * Allocate cpu_info structure if needed.
266 	 */
267 	ci = alloc_cpuinfo((u_int)node);
268 
269 	/*
270 	 * Only do this on the boot cpu.  Other cpu's call
271 	 * cpu_reset_fpustate() from cpu_hatch() before they
272 	 * call into the idle loop.
273 	 * For other cpus, we need to call mi_cpu_attach()
274 	 * and complete setting up cpcb.
275 	 */
276 	if (ci->ci_flags & CPUF_PRIMARY) {
277 		fpstate_cache = pool_cache_init(sizeof(struct fpstate64),
278 					SPARC64_BLOCK_SIZE, 0, 0, "fpstate",
279 					NULL, IPL_NONE, NULL, NULL, NULL);
280 		cpu_reset_fpustate();
281 	}
282 #ifdef MULTIPROCESSOR
283 	else {
284 		mi_cpu_attach(ci);
285 		ci->ci_cpcb = lwp_getpcb(ci->ci_data.cpu_idlelwp);
286 	}
287 	for (i = 0; i < IPI_EVCNT_NUM; ++i)
288 		evcnt_attach_dynamic(&ci->ci_ipi_evcnt[i], EVCNT_TYPE_INTR,
289 				     NULL, device_xname(dev), ipi_evcnt_names[i]);
290 #endif
291 	evcnt_attach_dynamic(&ci->ci_tick_evcnt, EVCNT_TYPE_INTR, NULL,
292 			     device_xname(dev), "timer");
293 	mutex_init(&ci->ci_ctx_lock, MUTEX_SPIN, IPL_VM);
294 
295 	clk = prom_getpropint(node, "clock-frequency", 0);
296 	if (clk == 0) {
297 		/*
298 		 * Try to find it in the OpenPROM root...
299 		 */
300 		clk = prom_getpropint(findroot(), "clock-frequency", 0);
301 	}
302 	if (clk) {
303 		/* Tell OS what frequency we run on */
304 		ci->ci_cpu_clockrate[0] = clk;
305 		ci->ci_cpu_clockrate[1] = clk / 1000000;
306 	}
307 
308 	sclk = prom_getpropint(findroot(), "stick-frequency", 0);
309 
310 	ci->ci_system_clockrate[0] = sclk;
311 	ci->ci_system_clockrate[1] = sclk / 1000000;
312 
313 	snprintf(buf, sizeof buf, "%s @ %s MHz",
314 		prom_getpropstring(node, "name"), clockfreq(clk / 1000));
315 	cpu_setmodel("%s (%s)", machine_model, buf);
316 
317 	aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid);
318 	aprint_naive("\n");
319 
320 	if (ci->ci_system_clockrate[0] != 0) {
321 		aprint_normal_dev(dev, "system tick frequency %d MHz\n",
322 		    (int)ci->ci_system_clockrate[1]);
323 	}
324 	aprint_normal_dev(dev, "");
325 
326 	bigcache = 0;
327 
328 	icachesize = prom_getpropint(node, "icache-size", 0);
329 	if (icachesize > icache_size)
330 		icache_size = icachesize;
331 	linesize = l = prom_getpropint(node, "icache-line-size", 0);
332 	if (linesize > icache_line_size)
333 		icache_line_size = linesize;
334 
335 	for (i = 0; (1 << i) < l && l; i++)
336 		/* void */;
337 	if ((1 << i) != l && l)
338 		panic("bad icache line size %d", l);
339 	totalsize = icachesize;
340 	if (totalsize == 0)
341 		totalsize = l *
342 			prom_getpropint(node, "icache-nlines", 64) *
343 			prom_getpropint(node, "icache-associativity", 1);
344 
345 	cachesize = totalsize /
346 	    prom_getpropint(node, "icache-associativity", 1);
347 	bigcache = cachesize;
348 
349 	sep = "";
350 	if (totalsize > 0) {
351 		aprint_normal("%s%ldK instruction (%ld b/l)", sep,
352 		       (long)totalsize/1024,
353 		       (long)linesize);
354 		sep = ", ";
355 	}
356 
357 	dcachesize = prom_getpropint(node, "dcache-size", 0);
358 	if (dcachesize > dcache_size)
359 		dcache_size = dcachesize;
360 	linesize = l = prom_getpropint(node, "dcache-line-size", 0);
361 	if (linesize > dcache_line_size)
362 		dcache_line_size = linesize;
363 
364 	for (i = 0; (1 << i) < l && l; i++)
365 		/* void */;
366 	if ((1 << i) != l && l)
367 		panic("bad dcache line size %d", l);
368 	totalsize = dcachesize;
369 	if (totalsize == 0)
370 		totalsize = l *
371 			prom_getpropint(node, "dcache-nlines", 128) *
372 			prom_getpropint(node, "dcache-associativity", 1);
373 
374 	cachesize = totalsize /
375 	    prom_getpropint(node, "dcache-associativity", 1);
376 	if (cachesize > bigcache)
377 		bigcache = cachesize;
378 
379 	if (totalsize > 0) {
380 		aprint_normal("%s%ldK data (%ld b/l)", sep,
381 		       (long)totalsize/1024,
382 		       (long)linesize);
383 		sep = ", ";
384 	}
385 
386 	linesize = l =
387 		prom_getpropint(node, "ecache-line-size", 0);
388 	for (i = 0; (1 << i) < l && l; i++)
389 		/* void */;
390 	if ((1 << i) != l && l)
391 		panic("bad ecache line size %d", l);
392 	totalsize = prom_getpropint(node, "ecache-size", 0);
393 	if (totalsize == 0)
394 		totalsize = l *
395 			prom_getpropint(node, "ecache-nlines", 32768) *
396 			prom_getpropint(node, "ecache-associativity", 1);
397 
398 	cachesize = totalsize /
399 	     prom_getpropint(node, "ecache-associativity", 1);
400 	if (cachesize > bigcache)
401 		bigcache = cachesize;
402 
403 	if (totalsize > 0) {
404 		aprint_normal("%s%ldK external (%ld b/l)", sep,
405 		       (long)totalsize/1024,
406 		       (long)linesize);
407 	}
408 	aprint_normal("\n");
409 
410 	if (ecache_min_line_size == 0 ||
411 	    linesize < ecache_min_line_size)
412 		ecache_min_line_size = linesize;
413 
414 	/*
415 	 * Now that we know the size of the largest cache on this CPU,
416 	 * re-color our pages.
417 	 */
418 	uvm_page_recolor(atop(bigcache)); /* XXX */
419 
420 }
421 
422 int
423 cpu_myid(void)
424 {
425 	char buf[32];
426 	int impl;
427 
428 #ifdef SUN4V
429 	if (CPU_ISSUN4V) {
430 		uint64_t myid;
431 		hv_cpu_myid(&myid);
432 		return myid;
433 	}
434 #endif
435 	if (OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 &&
436 	    strcmp(buf, "SUNW,Ultra-Enterprise-10000") == 0)
437 		return lduwa(0x1fff40000d0UL, ASI_PHYS_NON_CACHED);
438 	impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT;
439 	switch (impl) {
440 		case IMPL_OLYMPUS_C:
441 		case IMPL_JUPITER:
442 			return CPU_JUPITERID;
443 		case IMPL_CHEETAH:
444 		case IMPL_CHEETAH_PLUS:
445 		case IMPL_JAGUAR:
446 		case IMPL_PANTHER:
447 			return CPU_FIREPLANEID;
448 		default:
449 			return CPU_UPAID;
450 	}
451 }
452 
453 #if defined(MULTIPROCESSOR)
454 vaddr_t cpu_spinup_trampoline;
455 
456 /*
457  * Start secondary processors in motion.
458  */
459 void
460 cpu_boot_secondary_processors(void)
461 {
462 	int i, pstate;
463 	struct cpu_info *ci;
464 
465 	sync_tick = 0;
466 
467 	sparc64_ipi_init();
468 
469 	if (boothowto & RB_MD1) {
470 		cpus[0].ci_next = NULL;
471 		sparc_ncpus = ncpu = ncpuonline = 1;
472 		return;
473 	}
474 
475 	for (ci = cpus; ci != NULL; ci = ci->ci_next) {
476 		if (ci->ci_cpuid == CPU_UPAID)
477 			continue;
478 
479 		cpu_pmap_prepare(ci, false);
480 		cpu_args->cb_node = ci->ci_node;
481 		cpu_args->cb_cpuinfo = ci->ci_paddr;
482 		membar_Sync();
483 
484 		/* Disable interrupts and start another CPU. */
485 		pstate = getpstate();
486 		setpstate(PSTATE_KERN);
487 
488 		prom_startcpu(ci->ci_node, (void *)cpu_spinup_trampoline, 0);
489 
490 		for (i = 0; i < 2000; i++) {
491 			membar_Sync();
492 			if (CPUSET_HAS(cpus_active, ci->ci_index))
493 				break;
494 			delay(10000);
495 		}
496 
497 		/* synchronize %tick ( to some degree at least ) */
498 		delay(1000);
499 		sync_tick = 1;
500 		membar_Sync();
501 		settick(0);
502 		if (ci->ci_system_clockrate[0] != 0)
503 			setstick(0);
504 
505 		setpstate(pstate);
506 
507 		if (!CPUSET_HAS(cpus_active, ci->ci_index))
508 			printf("cpu%d: startup failed\n", ci->ci_cpuid);
509 	}
510 }
511 
512 void
513 cpu_hatch(void)
514 {
515 	char *v = (char*)CPUINFO_VA;
516 	int i;
517 
518 	for (i = 0; i < 4*PAGE_SIZE; i += sizeof(long))
519 		flush(v + i);
520 
521 	cpu_pmap_init(curcpu());
522 	CPUSET_ADD(cpus_active, cpu_number());
523 	cpu_reset_fpustate();
524 	curlwp = curcpu()->ci_data.cpu_idlelwp;
525 	membar_Sync();
526 
527 	/* wait for the boot CPU to flip the switch */
528 	while (sync_tick == 0) {
529 		/* we do nothing here */
530 	}
531 	settick(0);
532 	if (curcpu()->ci_system_clockrate[0] != 0) {
533 		setstick(0);
534 		stickintr_establish(PIL_CLOCK, stickintr);
535 	} else {
536 		tickintr_establish(PIL_CLOCK, tickintr);
537 	}
538 	spl0();
539 }
540 #endif /* MULTIPROCESSOR */
541