xref: /illumos-gate/usr/src/uts/sun4u/os/mach_startup.c (revision f5488aa822e08905cde61d596e965030a1dfffcd)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/machsystm.h>
29 #include <sys/archsystm.h>
30 #include <sys/vm.h>
31 #include <sys/cpu.h>
32 #include <sys/cpupart.h>
33 #include <sys/atomic.h>
34 #include <sys/reboot.h>
35 #include <sys/kdi.h>
36 #include <sys/bootconf.h>
37 #include <sys/memlist_plat.h>
38 #include <sys/memlist_impl.h>
39 #include <sys/prom_plat.h>
40 #include <sys/prom_isa.h>
41 #include <sys/autoconf.h>
42 #include <sys/intreg.h>
43 #include <sys/ivintr.h>
44 #include <sys/fpu/fpusystm.h>
45 #include <sys/iommutsb.h>
46 #include <vm/vm_dep.h>
47 #include <vm/seg_kmem.h>
48 #include <vm/seg_kpm.h>
49 #include <vm/seg_map.h>
50 #include <vm/seg_kp.h>
51 #include <sys/sysconf.h>
52 #include <vm/hat_sfmmu.h>
53 #include <sys/kobj.h>
54 #include <sys/sun4asi.h>
55 #include <sys/clconf.h>
56 #include <sys/platform_module.h>
57 #include <sys/panic.h>
58 #include <sys/cpu_sgnblk_defs.h>
59 #include <sys/clock.h>
60 #include <sys/fpras_impl.h>
61 #include <sys/prom_debug.h>
62 #include <sys/traptrace.h>
63 #include <sys/memnode.h>
64 #include <sys/mem_cage.h>
65 
66 /*
67  * fpRAS implementation structures.
68  */
69 struct fpras_chkfn *fpras_chkfnaddrs[FPRAS_NCOPYOPS];
70 struct fpras_chkfngrp *fpras_chkfngrps;
71 struct fpras_chkfngrp *fpras_chkfngrps_base;
72 int fpras_frequency = -1;
73 int64_t fpras_interval = -1;
74 
75 /*
76  * Halt idling cpus optimization
77  *
78  * This optimation is only enabled in platforms that have
79  * the CPU halt support. The cpu_halt_cpu() support is provided
80  * in the cpu module and it is referenced here with a pragma weak.
81  * The presence of this routine automatically enable the halt idling
82  * cpus functionality if the global switch enable_halt_idle_cpus
83  * is set (default is set).
84  *
85  */
86 #pragma weak	cpu_halt_cpu
87 extern void	cpu_halt_cpu();
88 
89 /*
90  * Defines for the idle_state_transition DTrace probe
91  *
92  * The probe fires when the CPU undergoes an idle state change (e.g. halting)
93  * The agument passed is the state to which the CPU is transitioning.
94  *
95  * The states are defined here.
96  */
97 #define	IDLE_STATE_NORMAL 0
98 #define	IDLE_STATE_HALTED 1
99 
100 int		enable_halt_idle_cpus = 1; /* global switch */
101 
102 void
103 setup_trap_table(void)
104 {
105 	intr_init(CPU);			/* init interrupt request free list */
106 	setwstate(WSTATE_KERN);
107 	prom_set_traptable(&trap_table);
108 }
109 
110 void
111 mach_fpras()
112 {
113 	if (fpras_implemented && !fpras_disable) {
114 		int i;
115 		struct fpras_chkfngrp *fcgp;
116 		size_t chkfngrpsallocsz;
117 
118 		/*
119 		 * Note that we size off of NCPU and setup for
120 		 * all those possibilities regardless of whether
121 		 * the cpu id is present or not.  We do this so that
122 		 * we don't have any construction or destruction
123 		 * activity to perform at DR time, and it's not
124 		 * costly in memory.  We require block alignment.
125 		 */
126 		chkfngrpsallocsz = NCPU * sizeof (struct fpras_chkfngrp);
127 		fpras_chkfngrps_base = kmem_alloc(chkfngrpsallocsz, KM_SLEEP);
128 		if (IS_P2ALIGNED((uintptr_t)fpras_chkfngrps_base, 64)) {
129 			fpras_chkfngrps = fpras_chkfngrps_base;
130 		} else {
131 			kmem_free(fpras_chkfngrps_base, chkfngrpsallocsz);
132 			chkfngrpsallocsz += 64;
133 			fpras_chkfngrps_base = kmem_alloc(chkfngrpsallocsz,
134 			    KM_SLEEP);
135 			fpras_chkfngrps = (struct fpras_chkfngrp *)
136 			    P2ROUNDUP((uintptr_t)fpras_chkfngrps_base, 64);
137 		}
138 
139 		/*
140 		 * Copy our check function into place for each copy operation
141 		 * and each cpu id.
142 		 */
143 		fcgp = &fpras_chkfngrps[0];
144 		for (i = 0; i < FPRAS_NCOPYOPS; ++i)
145 			bcopy((void *)fpras_chkfn_type1, &fcgp->fpras_fn[i],
146 			    sizeof (struct fpras_chkfn));
147 		for (i = 1; i < NCPU; ++i)
148 			*(&fpras_chkfngrps[i]) = *fcgp;
149 
150 		/*
151 		 * At definition fpras_frequency is set to -1, and it will
152 		 * still have that value unless changed in /etc/system (not
153 		 * strictly supported, but not preventable).  The following
154 		 * both sets the default and sanity checks anything from
155 		 * /etc/system.
156 		 */
157 		if (fpras_frequency < 0)
158 			fpras_frequency = FPRAS_DEFAULT_FREQUENCY;
159 
160 		/*
161 		 * Now calculate fpras_interval.  When fpras_interval
162 		 * becomes non-negative fpras checks will commence
163 		 * (copies before this point in boot will bypass fpras).
164 		 * Our stores of instructions must be visible; no need
165 		 * to flush as they're never been executed before.
166 		 */
167 		membar_producer();
168 		fpras_interval = (fpras_frequency == 0) ?
169 		    0 : sys_tick_freq / fpras_frequency;
170 	}
171 }
172 
173 void
174 mach_hw_copy_limit(void)
175 {
176 	if (!fpu_exists) {
177 		use_hw_bcopy = 0;
178 		hw_copy_limit_1 = 0;
179 		hw_copy_limit_2 = 0;
180 		hw_copy_limit_4 = 0;
181 		hw_copy_limit_8 = 0;
182 		use_hw_bzero = 0;
183 	}
184 }
185 
186 void
187 load_tod_module()
188 {
189 	/*
190 	 * Load tod driver module for the tod part found on this system.
191 	 * Recompute the cpu frequency/delays based on tod as tod part
192 	 * tends to keep time more accurately.
193 	 */
194 	if (tod_module_name == NULL || modload("tod", tod_module_name) == -1)
195 		halt("Can't load tod module");
196 }
197 
198 void
199 mach_memscrub(void)
200 {
201 	/*
202 	 * Startup memory scrubber, if not running fpu emulation code.
203 	 */
204 
205 #ifndef _HW_MEMSCRUB_SUPPORT
206 	if (fpu_exists) {
207 		if (memscrub_init()) {
208 			cmn_err(CE_WARN,
209 			    "Memory scrubber failed to initialize");
210 		}
211 	}
212 #endif /* _HW_MEMSCRUB_SUPPORT */
213 }
214 
215 /*
216  * Halt the calling CPU until awoken via an interrupt
217  * This routine should only be invoked if cpu_halt_cpu()
218  * exists and is supported, see mach_cpu_halt_idle()
219  */
220 static void
221 cpu_halt(void)
222 {
223 	cpu_t		*cpup = CPU;
224 	processorid_t	cpun = cpup->cpu_id;
225 	cpupart_t	*cp = cpup->cpu_part;
226 	int		hset_update = 1;
227 	uint_t		pstate;
228 	extern uint_t	getpstate(void);
229 	extern void	setpstate(uint_t);
230 
231 	/*
232 	 * If this CPU is online, and there's multiple CPUs
233 	 * in the system, then we should notate our halting
234 	 * by adding ourselves to the partition's halted CPU
235 	 * bitmap. This allows other CPUs to find/awaken us when
236 	 * work becomes available.
237 	 */
238 	if (CPU->cpu_flags & CPU_OFFLINE || ncpus == 1)
239 		hset_update = 0;
240 
241 	/*
242 	 * Add ourselves to the partition's halted CPUs bitmask
243 	 * and set our HALTED flag, if necessary.
244 	 *
245 	 * When a thread becomes runnable, it is placed on the queue
246 	 * and then the halted cpuset is checked to determine who
247 	 * (if anyone) should be awoken. We therefore need to first
248 	 * add ourselves to the halted cpuset, and then check if there
249 	 * is any work available.
250 	 */
251 	if (hset_update) {
252 		cpup->cpu_disp_flags |= CPU_DISP_HALTED;
253 		membar_producer();
254 		CPUSET_ATOMIC_ADD(cp->cp_mach->mc_haltset, cpun);
255 	}
256 
257 	/*
258 	 * Check to make sure there's really nothing to do.
259 	 * Work destined for this CPU may become available after
260 	 * this check. We'll be notified through the clearing of our
261 	 * bit in the halted CPU bitmask, and a poke.
262 	 */
263 	if (disp_anywork()) {
264 		if (hset_update) {
265 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
266 			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
267 		}
268 		return;
269 	}
270 
271 	/*
272 	 * We're on our way to being halted.
273 	 *
274 	 * Disable interrupts now, so that we'll awaken immediately
275 	 * after halting if someone tries to poke us between now and
276 	 * the time we actually halt.
277 	 *
278 	 * We check for the presence of our bit after disabling interrupts.
279 	 * If it's cleared, we'll return. If the bit is cleared after
280 	 * we check then the poke will pop us out of the halted state.
281 	 *
282 	 * The ordering of the poke and the clearing of the bit by cpu_wakeup
283 	 * is important.
284 	 * cpu_wakeup() must clear, then poke.
285 	 * cpu_halt() must disable interrupts, then check for the bit.
286 	 */
287 	pstate = getpstate();
288 	setpstate(pstate & ~PSTATE_IE);
289 
290 	if (hset_update && !CPU_IN_SET(cp->cp_mach->mc_haltset, cpun)) {
291 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
292 		setpstate(pstate);
293 		return;
294 	}
295 
296 	/*
297 	 * The check for anything locally runnable is here for performance
298 	 * and isn't needed for correctness. disp_nrunnable ought to be
299 	 * in our cache still, so it's inexpensive to check, and if there
300 	 * is anything runnable we won't have to wait for the poke.
301 	 */
302 	if (cpup->cpu_disp->disp_nrunnable != 0) {
303 		if (hset_update) {
304 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
305 			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
306 		}
307 		setpstate(pstate);
308 		return;
309 	}
310 
311 	/*
312 	 * Halt the strand.
313 	 */
314 	if (&cpu_halt_cpu) {
315 		DTRACE_PROBE1(idle__state__transition,
316 		    uint_t, IDLE_STATE_HALTED);
317 
318 		cpu_halt_cpu();
319 
320 		DTRACE_PROBE1(idle__state__transition,
321 		    uint_t, IDLE_STATE_NORMAL);
322 	}
323 
324 	/*
325 	 * We're no longer halted
326 	 */
327 	setpstate(pstate);
328 	if (hset_update) {
329 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
330 		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
331 	}
332 }
333 
334 /*
335  * If "cpu" is halted, then wake it up clearing its halted bit in advance.
336  * Otherwise, see if other CPUs in the cpu partition are halted and need to
337  * be woken up so that they can steal the thread we placed on this CPU.
338  * This function is only used on MP systems.
339  * This function should only be invoked if cpu_halt_cpu()
340  * exists and is supported, see mach_cpu_halt_idle()
341  */
342 static void
343 cpu_wakeup(cpu_t *cpu, int bound)
344 {
345 	uint_t		cpu_found;
346 	int		result;
347 	cpupart_t	*cp;
348 
349 	cp = cpu->cpu_part;
350 	if (CPU_IN_SET(cp->cp_mach->mc_haltset, cpu->cpu_id)) {
351 		/*
352 		 * Clear the halted bit for that CPU since it will be
353 		 * poked in a moment.
354 		 */
355 		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpu->cpu_id);
356 		/*
357 		 * We may find the current CPU present in the halted cpuset
358 		 * if we're in the context of an interrupt that occurred
359 		 * before we had a chance to clear our bit in cpu_halt().
360 		 * Poking ourself is obviously unnecessary, since if
361 		 * we're here, we're not halted.
362 		 */
363 		if (cpu != CPU)
364 			poke_cpu(cpu->cpu_id);
365 		return;
366 	} else {
367 		/*
368 		 * This cpu isn't halted, but it's idle or undergoing a
369 		 * context switch. No need to awaken anyone else.
370 		 */
371 		if (cpu->cpu_thread == cpu->cpu_idle_thread ||
372 		    cpu->cpu_disp_flags & CPU_DISP_DONTSTEAL)
373 			return;
374 	}
375 
376 	/*
377 	 * No need to wake up other CPUs if the thread we just enqueued
378 	 * is bound.
379 	 */
380 	if (bound)
381 		return;
382 
383 	/*
384 	 * See if there's any other halted CPUs. If there are, then
385 	 * select one, and awaken it.
386 	 * It's possible that after we find a CPU, somebody else
387 	 * will awaken it before we get the chance.
388 	 * In that case, look again.
389 	 */
390 	do {
391 		CPUSET_FIND(cp->cp_mach->mc_haltset, cpu_found);
392 		if (cpu_found == CPUSET_NOTINSET)
393 			return;
394 
395 		ASSERT(cpu_found >= 0 && cpu_found < NCPU);
396 		CPUSET_ATOMIC_XDEL(cp->cp_mach->mc_haltset, cpu_found, result);
397 	} while (result < 0);
398 
399 	if (cpu_found != CPU->cpu_id)
400 		poke_cpu(cpu_found);
401 }
402 
403 void
404 mach_cpu_halt_idle()
405 {
406 	if (enable_halt_idle_cpus) {
407 		if (&cpu_halt_cpu) {
408 			idle_cpu = cpu_halt;
409 			disp_enq_thread = cpu_wakeup;
410 		}
411 	}
412 }
413 
414 /*ARGSUSED*/
415 int
416 cpu_intrq_setup(struct cpu *cp)
417 {
418 	/* Interrupt mondo queues not applicable to sun4u */
419 	return (0);
420 }
421 
422 /*ARGSUSED*/
423 void
424 cpu_intrq_cleanup(struct cpu *cp)
425 {
426 	/* Interrupt mondo queues not applicable to sun4u */
427 }
428 
429 /*ARGSUSED*/
430 void
431 cpu_intrq_register(struct cpu *cp)
432 {
433 	/* Interrupt/error queues not applicable to sun4u */
434 }
435 
436 /*ARGSUSED*/
437 void
438 mach_htraptrace_setup(int cpuid)
439 {
440 	/* Setup hypervisor traptrace buffer, not applicable to sun4u */
441 }
442 
443 /*ARGSUSED*/
444 void
445 mach_htraptrace_configure(int cpuid)
446 {
447 	/* enable/ disable hypervisor traptracing, not applicable to sun4u */
448 }
449 
450 /*ARGSUSED*/
451 void
452 mach_htraptrace_cleanup(int cpuid)
453 {
454 	/* cleanup hypervisor traptrace buffer, not applicable to sun4u */
455 }
456 
457 void
458 mach_descrip_startup_init(void)
459 {
460 	/*
461 	 * Only for sun4v.
462 	 * Initialize Machine description framework during startup.
463 	 */
464 }
465 void
466 mach_descrip_startup_fini(void)
467 {
468 	/*
469 	 * Only for sun4v.
470 	 * Clean up Machine Description framework during startup.
471 	 */
472 }
473 
474 void
475 mach_descrip_init(void)
476 {
477 	/*
478 	 * Only for sun4v.
479 	 * Initialize Machine description framework.
480 	 */
481 }
482 
483 void
484 hsvc_setup(void)
485 {
486 	/* Setup hypervisor services, not applicable to sun4u */
487 }
488 
489 void
490 load_mach_drivers(void)
491 {
492 	/* Currently no machine class (sun4u) specific drivers to load */
493 }
494 
495 /*
496  * Return true if the machine we're running on is a Positron.
497  * (Positron is an unsupported developers platform.)
498  */
499 int
500 iam_positron(void)
501 {
502 	char model[32];
503 	const char proto_model[] = "SUNW,501-2732";
504 	pnode_t root = prom_rootnode();
505 
506 	if (prom_getproplen(root, "model") != sizeof (proto_model))
507 		return (0);
508 
509 	(void) prom_getprop(root, "model", model);
510 	if (strcmp(model, proto_model) == 0)
511 		return (1);
512 	return (0);
513 }
514 
515 /*
516  * Find a physically contiguous area of twice the largest ecache size
517  * to be used while doing displacement flush of ecaches.
518  */
519 uint64_t
520 ecache_flush_address(void)
521 {
522 	struct memlist *pmem;
523 	uint64_t flush_size;
524 	uint64_t ret_val;
525 
526 	flush_size = ecache_size * 2;
527 	for (pmem = phys_install; pmem; pmem = pmem->next) {
528 		ret_val = P2ROUNDUP(pmem->address, ecache_size);
529 		if (ret_val + flush_size <= pmem->address + pmem->size)
530 			return (ret_val);
531 	}
532 	return ((uint64_t)-1);
533 }
534 
535 /*
536  * Called with the memlist lock held to say that phys_install has
537  * changed.
538  */
539 void
540 phys_install_has_changed(void)
541 {
542 	/*
543 	 * Get the new address into a temporary just in case panicking
544 	 * involves use of ecache_flushaddr.
545 	 */
546 	uint64_t new_addr;
547 
548 	new_addr = ecache_flush_address();
549 	if (new_addr == (uint64_t)-1) {
550 		cmn_err(CE_PANIC,
551 		    "ecache_flush_address(): failed, ecache_size=%x",
552 		    ecache_size);
553 		/*NOTREACHED*/
554 	}
555 	ecache_flushaddr = new_addr;
556 	membar_producer();
557 }
558