Home | History | Annotate | Download | only in cpu
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <sys/systm.h>
     31 #include <sys/archsystm.h>
     32 #include <sys/machparam.h>
     33 #include <sys/machsystm.h>
     34 #include <sys/cpu.h>
     35 #include <sys/elf_SPARC.h>
     36 #include <vm/hat_sfmmu.h>
     37 #include <vm/page.h>
     38 #include <vm/vm_dep.h>
     39 #include <sys/cpuvar.h>
     40 #include <sys/async.h>
     41 #include <sys/cmn_err.h>
     42 #include <sys/debug.h>
     43 #include <sys/dditypes.h>
     44 #include <sys/sunddi.h>
     45 #include <sys/cpu_module.h>
     46 #include <sys/prom_debug.h>
     47 #include <sys/vmsystm.h>
     48 #include <sys/prom_plat.h>
     49 #include <sys/sysmacros.h>
     50 #include <sys/intreg.h>
     51 #include <sys/machtrap.h>
     52 #include <sys/ontrap.h>
     53 #include <sys/ivintr.h>
     54 #include <sys/atomic.h>
     55 #include <sys/panic.h>
     56 #include <sys/dtrace.h>
     57 #include <sys/simulate.h>
     58 #include <sys/fault.h>
     59 #include <sys/niagara2regs.h>
     60 #include <sys/hsvc.h>
     61 #include <sys/trapstat.h>
     62 #include <sys/mutex_impl.h>
     63 
     64 uint_t root_phys_addr_lo_mask = 0xffffffffU;
     65 #if defined(NIAGARA2_IMPL)
     66 char cpu_module_name[] = "SUNW,UltraSPARC-T2";
     67 #elif defined(VFALLS_IMPL)
     68 char cpu_module_name[] = "SUNW,UltraSPARC-T2+";
     69 #endif
     70 
     71 /*
     72  * Hypervisor services information for the NIAGARA2 and Victoria Falls
     73  * CPU module
     74  */
     75 static boolean_t cpu_hsvc_available = B_TRUE;
     76 static uint64_t cpu_sup_minor;		/* Supported minor number */
     77 #if defined(NIAGARA2_IMPL)
     78 static hsvc_info_t cpu_hsvc = {
     79 	HSVC_REV_1, NULL, HSVC_GROUP_NIAGARA2_CPU, NIAGARA2_HSVC_MAJOR,
     80 	NIAGARA2_HSVC_MINOR, cpu_module_name
     81 };
     82 #elif defined(VFALLS_IMPL)
     83 static hsvc_info_t cpu_hsvc = {
     84 	HSVC_REV_1, NULL, HSVC_GROUP_VFALLS_CPU, VFALLS_HSVC_MAJOR,
     85 	VFALLS_HSVC_MINOR, cpu_module_name
     86 };
     87 #endif
     88 
     89 void
     90 cpu_setup(void)
     91 {
     92 	extern int mmu_exported_pagesize_mask;
     93 	extern int cpc_has_overflow_intr;
     94 	extern size_t contig_mem_prealloc_base_size;
     95 	int status;
     96 
     97 	/*
     98 	 * Negotiate the API version for Niagara2 specific hypervisor
     99 	 * services.
    100 	 */
    101 	status = hsvc_register(&cpu_hsvc, &cpu_sup_minor);
    102 	if (status != 0) {
    103 		cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
    104 		    "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d",
    105 		    cpu_hsvc.hsvc_modname, cpu_hsvc.hsvc_group,
    106 		    cpu_hsvc.hsvc_major, cpu_hsvc.hsvc_minor, status);
    107 		cpu_hsvc_available = B_FALSE;
    108 	}
    109 
    110 	/*
    111 	 * The setup common to all CPU modules is done in cpu_setup_common
    112 	 * routine.
    113 	 */
    114 	cpu_setup_common(NULL);
    115 
    116 	cache |= (CACHE_PTAG | CACHE_IOCOHERENT);
    117 
    118 	if ((mmu_exported_pagesize_mask &
    119 	    DEFAULT_SUN4V_MMU_PAGESIZE_MASK) !=
    120 	    DEFAULT_SUN4V_MMU_PAGESIZE_MASK)
    121 		cmn_err(CE_PANIC, "machine description"
    122 		    " does not have required sun4v page sizes"
    123 		    " 8K, 64K and 4M: MD mask is 0x%x",
    124 		    mmu_exported_pagesize_mask);
    125 
    126 	cpu_hwcap_flags = AV_SPARC_VIS | AV_SPARC_VIS2 |
    127 	    AV_SPARC_ASI_BLK_INIT | AV_SPARC_POPC;
    128 
    129 	/*
    130 	 * Niagara2 supports a 48-bit subset of the full 64-bit virtual
    131 	 * address space. Virtual addresses between 0x0000800000000000
    132 	 * and 0xffff.7fff.ffff.ffff inclusive lie within a "VA Hole"
    133 	 * and must never be mapped. In addition, software must not use
    134 	 * pages within 4GB of the VA hole as instruction pages to
    135 	 * avoid problems with prefetching into the VA hole.
    136 	 */
    137 	hole_start = (caddr_t)((1ull << (va_bits - 1)) - (1ull << 32));
    138 	hole_end = (caddr_t)((0ull - (1ull << (va_bits - 1))) + (1ull << 32));
    139 
    140 	/*
    141 	 * Niagara2 has a performance counter overflow interrupt
    142 	 */
    143 	cpc_has_overflow_intr = 1;
    144 
    145 	/*
    146 	 * Enable 4M pages for OOB.
    147 	 */
    148 	max_uheap_lpsize = MMU_PAGESIZE4M;
    149 	max_ustack_lpsize = MMU_PAGESIZE4M;
    150 	max_privmap_lpsize = MMU_PAGESIZE4M;
    151 
    152 #ifdef SUN4V_CONTIG_MEM_PREALLOC_SIZE_MB
    153 	/*
    154 	 * Use CPU Makefile specific compile time define (if exists)
    155 	 * to add to the contig preallocation size.
    156 	 */
    157 	contig_mem_prealloc_base_size = MB(SUN4V_CONTIG_MEM_PREALLOC_SIZE_MB);
    158 #endif
    159 }
    160 
    161 /*
    162  * Set the magic constants of the implementation.
    163  */
    164 void
    165 cpu_fiximp(struct cpu_node *cpunode)
    166 {
    167 	/*
    168 	 * The Cache node is optional in MD. Therefore in case "Cache"
    169 	 * node does not exists in MD, set the default L2 cache associativity,
    170 	 * size, linesize.
    171 	 */
    172 	if (cpunode->ecache_size == 0)
    173 		cpunode->ecache_size = L2CACHE_SIZE;
    174 	if (cpunode->ecache_linesize == 0)
    175 		cpunode->ecache_linesize = L2CACHE_LINESIZE;
    176 	if (cpunode->ecache_associativity == 0)
    177 		cpunode->ecache_associativity = L2CACHE_ASSOCIATIVITY;
    178 }
    179 
    180 void
    181 cpu_map_exec_units(struct cpu *cp)
    182 {
    183 	ASSERT(MUTEX_HELD(&cpu_lock));
    184 
    185 	/*
    186 	 * The cpu_ipipe and cpu_fpu fields are initialized based on
    187 	 * the execution unit sharing information from the MD. They
    188 	 * default to the CPU id in the absence of such information.
    189 	 */
    190 	cp->cpu_m.cpu_ipipe = cpunodes[cp->cpu_id].exec_unit_mapping;
    191 	if (cp->cpu_m.cpu_ipipe == NO_EU_MAPPING_FOUND)
    192 		cp->cpu_m.cpu_ipipe = (id_t)(cp->cpu_id);
    193 
    194 	cp->cpu_m.cpu_fpu = cpunodes[cp->cpu_id].fpu_mapping;
    195 	if (cp->cpu_m.cpu_fpu == NO_EU_MAPPING_FOUND)
    196 		cp->cpu_m.cpu_fpu = (id_t)(cp->cpu_id);
    197 
    198 	/*
    199 	 * Niagara 2 defines the core to be at the FPU level
    200 	 */
    201 	cp->cpu_m.cpu_core = cp->cpu_m.cpu_fpu;
    202 
    203 	/*
    204 	 * The cpu_chip field is initialized based on the information
    205 	 * in the MD and assume that all cpus within a chip
    206 	 * share the same L2 cache. If no such info is available, we
    207 	 * set the cpu to belong to the defacto chip 0.
    208 	 */
    209 	cp->cpu_m.cpu_mpipe = cpunodes[cp->cpu_id].l2_cache_mapping;
    210 	if (cp->cpu_m.cpu_mpipe == NO_L2_CACHE_MAPPING_FOUND)
    211 		cp->cpu_m.cpu_mpipe = CPU_L2_CACHEID_INVALID;
    212 
    213 	cp->cpu_m.cpu_chip = cpunodes[cp->cpu_id].l2_cache_mapping;
    214 	if (cp->cpu_m.cpu_chip == NO_L2_CACHE_MAPPING_FOUND)
    215 		cp->cpu_m.cpu_chip = CPU_CHIPID_INVALID;
    216 }
    217 
    218 static int cpucnt;
    219 
    220 void
    221 cpu_init_private(struct cpu *cp)
    222 {
    223 	extern void niagara_kstat_init(void);
    224 
    225 	ASSERT(MUTEX_HELD(&cpu_lock));
    226 
    227 	cpu_map_exec_units(cp);
    228 
    229 	if ((cpucnt++ == 0) && (cpu_hsvc_available == B_TRUE))
    230 		(void) niagara_kstat_init();
    231 
    232 	mutex_delay = rdccr_delay;
    233 }
    234 
    235 /*ARGSUSED*/
    236 void
    237 cpu_uninit_private(struct cpu *cp)
    238 {
    239 	extern void niagara_kstat_fini(void);
    240 
    241 	ASSERT(MUTEX_HELD(&cpu_lock));
    242 	if ((--cpucnt == 0) && (cpu_hsvc_available == B_TRUE))
    243 		(void) niagara_kstat_fini();
    244 }
    245 
    246 /*
    247  * On Niagara2, any flush will cause all preceding stores to be
    248  * synchronized wrt the i$, regardless of address or ASI.  In fact,
    249  * the address is ignored, so we always flush address 0.
    250  */
    251 /*ARGSUSED*/
    252 void
    253 dtrace_flush_sec(uintptr_t addr)
    254 {
    255 	doflush(0);
    256 }
    257 
    258 /*
    259  * Trapstat support for Niagara2 processor
    260  * The Niagara2 provides HWTW support for TSB lookup and with HWTW
    261  * enabled no TSB hit information will be available. Therefore setting
    262  * the time spent in TLB miss handler for TSB hits to 0.
    263  */
    264 int
    265 cpu_trapstat_conf(int cmd)
    266 {
    267 	int status = 0;
    268 
    269 	switch (cmd) {
    270 	case CPU_TSTATCONF_INIT:
    271 	case CPU_TSTATCONF_FINI:
    272 	case CPU_TSTATCONF_ENABLE:
    273 	case CPU_TSTATCONF_DISABLE:
    274 		break;
    275 	default:
    276 		status = EINVAL;
    277 		break;
    278 	}
    279 	return (status);
    280 }
    281 
    282 void
    283 cpu_trapstat_data(void *buf, uint_t tstat_pgszs)
    284 {
    285 	tstat_pgszdata_t	*tstatp = (tstat_pgszdata_t *)buf;
    286 	int	i;
    287 
    288 	for (i = 0; i < tstat_pgszs; i++, tstatp++) {
    289 		tstatp->tpgsz_kernel.tmode_itlb.ttlb_tlb.tmiss_count = 0;
    290 		tstatp->tpgsz_kernel.tmode_itlb.ttlb_tlb.tmiss_time = 0;
    291 		tstatp->tpgsz_user.tmode_itlb.ttlb_tlb.tmiss_count = 0;
    292 		tstatp->tpgsz_user.tmode_itlb.ttlb_tlb.tmiss_time = 0;
    293 		tstatp->tpgsz_kernel.tmode_dtlb.ttlb_tlb.tmiss_count = 0;
    294 		tstatp->tpgsz_kernel.tmode_dtlb.ttlb_tlb.tmiss_time = 0;
    295 		tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_count = 0;
    296 		tstatp->tpgsz_user.tmode_dtlb.ttlb_tlb.tmiss_time = 0;
    297 	}
    298 }
    299 
    300 /*
    301  * Page coloring support for hashed cache index mode
    302  */
    303 
    304 /*
    305  * Node id bits from machine description (MD).  Node id distinguishes
    306  * local versus remote memory. Because of MPO, page allocation does
    307  * not cross node boundaries. Therefore, remove the node id bits from
    308  * the color, since they are fixed. Either bit 30, or 31:30 in
    309  * Victoria Falls processors.
    310  * The number of node id bits is always 0 in Niagara2.
    311  */
    312 typedef struct n2color {
    313 	uchar_t nnbits;	/* number of node id bits */
    314 	uchar_t nnmask; /* mask for node id bits */
    315 	uchar_t	lomask;	/* mask for bits below node id */
    316 	uchar_t lobits;	/* number of bits below node id */
    317 } n2color_t;
    318 
    319 n2color_t n2color[MMU_PAGE_SIZES];
    320 static uchar_t nhbits[] = {7, 7, 6, 5, 5, 5};
    321 
    322 /*
    323  * Remove node id bits from color bits 32:28.
    324  * This will reduce the number of colors.
    325  * No change if number of node bits is zero.
    326  */
    327 static inline uint_t
    328 n2_hash2color(uint_t color, uchar_t szc)
    329 {
    330 	n2color_t m = n2color[szc];
    331 
    332 	if (m.nnbits > 0) {
    333 		color = ((color >> m.nnbits) & ~m.lomask) | (color & m.lomask);
    334 		ASSERT((color & ~(hw_page_array[szc].hp_colors - 1)) == 0);
    335 	}
    336 
    337 	return (color);
    338 }
    339 
    340 /*
    341  * Restore node id bits into page color.
    342  * This will increase the number of colors to match N2.
    343  * No change if number of node bits is zero.
    344  */
    345 static inline uint_t
    346 n2_color2hash(uint_t color, uchar_t szc, uint_t node)
    347 {
    348 	n2color_t m = n2color[szc];
    349 
    350 	if (m.nnbits > 0) {
    351 		color = ((color & ~m.lomask) << m.nnbits) | (color & m.lomask);
    352 		color |= (node & m.nnmask) << m.lobits;
    353 	}
    354 
    355 	return (color);
    356 }
    357 
    358 /* NI2 L2$ index is pa[32:28]^pa[17:13].pa[19:18]^pa[12:11].pa[10:6] */
    359 
    360 /*
    361  * iterator NULL means pfn is VA, do not adjust ra_to_pa
    362  * iterator (-1) means pfn is RA, need to convert to PA
    363  * iterator non-null means pfn is RA, use ra_to_pa
    364  */
    365 uint_t
    366 page_pfn_2_color_cpu(pfn_t pfn, uchar_t szc, void *cookie)
    367 {
    368 	mem_node_iterator_t *it = cookie;
    369 	uint_t color;
    370 
    371 	ASSERT(szc <= TTE256M);
    372 
    373 	if (it == ((mem_node_iterator_t *)(-1))) {
    374 		pfn = plat_rapfn_to_papfn(pfn);
    375 	} else if (it != NULL) {
    376 		ASSERT(pfn >= it->mi_mblock_base && pfn <= it->mi_mblock_end);
    377 		pfn = pfn + it->mi_ra_to_pa;
    378 	}
    379 	pfn = PFN_BASE(pfn, szc);
    380 	color = ((pfn >> 15) ^ pfn) & 0x1f;
    381 	if (szc < TTE4M) {
    382 		/* 19:18 */
    383 		color = (color << 2) | ((pfn >> 5) & 0x3);
    384 		if (szc > TTE64K)
    385 			color >>= 1;    /* 19 */
    386 	}
    387 	return (n2_hash2color(color, szc));
    388 }
    389 
    390 static uint_t
    391 page_papfn_2_color_cpu(pfn_t papfn, uchar_t szc)
    392 {
    393 	uint_t color;
    394 
    395 	ASSERT(szc <= TTE256M);
    396 
    397 	papfn = PFN_BASE(papfn, szc);
    398 	color = ((papfn >> 15) ^ papfn) & 0x1f;
    399 	if (szc < TTE4M) {
    400 		/* 19:18 */
    401 		color = (color << 2) | ((papfn >> 5) & 0x3);
    402 		if (szc > TTE64K)
    403 			color >>= 1;    /* 19 */
    404 	}
    405 	return (color);
    406 }
    407 
    408 #if TTE256M != 5
    409 #error TTE256M is not 5
    410 #endif
    411 
    412 uint_t
    413 page_get_nsz_color_mask_cpu(uchar_t szc, uint_t mask)
    414 {
    415 	static uint_t ni2_color_masks[5] = {0x63, 0x1e, 0x3e, 0x1f, 0x1f};
    416 	ASSERT(szc < TTE256M);
    417 	mask = n2_color2hash(mask, szc, 0);
    418 	mask &= ni2_color_masks[szc];
    419 	if (szc == TTE64K || szc == TTE512K)
    420 		mask >>= 1;
    421 	return (n2_hash2color(mask, szc + 1));
    422 }
    423 
    424 uint_t
    425 page_get_nsz_color_cpu(uchar_t szc, uint_t color)
    426 {
    427 	ASSERT(szc < TTE256M);
    428 	color = n2_color2hash(color, szc, 0);
    429 	if (szc == TTE64K || szc == TTE512K)
    430 		color >>= 1;
    431 	return (n2_hash2color(color, szc + 1));
    432 }
    433 
    434 uint_t
    435 page_get_color_shift_cpu(uchar_t szc, uchar_t nszc)
    436 {
    437 	uint_t s;
    438 	ASSERT(nszc >= szc);
    439 	ASSERT(nszc <= TTE256M);
    440 
    441 	s = nhbits[szc] - n2color[szc].nnbits;
    442 	s -= nhbits[nszc] - n2color[nszc].nnbits;
    443 
    444 	return (s);
    445 }
    446 
    447 uint_t
    448 page_convert_color_cpu(uint_t ncolor, uchar_t szc, uchar_t nszc)
    449 {
    450 	uint_t color;
    451 
    452 	ASSERT(nszc > szc);
    453 	ASSERT(nszc <= TTE256M);
    454 	ncolor = n2_color2hash(ncolor, nszc, 0);
    455 	color = ncolor << (nhbits[szc] - nhbits[nszc]);
    456 	color = n2_hash2color(color, szc);
    457 	return (color);
    458 }
    459 
    460 #define	PAPFN_2_MNODE(pfn) \
    461 	(((pfn) & it->mi_mnode_pfn_mask) >> it->mi_mnode_pfn_shift)
    462 
    463 /*ARGSUSED*/
    464 pfn_t
    465 page_next_pfn_for_color_cpu(pfn_t pfn, uchar_t szc, uint_t color,
    466     uint_t ceq_mask, uint_t color_mask, void *cookie)
    467 {
    468 	mem_node_iterator_t *it = cookie;
    469 	pfn_t pstep = PNUM_SIZE(szc);
    470 	pfn_t npfn, pfn_ceq_mask, pfn_color;
    471 	pfn_t tmpmask, mask = (pfn_t)-1;
    472 	uint_t pfnmn;
    473 
    474 	ASSERT((color & ~ceq_mask) == 0);
    475 	ASSERT(pfn >= it->mi_mblock_base && pfn <= it->mi_mblock_end);
    476 
    477 	/* convert RA to PA for accurate color calculation */
    478 	if (it->mi_init) {
    479 		/* first call after it, so cache these values */
    480 		it->mi_hash_ceq_mask =
    481 		    n2_color2hash(ceq_mask, szc, it->mi_mnode_mask);
    482 		it->mi_hash_color =
    483 		    n2_color2hash(color, szc, it->mi_mnode);
    484 		it->mi_init = 0;
    485 	} else {
    486 		ASSERT(it->mi_hash_ceq_mask ==
    487 		    n2_color2hash(ceq_mask, szc, it->mi_mnode_mask));
    488 		ASSERT(it->mi_hash_color ==
    489 		    n2_color2hash(color, szc, it->mi_mnode));
    490 	}
    491 	ceq_mask = it->mi_hash_ceq_mask;
    492 	color = it->mi_hash_color;
    493 	pfn += it->mi_ra_to_pa;
    494 
    495 	/* restart here when we switch memblocks */
    496 next_mem_block:
    497 	if (szc <= TTE64K) {
    498 		pfnmn = PAPFN_2_MNODE(pfn);
    499 	}
    500 	if (((page_papfn_2_color_cpu(pfn, szc) ^ color) & ceq_mask) == 0 &&
    501 	    (szc > TTE64K || pfnmn == it->mi_mnode)) {
    502 
    503 		/* we start from the page with correct color */
    504 		if (szc >= TTE512K) {
    505 			if (szc >= TTE4M) {
    506 				/* page color is PA[32:28] */
    507 				pfn_ceq_mask = ceq_mask << 15;
    508 			} else {
    509 				/* page color is PA[32:28].PA[19:19] */
    510 				pfn_ceq_mask = ((ceq_mask & 1) << 6) |
    511 				    ((ceq_mask >> 1) << 15);
    512 			}
    513 			npfn = ADD_MASKED(pfn, pstep, pfn_ceq_mask, mask);
    514 			goto done;
    515 		} else {
    516 			/*
    517 			 * We deal 64K or 8K page. Check if we could the
    518 			 * satisfy the request without changing PA[32:28]
    519 			 */
    520 			pfn_ceq_mask = ((ceq_mask & 3) << 5) | (ceq_mask >> 2);
    521 			pfn_ceq_mask |= it->mi_mnode_pfn_mask;
    522 			npfn = ADD_MASKED(pfn, pstep, pfn_ceq_mask, mask);
    523 
    524 			if ((((npfn ^ pfn) >> 15) & 0x1f) == 0)
    525 				goto done;
    526 
    527 			/*
    528 			 * for next pfn we have to change bits PA[32:28]
    529 			 * set PA[63:28] and PA[19:18] of the next pfn
    530 			 */
    531 			npfn = (pfn >> 15) << 15;
    532 			npfn |= (ceq_mask & color & 3) << 5;
    533 			pfn_ceq_mask = (szc == TTE8K) ? 0 :
    534 			    (ceq_mask & 0x1c) << 13;
    535 			pfn_ceq_mask |= it->mi_mnode_pfn_mask;
    536 			npfn = ADD_MASKED(npfn, (1 << 15), pfn_ceq_mask, mask);
    537 
    538 			/*
    539 			 * set bits PA[17:13] to match the color
    540 			 */
    541 			npfn |= ((npfn >> 15) ^ (color >> 2)) & (ceq_mask >> 2);
    542 			goto done;
    543 		}
    544 	}
    545 
    546 	/*
    547 	 * we start from the page with incorrect color - rare case
    548 	 */
    549 	if (szc >= TTE512K) {
    550 		if (szc >= TTE4M) {
    551 			/* page color is in bits PA[32:28] */
    552 			npfn = ((pfn >> 20) << 20) | (color << 15);
    553 			pfn_ceq_mask = (ceq_mask << 15) | 0x7fff;
    554 		} else {
    555 			/* try get the right color by changing bit PA[19:19] */
    556 			npfn = pfn + pstep;
    557 			if (((page_papfn_2_color_cpu(npfn, szc) ^ color) &
    558 			    ceq_mask) == 0)
    559 				goto done;
    560 
    561 			/* page color is PA[32:28].PA[19:19] */
    562 			pfn_ceq_mask = ((ceq_mask & 1) << 6) |
    563 			    ((ceq_mask >> 1) << 15) | (0xff << 7);
    564 			pfn_color = ((color & 1) << 6) | ((color >> 1) << 15);
    565 			npfn = ((pfn >> 20) << 20) | pfn_color;
    566 		}
    567 
    568 		while (npfn <= pfn) {
    569 			npfn = ADD_MASKED(npfn, pstep, pfn_ceq_mask, mask);
    570 		}
    571 		goto done;
    572 	}
    573 
    574 	/*
    575 	 *  We deal 64K or 8K page of incorrect color.
    576 	 * Try correcting color without changing PA[32:28]
    577 	 */
    578 	pfn_ceq_mask = ((ceq_mask & 3) << 5) | (ceq_mask >> 2);
    579 	pfn_color = ((color & 3) << 5) | (color >> 2);
    580 	if (pfnmn == it->mi_mnode) {
    581 		npfn = (pfn & ~(pfn_t)0x7f);
    582 		npfn |= (((pfn >> 15) & 0x1f) ^ pfn_color) & pfn_ceq_mask;
    583 		npfn = (szc == TTE64K) ? (npfn & ~(pfn_t)0x7) : npfn;
    584 
    585 		if (((page_papfn_2_color_cpu(npfn, szc) ^ color) &
    586 		    ceq_mask) == 0) {
    587 			/* the color is fixed - find the next page */
    588 			pfn_ceq_mask |= it->mi_mnode_pfn_mask;
    589 			while (npfn <= pfn) {
    590 				npfn = ADD_MASKED(npfn, pstep, pfn_ceq_mask,
    591 				    mask);
    592 			}
    593 			if ((((npfn ^ pfn) >> 15) & 0x1f) == 0)
    594 				goto done;
    595 		}
    596 	}
    597 
    598 	/* to fix the color need to touch PA[32:28] */
    599 	npfn = (szc == TTE8K) ? ((pfn >> 15) << 15) :
    600 	    (((pfn >> 18) << 18) | ((color & 0x1c) << 13));
    601 
    602 	/* fix mnode if input pfn is in the wrong mnode. */
    603 	if ((pfnmn = PAPFN_2_MNODE(npfn)) != it->mi_mnode) {
    604 		npfn += ((it->mi_mnode - pfnmn) & it->mi_mnode_mask) <<
    605 		    it->mi_mnode_pfn_shift;
    606 	}
    607 
    608 	tmpmask = (szc == TTE8K) ? 0 : (ceq_mask & 0x1c) << 13;
    609 	tmpmask |= it->mi_mnode_pfn_mask;
    610 
    611 	while (npfn <= pfn) {
    612 		npfn = ADD_MASKED(npfn, (1 << 15), tmpmask, mask);
    613 	}
    614 
    615 	/* set bits PA[19:13] to match the color */
    616 	npfn |= (((npfn >> 15) & 0x1f) ^ pfn_color) & pfn_ceq_mask;
    617 	npfn = (szc == TTE64K) ? (npfn & ~(pfn_t)0x7) : npfn;
    618 
    619 done:
    620 	ASSERT(((page_papfn_2_color_cpu(npfn, szc) ^ color) & ceq_mask) == 0);
    621 	ASSERT(PAPFN_2_MNODE(npfn) == it->mi_mnode);
    622 
    623 	/* PA to RA */
    624 	npfn -= it->mi_ra_to_pa;
    625 
    626 	/* check for possible memblock switch */
    627 	if (npfn > it->mi_mblock_end) {
    628 		pfn = plat_mem_node_iterator_init(npfn, it->mi_mnode, szc, it,
    629 		    0);
    630 		if (pfn == (pfn_t)-1)
    631 			return (pfn);
    632 		ASSERT(pfn >= it->mi_mblock_base && pfn <= it->mi_mblock_end);
    633 		pfn += it->mi_ra_to_pa;
    634 		goto next_mem_block;
    635 	}
    636 
    637 	return (npfn);
    638 }
    639 
    640 /*
    641  * init page coloring
    642  * VF encodes node_id for an L-group in either bit 30 or 31:30,
    643  * which effectively reduces the number of colors available per mnode.
    644  */
    645 void
    646 page_coloring_init_cpu()
    647 {
    648 	int i;
    649 	uchar_t id;
    650 	uchar_t lo;
    651 	uchar_t hi;
    652 	n2color_t m;
    653 	mem_node_iterator_t it;
    654 	static uchar_t idmask[] = {0, 0x7, 0x1f, 0x1f, 0x1f, 0x1f};
    655 
    656 	for (i = 0; i < max_mem_nodes; i++) {
    657 		memset(&it, 0, sizeof (it));
    658 		if (plat_mem_node_iterator_init(0, i, 0, &it, 1) != (pfn_t)-1)
    659 			break;
    660 	}
    661 	ASSERT(i < max_mem_nodes);
    662 	for (i = 0; i < mmu_page_sizes; i++) {
    663 		(void) memset(&m, 0, sizeof (m));
    664 		id = it.mi_mnode_pfn_mask >> 15;	/* node id mask */
    665 		id &= idmask[i];
    666 		lo = lowbit(id);
    667 		if (lo > 0) {
    668 			hi = highbit(id);
    669 			m.nnbits = hi - lo + 1;
    670 			m.nnmask = (1 << m.nnbits) - 1;
    671 			lo += nhbits[i] - 5;
    672 			m.lomask = (1 << (lo - 1)) - 1;
    673 			m.lobits = lo - 1;
    674 		}
    675 		hw_page_array[i].hp_colors = 1 << (nhbits[i] - m.nnbits);
    676 		n2color[i] = m;
    677 	}
    678 }
    679 
    680 /*
    681  * group colorequiv colors on N2 by low order bits of the color first
    682  */
    683 void
    684 page_set_colorequiv_arr_cpu(void)
    685 {
    686 	static uint_t nequiv_shades_log2[MMU_PAGE_SIZES] = {2, 5, 0, 0, 0, 0};
    687 
    688 	nequiv_shades_log2[1] -= n2color[1].nnbits;
    689 	if (colorequiv > 1) {
    690 		int i;
    691 		uint_t sv_a = lowbit(colorequiv) - 1;
    692 
    693 		if (sv_a > 15)
    694 			sv_a = 15;
    695 
    696 		for (i = 0; i < MMU_PAGE_SIZES; i++) {
    697 			uint_t colors;
    698 			uint_t a = sv_a;
    699 
    700 			if ((colors = hw_page_array[i].hp_colors) <= 1)
    701 				continue;
    702 			while ((colors >> a) == 0)
    703 				a--;
    704 			if (a > (colorequivszc[i] & 0xf) +
    705 			    (colorequivszc[i] >> 4)) {
    706 				if (a <= nequiv_shades_log2[i]) {
    707 					colorequivszc[i] = (uchar_t)a;
    708 				} else {
    709 					colorequivszc[i] =
    710 					    ((a - nequiv_shades_log2[i]) << 4) |
    711 					    nequiv_shades_log2[i];
    712 				}
    713 			}
    714 		}
    715 	}
    716 }
    717