17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
51ae0874heppo * Common Development and Distribution License (the "License").
61ae0874heppo * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
2294c894bVikram Hegde * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bdstevel@tonic-gate */
247c478bdstevel@tonic-gate
257c478bdstevel@tonic-gate#include <sys/errno.h>
267c478bdstevel@tonic-gate#include <sys/types.h>
277c478bdstevel@tonic-gate#include <sys/param.h>
287c478bdstevel@tonic-gate#include <sys/cpu.h>
297c478bdstevel@tonic-gate#include <sys/cpuvar.h>
307c478bdstevel@tonic-gate#include <sys/clock.h>
317c478bdstevel@tonic-gate#include <sys/promif.h>
327c478bdstevel@tonic-gate#include <sys/promimpl.h>
337c478bdstevel@tonic-gate#include <sys/systm.h>
347c478bdstevel@tonic-gate#include <sys/machsystm.h>
357c478bdstevel@tonic-gate#include <sys/debug.h>
367c478bdstevel@tonic-gate#include <sys/sunddi.h>
377c478bdstevel@tonic-gate#include <sys/modctl.h>
387c478bdstevel@tonic-gate#include <sys/cpu_module.h>
397c478bdstevel@tonic-gate#include <sys/kobj.h>
407c478bdstevel@tonic-gate#include <sys/cmp.h>
417c478bdstevel@tonic-gate#include <sys/async.h>
427c478bdstevel@tonic-gate#include <vm/page.h>
431ae0874heppo#include <vm/hat_sfmmu.h>
441ae0874heppo#include <sys/sysmacros.h>
451ae0874heppo#include <sys/mach_descrip.h>
461ae0874heppo#include <sys/mdesc.h>
471ae0874heppo#include <sys/archsystm.h>
481ae0874heppo#include <sys/error.h>
491ae0874heppo#include <sys/mmu.h>
501ae0874heppo#include <sys/bitmap.h>
514bac220narayan#include <sys/intreg.h>
5294c894bVikram Hegde#include <sys/instance.h>
537c478bdstevel@tonic-gate
547c478bdstevel@tonic-gatestruct cpu_node cpunodes[NCPU];
557c478bdstevel@tonic-gate
561ae0874heppouint64_t cpu_q_entries;
571ae0874heppouint64_t dev_q_entries;
581ae0874heppouint64_t cpu_rq_entries;
591ae0874heppouint64_t cpu_nrq_entries;
60aaa10e6hauint64_t ncpu_guest_max;
611ae0874heppo
621ae0874heppovoid fill_cpu(md_t *, mde_cookie_t);
631ae0874heppo
641ae0874heppostatic uint64_t get_mmu_ctx_bits(md_t *, mde_cookie_t);
6505d3dc4paulsanstatic uint64_t get_mmu_tsbs(md_t *, mde_cookie_t);
6605d3dc4paulsanstatic uint64_t	get_mmu_shcontexts(md_t *, mde_cookie_t);
671ae0874heppostatic uint64_t get_cpu_pagesizes(md_t *, mde_cookie_t);
681ae0874heppostatic char *construct_isalist(md_t *, mde_cookie_t, char **);
694bac220narayanstatic void init_md_broken(md_t *, mde_cookie_t *);
701ae0874heppostatic int get_l2_cache_info(md_t *, mde_cookie_t, uint64_t *, uint64_t *,
711ae0874heppo    uint64_t *);
722f0fcb9Jason Belorostatic void get_hwcaps(md_t *, mde_cookie_t);
732c5124aPrashanth Sreenivasastatic void get_weakest_mem_model(md_t *, mde_cookie_t);
741ae0874heppostatic void get_q_sizes(md_t *, mde_cookie_t);
751ae0874heppostatic void get_va_bits(md_t *, mde_cookie_t);
769853d9eJason Belorostatic size_t get_ra_limit(md_t *, mde_cookie_t);
77575a742ptstatic int get_l2_cache_node_count(md_t *);
782f0fcb9Jason Belorostatic unsigned long names2bits(char *tokens, size_t tokenslen,
792f0fcb9Jason Beloro    char *bit_formatter, char *warning);
807c478bdstevel@tonic-gate
817c478bdstevel@tonic-gateuint64_t	system_clock_freq;
827c478bdstevel@tonic-gateuint_t		niommu_tsbs = 0;
837c478bdstevel@tonic-gate
84575a742ptstatic int n_l2_caches = 0;
85575a742pt
86fedab56ae/* prevent compilation with VAC defined */
87fedab56ae#ifdef VAC
88fedab56ae#error "The sun4v architecture does not support VAC"
89fedab56ae#endif
90fedab56ae
91fedab56ae#define	S_VAC_SIZE	MMU_PAGESIZE
92fedab56ae#define	S_VAC_SHIFT	MMU_PAGESHIFT
93fedab56ae
94fedab56aeint		vac_size = S_VAC_SIZE;
95fedab56aeuint_t		vac_mask = MMU_PAGEMASK & (S_VAC_SIZE - 1);
96fedab56aeint		vac_shift = S_VAC_SHIFT;
97fedab56aeuintptr_t	shm_alignment = S_VAC_SIZE;
98fedab56ae
991ae0874heppovoid
1001ae0874heppomap_wellknown_devices()
1011ae0874heppo{
1021ae0874heppo}
1037c478bdstevel@tonic-gate
1047c478bdstevel@tonic-gatevoid
1051ae0874heppofill_cpu(md_t *mdp, mde_cookie_t cpuc)
1067c478bdstevel@tonic-gate{
1071ae0874heppo	struct cpu_node *cpunode;
1081ae0874heppo	uint64_t cpuid;
1091ae0874heppo	uint64_t clk_freq;
1101ae0874heppo	char *namebuf;
1111ae0874heppo	char *namebufp;
1121ae0874heppo	int namelen;
1131ae0874heppo	uint64_t associativity = 0, linesize = 0, size = 0;
1141ae0874heppo
1151ae0874heppo	if (md_get_prop_val(mdp, cpuc, "id", &cpuid)) {
1161ae0874heppo		return;
1171ae0874heppo	}
1187c478bdstevel@tonic-gate
1194bac220narayan	/* All out-of-range cpus will be stopped later. */
1201ae0874heppo	if (cpuid >= NCPU) {
1211ae0874heppo		cmn_err(CE_CONT, "fill_cpu: out of range cpuid %ld - "
1224bac220narayan		    "cpu excluded from configuration\n", cpuid);
1231ae0874heppo
1241ae0874heppo		return;
1251ae0874heppo	}
1261ae0874heppo
1271ae0874heppo	cpunode = &cpunodes[cpuid];
1281ae0874heppo	cpunode->cpuid = (int)cpuid;
1291ae0874heppo	cpunode->device_id = cpuid;
1301ae0874heppo
1311ae0874heppo	if (sizeof (cpunode->fru_fmri) > strlen(CPU_FRU_FMRI))
1321ae0874heppo		(void) strcpy(cpunode->fru_fmri, CPU_FRU_FMRI);
1331ae0874heppo
1341ae0874heppo	if (md_get_prop_data(mdp, cpuc,
1351ae0874heppo	    "compatible", (uint8_t **)&namebuf, &namelen)) {
1361ae0874heppo		cmn_err(CE_PANIC, "fill_cpu: Cannot read compatible "
1371ae0874heppo		    "property");
1381ae0874heppo	}
1391ae0874heppo	namebufp = namebuf;
1401ae0874heppo	if (strncmp(namebufp, "SUNW,", 5) == 0)
1411ae0874heppo		namebufp += 5;
1421ae0874heppo	if (strlen(namebufp) > sizeof (cpunode->name))
1431ae0874heppo		cmn_err(CE_PANIC, "Compatible property too big to "
1441ae0874heppo		    "fit into the cpunode name buffer");
1451ae0874heppo	(void) strcpy(cpunode->name, namebufp);
1461ae0874heppo
1471ae0874heppo	if (md_get_prop_val(mdp, cpuc,
1481ae0874heppo	    "clock-frequency", &clk_freq)) {
1491ae0874heppo			clk_freq = 0;
1501ae0874heppo	}
1511ae0874heppo	cpunode->clock_freq = clk_freq;
1521ae0874heppo
1531ae0874heppo	ASSERT(cpunode->clock_freq != 0);
1547c478bdstevel@tonic-gate	/*
1551ae0874heppo	 * Compute scaling factor based on rate of %tick. This is used
1561ae0874heppo	 * to convert from ticks derived from %tick to nanoseconds. See
1571ae0874heppo	 * comment in sun4u/sys/clock.h for details.
1587c478bdstevel@tonic-gate	 */
1591ae0874heppo	cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC <<
1601ae0874heppo	    (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq);
1617c478bdstevel@tonic-gate
1627c478bdstevel@tonic-gate	/*
1631ae0874heppo	 * The nodeid is not used in sun4v at all. Setting it
1641ae0874heppo	 * to positive value to make starting of slave CPUs
1651ae0874heppo	 * code happy.
1667c478bdstevel@tonic-gate	 */
1671ae0874heppo	cpunode->nodeid = cpuid + 1;
1687c478bdstevel@tonic-gate
1697c478bdstevel@tonic-gate	/*
1701ae0874heppo	 * Obtain the L2 cache information from MD.
1711ae0874heppo	 * If "Cache" node exists, then set L2 cache properties
1721ae0874heppo	 * as read from MD.
1731ae0874heppo	 * If node does not exists, then set the L2 cache properties
1741ae0874heppo	 * in individual CPU module.
1757c478bdstevel@tonic-gate	 */
1761ae0874heppo	if ((!get_l2_cache_info(mdp, cpuc,
1771ae0874heppo	    &associativity, &size, &linesize)) ||
1781ae0874heppo	    associativity == 0 || size == 0 || linesize == 0) {
1791ae0874heppo		cpu_fiximp(cpunode);
1801ae0874heppo	} else {
1811ae0874heppo		/*
1821ae0874heppo		 * Do not expect L2 cache properties to be bigger
1831ae0874heppo		 * than 32-bit quantity.
1841ae0874heppo		 */
1851ae0874heppo		cpunode->ecache_associativity = (int)associativity;
1861ae0874heppo		cpunode->ecache_size = (int)size;
1871ae0874heppo		cpunode->ecache_linesize = (int)linesize;
1887c478bdstevel@tonic-gate	}
1891ae0874heppo
1901ae0874heppo	cpunode->ecache_setsize =
1911ae0874heppo	    cpunode->ecache_size / cpunode->ecache_associativity;
1921ae0874heppo
19359ac0c1davemq	/*
19459ac0c1davemq	 * Initialize the mapping for exec unit, chip and core.
19559ac0c1davemq	 */
1961ae0874heppo	cpunode->exec_unit_mapping = NO_EU_MAPPING_FOUND;
19759ac0c1davemq	cpunode->l2_cache_mapping = NO_MAPPING_FOUND;
19859ac0c1davemq	cpunode->core_mapping = NO_CORE_MAPPING_FOUND;
1991ae0874heppo
2001ae0874heppo	if (ecache_setsize == 0)
2011ae0874heppo		ecache_setsize = cpunode->ecache_setsize;
2021ae0874heppo	if (ecache_alignsize == 0)
2031ae0874heppo		ecache_alignsize = cpunode->ecache_linesize;
2041ae0874heppo
2057c478bdstevel@tonic-gate}
2067c478bdstevel@tonic-gate
2071ae0874heppovoid
2081ae0874heppoempty_cpu(int cpuid)
2097c478bdstevel@tonic-gate{
2101ae0874heppo	bzero(&cpunodes[cpuid], sizeof (struct cpu_node));
2111ae0874heppo}
2127c478bdstevel@tonic-gate
21359ac0c1davemq/*
21459ac0c1davemq * Use L2 cache node to derive the chip mapping.
21559ac0c1davemq */
21659ac0c1davemqvoid
21759ac0c1davemqsetup_chip_mappings(md_t *mdp)
21859ac0c1davemq{
2192f0fcb9Jason Beloro	int ncache, ncpu;
22059ac0c1davemq	mde_cookie_t *node, *cachelist;
22159ac0c1davemq	int i, j;
22259ac0c1davemq	processorid_t cpuid;
22359ac0c1davemq	int idx = 0;
22459ac0c1davemq
22559ac0c1davemq	ncache = md_alloc_scan_dag(mdp, md_root_node(mdp), "cache",
22659ac0c1davemq	    "fwd", &cachelist);
22759ac0c1davemq
22859ac0c1davemq	/*
22959ac0c1davemq	 * The "cache" node is optional in MD, therefore ncaches can be 0.
23059ac0c1davemq	 */
23159ac0c1davemq	if (ncache < 1) {
23259ac0c1davemq		return;
23359ac0c1davemq	}
23459ac0c1davemq
23559ac0c1davemq	for (i = 0; i < ncache; i++) {
23659ac0c1davemq		uint64_t cache_level;
23759ac0c1davemq		uint64_t lcpuid;
23859ac0c1davemq
23959ac0c1davemq		if (md_get_prop_val(mdp, cachelist[i], "level", &cache_level))
24059ac0c1davemq			continue;
24159ac0c1davemq
24259ac0c1davemq		if (cache_level != 2)
24359ac0c1davemq			continue;
24459ac0c1davemq
24559ac0c1davemq		/*
24659ac0c1davemq		 * Found a l2 cache node. Find out the cpu nodes it
24759ac0c1davemq		 * points to.
24859ac0c1davemq		 */
24959ac0c1davemq		ncpu = md_alloc_scan_dag(mdp, cachelist[i], "cpu",
25059ac0c1davemq		    "back", &node);
25159ac0c1davemq
25259ac0c1davemq		if (ncpu < 1)
25359ac0c1davemq			continue;
25459ac0c1davemq
25559ac0c1davemq		for (j = 0; j < ncpu; j++) {
25659ac0c1davemq			if (md_get_prop_val(mdp, node[j], "id", &lcpuid))
25759ac0c1davemq				continue;
25859ac0c1davemq			if (lcpuid >= NCPU)
25959ac0c1davemq				continue;
26059ac0c1davemq			cpuid = (processorid_t)lcpuid;
26159ac0c1davemq			cpunodes[cpuid].l2_cache_mapping = idx;
26259ac0c1davemq		}
26359ac0c1davemq		md_free_scan_dag(mdp, &node);
26459ac0c1davemq
26559ac0c1davemq		idx++;
26659ac0c1davemq	}
26759ac0c1davemq
26859ac0c1davemq	md_free_scan_dag(mdp, &cachelist);
26959ac0c1davemq}
27059ac0c1davemq
2711ae0874heppovoid
2721ae0874hepposetup_exec_unit_mappings(md_t *mdp)
2731ae0874heppo{
2742f0fcb9Jason Beloro	int num, num_eunits;
2751ae0874heppo	mde_cookie_t cpus_node;
2761ae0874heppo	mde_cookie_t *node, *eunit;
2771ae0874heppo	int idx, i, j;
2781ae0874heppo	processorid_t cpuid;
2791ae0874heppo	char *eunit_name = broken_md_flag ? "exec_unit" : "exec-unit";
280fb2f18fesaxe	enum eu_type { INTEGER, FPU } etype;
2817c478bdstevel@tonic-gate
2821ae0874heppo	/*
2831ae0874heppo	 * Find the cpu integer exec units - and
2841ae0874heppo	 * setup the mappings appropriately.
2851ae0874heppo	 */
2861ae0874heppo	num = md_alloc_scan_dag(mdp, md_root_node(mdp), "cpus", "fwd", &node);
2871ae0874heppo	if (num < 1)
2884bac220narayan		cmn_err(CE_PANIC, "No cpus node in machine description");
2891ae0874heppo	if (num > 1)
2901ae0874heppo		cmn_err(CE_PANIC, "More than 1 cpus node in machine"
2911ae0874heppo		    " description");
2921ae0874heppo
2931ae0874heppo	cpus_node = node[0];
2941ae0874heppo	md_free_scan_dag(mdp, &node);
2951ae0874heppo
2961ae0874heppo	num_eunits = md_alloc_scan_dag(mdp, cpus_node, eunit_name,
2971ae0874heppo	    "fwd", &eunit);
2981ae0874heppo	if (num_eunits > 0) {
299fb2f18fesaxe		char *int_str = broken_md_flag ? "int" : "integer";
300fb2f18fesaxe		char *fpu_str = "fp";
3011ae0874heppo
3021ae0874heppo		/* Spin through and find all the integer exec units */
3031ae0874heppo		for (i = 0; i < num_eunits; i++) {
3041ae0874heppo			char *p;
3051ae0874heppo			char *val;
3061ae0874heppo			int vallen;
3071ae0874heppo			uint64_t lcpuid;
3081ae0874heppo
309fb2f18fesaxe			/* ignore nodes with no type */
3101ae0874heppo			if (md_get_prop_data(mdp, eunit[i], "type",
311ad8d2ebzx			    (uint8_t **)&val, &vallen))
312ad8d2ebzx				continue;
3131ae0874heppo
3141ae0874heppo			for (p = val; *p != '\0'; p += strlen(p) + 1) {
315fb2f18fesaxe				if (strcmp(p, int_str) == 0) {
316fb2f18fesaxe					etype = INTEGER;
3171ae0874heppo					goto found;
318fb2f18fesaxe				}
319fb2f18fesaxe				if (strcmp(p, fpu_str) == 0) {
320fb2f18fesaxe					etype = FPU;
321fb2f18fesaxe					goto found;
322fb2f18fesaxe				}
3237c478bdstevel@tonic-gate			}
3241ae0874heppo
3251ae0874heppo			continue;
3261ae0874heppofound:
3271ae0874heppo			idx = NCPU + i;
3287c478bdstevel@tonic-gate			/*
3291ae0874heppo			 * find the cpus attached to this EU and
3301ae0874heppo			 * update their mapping indices
3317c478bdstevel@tonic-gate			 */
3321ae0874heppo			num = md_alloc_scan_dag(mdp, eunit[i], "cpu",
3331ae0874heppo			    "back", &node);
3341ae0874heppo
3351ae0874heppo			if (num < 1)
3361ae0874heppo				cmn_err(CE_PANIC, "exec-unit node in MD"
3371ae0874heppo				    " not attached to a cpu node");
3381ae0874heppo
3391ae0874heppo			for (j = 0; j < num; j++) {
3401ae0874heppo				if (md_get_prop_val(mdp, node[j], "id",
3411ae0874heppo				    &lcpuid))
3421ae0874heppo					continue;
3431ae0874heppo				if (lcpuid >= NCPU)
3441ae0874heppo					continue;
3451ae0874heppo				cpuid = (processorid_t)lcpuid;
346fb2f18fesaxe				switch (etype) {
347fb2f18fesaxe				case INTEGER:
348fb2f18fesaxe					cpunodes[cpuid].exec_unit_mapping = idx;
349fb2f18fesaxe					break;
350fb2f18fesaxe				case FPU:
351fb2f18fesaxe					cpunodes[cpuid].fpu_mapping = idx;
352fb2f18fesaxe					break;
353fb2f18fesaxe				}
3541ae0874heppo			}
3551ae0874heppo			md_free_scan_dag(mdp, &node);
3567c478bdstevel@tonic-gate		}
3572f0fcb9Jason Beloro
3582f0fcb9Jason Beloro
3599d0d62aJason Beloro		md_free_scan_dag(mdp, &eunit);
3602f0fcb9Jason Beloro	}
3617c478bdstevel@tonic-gate}
3627c478bdstevel@tonic-gate
3631ae0874heppo/*
3641ae0874heppo * All the common setup of sun4v CPU modules is done by this routine.
3651ae0874heppo */
3661ae0874heppovoid
3671ae0874heppocpu_setup_common(char **cpu_module_isa_set)
3687c478bdstevel@tonic-gate{
3691ae0874heppo	extern int mmu_exported_pagesize_mask;
3701ae0874heppo	int nocpus, i;
3711ae0874heppo	size_t ra_limit;
3721ae0874heppo	mde_cookie_t *cpulist;
3731ae0874heppo	md_t *mdp;
3741ae0874heppo
3751ae0874heppo	if ((mdp = md_get_handle()) == NULL)
3761ae0874heppo		cmn_err(CE_PANIC, "Unable to initialize machine description");
3771ae0874heppo
37806fb6a3dv	boot_ncpus = nocpus = md_alloc_scan_dag(mdp,
3791ae0874heppo	    md_root_node(mdp), "cpu", "fwd", &cpulist);
3801ae0874heppo	if (nocpus < 1) {
3811ae0874heppo		cmn_err(CE_PANIC, "cpu_common_setup: cpulist allocation "
3821ae0874heppo		    "failed or incorrect number of CPUs in MD");
3831ae0874heppo	}
3847c478bdstevel@tonic-gate
3854bac220narayan	init_md_broken(mdp, cpulist);
3864bac220narayan
3871ae0874heppo	if (use_page_coloring) {
3881ae0874heppo		do_pg_coloring = 1;
3891ae0874heppo	}
3901ae0874heppo
3911ae0874heppo	/*
3921e2e7a7huah	 * Get the valid mmu page sizes mask, Q sizes and isalist/r
3931ae0874heppo	 * from the MD for the first available CPU in cpulist.
3941e2e7a7huah	 *
3951e2e7a7huah	 * Do not expect the MMU page sizes mask to be more than 32-bit.
3961ae0874heppo	 */
3971ae0874heppo	mmu_exported_pagesize_mask = (int)get_cpu_pagesizes(mdp, cpulist[0]);
3981ae0874heppo
39905d3dc4paulsan	/*
40005d3dc4paulsan	 * Get the number of contexts and tsbs supported.
40105d3dc4paulsan	 */
40205d3dc4paulsan	if (get_mmu_shcontexts(mdp, cpulist[0]) >= MIN_NSHCONTEXTS &&
40305d3dc4paulsan	    get_mmu_tsbs(mdp, cpulist[0]) >= MIN_NTSBS) {
40405d3dc4paulsan		shctx_on = 1;
40505d3dc4paulsan	}
40605d3dc4paulsan
4071ae0874heppo	for (i = 0; i < nocpus; i++)
4081ae0874heppo		fill_cpu(mdp, cpulist[i]);
4091ae0874heppo
410575a742pt	/* setup l2 cache count. */
411575a742pt	n_l2_caches = get_l2_cache_node_count(mdp);
412575a742pt
41359ac0c1davemq	setup_chip_mappings(mdp);
4141ae0874heppo	setup_exec_unit_mappings(mdp);
4151ae0874heppo
4161ae0874heppo	/*
4171ae0874heppo	 * If MD is broken then append the passed ISA set,
4181ae0874heppo	 * otherwise trust the MD.
4191ae0874heppo	 */
4201ae0874heppo
4211ae0874heppo	if (broken_md_flag)
4221ae0874heppo		isa_list = construct_isalist(mdp, cpulist[0],
4231ae0874heppo		    cpu_module_isa_set);
4241ae0874heppo	else
4251ae0874heppo		isa_list = construct_isalist(mdp, cpulist[0], NULL);
4261ae0874heppo
4272f0fcb9Jason Beloro	get_hwcaps(mdp, cpulist[0]);
4282c5124aPrashanth Sreenivasa	get_weakest_mem_model(mdp, cpulist[0]);
4291ae0874heppo	get_q_sizes(mdp, cpulist[0]);
4301ae0874heppo	get_va_bits(mdp, cpulist[0]);
4311ae0874heppo
4321ae0874heppo	/*
4331ae0874heppo	 * ra_limit is the highest real address in the machine.
4341ae0874heppo	 */
4359853d9eJason Beloro	ra_limit = get_ra_limit(mdp, cpulist[0]);
4361ae0874heppo
4371ae0874heppo	md_free_scan_dag(mdp, &cpulist);
4381ae0874heppo
4391ae0874heppo	(void) md_fini_handle(mdp);
4401ae0874heppo
4411ae0874heppo	/*
4421ae0874heppo	 * Block stores invalidate all pages of the d$ so pagecopy
4431ae0874heppo	 * et. al. do not need virtual translations with virtual
4441ae0874heppo	 * coloring taken into consideration.
4451ae0874heppo	 */
4461ae0874heppo	pp_consistent_coloring = 0;
4471ae0874heppo
4481ae0874heppo	/*
4491ae0874heppo	 * The kpm mapping window.
4501ae0874heppo	 * kpm_size:
4511ae0874heppo	 *	The size of a single kpm range.
4521ae0874heppo	 *	The overall size will be: kpm_size * vac_colors.
4531ae0874heppo	 * kpm_vbase:
4541ae0874heppo	 *	The virtual start address of the kpm range within the kernel
4551ae0874heppo	 *	virtual address space. kpm_vbase has to be kpm_size aligned.
4561ae0874heppo	 */
4571ae0874heppo
4581ae0874heppo	/*
4591ae0874heppo	 * Make kpm_vbase, kpm_size aligned to kpm_size_shift.
4601ae0874heppo	 * To do this find the nearest power of 2 size that the
4611ae0874heppo	 * actual ra_limit fits within.
4621ae0874heppo	 * If it is an even power of two use that, otherwise use the
4631ae0874heppo	 * next power of two larger than ra_limit.
4641ae0874heppo	 */
4651ae0874heppo
4661ae0874heppo	ASSERT(ra_limit != 0);
4671ae0874heppo
468de710d2Josef 'Jeff' Sipek	kpm_size_shift = !ISP2(ra_limit) ?
469ad8d2ebzx	    highbit(ra_limit) : highbit(ra_limit) - 1;
4701ae0874heppo
4711ae0874heppo	/*
4721ae0874heppo	 * No virtual caches on sun4v so size matches size shift
4731ae0874heppo	 */
4741ae0874heppo	kpm_size = 1ul << kpm_size_shift;
4751ae0874heppo
476