xref: /illumos-gate/usr/src/uts/sun4u/os/cmp.c (revision b885580b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
525cf1a30Sjl  * Common Development and Distribution License (the "License").
625cf1a30Sjl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
220e751525SEric Saxe  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
287c478bd9Sstevel@tonic-gate #include <sys/x_call.h>
297c478bd9Sstevel@tonic-gate #include <sys/cmp.h>
30d129bde2Sesaxe #include <sys/cmt.h>
317c478bd9Sstevel@tonic-gate #include <sys/debug.h>
32685679f7Sakolb #include <sys/disp.h>
337c478bd9Sstevel@tonic-gate #include <sys/cheetahregs.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Note: We assume that chipid == portid.  This is not necessarily true.
377c478bd9Sstevel@tonic-gate  * We buried it down here in the implementation, and not in the
387c478bd9Sstevel@tonic-gate  * interfaces, so that we can change it later.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * pre-alloc'ed because this is used early in boot (before the memory
437c478bd9Sstevel@tonic-gate  * allocator is available).
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate static cpuset_t chips[MAX_CPU_CHIPID];
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * Returns 1 if cpuid is CMP-capable, 0 otherwise.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate int
cmp_cpu_is_cmp(processorid_t cpuid)517c478bd9Sstevel@tonic-gate cmp_cpu_is_cmp(processorid_t cpuid)
527c478bd9Sstevel@tonic-gate {
537c478bd9Sstevel@tonic-gate 	chipid_t chipid;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	/* N.B. We're assuming that the cpunode[].portid is still intact */
567c478bd9Sstevel@tonic-gate 	chipid = cpunodes[cpuid].portid;
577c478bd9Sstevel@tonic-gate 	return (!CPUSET_ISNULL(chips[chipid]));
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * Indicate that this core (cpuid) resides on the chip indicated by chipid.
627c478bd9Sstevel@tonic-gate  * Called during boot and DR add.
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate void
cmp_add_cpu(chipid_t chipid,processorid_t cpuid)657c478bd9Sstevel@tonic-gate cmp_add_cpu(chipid_t chipid, processorid_t cpuid)
667c478bd9Sstevel@tonic-gate {
677c478bd9Sstevel@tonic-gate 	CPUSET_ADD(chips[chipid], cpuid);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * Indicate that this core (cpuid) is being DR removed.
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate void
cmp_delete_cpu(processorid_t cpuid)747c478bd9Sstevel@tonic-gate cmp_delete_cpu(processorid_t cpuid)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	chipid_t chipid;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	/* N.B. We're assuming that the cpunode[].portid is still intact */
797c478bd9Sstevel@tonic-gate 	chipid = cpunodes[cpuid].portid;
807c478bd9Sstevel@tonic-gate 	CPUSET_DEL(chips[chipid], cpuid);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate  * Called when cpuid is being onlined or offlined.  If the offlined
857c478bd9Sstevel@tonic-gate  * processor is CMP-capable then current target of the CMP Error Steering
867c478bd9Sstevel@tonic-gate  * Register is set to either the lowest numbered on-line sibling core, if
877c478bd9Sstevel@tonic-gate  * one exists, or else to this core.
887c478bd9Sstevel@tonic-gate  */
8925cf1a30Sjl /* ARGSUSED */
907c478bd9Sstevel@tonic-gate void
cmp_error_resteer(processorid_t cpuid)917c478bd9Sstevel@tonic-gate cmp_error_resteer(processorid_t cpuid)
927c478bd9Sstevel@tonic-gate {
9325cf1a30Sjl #ifndef	_CMP_NO_ERROR_STEERING
947c478bd9Sstevel@tonic-gate 	cpuset_t mycores;
957c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
967c478bd9Sstevel@tonic-gate 	chipid_t chipid;
977c478bd9Sstevel@tonic-gate 	int i;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	if (!cmp_cpu_is_cmp(cpuid))
100d129bde2Sesaxe 		return;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock));
1037c478bd9Sstevel@tonic-gate 	chipid = cpunodes[cpuid].portid;
1047c478bd9Sstevel@tonic-gate 	mycores = chips[chipid];
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	/* Look for an online sibling core */
1077c478bd9Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++) {
1087c478bd9Sstevel@tonic-gate 		if (i == cpuid)
1097c478bd9Sstevel@tonic-gate 			continue;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 		if (CPU_IN_SET(mycores, i) &&
1127c478bd9Sstevel@tonic-gate 		    (cpu = cpu_get(i)) != NULL && cpu_is_active(cpu)) {
1137c478bd9Sstevel@tonic-gate 			/* Found one, reset error steering  */
1147c478bd9Sstevel@tonic-gate 			xc_one(i, (xcfunc_t *)set_cmp_error_steering, 0, 0);
1157c478bd9Sstevel@tonic-gate 			break;
1167c478bd9Sstevel@tonic-gate 		}
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	/* No online sibling cores, point to this core.  */
1207c478bd9Sstevel@tonic-gate 	if (i == NCPU) {
1217c478bd9Sstevel@tonic-gate 		xc_one(cpuid, (xcfunc_t *)set_cmp_error_steering, 0, 0);
1227c478bd9Sstevel@tonic-gate 	}
12325cf1a30Sjl #else
12425cf1a30Sjl 	/* Not all CMP's support (e.g. Olympus-C by Fujitsu) error steering */
12525cf1a30Sjl 	return;
12625cf1a30Sjl #endif /* _CMP_NO_ERROR_STEERING */
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate chipid_t
cmp_cpu_to_chip(processorid_t cpuid)1307c478bd9Sstevel@tonic-gate cmp_cpu_to_chip(processorid_t cpuid)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	if (!cmp_cpu_is_cmp(cpuid)) {
1337c478bd9Sstevel@tonic-gate 		/* This CPU is not a CMP, so by definition chipid==cpuid */
1347c478bd9Sstevel@tonic-gate 		ASSERT(cpuid < MAX_CPU_CHIPID && CPUSET_ISNULL(chips[cpuid]));
1357c478bd9Sstevel@tonic-gate 		return (cpuid);
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/* N.B. We're assuming that the cpunode[].portid is still intact */
1397c478bd9Sstevel@tonic-gate 	return (cpunodes[cpuid].portid);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
142fb2f18f8Sesaxe /* ARGSUSED */
143fb2f18f8Sesaxe int
pg_plat_hw_shared(cpu_t * cp,pghw_type_t hw)144fb2f18f8Sesaxe pg_plat_hw_shared(cpu_t *cp, pghw_type_t hw)
1458949bcd6Sandrei {
14625cf1a30Sjl 	int impl;
14725cf1a30Sjl 
14825cf1a30Sjl 	impl = cpunodes[cp->cpu_id].implementation;
14925cf1a30Sjl 
150fb2f18f8Sesaxe 	switch (hw) {
151fb2f18f8Sesaxe 	case PGHW_IPIPE:
152e98fafb9Sjl 		if ((IS_OLYMPUS_C(impl)) || (IS_JUPITER(impl)))
153fb2f18f8Sesaxe 			return (1);
154fb2f18f8Sesaxe 		break;
155fb2f18f8Sesaxe 	case PGHW_CHIP:
156e98fafb9Sjl 		if (IS_JAGUAR(impl) || IS_PANTHER(impl) ||
157e98fafb9Sjl 		    IS_OLYMPUS_C(impl) || IS_JUPITER(impl))
158fb2f18f8Sesaxe 			return (1);
159fb2f18f8Sesaxe 		break;
160fb2f18f8Sesaxe 	case PGHW_CACHE:
161e98fafb9Sjl 		if (IS_PANTHER(impl) || IS_OLYMPUS_C(impl) || IS_JUPITER(impl))
162fb2f18f8Sesaxe 			return (1);
163fb2f18f8Sesaxe 		break;
16425cf1a30Sjl 	}
165fb2f18f8Sesaxe 	return (0);
1668949bcd6Sandrei }
1678949bcd6Sandrei 
168fb2f18f8Sesaxe int
pg_plat_cpus_share(cpu_t * cpu_a,cpu_t * cpu_b,pghw_type_t hw)169fb2f18f8Sesaxe pg_plat_cpus_share(cpu_t *cpu_a, cpu_t *cpu_b, pghw_type_t hw)
1707c478bd9Sstevel@tonic-gate {
171a6604450Sesaxe 	int impl;
172fb2f18f8Sesaxe 
173a6604450Sesaxe 	impl = cpunodes[cpu_a->cpu_id].implementation;
174fb2f18f8Sesaxe 
175fb2f18f8Sesaxe 	switch (hw) {
176fb2f18f8Sesaxe 	case PGHW_IPIPE:
177fb2f18f8Sesaxe 	case PGHW_CHIP:
178fb2f18f8Sesaxe 		return (pg_plat_hw_instance_id(cpu_a, hw) ==
179fb2f18f8Sesaxe 		    pg_plat_hw_instance_id(cpu_b, hw));
180fb2f18f8Sesaxe 	case PGHW_CACHE:
181e98fafb9Sjl 		if ((IS_PANTHER(impl) || IS_OLYMPUS_C(impl) ||
182e98fafb9Sjl 		    IS_JUPITER(impl)) && pg_plat_cpus_share(cpu_a,
183e98fafb9Sjl 		    cpu_b, PGHW_CHIP)) {
184a6604450Sesaxe 			return (1);
185a6604450Sesaxe 		} else {
186a6604450Sesaxe 			return (0);
187a6604450Sesaxe 		}
188fb2f18f8Sesaxe 	}
189fb2f18f8Sesaxe 	return (0);
190fb2f18f8Sesaxe }
1917c478bd9Sstevel@tonic-gate 
192fb2f18f8Sesaxe id_t
pg_plat_hw_instance_id(cpu_t * cpu,pghw_type_t hw)193fb2f18f8Sesaxe pg_plat_hw_instance_id(cpu_t *cpu, pghw_type_t hw)
194fb2f18f8Sesaxe {
195fb2f18f8Sesaxe 	int impl;
196fb2f18f8Sesaxe 
197a6604450Sesaxe 	impl = cpunodes[cpu->cpu_id].implementation;
198a6604450Sesaxe 
199fb2f18f8Sesaxe 	switch (hw) {
200fb2f18f8Sesaxe 	case PGHW_IPIPE:
201e98fafb9Sjl 		if (IS_OLYMPUS_C(impl) || IS_JUPITER(impl)) {
202fb2f18f8Sesaxe 			/*
203e98fafb9Sjl 			 * Currently only Fujitsu Olympus-C (SPARC64-VI) and
204e98fafb9Sjl 			 * Jupiter (SPARC64-VII) processors support
205e98fafb9Sjl 			 * multi-stranded cores. Return the cpu_id with the
206e98fafb9Sjl 			 * strand bit masked out.
207fb2f18f8Sesaxe 			 */
208fb2f18f8Sesaxe 			return ((id_t)((uint_t)cpu->cpu_id & ~(0x1)));
209fb2f18f8Sesaxe 		} else {
210fb2f18f8Sesaxe 			return (cpu->cpu_id);
211fb2f18f8Sesaxe 		}
212fb2f18f8Sesaxe 	case PGHW_CHIP:
213fb2f18f8Sesaxe 		return (cmp_cpu_to_chip(cpu->cpu_id));
214fb2f18f8Sesaxe 	case PGHW_CACHE:
215e98fafb9Sjl 		if (IS_PANTHER(impl) ||
216e98fafb9Sjl 		    IS_OLYMPUS_C(impl) || IS_JUPITER(impl))
217a6604450Sesaxe 			return (pg_plat_hw_instance_id(cpu, PGHW_CHIP));
218a6604450Sesaxe 		else
219a6604450Sesaxe 			return (cpu->cpu_id);
220fb2f18f8Sesaxe 	default:
221fb2f18f8Sesaxe 		return (-1);
222fb2f18f8Sesaxe 	}
223fb2f18f8Sesaxe }
2247c478bd9Sstevel@tonic-gate 
2250e751525SEric Saxe /*
2260e751525SEric Saxe  * Rank the relative importance of optimizing for hw1 or hw2
2270e751525SEric Saxe  */
2280e751525SEric Saxe pghw_type_t
pg_plat_hw_rank(pghw_type_t hw1,pghw_type_t hw2)2290e751525SEric Saxe pg_plat_hw_rank(pghw_type_t hw1, pghw_type_t hw2)
230fb2f18f8Sesaxe {
231fb2f18f8Sesaxe 	int i;
2320e751525SEric Saxe 	int rank1 = 0;
2330e751525SEric Saxe 	int rank2 = 0;
2340e751525SEric Saxe 
235fb2f18f8Sesaxe 	static pghw_type_t hw_hier[] = {
236fb2f18f8Sesaxe 		PGHW_IPIPE,
237fb2f18f8Sesaxe 		PGHW_CHIP,
238fb2f18f8Sesaxe 		PGHW_CACHE,
239fb2f18f8Sesaxe 		PGHW_NUM_COMPONENTS
240fb2f18f8Sesaxe 	};
241fb2f18f8Sesaxe 
242fb2f18f8Sesaxe 	for (i = 0; hw_hier[i] != PGHW_NUM_COMPONENTS; i++) {
2430e751525SEric Saxe 		if (hw_hier[i] == hw1)
2440e751525SEric Saxe 			rank1 = i;
2450e751525SEric Saxe 		if (hw_hier[i] == hw2)
2460e751525SEric Saxe 			rank2 = i;
2477c478bd9Sstevel@tonic-gate 	}
248fb2f18f8Sesaxe 
2490e751525SEric Saxe 	if (rank1 > rank2)
2500e751525SEric Saxe 		return (hw1);
251d129bde2Sesaxe 	else
2520e751525SEric Saxe 		return (hw2);
253d129bde2Sesaxe }
254d129bde2Sesaxe 
255d129bde2Sesaxe /*
2560e751525SEric Saxe  * Override the default CMT dispatcher policy for the specified
2570e751525SEric Saxe  * hardware sharing relationship
258d129bde2Sesaxe  */
2590e751525SEric Saxe /* ARGSUSED */
2600e751525SEric Saxe pg_cmt_policy_t
pg_plat_cmt_policy(pghw_type_t hw)2610e751525SEric Saxe pg_plat_cmt_policy(pghw_type_t hw)
262d129bde2Sesaxe {
2630e751525SEric Saxe 	/* Accept the default polices */
2640e751525SEric Saxe 	return (CMT_NO_POLICY);
265d129bde2Sesaxe }
266d129bde2Sesaxe 
267fb2f18f8Sesaxe id_t
pg_plat_get_core_id(cpu_t * cp)268fb2f18f8Sesaxe pg_plat_get_core_id(cpu_t *cp)
269fb2f18f8Sesaxe {
270fb2f18f8Sesaxe 	return (pg_plat_hw_instance_id(cp, PGHW_IPIPE));
271fb2f18f8Sesaxe }
2727c478bd9Sstevel@tonic-gate 
273fb2f18f8Sesaxe void
cmp_set_nosteal_interval(void)274fb2f18f8Sesaxe cmp_set_nosteal_interval(void)
275fb2f18f8Sesaxe {
276fb2f18f8Sesaxe 	/* Set the nosteal interval (used by disp_getbest()) to 100us */
277fb2f18f8Sesaxe 	nosteal_nsec = 100000UL;
2787c478bd9Sstevel@tonic-gate }
279ce8eb11aSdp /*
280ce8eb11aSdp  * Return 1 if CMT load balancing policies should be
281ce8eb11aSdp  * implemented across instances of the specified hardware
282ce8eb11aSdp  * sharing relationship.
283ce8eb11aSdp  */
284ce8eb11aSdp int
pg_cmt_load_bal_hw(pghw_type_t hw)285ce8eb11aSdp pg_cmt_load_bal_hw(pghw_type_t hw)
286ce8eb11aSdp {
287ce8eb11aSdp 	if (hw == PGHW_IPIPE ||
288ce8eb11aSdp 	    hw == PGHW_FPU ||
289ce8eb11aSdp 	    hw == PGHW_CHIP)
290ce8eb11aSdp 		return (1);
291ce8eb11aSdp 	else
292ce8eb11aSdp 		return (0);
293ce8eb11aSdp }
294ce8eb11aSdp /*
295ce8eb11aSdp  * Return 1 if thread affinity polices should be implemented
296ce8eb11aSdp  * for instances of the specifed hardware sharing relationship.
297ce8eb11aSdp  */
298ce8eb11aSdp int
pg_cmt_affinity_hw(pghw_type_t hw)299ce8eb11aSdp pg_cmt_affinity_hw(pghw_type_t hw)
300ce8eb11aSdp {
301ce8eb11aSdp 	if (hw == PGHW_CACHE)
302ce8eb11aSdp 		return (1);
303ce8eb11aSdp 	else
304ce8eb11aSdp 		return (0);
305ce8eb11aSdp }
306*b885580bSAlexander Kolbasov 
307*b885580bSAlexander Kolbasov /*
308*b885580bSAlexander Kolbasov  * Return number of counter events requested to measure hardware capacity and
309*b885580bSAlexander Kolbasov  * utilization and setup CPC requests for specified CPU if list where to add
310*b885580bSAlexander Kolbasov  * CPC requests is given
311*b885580bSAlexander Kolbasov  */
312*b885580bSAlexander Kolbasov int
313*b885580bSAlexander Kolbasov /* LINTED E_FUNC_ARG_UNUSED */
cu_plat_cpc_init(cpu_t * cp,kcpc_request_list_t * reqs,int nreqs)314*b885580bSAlexander Kolbasov cu_plat_cpc_init(cpu_t *cp, kcpc_request_list_t *reqs, int nreqs)
315*b885580bSAlexander Kolbasov {
316*b885580bSAlexander Kolbasov 	/*
317*b885580bSAlexander Kolbasov 	 * Return error to tell common code to decide what counter events to
318*b885580bSAlexander Kolbasov 	 * program on this CPU for measuring hardware capacity and utilization
319*b885580bSAlexander Kolbasov 	 */
320*b885580bSAlexander Kolbasov 	return (-1);
321*b885580bSAlexander Kolbasov }
322