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 /*
228906SEric.Saxe@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/machsystm.h>
280Sstevel@tonic-gate #include <sys/x_call.h>
290Sstevel@tonic-gate #include <sys/cmp.h>
304606Sesaxe #include <sys/cmt.h>
310Sstevel@tonic-gate #include <sys/debug.h>
322041Sakolb #include <sys/disp.h>
330Sstevel@tonic-gate #include <sys/cheetahregs.h>
340Sstevel@tonic-gate
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate * Note: We assume that chipid == portid. This is not necessarily true.
370Sstevel@tonic-gate * We buried it down here in the implementation, and not in the
380Sstevel@tonic-gate * interfaces, so that we can change it later.
390Sstevel@tonic-gate */
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * pre-alloc'ed because this is used early in boot (before the memory
430Sstevel@tonic-gate * allocator is available).
440Sstevel@tonic-gate */
450Sstevel@tonic-gate static cpuset_t chips[MAX_CPU_CHIPID];
460Sstevel@tonic-gate
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate * Returns 1 if cpuid is CMP-capable, 0 otherwise.
490Sstevel@tonic-gate */
500Sstevel@tonic-gate int
cmp_cpu_is_cmp(processorid_t cpuid)510Sstevel@tonic-gate cmp_cpu_is_cmp(processorid_t cpuid)
520Sstevel@tonic-gate {
530Sstevel@tonic-gate chipid_t chipid;
540Sstevel@tonic-gate
550Sstevel@tonic-gate /* N.B. We're assuming that the cpunode[].portid is still intact */
560Sstevel@tonic-gate chipid = cpunodes[cpuid].portid;
570Sstevel@tonic-gate return (!CPUSET_ISNULL(chips[chipid]));
580Sstevel@tonic-gate }
590Sstevel@tonic-gate
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate * Indicate that this core (cpuid) resides on the chip indicated by chipid.
620Sstevel@tonic-gate * Called during boot and DR add.
630Sstevel@tonic-gate */
640Sstevel@tonic-gate void
cmp_add_cpu(chipid_t chipid,processorid_t cpuid)650Sstevel@tonic-gate cmp_add_cpu(chipid_t chipid, processorid_t cpuid)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate CPUSET_ADD(chips[chipid], cpuid);
680Sstevel@tonic-gate }
690Sstevel@tonic-gate
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * Indicate that this core (cpuid) is being DR removed.
720Sstevel@tonic-gate */
730Sstevel@tonic-gate void
cmp_delete_cpu(processorid_t cpuid)740Sstevel@tonic-gate cmp_delete_cpu(processorid_t cpuid)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate chipid_t chipid;
770Sstevel@tonic-gate
780Sstevel@tonic-gate /* N.B. We're assuming that the cpunode[].portid is still intact */
790Sstevel@tonic-gate chipid = cpunodes[cpuid].portid;
800Sstevel@tonic-gate CPUSET_DEL(chips[chipid], cpuid);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate * Called when cpuid is being onlined or offlined. If the offlined
850Sstevel@tonic-gate * processor is CMP-capable then current target of the CMP Error Steering
860Sstevel@tonic-gate * Register is set to either the lowest numbered on-line sibling core, if
870Sstevel@tonic-gate * one exists, or else to this core.
880Sstevel@tonic-gate */
891772Sjl139090 /* ARGSUSED */
900Sstevel@tonic-gate void
cmp_error_resteer(processorid_t cpuid)910Sstevel@tonic-gate cmp_error_resteer(processorid_t cpuid)
920Sstevel@tonic-gate {
931772Sjl139090 #ifndef _CMP_NO_ERROR_STEERING
940Sstevel@tonic-gate cpuset_t mycores;
950Sstevel@tonic-gate cpu_t *cpu;
960Sstevel@tonic-gate chipid_t chipid;
970Sstevel@tonic-gate int i;
980Sstevel@tonic-gate
990Sstevel@tonic-gate if (!cmp_cpu_is_cmp(cpuid))
1004606Sesaxe return;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock));
1030Sstevel@tonic-gate chipid = cpunodes[cpuid].portid;
1040Sstevel@tonic-gate mycores = chips[chipid];
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate /* Look for an online sibling core */
1070Sstevel@tonic-gate for (i = 0; i < NCPU; i++) {
1080Sstevel@tonic-gate if (i == cpuid)
1090Sstevel@tonic-gate continue;
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate if (CPU_IN_SET(mycores, i) &&
1120Sstevel@tonic-gate (cpu = cpu_get(i)) != NULL && cpu_is_active(cpu)) {
1130Sstevel@tonic-gate /* Found one, reset error steering */
1140Sstevel@tonic-gate xc_one(i, (xcfunc_t *)set_cmp_error_steering, 0, 0);
1150Sstevel@tonic-gate break;
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /* No online sibling cores, point to this core. */
1200Sstevel@tonic-gate if (i == NCPU) {
1210Sstevel@tonic-gate xc_one(cpuid, (xcfunc_t *)set_cmp_error_steering, 0, 0);
1220Sstevel@tonic-gate }
1231772Sjl139090 #else
1241772Sjl139090 /* Not all CMP's support (e.g. Olympus-C by Fujitsu) error steering */
1251772Sjl139090 return;
1261772Sjl139090 #endif /* _CMP_NO_ERROR_STEERING */
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate chipid_t
cmp_cpu_to_chip(processorid_t cpuid)1300Sstevel@tonic-gate cmp_cpu_to_chip(processorid_t cpuid)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate if (!cmp_cpu_is_cmp(cpuid)) {
1330Sstevel@tonic-gate /* This CPU is not a CMP, so by definition chipid==cpuid */
1340Sstevel@tonic-gate ASSERT(cpuid < MAX_CPU_CHIPID && CPUSET_ISNULL(chips[cpuid]));
1350Sstevel@tonic-gate return (cpuid);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate /* N.B. We're assuming that the cpunode[].portid is still intact */
1390Sstevel@tonic-gate return (cpunodes[cpuid].portid);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1423434Sesaxe /* ARGSUSED */
1433434Sesaxe int
pg_plat_hw_shared(cpu_t * cp,pghw_type_t hw)1443434Sesaxe pg_plat_hw_shared(cpu_t *cp, pghw_type_t hw)
1451228Sandrei {
1461772Sjl139090 int impl;
1471772Sjl139090
1481772Sjl139090 impl = cpunodes[cp->cpu_id].implementation;
1491772Sjl139090
1503434Sesaxe switch (hw) {
1513434Sesaxe case PGHW_IPIPE:
1525037Sjl139090 if ((IS_OLYMPUS_C(impl)) || (IS_JUPITER(impl)))
1533434Sesaxe return (1);
1543434Sesaxe break;
1553434Sesaxe case PGHW_CHIP:
1565037Sjl139090 if (IS_JAGUAR(impl) || IS_PANTHER(impl) ||
1575037Sjl139090 IS_OLYMPUS_C(impl) || IS_JUPITER(impl))
1583434Sesaxe return (1);
1593434Sesaxe break;
1603434Sesaxe case PGHW_CACHE:
1615037Sjl139090 if (IS_PANTHER(impl) || IS_OLYMPUS_C(impl) || IS_JUPITER(impl))
1623434Sesaxe return (1);
1633434Sesaxe break;
1643434Sesaxe }
1653434Sesaxe return (0);
1663434Sesaxe }
1673434Sesaxe
1683434Sesaxe int
pg_plat_cpus_share(cpu_t * cpu_a,cpu_t * cpu_b,pghw_type_t hw)1693434Sesaxe pg_plat_cpus_share(cpu_t *cpu_a, cpu_t *cpu_b, pghw_type_t hw)
1703434Sesaxe {
1713676Sesaxe int impl;
1723434Sesaxe
1733676Sesaxe impl = cpunodes[cpu_a->cpu_id].implementation;
1743434Sesaxe
1753434Sesaxe switch (hw) {
1763434Sesaxe case PGHW_IPIPE:
1773434Sesaxe case PGHW_CHIP:
1783434Sesaxe return (pg_plat_hw_instance_id(cpu_a, hw) ==
1793434Sesaxe pg_plat_hw_instance_id(cpu_b, hw));
1803434Sesaxe case PGHW_CACHE:
1815037Sjl139090 if ((IS_PANTHER(impl) || IS_OLYMPUS_C(impl) ||
1825037Sjl139090 IS_JUPITER(impl)) && pg_plat_cpus_share(cpu_a,
1835037Sjl139090 cpu_b, PGHW_CHIP)) {
1843676Sesaxe return (1);
1853676Sesaxe } else {
1863676Sesaxe return (0);
1873676Sesaxe }
1881772Sjl139090 }
1893434Sesaxe return (0);
1903434Sesaxe }
1913434Sesaxe
1923434Sesaxe id_t
pg_plat_hw_instance_id(cpu_t * cpu,pghw_type_t hw)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:
2015037Sjl139090 if (IS_OLYMPUS_C(impl) || IS_JUPITER(impl)) {
2023434Sesaxe /*
2035037Sjl139090 * Currently only Fujitsu Olympus-C (SPARC64-VI) and
2045037Sjl139090 * Jupiter (SPARC64-VII) processors support
2055037Sjl139090 * multi-stranded cores. Return the cpu_id with the
2065037Sjl139090 * strand bit masked out.
2073434Sesaxe */
2083434Sesaxe return ((id_t)((uint_t)cpu->cpu_id & ~(0x1)));
2093434Sesaxe } else {
2103434Sesaxe return (cpu->cpu_id);
2113434Sesaxe }
2123434Sesaxe case PGHW_CHIP:
2133434Sesaxe return (cmp_cpu_to_chip(cpu->cpu_id));
2143434Sesaxe case PGHW_CACHE:
2155037Sjl139090 if (IS_PANTHER(impl) ||
2165037Sjl139090 IS_OLYMPUS_C(impl) || IS_JUPITER(impl))
2173676Sesaxe return (pg_plat_hw_instance_id(cpu, PGHW_CHIP));
2183676Sesaxe else
2193676Sesaxe return (cpu->cpu_id);
2203434Sesaxe default:
2213434Sesaxe return (-1);
2223434Sesaxe }
2233434Sesaxe }
2243434Sesaxe
2258906SEric.Saxe@Sun.COM /*
2268906SEric.Saxe@Sun.COM * Rank the relative importance of optimizing for hw1 or hw2
2278906SEric.Saxe@Sun.COM */
2288906SEric.Saxe@Sun.COM pghw_type_t
pg_plat_hw_rank(pghw_type_t hw1,pghw_type_t hw2)2298906SEric.Saxe@Sun.COM pg_plat_hw_rank(pghw_type_t hw1, pghw_type_t hw2)
2303434Sesaxe {
2313434Sesaxe int i;
2328906SEric.Saxe@Sun.COM int rank1 = 0;
2338906SEric.Saxe@Sun.COM int rank2 = 0;
2348906SEric.Saxe@Sun.COM
2353434Sesaxe static pghw_type_t hw_hier[] = {
2363434Sesaxe PGHW_IPIPE,
2373434Sesaxe PGHW_CHIP,
2383434Sesaxe PGHW_CACHE,
2393434Sesaxe PGHW_NUM_COMPONENTS
2403434Sesaxe };
2413434Sesaxe
2423434Sesaxe for (i = 0; hw_hier[i] != PGHW_NUM_COMPONENTS; i++) {
2438906SEric.Saxe@Sun.COM if (hw_hier[i] == hw1)
2448906SEric.Saxe@Sun.COM rank1 = i;
2458906SEric.Saxe@Sun.COM if (hw_hier[i] == hw2)
2468906SEric.Saxe@Sun.COM rank2 = i;
2473434Sesaxe }
2488906SEric.Saxe@Sun.COM
2498906SEric.Saxe@Sun.COM if (rank1 > rank2)
2508906SEric.Saxe@Sun.COM return (hw1);
2518906SEric.Saxe@Sun.COM else
2528906SEric.Saxe@Sun.COM return (hw2);
2533434Sesaxe }
2543434Sesaxe
2554606Sesaxe /*
2568906SEric.Saxe@Sun.COM * Override the default CMT dispatcher policy for the specified
2578906SEric.Saxe@Sun.COM * hardware sharing relationship
2584606Sesaxe */
2598906SEric.Saxe@Sun.COM /* ARGSUSED */
2608906SEric.Saxe@Sun.COM pg_cmt_policy_t
pg_plat_cmt_policy(pghw_type_t hw)2618906SEric.Saxe@Sun.COM pg_plat_cmt_policy(pghw_type_t hw)
2624606Sesaxe {
2638906SEric.Saxe@Sun.COM /* Accept the default polices */
2648906SEric.Saxe@Sun.COM return (CMT_NO_POLICY);
2654606Sesaxe }
2664606Sesaxe
2673434Sesaxe id_t
pg_plat_get_core_id(cpu_t * cp)2683434Sesaxe pg_plat_get_core_id(cpu_t *cp)
2693434Sesaxe {
2703434Sesaxe return (pg_plat_hw_instance_id(cp, PGHW_IPIPE));
2711228Sandrei }
2721228Sandrei
2730Sstevel@tonic-gate void
cmp_set_nosteal_interval(void)2743434Sesaxe cmp_set_nosteal_interval(void)
2750Sstevel@tonic-gate {
2763434Sesaxe /* Set the nosteal interval (used by disp_getbest()) to 100us */
2773434Sesaxe nosteal_nsec = 100000UL;
2780Sstevel@tonic-gate }
2794769Sdp78419 /*
2804769Sdp78419 * Return 1 if CMT load balancing policies should be
2814769Sdp78419 * implemented across instances of the specified hardware
2824769Sdp78419 * sharing relationship.
2834769Sdp78419 */
2844769Sdp78419 int
pg_cmt_load_bal_hw(pghw_type_t hw)2854769Sdp78419 pg_cmt_load_bal_hw(pghw_type_t hw)
2864769Sdp78419 {
2874769Sdp78419 if (hw == PGHW_IPIPE ||
2884769Sdp78419 hw == PGHW_FPU ||
2894769Sdp78419 hw == PGHW_CHIP)
2904769Sdp78419 return (1);
2914769Sdp78419 else
2924769Sdp78419 return (0);
2934769Sdp78419 }
2944769Sdp78419 /*
2954769Sdp78419 * Return 1 if thread affinity polices should be implemented
2964769Sdp78419 * for instances of the specifed hardware sharing relationship.
2974769Sdp78419 */
2984769Sdp78419 int
pg_cmt_affinity_hw(pghw_type_t hw)2994769Sdp78419 pg_cmt_affinity_hw(pghw_type_t hw)
3004769Sdp78419 {
3014769Sdp78419 if (hw == PGHW_CACHE)
3024769Sdp78419 return (1);
3034769Sdp78419 else
3044769Sdp78419 return (0);
3054769Sdp78419 }
306*11389SAlexander.Kolbasov@Sun.COM
307*11389SAlexander.Kolbasov@Sun.COM /*
308*11389SAlexander.Kolbasov@Sun.COM * Return number of counter events requested to measure hardware capacity and
309*11389SAlexander.Kolbasov@Sun.COM * utilization and setup CPC requests for specified CPU if list where to add
310*11389SAlexander.Kolbasov@Sun.COM * CPC requests is given
311*11389SAlexander.Kolbasov@Sun.COM */
312*11389SAlexander.Kolbasov@Sun.COM int
313*11389SAlexander.Kolbasov@Sun.COM /* LINTED E_FUNC_ARG_UNUSED */
cu_plat_cpc_init(cpu_t * cp,kcpc_request_list_t * reqs,int nreqs)314*11389SAlexander.Kolbasov@Sun.COM cu_plat_cpc_init(cpu_t *cp, kcpc_request_list_t *reqs, int nreqs)
315*11389SAlexander.Kolbasov@Sun.COM {
316*11389SAlexander.Kolbasov@Sun.COM /*
317*11389SAlexander.Kolbasov@Sun.COM * Return error to tell common code to decide what counter events to
318*11389SAlexander.Kolbasov@Sun.COM * program on this CPU for measuring hardware capacity and utilization
319*11389SAlexander.Kolbasov@Sun.COM */
320*11389SAlexander.Kolbasov@Sun.COM return (-1);
321*11389SAlexander.Kolbasov@Sun.COM }
322