xref: /onnv-gate/usr/src/uts/sun4u/os/cmp.c (revision 4606:ffcd05844ec5)
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
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * 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 /*
223434Sesaxe  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/machsystm.h>
300Sstevel@tonic-gate #include <sys/x_call.h>
310Sstevel@tonic-gate #include <sys/cmp.h>
32*4606Sesaxe #include <sys/cmt.h>
330Sstevel@tonic-gate #include <sys/debug.h>
342041Sakolb #include <sys/disp.h>
350Sstevel@tonic-gate #include <sys/cheetahregs.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * Note: We assume that chipid == portid.  This is not necessarily true.
390Sstevel@tonic-gate  * We buried it down here in the implementation, and not in the
400Sstevel@tonic-gate  * interfaces, so that we can change it later.
410Sstevel@tonic-gate  */
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  * pre-alloc'ed because this is used early in boot (before the memory
450Sstevel@tonic-gate  * allocator is available).
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate static cpuset_t chips[MAX_CPU_CHIPID];
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * Returns 1 if cpuid is CMP-capable, 0 otherwise.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate int
530Sstevel@tonic-gate cmp_cpu_is_cmp(processorid_t cpuid)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate 	chipid_t chipid;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 	/* N.B. We're assuming that the cpunode[].portid is still intact */
580Sstevel@tonic-gate 	chipid = cpunodes[cpuid].portid;
590Sstevel@tonic-gate 	return (!CPUSET_ISNULL(chips[chipid]));
600Sstevel@tonic-gate }
610Sstevel@tonic-gate 
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate  * Indicate that this core (cpuid) resides on the chip indicated by chipid.
640Sstevel@tonic-gate  * Called during boot and DR add.
650Sstevel@tonic-gate  */
660Sstevel@tonic-gate void
670Sstevel@tonic-gate cmp_add_cpu(chipid_t chipid, processorid_t cpuid)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	CPUSET_ADD(chips[chipid], cpuid);
700Sstevel@tonic-gate }
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate  * Indicate that this core (cpuid) is being DR removed.
740Sstevel@tonic-gate  */
750Sstevel@tonic-gate void
760Sstevel@tonic-gate cmp_delete_cpu(processorid_t cpuid)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate 	chipid_t chipid;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	/* N.B. We're assuming that the cpunode[].portid is still intact */
810Sstevel@tonic-gate 	chipid = cpunodes[cpuid].portid;
820Sstevel@tonic-gate 	CPUSET_DEL(chips[chipid], cpuid);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate  * Called when cpuid is being onlined or offlined.  If the offlined
870Sstevel@tonic-gate  * processor is CMP-capable then current target of the CMP Error Steering
880Sstevel@tonic-gate  * Register is set to either the lowest numbered on-line sibling core, if
890Sstevel@tonic-gate  * one exists, or else to this core.
900Sstevel@tonic-gate  */
911772Sjl139090 /* ARGSUSED */
920Sstevel@tonic-gate void
930Sstevel@tonic-gate cmp_error_resteer(processorid_t cpuid)
940Sstevel@tonic-gate {
951772Sjl139090 #ifndef	_CMP_NO_ERROR_STEERING
960Sstevel@tonic-gate 	cpuset_t mycores;
970Sstevel@tonic-gate 	cpu_t *cpu;
980Sstevel@tonic-gate 	chipid_t chipid;
990Sstevel@tonic-gate 	int i;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	if (!cmp_cpu_is_cmp(cpuid))
102*4606Sesaxe 		return;
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
1050Sstevel@tonic-gate 	chipid = cpunodes[cpuid].portid;
1060Sstevel@tonic-gate 	mycores = chips[chipid];
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	/* Look for an online sibling core */
1090Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++) {
1100Sstevel@tonic-gate 		if (i == cpuid)
1110Sstevel@tonic-gate 			continue;
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 		if (CPU_IN_SET(mycores, i) &&
1140Sstevel@tonic-gate 		    (cpu = cpu_get(i)) != NULL && cpu_is_active(cpu)) {
1150Sstevel@tonic-gate 			/* Found one, reset error steering  */
1160Sstevel@tonic-gate 			xc_one(i, (xcfunc_t *)set_cmp_error_steering, 0, 0);
1170Sstevel@tonic-gate 			break;
1180Sstevel@tonic-gate 		}
1190Sstevel@tonic-gate 	}
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	/* No online sibling cores, point to this core.  */
1220Sstevel@tonic-gate 	if (i == NCPU) {
1230Sstevel@tonic-gate 		xc_one(cpuid, (xcfunc_t *)set_cmp_error_steering, 0, 0);
1240Sstevel@tonic-gate 	}
1251772Sjl139090 #else
1261772Sjl139090 	/* Not all CMP's support (e.g. Olympus-C by Fujitsu) error steering */
1271772Sjl139090 	return;
1281772Sjl139090 #endif /* _CMP_NO_ERROR_STEERING */
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate chipid_t
1320Sstevel@tonic-gate cmp_cpu_to_chip(processorid_t cpuid)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate 	if (!cmp_cpu_is_cmp(cpuid)) {
1350Sstevel@tonic-gate 		/* This CPU is not a CMP, so by definition chipid==cpuid */
1360Sstevel@tonic-gate 		ASSERT(cpuid < MAX_CPU_CHIPID && CPUSET_ISNULL(chips[cpuid]));
1370Sstevel@tonic-gate 		return (cpuid);
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	/* N.B. We're assuming that the cpunode[].portid is still intact */
1410Sstevel@tonic-gate 	return (cpunodes[cpuid].portid);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
1443434Sesaxe /* ARGSUSED */
1453434Sesaxe int
1463434Sesaxe pg_plat_hw_shared(cpu_t *cp, pghw_type_t hw)
1471228Sandrei {
1481772Sjl139090 	int impl;
1491772Sjl139090 
1501772Sjl139090 	impl = cpunodes[cp->cpu_id].implementation;
1511772Sjl139090 
1523434Sesaxe 	switch (hw) {
1533434Sesaxe 	case PGHW_IPIPE:
1543434Sesaxe 		if (IS_OLYMPUS_C(impl))
1553434Sesaxe 			return (1);
1563434Sesaxe 		break;
1573434Sesaxe 	case PGHW_CHIP:
1583676Sesaxe 		if (IS_JAGUAR(impl) || IS_PANTHER(impl) || IS_OLYMPUS_C(impl))
1593434Sesaxe 			return (1);
1603434Sesaxe 		break;
1613434Sesaxe 	case PGHW_CACHE:
1623676Sesaxe 		if (IS_PANTHER(impl) || IS_OLYMPUS_C(impl))
1633434Sesaxe 			return (1);
1643434Sesaxe 		break;
1653434Sesaxe 	}
1663434Sesaxe 	return (0);
1673434Sesaxe }
1683434Sesaxe 
1693434Sesaxe int
1703434Sesaxe pg_plat_cpus_share(cpu_t *cpu_a, cpu_t *cpu_b, pghw_type_t hw)
1713434Sesaxe {
1723676Sesaxe 	int impl;
1733434Sesaxe 
1743676Sesaxe 	impl = cpunodes[cpu_a->cpu_id].implementation;
1753434Sesaxe 
1763434Sesaxe 	switch (hw) {
1773434Sesaxe 	case PGHW_IPIPE:
1783434Sesaxe 	case PGHW_CHIP:
1793434Sesaxe 		return (pg_plat_hw_instance_id(cpu_a, hw) ==
1803434Sesaxe 		    pg_plat_hw_instance_id(cpu_b, hw));
1813434Sesaxe 	case PGHW_CACHE:
1823676Sesaxe 		if ((IS_PANTHER(impl) || IS_OLYMPUS_C(impl)) &&
1833676Sesaxe 		    pg_plat_cpus_share(cpu_a, cpu_b, PGHW_CHIP)) {
1843676Sesaxe 			return (1);
1853676Sesaxe 		} else {
1863676Sesaxe 			return (0);
1873676Sesaxe 		}
1881772Sjl139090 	}
1893434Sesaxe 	return (0);
1903434Sesaxe }
1913434Sesaxe 
1923434Sesaxe id_t
1933434Sesaxe pg_plat_hw_instance_id(cpu_t *cpu, pghw_type_t hw)
1943434Sesaxe {
1953434Sesaxe 	int impl;
1963434Sesaxe 
1973676Sesaxe 	impl = cpunodes[cpu->cpu_id].implementation;
1983676Sesaxe 
1993434Sesaxe 	switch (hw) {
2003434Sesaxe 	case PGHW_IPIPE:
2013434Sesaxe 		if (IS_OLYMPUS_C(impl)) {
2023434Sesaxe 			/*
2033434Sesaxe 			 * Currently only Fujitsu Olympus-c processor supports
2043434Sesaxe 			 * multi-stranded cores. Return the cpu_id with
2053434Sesaxe 			 * the strand bit masked out.
2063434Sesaxe 			 */
2073434Sesaxe 			return ((id_t)((uint_t)cpu->cpu_id & ~(0x1)));
2083434Sesaxe 		} else {
2093434Sesaxe 			return (cpu->cpu_id);
2103434Sesaxe 		}
2113434Sesaxe 	case PGHW_CHIP:
2123434Sesaxe 		return (cmp_cpu_to_chip(cpu->cpu_id));
2133434Sesaxe 	case PGHW_CACHE:
2143676Sesaxe 		if (IS_PANTHER(impl) || IS_OLYMPUS_C(impl))
2153676Sesaxe 			return (pg_plat_hw_instance_id(cpu, PGHW_CHIP));
2163676Sesaxe 		else
2173676Sesaxe 			return (cpu->cpu_id);
2183434Sesaxe 	default:
2193434Sesaxe 		return (-1);
2203434Sesaxe 	}
2213434Sesaxe }
2223434Sesaxe 
2233434Sesaxe int
2243434Sesaxe pg_plat_hw_level(pghw_type_t hw)
2253434Sesaxe {
2263434Sesaxe 	int i;
2273434Sesaxe 	static pghw_type_t hw_hier[] = {
2283434Sesaxe 		PGHW_IPIPE,
2293434Sesaxe 		PGHW_CHIP,
2303434Sesaxe 		PGHW_CACHE,
2313434Sesaxe 		PGHW_NUM_COMPONENTS
2323434Sesaxe 	};
2333434Sesaxe 
2343434Sesaxe 	for (i = 0; hw_hier[i] != PGHW_NUM_COMPONENTS; i++) {
2353434Sesaxe 		if (hw_hier[i] == hw)
2363434Sesaxe 			return (i);
2373434Sesaxe 	}
2383434Sesaxe 	return (-1);
2393434Sesaxe }
2403434Sesaxe 
241*4606Sesaxe /*
242*4606Sesaxe  * Return 1 if CMT load balancing policies should be
243*4606Sesaxe  * implemented across instances of the specified hardware
244*4606Sesaxe  * sharing relationship.
245*4606Sesaxe  */
246*4606Sesaxe int
247*4606Sesaxe pg_plat_cmt_load_bal_hw(pghw_type_t hw)
248*4606Sesaxe {
249*4606Sesaxe 	if (hw == PGHW_IPIPE ||
250*4606Sesaxe 	    hw == PGHW_FPU ||
251*4606Sesaxe 	    hw == PGHW_CHIP)
252*4606Sesaxe 		return (1);
253*4606Sesaxe 	else
254*4606Sesaxe 		return (0);
255*4606Sesaxe }
256*4606Sesaxe 
257*4606Sesaxe 
258*4606Sesaxe /*
259*4606Sesaxe  * Return 1 if thread affinity polices should be implemented
260*4606Sesaxe  * for instances of the specifed hardware sharing relationship.
261*4606Sesaxe  */
262*4606Sesaxe int
263*4606Sesaxe pg_plat_cmt_affinity_hw(pghw_type_t hw)
264*4606Sesaxe {
265*4606Sesaxe 	if (hw == PGHW_CACHE)
266*4606Sesaxe 		return (1);
267*4606Sesaxe 	else
268*4606Sesaxe 		return (0);
269*4606Sesaxe }
270*4606Sesaxe 
2713434Sesaxe id_t
2723434Sesaxe pg_plat_get_core_id(cpu_t *cp)
2733434Sesaxe {
2743434Sesaxe 	return (pg_plat_hw_instance_id(cp, PGHW_IPIPE));
2751228Sandrei }
2761228Sandrei 
2770Sstevel@tonic-gate void
2783434Sesaxe cmp_set_nosteal_interval(void)
2790Sstevel@tonic-gate {
2803434Sesaxe 	/* Set the nosteal interval (used by disp_getbest()) to 100us */
2813434Sesaxe 	nosteal_nsec = 100000UL;
2820Sstevel@tonic-gate }
283