10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51592Sgirish * Common Development and Distribution License (the "License").
61592Sgirish * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12149Srafael.vanoni@sun.com * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <sys/machsystm.h>
260Sstevel@tonic-gate #include <sys/archsystm.h>
270Sstevel@tonic-gate #include <sys/vm.h>
280Sstevel@tonic-gate #include <sys/cpu.h>
291772Sjl139090 #include <sys/cpupart.h>
308408SEric.Saxe@Sun.COM #include <sys/cmt.h>
318408SEric.Saxe@Sun.COM #include <sys/bitset.h>
320Sstevel@tonic-gate #include <sys/reboot.h>
330Sstevel@tonic-gate #include <sys/kdi.h>
340Sstevel@tonic-gate #include <sys/bootconf.h>
350Sstevel@tonic-gate #include <sys/memlist_plat.h>
360Sstevel@tonic-gate #include <sys/memlist_impl.h>
370Sstevel@tonic-gate #include <sys/prom_plat.h>
380Sstevel@tonic-gate #include <sys/prom_isa.h>
390Sstevel@tonic-gate #include <sys/autoconf.h>
400Sstevel@tonic-gate #include <sys/intreg.h>
410Sstevel@tonic-gate #include <sys/ivintr.h>
420Sstevel@tonic-gate #include <sys/fpu/fpusystm.h>
430Sstevel@tonic-gate #include <sys/iommutsb.h>
440Sstevel@tonic-gate #include <vm/vm_dep.h>
450Sstevel@tonic-gate #include <vm/seg_kmem.h>
460Sstevel@tonic-gate #include <vm/seg_kpm.h>
470Sstevel@tonic-gate #include <vm/seg_map.h>
480Sstevel@tonic-gate #include <vm/seg_kp.h>
490Sstevel@tonic-gate #include <sys/sysconf.h>
500Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
510Sstevel@tonic-gate #include <sys/kobj.h>
520Sstevel@tonic-gate #include <sys/sun4asi.h>
530Sstevel@tonic-gate #include <sys/clconf.h>
540Sstevel@tonic-gate #include <sys/platform_module.h>
550Sstevel@tonic-gate #include <sys/panic.h>
560Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h>
570Sstevel@tonic-gate #include <sys/clock.h>
580Sstevel@tonic-gate #include <sys/fpras_impl.h>
590Sstevel@tonic-gate #include <sys/prom_debug.h>
600Sstevel@tonic-gate #include <sys/traptrace.h>
610Sstevel@tonic-gate #include <sys/memnode.h>
620Sstevel@tonic-gate #include <sys/mem_cage.h>
630Sstevel@tonic-gate
640Sstevel@tonic-gate /*
650Sstevel@tonic-gate * fpRAS implementation structures.
660Sstevel@tonic-gate */
670Sstevel@tonic-gate struct fpras_chkfn *fpras_chkfnaddrs[FPRAS_NCOPYOPS];
680Sstevel@tonic-gate struct fpras_chkfngrp *fpras_chkfngrps;
690Sstevel@tonic-gate struct fpras_chkfngrp *fpras_chkfngrps_base;
700Sstevel@tonic-gate int fpras_frequency = -1;
710Sstevel@tonic-gate int64_t fpras_interval = -1;
720Sstevel@tonic-gate
731772Sjl139090 /*
749350SJerry.Gilliam@Sun.COM * Increase unix symbol table size as a work around for 6828121
759350SJerry.Gilliam@Sun.COM */
769350SJerry.Gilliam@Sun.COM int alloc_mem_bermuda_triangle;
779350SJerry.Gilliam@Sun.COM
789350SJerry.Gilliam@Sun.COM /*
791772Sjl139090 * Halt idling cpus optimization
801772Sjl139090 *
811772Sjl139090 * This optimation is only enabled in platforms that have
821772Sjl139090 * the CPU halt support. The cpu_halt_cpu() support is provided
831772Sjl139090 * in the cpu module and it is referenced here with a pragma weak.
841772Sjl139090 * The presence of this routine automatically enable the halt idling
851772Sjl139090 * cpus functionality if the global switch enable_halt_idle_cpus
861772Sjl139090 * is set (default is set).
871772Sjl139090 *
881772Sjl139090 */
891772Sjl139090 #pragma weak cpu_halt_cpu
901772Sjl139090 extern void cpu_halt_cpu();
911772Sjl139090
925864Sesaxe /*
935864Sesaxe * Defines for the idle_state_transition DTrace probe
945864Sesaxe *
955864Sesaxe * The probe fires when the CPU undergoes an idle state change (e.g. halting)
965864Sesaxe * The agument passed is the state to which the CPU is transitioning.
975864Sesaxe *
985864Sesaxe * The states are defined here.
995864Sesaxe */
1005864Sesaxe #define IDLE_STATE_NORMAL 0
1015864Sesaxe #define IDLE_STATE_HALTED 1
1025864Sesaxe
1031772Sjl139090 int enable_halt_idle_cpus = 1; /* global switch */
1041772Sjl139090
105*12149Srafael.vanoni@sun.com uint_t cp_haltset_fanout = 3;
106*12149Srafael.vanoni@sun.com
1070Sstevel@tonic-gate void
setup_trap_table(void)1080Sstevel@tonic-gate setup_trap_table(void)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate intr_init(CPU); /* init interrupt request free list */
1110Sstevel@tonic-gate setwstate(WSTATE_KERN);
1120Sstevel@tonic-gate prom_set_traptable(&trap_table);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate void
mach_fpras()1160Sstevel@tonic-gate mach_fpras()
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate if (fpras_implemented && !fpras_disable) {
1190Sstevel@tonic-gate int i;
1200Sstevel@tonic-gate struct fpras_chkfngrp *fcgp;
1210Sstevel@tonic-gate size_t chkfngrpsallocsz;
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate * Note that we size off of NCPU and setup for
1250Sstevel@tonic-gate * all those possibilities regardless of whether
1260Sstevel@tonic-gate * the cpu id is present or not. We do this so that
1270Sstevel@tonic-gate * we don't have any construction or destruction
1280Sstevel@tonic-gate * activity to perform at DR time, and it's not
1290Sstevel@tonic-gate * costly in memory. We require block alignment.
1300Sstevel@tonic-gate */
1310Sstevel@tonic-gate chkfngrpsallocsz = NCPU * sizeof (struct fpras_chkfngrp);
1320Sstevel@tonic-gate fpras_chkfngrps_base = kmem_alloc(chkfngrpsallocsz, KM_SLEEP);
1330Sstevel@tonic-gate if (IS_P2ALIGNED((uintptr_t)fpras_chkfngrps_base, 64)) {
1340Sstevel@tonic-gate fpras_chkfngrps = fpras_chkfngrps_base;
1350Sstevel@tonic-gate } else {
1360Sstevel@tonic-gate kmem_free(fpras_chkfngrps_base, chkfngrpsallocsz);
1370Sstevel@tonic-gate chkfngrpsallocsz += 64;
1380Sstevel@tonic-gate fpras_chkfngrps_base = kmem_alloc(chkfngrpsallocsz,
1390Sstevel@tonic-gate KM_SLEEP);
1400Sstevel@tonic-gate fpras_chkfngrps = (struct fpras_chkfngrp *)
1410Sstevel@tonic-gate P2ROUNDUP((uintptr_t)fpras_chkfngrps_base, 64);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate /*
1450Sstevel@tonic-gate * Copy our check function into place for each copy operation
1460Sstevel@tonic-gate * and each cpu id.
1470Sstevel@tonic-gate */
1480Sstevel@tonic-gate fcgp = &fpras_chkfngrps[0];
1490Sstevel@tonic-gate for (i = 0; i < FPRAS_NCOPYOPS; ++i)
1500Sstevel@tonic-gate bcopy((void *)fpras_chkfn_type1, &fcgp->fpras_fn[i],
1510Sstevel@tonic-gate sizeof (struct fpras_chkfn));
1520Sstevel@tonic-gate for (i = 1; i < NCPU; ++i)
1530Sstevel@tonic-gate *(&fpras_chkfngrps[i]) = *fcgp;
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate * At definition fpras_frequency is set to -1, and it will
1570Sstevel@tonic-gate * still have that value unless changed in /etc/system (not
1580Sstevel@tonic-gate * strictly supported, but not preventable). The following
1590Sstevel@tonic-gate * both sets the default and sanity checks anything from
1600Sstevel@tonic-gate * /etc/system.
1610Sstevel@tonic-gate */
1620Sstevel@tonic-gate if (fpras_frequency < 0)
1630Sstevel@tonic-gate fpras_frequency = FPRAS_DEFAULT_FREQUENCY;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate * Now calculate fpras_interval. When fpras_interval
1670Sstevel@tonic-gate * becomes non-negative fpras checks will commence
1680Sstevel@tonic-gate * (copies before this point in boot will bypass fpras).
1690Sstevel@tonic-gate * Our stores of instructions must be visible; no need
1700Sstevel@tonic-gate * to flush as they're never been executed before.
1710Sstevel@tonic-gate */
1720Sstevel@tonic-gate membar_producer();
1730Sstevel@tonic-gate fpras_interval = (fpras_frequency == 0) ?
1740Sstevel@tonic-gate 0 : sys_tick_freq / fpras_frequency;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate void
mach_hw_copy_limit(void)1790Sstevel@tonic-gate mach_hw_copy_limit(void)
1800Sstevel@tonic-gate {
1810Sstevel@tonic-gate if (!fpu_exists) {
1820Sstevel@tonic-gate use_hw_bcopy = 0;
1830Sstevel@tonic-gate hw_copy_limit_1 = 0;
1840Sstevel@tonic-gate hw_copy_limit_2 = 0;
1850Sstevel@tonic-gate hw_copy_limit_4 = 0;
1860Sstevel@tonic-gate hw_copy_limit_8 = 0;
1870Sstevel@tonic-gate use_hw_bzero = 0;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate void
load_tod_module()1920Sstevel@tonic-gate load_tod_module()
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate /*
1950Sstevel@tonic-gate * Load tod driver module for the tod part found on this system.
1960Sstevel@tonic-gate * Recompute the cpu frequency/delays based on tod as tod part
1970Sstevel@tonic-gate * tends to keep time more accurately.
1980Sstevel@tonic-gate */
1990Sstevel@tonic-gate if (tod_module_name == NULL || modload("tod", tod_module_name) == -1)
2000Sstevel@tonic-gate halt("Can't load tod module");
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate void
mach_memscrub(void)2040Sstevel@tonic-gate mach_memscrub(void)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate /*
2070Sstevel@tonic-gate * Startup memory scrubber, if not running fpu emulation code.
2080Sstevel@tonic-gate */
2090Sstevel@tonic-gate
2101772Sjl139090 #ifndef _HW_MEMSCRUB_SUPPORT
2110Sstevel@tonic-gate if (fpu_exists) {
2120Sstevel@tonic-gate if (memscrub_init()) {
2130Sstevel@tonic-gate cmn_err(CE_WARN,
2140Sstevel@tonic-gate "Memory scrubber failed to initialize");
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate }
2171772Sjl139090 #endif /* _HW_MEMSCRUB_SUPPORT */
2181772Sjl139090 }
2191772Sjl139090
2201772Sjl139090 /*
2218931SDave.Plauger@Sun.COM * Halt the present CPU until awoken via an interrupt.
2221772Sjl139090 * This routine should only be invoked if cpu_halt_cpu()
2231772Sjl139090 * exists and is supported, see mach_cpu_halt_idle()
2241772Sjl139090 */
2258931SDave.Plauger@Sun.COM void
cpu_halt(void)2261772Sjl139090 cpu_halt(void)
2271772Sjl139090 {
2288931SDave.Plauger@Sun.COM cpu_t *cpup = CPU;
2298931SDave.Plauger@Sun.COM processorid_t cpu_sid = cpup->cpu_seqid;
2308931SDave.Plauger@Sun.COM cpupart_t *cp = cpup->cpu_part;
2318931SDave.Plauger@Sun.COM int hset_update = 1;
2328931SDave.Plauger@Sun.COM volatile int *p = &cpup->cpu_disp->disp_nrunnable;
2338931SDave.Plauger@Sun.COM uint_t s;
2341772Sjl139090
2351772Sjl139090 /*
2368931SDave.Plauger@Sun.COM * If this CPU is online then we should notate our halting
2371772Sjl139090 * by adding ourselves to the partition's halted CPU
2388408SEric.Saxe@Sun.COM * bitset. This allows other CPUs to find/awaken us when
2391772Sjl139090 * work becomes available.
2401772Sjl139090 */
2418931SDave.Plauger@Sun.COM if (CPU->cpu_flags & CPU_OFFLINE)
2421772Sjl139090 hset_update = 0;
2431772Sjl139090
2441772Sjl139090 /*
2458931SDave.Plauger@Sun.COM * Add ourselves to the partition's halted CPUs bitset
2461772Sjl139090 * and set our HALTED flag, if necessary.
2471772Sjl139090 *
2481772Sjl139090 * When a thread becomes runnable, it is placed on the queue
2498408SEric.Saxe@Sun.COM * and then the halted cpu bitset is checked to determine who
2501772Sjl139090 * (if anyone) should be awoken. We therefore need to first
2518931SDave.Plauger@Sun.COM * add ourselves to the halted bitset, and then check if there
2528931SDave.Plauger@Sun.COM * is any work available. The order is important to prevent a race
2538408SEric.Saxe@Sun.COM * that can lead to work languishing on a run queue somewhere while
2548408SEric.Saxe@Sun.COM * this CPU remains halted.
2558408SEric.Saxe@Sun.COM *
2568408SEric.Saxe@Sun.COM * Either the producing CPU will see we're halted and will awaken us,
2578408SEric.Saxe@Sun.COM * or this CPU will see the work available in disp_anywork()
2581772Sjl139090 */
2591772Sjl139090 if (hset_update) {
2601772Sjl139090 cpup->cpu_disp_flags |= CPU_DISP_HALTED;
2611772Sjl139090 membar_producer();
2628408SEric.Saxe@Sun.COM bitset_atomic_add(&cp->cp_haltset, cpu_sid);
2631772Sjl139090 }
2641772Sjl139090
2651772Sjl139090 /*
2661772Sjl139090 * Check to make sure there's really nothing to do.
2671772Sjl139090 * Work destined for this CPU may become available after
2681772Sjl139090 * this check. We'll be notified through the clearing of our
2698408SEric.Saxe@Sun.COM * bit in the halted CPU bitset, and a poke.
2701772Sjl139090 */
2711772Sjl139090 if (disp_anywork()) {
2721772Sjl139090 if (hset_update) {
2731772Sjl139090 cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
2748408SEric.Saxe@Sun.COM bitset_atomic_del(&cp->cp_haltset, cpu_sid);
2751772Sjl139090 }
2761772Sjl139090 return;
2771772Sjl139090 }
2781772Sjl139090
2791772Sjl139090 /*
2808931SDave.Plauger@Sun.COM * We're on our way to being halted. Wait until something becomes
2818931SDave.Plauger@Sun.COM * runnable locally or we are awaken (i.e. removed from the halt set).
2828931SDave.Plauger@Sun.COM * Note that the call to hv_cpu_yield() can return even if we have
2838931SDave.Plauger@Sun.COM * nothing to do.
2841772Sjl139090 *
2851772Sjl139090 * Disable interrupts now, so that we'll awaken immediately
2861772Sjl139090 * after halting if someone tries to poke us between now and
2871772Sjl139090 * the time we actually halt.
2881772Sjl139090 *
2891772Sjl139090 * We check for the presence of our bit after disabling interrupts.
2901772Sjl139090 * If it's cleared, we'll return. If the bit is cleared after
2911772Sjl139090 * we check then the poke will pop us out of the halted state.
2928931SDave.Plauger@Sun.COM * Also, if the offlined CPU has been brought back on-line, then
2938931SDave.Plauger@Sun.COM * we return as well.
2941772Sjl139090 *
2951772Sjl139090 * The ordering of the poke and the clearing of the bit by cpu_wakeup
2961772Sjl139090 * is important.
2971772Sjl139090 * cpu_wakeup() must clear, then poke.
2981772Sjl139090 * cpu_halt() must disable interrupts, then check for the bit.
2998931SDave.Plauger@Sun.COM *
3001772Sjl139090 * The check for anything locally runnable is here for performance
3011772Sjl139090 * and isn't needed for correctness. disp_nrunnable ought to be
3021772Sjl139090 * in our cache still, so it's inexpensive to check, and if there
3031772Sjl139090 * is anything runnable we won't have to wait for the poke.
3048931SDave.Plauger@Sun.COM *
3058931SDave.Plauger@Sun.COM * Any interrupt will awaken the cpu from halt. Looping here
3068931SDave.Plauger@Sun.COM * will filter spurious interrupts that wake us up, but don't
3078931SDave.Plauger@Sun.COM * represent a need for us to head back out to idle(). This
3088931SDave.Plauger@Sun.COM * will enable the idle loop to be more efficient and sleep in
3098931SDave.Plauger@Sun.COM * the processor pipeline for a larger percent of the time,
3108931SDave.Plauger@Sun.COM * which returns useful cycles to the peer hardware strand
3118931SDave.Plauger@Sun.COM * that shares the pipeline.
3121772Sjl139090 */
3138931SDave.Plauger@Sun.COM s = disable_vec_intr();
3148931SDave.Plauger@Sun.COM while (*p == 0 &&
3158931SDave.Plauger@Sun.COM ((hset_update && bitset_in_set(&cp->cp_haltset, cpu_sid)) ||
3168931SDave.Plauger@Sun.COM (!hset_update && (CPU->cpu_flags & CPU_OFFLINE)))) {
3171772Sjl139090
3185864Sesaxe DTRACE_PROBE1(idle__state__transition,
3195864Sesaxe uint_t, IDLE_STATE_HALTED);
3208931SDave.Plauger@Sun.COM (void) cpu_halt_cpu();
3215864Sesaxe DTRACE_PROBE1(idle__state__transition,
3225864Sesaxe uint_t, IDLE_STATE_NORMAL);
3238931SDave.Plauger@Sun.COM
3248931SDave.Plauger@Sun.COM enable_vec_intr(s);
3258931SDave.Plauger@Sun.COM s = disable_vec_intr();
3265864Sesaxe }
3275864Sesaxe
3281772Sjl139090 /*
3291772Sjl139090 * We're no longer halted
3301772Sjl139090 */
3318931SDave.Plauger@Sun.COM enable_vec_intr(s);
3321772Sjl139090 if (hset_update) {
3331772Sjl139090 cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
3348408SEric.Saxe@Sun.COM bitset_atomic_del(&cp->cp_haltset, cpu_sid);
3351772Sjl139090 }
3361772Sjl139090 }
3371772Sjl139090
3381772Sjl139090 /*
3391772Sjl139090 * If "cpu" is halted, then wake it up clearing its halted bit in advance.
3401772Sjl139090 * Otherwise, see if other CPUs in the cpu partition are halted and need to
3411772Sjl139090 * be woken up so that they can steal the thread we placed on this CPU.
3421772Sjl139090 * This function is only used on MP systems.
3431772Sjl139090 * This function should only be invoked if cpu_halt_cpu()
3441772Sjl139090 * exists and is supported, see mach_cpu_halt_idle()
3451772Sjl139090 */
3461772Sjl139090 static void
cpu_wakeup(cpu_t * cpu,int bound)3471772Sjl139090 cpu_wakeup(cpu_t *cpu, int bound)
3481772Sjl139090 {
3491772Sjl139090 uint_t cpu_found;
3508408SEric.Saxe@Sun.COM processorid_t cpu_sid;
3511772Sjl139090 cpupart_t *cp;
3521772Sjl139090
3531772Sjl139090 cp = cpu->cpu_part;
3548408SEric.Saxe@Sun.COM cpu_sid = cpu->cpu_seqid;
3558408SEric.Saxe@Sun.COM if (bitset_in_set(&cp->cp_haltset, cpu_sid)) {
3561772Sjl139090 /*
3571772Sjl139090 * Clear the halted bit for that CPU since it will be
3581772Sjl139090 * poked in a moment.
3591772Sjl139090 */
3608408SEric.Saxe@Sun.COM bitset_atomic_del(&cp->cp_haltset, cpu_sid);
3611772Sjl139090 /*
3628408SEric.Saxe@Sun.COM * We may find the current CPU present in the halted cpu bitset
3631772Sjl139090 * if we're in the context of an interrupt that occurred
3641772Sjl139090 * before we had a chance to clear our bit in cpu_halt().
3651772Sjl139090 * Poking ourself is obviously unnecessary, since if
3661772Sjl139090 * we're here, we're not halted.
3671772Sjl139090 */
3681772Sjl139090 if (cpu != CPU)
3691772Sjl139090 poke_cpu(cpu->cpu_id);
3701772Sjl139090 return;
3711772Sjl139090 } else {
3721772Sjl139090 /*
3731772Sjl139090 * This cpu isn't halted, but it's idle or undergoing a
3741772Sjl139090 * context switch. No need to awaken anyone else.
3751772Sjl139090 */
3761772Sjl139090 if (cpu->cpu_thread == cpu->cpu_idle_thread ||
3771772Sjl139090 cpu->cpu_disp_flags & CPU_DISP_DONTSTEAL)
3781772Sjl139090 return;
3791772Sjl139090 }
3801772Sjl139090
3811772Sjl139090 /*
3828408SEric.Saxe@Sun.COM * No need to wake up other CPUs if this is for a bound thread.
3831772Sjl139090 */
3841772Sjl139090 if (bound)
3851772Sjl139090 return;
3861772Sjl139090
3871772Sjl139090 /*
3888408SEric.Saxe@Sun.COM * The CPU specified for wakeup isn't currently halted, so check
3898408SEric.Saxe@Sun.COM * to see if there are any other halted CPUs in the partition,
3908408SEric.Saxe@Sun.COM * and if there are then awaken one.
3918408SEric.Saxe@Sun.COM *
3928408SEric.Saxe@Sun.COM * If possible, try to select a CPU close to the target, since this
3938408SEric.Saxe@Sun.COM * will likely trigger a migration.
3941772Sjl139090 */
3951772Sjl139090 do {
3968408SEric.Saxe@Sun.COM cpu_found = bitset_find(&cp->cp_haltset);
3978408SEric.Saxe@Sun.COM if (cpu_found == (uint_t)-1)
3981772Sjl139090 return;
3998408SEric.Saxe@Sun.COM } while (bitset_atomic_test_and_del(&cp->cp_haltset, cpu_found) < 0);
4001772Sjl139090
4018408SEric.Saxe@Sun.COM if (cpu_found != CPU->cpu_seqid)
4028408SEric.Saxe@Sun.COM poke_cpu(cpu_seq[cpu_found]->cpu_id);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate void
mach_cpu_halt_idle(void)4068906SEric.Saxe@Sun.COM mach_cpu_halt_idle(void)
4070Sstevel@tonic-gate {
4081772Sjl139090 if (enable_halt_idle_cpus) {
4091772Sjl139090 if (&cpu_halt_cpu) {
4101772Sjl139090 idle_cpu = cpu_halt;
4111772Sjl139090 disp_enq_thread = cpu_wakeup;
4121772Sjl139090 }
4131772Sjl139090 }
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate /*ARGSUSED*/
4174050Sjb145095 int
cpu_intrq_setup(struct cpu * cp)4180Sstevel@tonic-gate cpu_intrq_setup(struct cpu *cp)
4190Sstevel@tonic-gate {
4200Sstevel@tonic-gate /* Interrupt mondo queues not applicable to sun4u */
4214050Sjb145095 return (0);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /*ARGSUSED*/
4250Sstevel@tonic-gate void
cpu_intrq_cleanup(struct cpu * cp)4261991Sheppo cpu_intrq_cleanup(struct cpu *cp)
4271991Sheppo {
4281991Sheppo /* Interrupt mondo queues not applicable to sun4u */
4291991Sheppo }
4301991Sheppo
4311991Sheppo /*ARGSUSED*/
4321991Sheppo void
cpu_intrq_register(struct cpu * cp)4330Sstevel@tonic-gate cpu_intrq_register(struct cpu *cp)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate /* Interrupt/error queues not applicable to sun4u */
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate /*ARGSUSED*/
4390Sstevel@tonic-gate void
mach_htraptrace_setup(int cpuid)4401077Ssvemuri mach_htraptrace_setup(int cpuid)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate /* Setup hypervisor traptrace buffer, not applicable to sun4u */
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate /*ARGSUSED*/
4460Sstevel@tonic-gate void
mach_htraptrace_configure(int cpuid)4471077Ssvemuri mach_htraptrace_configure(int cpuid)
4481077Ssvemuri {
4491077Ssvemuri /* enable/ disable hypervisor traptracing, not applicable to sun4u */
4501077Ssvemuri }
4511077Ssvemuri
4521077Ssvemuri /*ARGSUSED*/
4531077Ssvemuri void
mach_htraptrace_cleanup(int cpuid)4541077Ssvemuri mach_htraptrace_cleanup(int cpuid)
4551077Ssvemuri {
4561077Ssvemuri /* cleanup hypervisor traptrace buffer, not applicable to sun4u */
4571077Ssvemuri }
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate void
mach_descrip_startup_init(void)4601991Sheppo mach_descrip_startup_init(void)
4611991Sheppo {
4621991Sheppo /*
4631991Sheppo * Only for sun4v.
4641991Sheppo * Initialize Machine description framework during startup.
4651991Sheppo */
4661991Sheppo }
4671991Sheppo void
mach_descrip_startup_fini(void)4681991Sheppo mach_descrip_startup_fini(void)
4691991Sheppo {
4701991Sheppo /*
4711991Sheppo * Only for sun4v.
4721991Sheppo * Clean up Machine Description framework during startup.
4731991Sheppo */
4741991Sheppo }
4751991Sheppo
4761991Sheppo void
mach_descrip_init(void)4770Sstevel@tonic-gate mach_descrip_init(void)
4780Sstevel@tonic-gate {
4791991Sheppo /*
4801991Sheppo * Only for sun4v.
4811991Sheppo * Initialize Machine description framework.
4821991Sheppo */
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate
4851592Sgirish void
hsvc_setup(void)4861592Sgirish hsvc_setup(void)
4871592Sgirish {
4881592Sgirish /* Setup hypervisor services, not applicable to sun4u */
4891592Sgirish }
4901592Sgirish
4911991Sheppo void
load_mach_drivers(void)4921991Sheppo load_mach_drivers(void)
4931991Sheppo {
4941991Sheppo /* Currently no machine class (sun4u) specific drivers to load */
4951991Sheppo }
4961991Sheppo
4970Sstevel@tonic-gate /*
4980Sstevel@tonic-gate * Return true if the machine we're running on is a Positron.
4990Sstevel@tonic-gate * (Positron is an unsupported developers platform.)
5000Sstevel@tonic-gate */
5010Sstevel@tonic-gate int
iam_positron(void)5020Sstevel@tonic-gate iam_positron(void)
5030Sstevel@tonic-gate {
5040Sstevel@tonic-gate char model[32];
5050Sstevel@tonic-gate const char proto_model[] = "SUNW,501-2732";
506789Sahrens pnode_t root = prom_rootnode();
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate if (prom_getproplen(root, "model") != sizeof (proto_model))
5090Sstevel@tonic-gate return (0);
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate (void) prom_getprop(root, "model", model);
5120Sstevel@tonic-gate if (strcmp(model, proto_model) == 0)
5130Sstevel@tonic-gate return (1);
5140Sstevel@tonic-gate return (0);
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate /*
5180Sstevel@tonic-gate * Find a physically contiguous area of twice the largest ecache size
5190Sstevel@tonic-gate * to be used while doing displacement flush of ecaches.
5200Sstevel@tonic-gate */
5210Sstevel@tonic-gate uint64_t
ecache_flush_address(void)5220Sstevel@tonic-gate ecache_flush_address(void)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate struct memlist *pmem;
5250Sstevel@tonic-gate uint64_t flush_size;
5260Sstevel@tonic-gate uint64_t ret_val;
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate flush_size = ecache_size * 2;
52911474SJonathan.Adams@Sun.COM for (pmem = phys_install; pmem; pmem = pmem->ml_next) {
53011474SJonathan.Adams@Sun.COM ret_val = P2ROUNDUP(pmem->ml_address, ecache_size);
53111474SJonathan.Adams@Sun.COM if (ret_val + flush_size <= pmem->ml_address + pmem->ml_size)
5320Sstevel@tonic-gate return (ret_val);
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate return ((uint64_t)-1);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate /*
5380Sstevel@tonic-gate * Called with the memlist lock held to say that phys_install has
5390Sstevel@tonic-gate * changed.
5400Sstevel@tonic-gate */
5410Sstevel@tonic-gate void
phys_install_has_changed(void)5420Sstevel@tonic-gate phys_install_has_changed(void)
5430Sstevel@tonic-gate {
5440Sstevel@tonic-gate /*
5450Sstevel@tonic-gate * Get the new address into a temporary just in case panicking
5460Sstevel@tonic-gate * involves use of ecache_flushaddr.
5470Sstevel@tonic-gate */
5480Sstevel@tonic-gate uint64_t new_addr;
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate new_addr = ecache_flush_address();
5510Sstevel@tonic-gate if (new_addr == (uint64_t)-1) {
5520Sstevel@tonic-gate cmn_err(CE_PANIC,
5530Sstevel@tonic-gate "ecache_flush_address(): failed, ecache_size=%x",
5540Sstevel@tonic-gate ecache_size);
5550Sstevel@tonic-gate /*NOTREACHED*/
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate ecache_flushaddr = new_addr;
5580Sstevel@tonic-gate membar_producer();
5590Sstevel@tonic-gate }
560