xref: /illumos-gate/usr/src/uts/sun4v/vm/mach_sfmmu.c (revision 12551037)
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
51ce12b49Svb  * Common Development and Distribution License (the "License").
61ce12b49Svb  * 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 /*
22125be069SJason Beloro  * 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 <vm/hat.h>
287c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
297c478bd9Sstevel@tonic-gate #include <vm/page.h>
307c478bd9Sstevel@tonic-gate #include <sys/pte.h>
317c478bd9Sstevel@tonic-gate #include <sys/systm.h>
327c478bd9Sstevel@tonic-gate #include <sys/mman.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/machparam.h>
357c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
367c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
377c478bd9Sstevel@tonic-gate #include <sys/mmu.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
407c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
417c478bd9Sstevel@tonic-gate #include <sys/debug.h>
427c478bd9Sstevel@tonic-gate #include <sys/lgrp.h>
437c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
447c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
457c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
467c478bd9Sstevel@tonic-gate #include <sys/bitmap.h>
477c478bd9Sstevel@tonic-gate #include <vm/rm.h>
487c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
497c478bd9Sstevel@tonic-gate #include <sys/vm_machparam.h>
507c478bd9Sstevel@tonic-gate #include <sys/promif.h>
517c478bd9Sstevel@tonic-gate #include <sys/prom_isa.h>
527c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h>
537c478bd9Sstevel@tonic-gate #include <sys/prom_debug.h>
547c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
557c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
567c478bd9Sstevel@tonic-gate #include <sys/memlist.h>
577c478bd9Sstevel@tonic-gate #include <sys/memlist_plat.h>
587c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h>
597c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
607c478bd9Sstevel@tonic-gate #include <sys/kdi.h>
617c478bd9Sstevel@tonic-gate #include <sys/hypervisor_api.h>
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * External routines and data structures
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate extern void	sfmmu_cache_flushcolor(int, pfn_t);
6705d3dc4bSpaulsan extern uint_t	mmu_page_sizes;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Static routines
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate static void	sfmmu_set_tlb(void);
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * Global Data:
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate caddr_t	textva, datava;
787c478bd9Sstevel@tonic-gate tte_t	ktext_tte, kdata_tte;		/* ttes for kernel text and data */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate int	enable_bigktsb = 1;
8105d3dc4bSpaulsan int	shtsb4m_first = 0;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate tte_t bigktsb_ttes[MAX_BIGKTSB_TTES];
847c478bd9Sstevel@tonic-gate int bigktsb_nttes = 0;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Controls the logic which enables the use of the
887c478bd9Sstevel@tonic-gate  * QUAD_LDD_PHYS ASI for TSB accesses.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate int	ktsb_phys = 1;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #ifdef SET_MMU_STATS
937c478bd9Sstevel@tonic-gate struct mmu_stat	mmu_stat_area[NCPU];
947c478bd9Sstevel@tonic-gate #endif /* SET_MMU_STATS */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #ifdef DEBUG
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * The following two variables control if the hypervisor/hardware will
997c478bd9Sstevel@tonic-gate  * be used to do the TSB table walk for kernel and user contexts.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate int hv_use_0_tsb = 1;
1027c478bd9Sstevel@tonic-gate int hv_use_non0_tsb = 1;
1037c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static void
sfmmu_set_fault_status_area(void)1067c478bd9Sstevel@tonic-gate sfmmu_set_fault_status_area(void)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	caddr_t mmfsa_va;
1097c478bd9Sstevel@tonic-gate 	extern	caddr_t mmu_fault_status_area;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	mmfsa_va =
1127c478bd9Sstevel@tonic-gate 	    mmu_fault_status_area + (MMFSA_SIZE  * getprocessorid());
1137c478bd9Sstevel@tonic-gate 	set_mmfsa_scratchpad(mmfsa_va);
1147c478bd9Sstevel@tonic-gate 	prom_set_mmfsa_traptable(&trap_table, va_to_pa(mmfsa_va));
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate void
sfmmu_set_tsbs()1187c478bd9Sstevel@tonic-gate sfmmu_set_tsbs()
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate 	uint64_t rv;
1217c478bd9Sstevel@tonic-gate 	struct hv_tsb_block *hvbp = &ksfmmup->sfmmu_hvblock;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate #ifdef DEBUG
1247c478bd9Sstevel@tonic-gate 	if (hv_use_0_tsb == 0)
1257c478bd9Sstevel@tonic-gate 		return;
1267c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	rv = hv_set_ctx0(hvbp->hv_tsb_info_cnt,
1297c478bd9Sstevel@tonic-gate 	    hvbp->hv_tsb_info_pa);
1307c478bd9Sstevel@tonic-gate 	if (rv != H_EOK)
1317c478bd9Sstevel@tonic-gate 		prom_printf("cpu%d: hv_set_ctx0() returned %lx\n",
1327c478bd9Sstevel@tonic-gate 		    getprocessorid(), rv);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate #ifdef SET_MMU_STATS
1357c478bd9Sstevel@tonic-gate 	ASSERT(getprocessorid() < NCPU);
1367c478bd9Sstevel@tonic-gate 	rv = hv_mmu_set_stat_area(va_to_pa(&mmu_stat_area[getprocessorid()]),
1377c478bd9Sstevel@tonic-gate 	    sizeof (mmu_stat_area[0]));
1387c478bd9Sstevel@tonic-gate 	if (rv != H_EOK)
1397c478bd9Sstevel@tonic-gate 		prom_printf("cpu%d: hv_mmu_set_stat_area() returned %lx\n",
1407c478bd9Sstevel@tonic-gate 		    getprocessorid(), rv);
1417c478bd9Sstevel@tonic-gate #endif /* SET_MMU_STATS */
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  * This routine remaps the kernel using large ttes
1467c478bd9Sstevel@tonic-gate  * All entries except locked ones will be removed from the tlb.
1477c478bd9Sstevel@tonic-gate  * It assumes that both the text and data segments reside in a separate
1487c478bd9Sstevel@tonic-gate  * 4mb virtual and physical contigous memory chunk.  This routine
1497c478bd9Sstevel@tonic-gate  * is only executed by the first cpu.  The remaining cpus execute
1507c478bd9Sstevel@tonic-gate  * sfmmu_mp_startup() instead.
1517c478bd9Sstevel@tonic-gate  * XXX It assumes that the start of the text segment is KERNELBASE.  It should
1527c478bd9Sstevel@tonic-gate  * actually be based on start.
1537c478bd9Sstevel@tonic-gate  */
1547c478bd9Sstevel@tonic-gate void
sfmmu_remap_kernel(void)1557c478bd9Sstevel@tonic-gate sfmmu_remap_kernel(void)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate 	pfn_t	pfn;
1587c478bd9Sstevel@tonic-gate 	uint_t	attr;
1597c478bd9Sstevel@tonic-gate 	int	flags;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	extern char end[];
1627c478bd9Sstevel@tonic-gate 	extern struct as kas;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	textva = (caddr_t)(KERNELBASE & MMU_PAGEMASK4M);
1657c478bd9Sstevel@tonic-gate 	pfn = va_to_pfn(textva);
1667c478bd9Sstevel@tonic-gate 	if (pfn == PFN_INVALID)
1677c478bd9Sstevel@tonic-gate 		prom_panic("can't find kernel text pfn");
1687c478bd9Sstevel@tonic-gate 	pfn &= TTE_PFNMASK(TTE4M);
1697c478bd9Sstevel@tonic-gate 
1709d0d62adSJason Beloro 	attr = PROC_TEXT | HAT_NOSYNC;
1717c478bd9Sstevel@tonic-gate 	flags = HAT_LOAD_LOCK | SFMMU_NO_TSBLOAD;
1727c478bd9Sstevel@tonic-gate 	sfmmu_memtte(&ktext_tte, pfn, attr, TTE4M);
1737c478bd9Sstevel@tonic-gate 	/*
1747c478bd9Sstevel@tonic-gate 	 * We set the lock bit in the tte to lock the translation in
1757c478bd9Sstevel@tonic-gate 	 * the tlb.
1767c478bd9Sstevel@tonic-gate 	 */
1777c478bd9Sstevel@tonic-gate 	TTE_SET_LOCKED(&ktext_tte);
1787c478bd9Sstevel@tonic-gate 	sfmmu_tteload(kas.a_hat, &ktext_tte, textva, NULL, flags);
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	datava = (caddr_t)((uintptr_t)end & MMU_PAGEMASK4M);
1817c478bd9Sstevel@tonic-gate 	pfn = va_to_pfn(datava);
1827c478bd9Sstevel@tonic-gate 	if (pfn == PFN_INVALID)
1837c478bd9Sstevel@tonic-gate 		prom_panic("can't find kernel data pfn");
1847c478bd9Sstevel@tonic-gate 	pfn &= TTE_PFNMASK(TTE4M);
1857c478bd9Sstevel@tonic-gate 
1869d0d62adSJason Beloro 	attr = PROC_DATA | HAT_NOSYNC;
1877c478bd9Sstevel@tonic-gate 	sfmmu_memtte(&kdata_tte, pfn, attr, TTE4M);
1887c478bd9Sstevel@tonic-gate 	/*
1897c478bd9Sstevel@tonic-gate 	 * We set the lock bit in the tte to lock the translation in
1907c478bd9Sstevel@tonic-gate 	 * the tlb.  We also set the mod bit to avoid taking dirty bit
1917c478bd9Sstevel@tonic-gate 	 * traps on kernel data.
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 	TTE_SET_LOCKED(&kdata_tte);
1947c478bd9Sstevel@tonic-gate 	TTE_SET_LOFLAGS(&kdata_tte, 0, TTE_HWWR_INT);
1957c478bd9Sstevel@tonic-gate 	sfmmu_tteload(kas.a_hat, &kdata_tte, datava,
1967c478bd9Sstevel@tonic-gate 	    (struct page *)NULL, flags);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	/*
1997c478bd9Sstevel@tonic-gate 	 * create bigktsb ttes if necessary.
2007c478bd9Sstevel@tonic-gate 	 */
2017c478bd9Sstevel@tonic-gate 	if (enable_bigktsb) {
2027c478bd9Sstevel@tonic-gate 		int i = 0;
2037c478bd9Sstevel@tonic-gate 		caddr_t va = ktsb_base;
2047c478bd9Sstevel@tonic-gate 		size_t tsbsz = ktsb_sz;
2057c478bd9Sstevel@tonic-gate 		tte_t tte;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 		ASSERT(va >= datava + MMU_PAGESIZE4M);
2087c478bd9Sstevel@tonic-gate 		ASSERT(tsbsz >= MMU_PAGESIZE4M);
2097c478bd9Sstevel@tonic-gate 		ASSERT(IS_P2ALIGNED(tsbsz, tsbsz));
2107c478bd9Sstevel@tonic-gate 		ASSERT(IS_P2ALIGNED(va, tsbsz));
2119d0d62adSJason Beloro 		attr = PROC_DATA | HAT_NOSYNC;
2127c478bd9Sstevel@tonic-gate 		while (tsbsz != 0) {
2137c478bd9Sstevel@tonic-gate 			ASSERT(i < MAX_BIGKTSB_TTES);
2147c478bd9Sstevel@tonic-gate 			pfn = va_to_pfn(va);
2157c478bd9Sstevel@tonic-gate 			ASSERT(pfn != PFN_INVALID);
2167c478bd9Sstevel@tonic-gate 			ASSERT((pfn & ~TTE_PFNMASK(TTE4M)) == 0);
2177c478bd9Sstevel@tonic-gate 			sfmmu_memtte(&tte, pfn, attr, TTE4M);
2187c478bd9Sstevel@tonic-gate 			ASSERT(TTE_IS_MOD(&tte));
2197c478bd9Sstevel@tonic-gate 			/*
2207c478bd9Sstevel@tonic-gate 			 * No need to lock if we use physical addresses.
2217c478bd9Sstevel@tonic-gate 			 * Since we invalidate the kernel TSB using virtual
2227c478bd9Sstevel@tonic-gate 			 * addresses, it's an optimization to load them now
2237c478bd9Sstevel@tonic-gate 			 * so that we won't have to load them later.
2247c478bd9Sstevel@tonic-gate 			 */
2257c478bd9Sstevel@tonic-gate 			if (!ktsb_phys) {
2267c478bd9Sstevel@tonic-gate 				TTE_SET_LOCKED(&tte);
2277c478bd9Sstevel@tonic-gate 			}
2287c478bd9Sstevel@tonic-gate 			sfmmu_tteload(kas.a_hat, &tte, va, NULL, flags);
2297c478bd9Sstevel@tonic-gate 			bigktsb_ttes[i] = tte;
2307c478bd9Sstevel@tonic-gate 			va += MMU_PAGESIZE4M;
2317c478bd9Sstevel@tonic-gate 			tsbsz -= MMU_PAGESIZE4M;
2327c478bd9Sstevel@tonic-gate 			i++;
2337c478bd9Sstevel@tonic-gate 		}
2347c478bd9Sstevel@tonic-gate 		bigktsb_nttes = i;
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	sfmmu_set_tlb();
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate /*
2417c478bd9Sstevel@tonic-gate  * Setup the kernel's locked tte's
2427c478bd9Sstevel@tonic-gate  */
2437c478bd9Sstevel@tonic-gate void
sfmmu_set_tlb(void)2447c478bd9Sstevel@tonic-gate sfmmu_set_tlb(void)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 	(void) hv_mmu_map_perm_addr(textva, KCONTEXT, *(uint64_t *)&ktext_tte,
2477c478bd9Sstevel@tonic-gate 	    MAP_ITLB | MAP_DTLB);
2487c478bd9Sstevel@tonic-gate 	(void) hv_mmu_map_perm_addr(datava, KCONTEXT, *(uint64_t *)&kdata_tte,
2497c478bd9Sstevel@tonic-gate 	    MAP_DTLB);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	if (!ktsb_phys && enable_bigktsb) {
2527c478bd9Sstevel@tonic-gate 		int i;
2537c478bd9Sstevel@tonic-gate 		caddr_t va = ktsb_base;
2547c478bd9Sstevel@tonic-gate 		uint64_t tte;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		ASSERT(bigktsb_nttes <= MAX_BIGKTSB_TTES);
2577c478bd9Sstevel@tonic-gate 		for (i = 0; i < bigktsb_nttes; i++) {
2587c478bd9Sstevel@tonic-gate 			tte = *(uint64_t *)&bigktsb_ttes[i];
2597c478bd9Sstevel@tonic-gate 			(void) hv_mmu_map_perm_addr(va, KCONTEXT, tte,
2607c478bd9Sstevel@tonic-gate 			    MAP_DTLB);
2617c478bd9Sstevel@tonic-gate 			va += MMU_PAGESIZE4M;
2627c478bd9Sstevel@tonic-gate 		}
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate  * This routine is executed by all other cpus except the first one
2687c478bd9Sstevel@tonic-gate  * at initialization time.  It is responsible for taking over the
2697c478bd9Sstevel@tonic-gate  * mmu from the prom.  We follow these steps.
2707c478bd9Sstevel@tonic-gate  * Lock the kernel's ttes in the TLB
2717c478bd9Sstevel@tonic-gate  * Initialize the tsb hardware registers
2727c478bd9Sstevel@tonic-gate  * Take over the trap table
2737c478bd9Sstevel@tonic-gate  * Flush the prom's locked entries from the TLB
2747c478bd9Sstevel@tonic-gate  */
2757c478bd9Sstevel@tonic-gate void
sfmmu_mp_startup(void)2767c478bd9Sstevel@tonic-gate sfmmu_mp_startup(void)
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate 	sfmmu_set_tlb();
2797c478bd9Sstevel@tonic-gate 	setwstate(WSTATE_KERN);
2807c478bd9Sstevel@tonic-gate 	/*
2817c478bd9Sstevel@tonic-gate 	 * sfmmu_set_fault_status_area() takes over trap_table
2827c478bd9Sstevel@tonic-gate 	 */
2837c478bd9Sstevel@tonic-gate 	sfmmu_set_fault_status_area();
2847c478bd9Sstevel@tonic-gate 	sfmmu_set_tsbs();
2857c478bd9Sstevel@tonic-gate 	install_va_to_tte();
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate void
kdi_tlb_page_lock(caddr_t va,int do_dtlb)2897c478bd9Sstevel@tonic-gate kdi_tlb_page_lock(caddr_t va, int do_dtlb)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 	tte_t tte;
2927c478bd9Sstevel@tonic-gate 	pfn_t pfn = va_to_pfn(va);
2937c478bd9Sstevel@tonic-gate 	uint64_t ret;
2947c478bd9Sstevel@tonic-gate 
2959d0d62adSJason Beloro 	sfmmu_memtte(&tte, pfn, (PROC_TEXT | HAT_NOSYNC), TTE8K);
2967c478bd9Sstevel@tonic-gate 	ret = hv_mmu_map_perm_addr(va, KCONTEXT, *(uint64_t *)&tte,
2977c478bd9Sstevel@tonic-gate 	    MAP_ITLB | (do_dtlb ? MAP_DTLB : 0));
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (ret != H_EOK) {
3007c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "cpu%d: cannot set permanent mapping for "
30144961713Sgirish 		    "va=0x%p, hv error code 0x%lx",
3027c478bd9Sstevel@tonic-gate 		    getprocessorid(), (void *)va, ret);
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate void
kdi_tlb_page_unlock(caddr_t va,int do_dtlb)3077c478bd9Sstevel@tonic-gate kdi_tlb_page_unlock(caddr_t va, int do_dtlb)
3087c478bd9Sstevel@tonic-gate {
3097c478bd9Sstevel@tonic-gate 	(void) hv_mmu_unmap_perm_addr(va, KCONTEXT,
3107c478bd9Sstevel@tonic-gate 	    MAP_ITLB | (do_dtlb ? MAP_DTLB : 0));
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate  * Clear machine specific TSB information for a user process
3157c478bd9Sstevel@tonic-gate  */
3167c478bd9Sstevel@tonic-gate void
sfmmu_clear_utsbinfo()3177c478bd9Sstevel@tonic-gate sfmmu_clear_utsbinfo()
3187c478bd9Sstevel@tonic-gate {
319*12551037SToomas Soome 	(void) hv_set_ctxnon0(0, 0);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate /*
3237dacfc44Spaulsan  * The tsbord[] array is set up to translate from the order of tsbs in the sfmmu
3247dacfc44Spaulsan  * list to the order of tsbs in the tsb descriptor array passed to the hv, which
3257dacfc44Spaulsan  * is the search order used during Hardware Table Walk.
3267dacfc44Spaulsan  * So, the tsb with index i in the sfmmu list will have search order tsbord[i].
3277dacfc44Spaulsan  *
3287dacfc44Spaulsan  * The order of tsbs in the sfmmu list will be as follows:
3297dacfc44Spaulsan  *
3307dacfc44Spaulsan  *              0 8K - 512K private TSB
3317dacfc44Spaulsan  *              1 4M - 256M private TSB
3327dacfc44Spaulsan  *              2 8K - 512K shared TSB
3337dacfc44Spaulsan  *              3 4M - 256M shared TSB
3347dacfc44Spaulsan  *
3357dacfc44Spaulsan  * Shared TSBs are only used if a process is part of an SCD.
3367dacfc44Spaulsan  *
3377dacfc44Spaulsan  * So, e.g. tsbord[3] = 1;
3387dacfc44Spaulsan  *         corresponds to searching the shared 4M TSB second.
3397dacfc44Spaulsan  *
3407dacfc44Spaulsan  * The search order is selected so that the 8K-512K private TSB is always first.
3417dacfc44Spaulsan  * Currently shared context is not expected to map many 8K-512K pages that cause
3427dacfc44Spaulsan  * TLB misses so we order the shared TSB for 4M-256M pages in front of the
3437dacfc44Spaulsan  * shared TSB for 8K-512K pages. We also expect more TLB misses against private
3447dacfc44Spaulsan  * context mappings than shared context mappings and place private TSBs ahead of
3457dacfc44Spaulsan  * shared TSBs in descriptor order. The shtsb4m_first /etc/system tuneable can
3467dacfc44Spaulsan  * be used to change the default ordering of private and shared TSBs for
3477dacfc44Spaulsan  * 4M-256M pages.
3487c478bd9Sstevel@tonic-gate  */
3497c478bd9Sstevel@tonic-gate void
sfmmu_setup_tsbinfo(sfmmu_t * sfmmup)3507c478bd9Sstevel@tonic-gate sfmmu_setup_tsbinfo(sfmmu_t *sfmmup)
3517c478bd9Sstevel@tonic-gate {
35205d3dc4bSpaulsan 	struct tsb_info		*tsbinfop;
35305d3dc4bSpaulsan 	hv_tsb_info_t		*tdp;
35405d3dc4bSpaulsan 	int			i;
35505d3dc4bSpaulsan 	int			j;
35605d3dc4bSpaulsan 	int			scd = 0;
35705d3dc4bSpaulsan 	int			tsbord[NHV_TSB_INFO];
35805d3dc4bSpaulsan 
35905d3dc4bSpaulsan #ifdef DEBUG
36005d3dc4bSpaulsan 	ASSERT(max_mmu_ctxdoms > 0);
36105d3dc4bSpaulsan 	if (sfmmup != ksfmmup) {
36205d3dc4bSpaulsan 		/* Process should have INVALID_CONTEXT on all MMUs. */
36305d3dc4bSpaulsan 		for (i = 0; i < max_mmu_ctxdoms; i++) {
36405d3dc4bSpaulsan 			ASSERT(sfmmup->sfmmu_ctxs[i].cnum == INVALID_CONTEXT);
36505d3dc4bSpaulsan 		}
36605d3dc4bSpaulsan 	}
36705d3dc4bSpaulsan #endif
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	tsbinfop = sfmmup->sfmmu_tsb;
3707c478bd9Sstevel@tonic-gate 	if (tsbinfop == NULL) {
3717c478bd9Sstevel@tonic-gate 		sfmmup->sfmmu_hvblock.hv_tsb_info_pa = (uint64_t)-1;
3727c478bd9Sstevel@tonic-gate 		sfmmup->sfmmu_hvblock.hv_tsb_info_cnt = 0;
3737c478bd9Sstevel@tonic-gate 		return;
3747c478bd9Sstevel@tonic-gate 	}
37505d3dc4bSpaulsan 
37605d3dc4bSpaulsan 	ASSERT(sfmmup != ksfmmup || sfmmup->sfmmu_scdp == NULL);
37705d3dc4bSpaulsan 	ASSERT(sfmmup->sfmmu_scdp == NULL ||
37805d3dc4bSpaulsan 	    sfmmup->sfmmu_scdp->scd_sfmmup->sfmmu_tsb != NULL);
37905d3dc4bSpaulsan 
38005d3dc4bSpaulsan 	tsbord[0] = 0;
38105d3dc4bSpaulsan 	if (sfmmup->sfmmu_scdp == NULL) {
38205d3dc4bSpaulsan 		tsbord[1] = 1;
38305d3dc4bSpaulsan 	} else {
38405d3dc4bSpaulsan 		struct tsb_info *scd8ktsbp =
38505d3dc4bSpaulsan 		    sfmmup->sfmmu_scdp->scd_sfmmup->sfmmu_tsb;
38605d3dc4bSpaulsan 		ulong_t shared_4mttecnt = 0;
38705d3dc4bSpaulsan 		ulong_t priv_4mttecnt = 0;
38805d3dc4bSpaulsan 		int scd4mtsb = (scd8ktsbp->tsb_next != NULL);
38905d3dc4bSpaulsan 
39005d3dc4bSpaulsan 		for (i = TTE4M; i < MMU_PAGE_SIZES; i++) {
39105d3dc4bSpaulsan 			if (scd4mtsb) {
39205d3dc4bSpaulsan 				shared_4mttecnt +=
39305d3dc4bSpaulsan 				    sfmmup->sfmmu_scdismttecnt[i] +
39405d3dc4bSpaulsan 				    sfmmup->sfmmu_scdrttecnt[i];
39505d3dc4bSpaulsan 			}
39605d3dc4bSpaulsan 			if (tsbinfop->tsb_next != NULL) {
39705d3dc4bSpaulsan 				priv_4mttecnt += sfmmup->sfmmu_ttecnt[i] +
39805d3dc4bSpaulsan 				    sfmmup->sfmmu_ismttecnt[i];
39905d3dc4bSpaulsan 			}
40005d3dc4bSpaulsan 		}
40105d3dc4bSpaulsan 		if (tsbinfop->tsb_next == NULL) {
40205d3dc4bSpaulsan 			if (shared_4mttecnt) {
40305d3dc4bSpaulsan 				tsbord[1] = 2;
40405d3dc4bSpaulsan 				tsbord[2] = 1;
40505d3dc4bSpaulsan 			} else {
40605d3dc4bSpaulsan 				tsbord[1] = 1;
40705d3dc4bSpaulsan 				tsbord[2] = 2;
40805d3dc4bSpaulsan 			}
40905d3dc4bSpaulsan 		} else if (priv_4mttecnt) {
41005d3dc4bSpaulsan 			if (shared_4mttecnt) {
41105d3dc4bSpaulsan 				tsbord[1] = shtsb4m_first ? 2 : 1;
41205d3dc4bSpaulsan 				tsbord[2] = 3;
41305d3dc4bSpaulsan 				tsbord[3] = shtsb4m_first ? 1 : 2;
41405d3dc4bSpaulsan 			} else {
41505d3dc4bSpaulsan 				tsbord[1] = 1;
41605d3dc4bSpaulsan 				tsbord[2] = 2;
41705d3dc4bSpaulsan 				tsbord[3] = 3;
41805d3dc4bSpaulsan 			}
41905d3dc4bSpaulsan 		} else if (shared_4mttecnt) {
42005d3dc4bSpaulsan 			tsbord[1] = 3;
42105d3dc4bSpaulsan 			tsbord[2] = 2;
42205d3dc4bSpaulsan 			tsbord[3] = 1;
42305d3dc4bSpaulsan 		} else {
42405d3dc4bSpaulsan 			tsbord[1] = 2;
42505d3dc4bSpaulsan 			tsbord[2] = 1;
42605d3dc4bSpaulsan 			tsbord[3] = 3;
42705d3dc4bSpaulsan 		}
42805d3dc4bSpaulsan 	}
42905d3dc4bSpaulsan 
43005d3dc4bSpaulsan 	ASSERT(tsbinfop != NULL);
43105d3dc4bSpaulsan 	for (i = 0; tsbinfop != NULL && i < NHV_TSB_INFO; i++) {
43205d3dc4bSpaulsan 		if (i == 0) {
43305d3dc4bSpaulsan 			tdp = &sfmmup->sfmmu_hvblock.hv_tsb_info[i];
43405d3dc4bSpaulsan 			sfmmup->sfmmu_hvblock.hv_tsb_info_pa = va_to_pa(tdp);
43505d3dc4bSpaulsan 		}
43605d3dc4bSpaulsan 
43705d3dc4bSpaulsan 
43805d3dc4bSpaulsan 		j = tsbord[i];
43905d3dc4bSpaulsan 
44005d3dc4bSpaulsan 		tdp = &sfmmup->sfmmu_hvblock.hv_tsb_info[j];
44105d3dc4bSpaulsan 
44205d3dc4bSpaulsan 		ASSERT(tsbinfop->tsb_ttesz_mask != 0);
44305d3dc4bSpaulsan 		tdp->hvtsb_idxpgsz = lowbit(tsbinfop->tsb_ttesz_mask) - 1;
44405d3dc4bSpaulsan 		tdp->hvtsb_assoc = 1;
44505d3dc4bSpaulsan 		tdp->hvtsb_ntte = TSB_ENTRIES(tsbinfop->tsb_szc);
44605d3dc4bSpaulsan 		tdp->hvtsb_ctx_index = scd;
44705d3dc4bSpaulsan 		tdp->hvtsb_pgszs = tsbinfop->tsb_ttesz_mask;
44805d3dc4bSpaulsan 		tdp->hvtsb_rsvd = 0;
44905d3dc4bSpaulsan 		tdp->hvtsb_pa = tsbinfop->tsb_pa;
45005d3dc4bSpaulsan 
45105d3dc4bSpaulsan 		tsbinfop = tsbinfop->tsb_next;
45205d3dc4bSpaulsan 		if (tsbinfop == NULL && !scd && sfmmup->sfmmu_scdp != NULL) {
45305d3dc4bSpaulsan 			tsbinfop =
45405d3dc4bSpaulsan 			    sfmmup->sfmmu_scdp->scd_sfmmup->sfmmu_tsb;
45505d3dc4bSpaulsan 			scd = 1;
45605d3dc4bSpaulsan 		}
45705d3dc4bSpaulsan 	}
45805d3dc4bSpaulsan 	sfmmup->sfmmu_hvblock.hv_tsb_info_cnt = i;
45905d3dc4bSpaulsan 	ASSERT(tsbinfop == NULL);
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate  * Invalidate a TSB via processor specific TSB invalidation routine
4647c478bd9Sstevel@tonic-gate  */
4657c478bd9Sstevel@tonic-gate void
sfmmu_inv_tsb(caddr_t tsb_base,uint_t tsb_bytes)4667c478bd9Sstevel@tonic-gate sfmmu_inv_tsb(caddr_t tsb_base, uint_t tsb_bytes)
4677c478bd9Sstevel@tonic-gate {
4687c478bd9Sstevel@tonic-gate 	extern void cpu_inv_tsb(caddr_t, uint_t);
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	cpu_inv_tsb(tsb_base, tsb_bytes);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate  * Completely flush the D-cache on all cpus.
4757c478bd9Sstevel@tonic-gate  * Not applicable to sun4v.
4767c478bd9Sstevel@tonic-gate  */
4777c478bd9Sstevel@tonic-gate void
sfmmu_cache_flushall()4787c478bd9Sstevel@tonic-gate sfmmu_cache_flushall()
4797c478bd9Sstevel@tonic-gate {
4807c478bd9Sstevel@tonic-gate }
481