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
51ce12b49Svb70745 * Common Development and Distribution License (the "License").
61ce12b49Svb70745 * 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
170*9d0d62adSJason 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
186*9d0d62adSJason 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));
211*9d0d62adSJason 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
295*9d0d62adSJason 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 {
3197c478bd9Sstevel@tonic-gate (void) hv_set_ctxnon0(0, NULL);
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 {
3527c478bd9Sstevel@tonic-gate struct tsb_info *tsbinfop;
3537c478bd9Sstevel@tonic-gate 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];
4347c478bd9Sstevel@tonic-gate 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;
4447c478bd9Sstevel@tonic-gate tdp->hvtsb_assoc = 1;
4457c478bd9Sstevel@tonic-gate tdp->hvtsb_ntte = TSB_ENTRIES(tsbinfop->tsb_szc);
44605d3dc4bSpaulsan tdp->hvtsb_ctx_index = scd;
4477c478bd9Sstevel@tonic-gate tdp->hvtsb_pgszs = tsbinfop->tsb_ttesz_mask;
4487c478bd9Sstevel@tonic-gate tdp->hvtsb_rsvd = 0;
4497c478bd9Sstevel@tonic-gate 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