xref: /onnv-gate/usr/src/uts/i86pc/vm/kboot_mmu.c (revision 7542:42d86bdbde36)
13446Smrj /*
23446Smrj  * CDDL HEADER START
33446Smrj  *
43446Smrj  * The contents of this file are subject to the terms of the
53446Smrj  * Common Development and Distribution License (the "License").
63446Smrj  * You may not use this file except in compliance with the License.
73446Smrj  *
83446Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93446Smrj  * or http://www.opensolaris.org/os/licensing.
103446Smrj  * See the License for the specific language governing permissions
113446Smrj  * and limitations under the License.
123446Smrj  *
133446Smrj  * When distributing Covered Code, include this CDDL HEADER in each
143446Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153446Smrj  * If applicable, add the following below this CDDL HEADER, with the
163446Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
173446Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
183446Smrj  *
193446Smrj  * CDDL HEADER END
203446Smrj  */
213446Smrj 
223446Smrj /*
23*7542SRichard.Bean@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
243446Smrj  * Use is subject to license terms.
253446Smrj  */
263446Smrj 
273446Smrj #include <sys/types.h>
283446Smrj #include <sys/systm.h>
293446Smrj #include <sys/archsystm.h>
303446Smrj #include <sys/debug.h>
313446Smrj #include <sys/bootconf.h>
323446Smrj #include <sys/bootsvcs.h>
333446Smrj #include <sys/bootinfo.h>
343446Smrj #include <sys/mman.h>
353446Smrj #include <sys/cmn_err.h>
363446Smrj #include <sys/param.h>
373446Smrj #include <sys/machparam.h>
383446Smrj #include <sys/machsystm.h>
393446Smrj #include <sys/promif.h>
403446Smrj #include <sys/kobj.h>
415084Sjohnlev #ifdef __xpv
425084Sjohnlev #include <sys/hypervisor.h>
435084Sjohnlev #endif
443446Smrj #include <vm/kboot_mmu.h>
453446Smrj #include <vm/hat_pte.h>
463446Smrj #include <vm/hat_i86.h>
473446Smrj #include <vm/seg_kmem.h>
483446Smrj 
493446Smrj #if 0
503446Smrj /*
513446Smrj  * Joe's debug printing
523446Smrj  */
533446Smrj #define	DBG(x)    \
54*7542SRichard.Bean@Sun.COM 	bop_printf(NULL, "kboot_mmu.c: %s is %" PRIx64 "\n", #x, (uint64_t)(x));
553446Smrj #else
563446Smrj #define	DBG(x)	/* naught */
573446Smrj #endif
583446Smrj 
593446Smrj /*
603446Smrj  * Page table and memory stuff.
613446Smrj  */
623446Smrj static caddr_t window;
633446Smrj static caddr_t pte_to_window;
643446Smrj 
653446Smrj /*
663446Smrj  * this are needed by mmu_init()
673446Smrj  */
683446Smrj int kbm_nx_support = 0;		/* NX bit in PTEs is in use */
693446Smrj int kbm_pae_support = 0;	/* PAE is 64 bit Page table entries */
703446Smrj int kbm_pge_support = 0;	/* PGE is Page table global bit enabled */
713446Smrj int kbm_largepage_support = 0;
723446Smrj uint_t kbm_nucleus_size = 0;
733446Smrj 
743446Smrj #define	BOOT_SHIFT(l)	(shift_amt[l])
753446Smrj #define	BOOT_SZ(l)	((size_t)1 << BOOT_SHIFT(l))
763446Smrj #define	BOOT_OFFSET(l)	(BOOT_SZ(l) - 1)
773446Smrj #define	BOOT_MASK(l)	(~BOOT_OFFSET(l))
783446Smrj 
793446Smrj /*
803446Smrj  * Initialize memory management parameters for boot time page table management
813446Smrj  */
823446Smrj void
kbm_init(struct xboot_info * bi)833446Smrj kbm_init(struct xboot_info *bi)
843446Smrj {
853446Smrj 	/*
863446Smrj 	 * configure mmu information
873446Smrj 	 */
883446Smrj 	kbm_nucleus_size = (uintptr_t)bi->bi_kseg_size;
893446Smrj 	kbm_largepage_support = bi->bi_use_largepage;
903446Smrj 	kbm_nx_support = bi->bi_use_nx;
913446Smrj 	kbm_pae_support = bi->bi_use_pae;
923446Smrj 	kbm_pge_support = bi->bi_use_pge;
933446Smrj 	window = bi->bi_pt_window;
943446Smrj 	DBG(window);
953446Smrj 	pte_to_window = bi->bi_pte_to_pt_window;
963446Smrj 	DBG(pte_to_window);
973446Smrj 	if (kbm_pae_support) {
983446Smrj 		shift_amt = shift_amt_pae;
993446Smrj 		ptes_per_table = 512;
1003446Smrj 		pte_size = 8;
1013446Smrj 		lpagesize = TWO_MEG;
1023446Smrj #ifdef __amd64
1033446Smrj 		top_level = 3;
1043446Smrj #else
1053446Smrj 		top_level = 2;
1063446Smrj #endif
1073446Smrj 	} else {
1083446Smrj 		shift_amt = shift_amt_nopae;
1093446Smrj 		ptes_per_table = 1024;
1103446Smrj 		pte_size = 4;
1113446Smrj 		lpagesize = FOUR_MEG;
1123446Smrj 		top_level = 1;
1133446Smrj 	}
1143446Smrj 
1155084Sjohnlev #ifdef __xpv
1165084Sjohnlev 	xen_info = bi->bi_xen_start_info;
1175084Sjohnlev 	mfn_list = (mfn_t *)xen_info->mfn_list;
1185084Sjohnlev 	DBG(mfn_list);
1195084Sjohnlev 	mfn_count = xen_info->nr_pages;
1205084Sjohnlev 	DBG(mfn_count);
1215084Sjohnlev #endif
1223446Smrj 	top_page_table = bi->bi_top_page_table;
1233446Smrj 	DBG(top_page_table);
1243446Smrj }
1253446Smrj 
1263446Smrj /*
1273446Smrj  * Change the addressible page table window to point at a given page
1283446Smrj  */
1293446Smrj /*ARGSUSED*/
1303446Smrj void *
kbm_remap_window(paddr_t physaddr,int writeable)1313446Smrj kbm_remap_window(paddr_t physaddr, int writeable)
1323446Smrj {
1335084Sjohnlev 	x86pte_t pt_bits = PT_NOCONSIST | PT_VALID | PT_WRITABLE;
1343446Smrj 
1353446Smrj 	DBG(physaddr);
1363446Smrj 
1375084Sjohnlev #ifdef __xpv
1385084Sjohnlev 	if (!writeable)
1395084Sjohnlev 		pt_bits &= ~PT_WRITABLE;
1405084Sjohnlev 	if (HYPERVISOR_update_va_mapping((uintptr_t)window,
1415084Sjohnlev 	    pa_to_ma(physaddr) | pt_bits, UVMF_INVLPG | UVMF_LOCAL) < 0)
1425084Sjohnlev 		bop_panic("HYPERVISOR_update_va_mapping() failed");
1435084Sjohnlev #else
1443446Smrj 	if (kbm_pae_support)
1453446Smrj 		*((x86pte_t *)pte_to_window) = physaddr | pt_bits;
1463446Smrj 	else
1473446Smrj 		*((x86pte32_t *)pte_to_window) = physaddr | pt_bits;
1483446Smrj 	mmu_tlbflush_entry(window);
1495084Sjohnlev #endif
1503446Smrj 	DBG(window);
1513446Smrj 	return (window);
1523446Smrj }
1533446Smrj 
1543446Smrj /*
1553446Smrj  * Add a mapping for the physical page at the given virtual address.
1563446Smrj  */
1573446Smrj void
kbm_map(uintptr_t va,paddr_t pa,uint_t level,uint_t is_kernel)1583446Smrj kbm_map(uintptr_t va, paddr_t pa, uint_t level, uint_t is_kernel)
1593446Smrj {
1603446Smrj 	x86pte_t *ptep;
1613446Smrj 	paddr_t pte_physaddr;
1623446Smrj 	x86pte_t pteval;
1633446Smrj 
1643446Smrj 	if (khat_running)
1653446Smrj 		panic("kbm_map() called too late");
1663446Smrj 
1673446Smrj 	pteval = pa_to_ma(pa) | PT_NOCONSIST | PT_VALID | PT_WRITABLE;
1685349Skchow 	if (level >= 1)
1693446Smrj 		pteval |= PT_PAGESIZE;
1703446Smrj 	if (kbm_pge_support && is_kernel)
1713446Smrj 		pteval |= PT_GLOBAL;
1723446Smrj 
1735084Sjohnlev #ifdef __xpv
1745084Sjohnlev 	/*
1755084Sjohnlev 	 * try update_va_mapping first - fails if page table is missing.
1765084Sjohnlev 	 */
1775084Sjohnlev 	if (HYPERVISOR_update_va_mapping(va, pteval,
1785084Sjohnlev 	    UVMF_INVLPG | UVMF_LOCAL) == 0)
1795084Sjohnlev 		return;
1805084Sjohnlev #endif
1815084Sjohnlev 
1823446Smrj 	/*
1833446Smrj 	 * Find the pte that will map this address. This creates any
1843446Smrj 	 * missing intermediate level page tables.
1853446Smrj 	 */
1863446Smrj 	ptep = find_pte(va, &pte_physaddr, level, 0);
1873446Smrj 	if (ptep == NULL)
1883446Smrj 		bop_panic("kbm_map: find_pte returned NULL");
1893446Smrj 
1905084Sjohnlev #ifdef __xpv
1915084Sjohnlev 	if (HYPERVISOR_update_va_mapping(va, pteval, UVMF_INVLPG | UVMF_LOCAL))
1925084Sjohnlev 		bop_panic("HYPERVISOR_update_va_mapping() failed");
1935084Sjohnlev #else
1943446Smrj 	if (kbm_pae_support)
1953446Smrj 		*ptep = pteval;
1963446Smrj 	else
1973446Smrj 		*((x86pte32_t *)ptep) = pteval;
1983446Smrj 	mmu_tlbflush_entry((caddr_t)va);
1995084Sjohnlev #endif
2003446Smrj }
2013446Smrj 
2025084Sjohnlev #ifdef __xpv
2035084Sjohnlev 
2045084Sjohnlev /*
2055084Sjohnlev  * Add a mapping for the machine page at the given virtual address.
2065084Sjohnlev  */
2075084Sjohnlev void
kbm_map_ma(maddr_t ma,uintptr_t va,uint_t level)2085084Sjohnlev kbm_map_ma(maddr_t ma, uintptr_t va, uint_t level)
2095084Sjohnlev {
2105084Sjohnlev 	paddr_t pte_physaddr;
2115084Sjohnlev 	x86pte_t pteval;
2125084Sjohnlev 
2135084Sjohnlev 	pteval = ma | PT_NOCONSIST | PT_VALID | PT_REF | PT_WRITABLE;
2145084Sjohnlev 	if (level == 1)
2155084Sjohnlev 		pteval |= PT_PAGESIZE;
2165084Sjohnlev 
2175084Sjohnlev 	/*
2185084Sjohnlev 	 * try update_va_mapping first - fails if page table is missing.
2195084Sjohnlev 	 */
2205084Sjohnlev 	if (HYPERVISOR_update_va_mapping(va,
2215084Sjohnlev 	    pteval, UVMF_INVLPG | UVMF_LOCAL) == 0)
2225084Sjohnlev 		return;
2235084Sjohnlev 
2245084Sjohnlev 	/*
2255084Sjohnlev 	 * Find the pte that will map this address. This creates any
2265084Sjohnlev 	 * missing intermediate level page tables
2275084Sjohnlev 	 */
2285084Sjohnlev 	(void) find_pte(va, &pte_physaddr, level, 0);
2295084Sjohnlev 
2305084Sjohnlev 	if (HYPERVISOR_update_va_mapping(va,
2315084Sjohnlev 	    pteval, UVMF_INVLPG | UVMF_LOCAL) != 0)
2325084Sjohnlev 		bop_panic("HYPERVISOR_update_va_mapping failed");
2335084Sjohnlev }
2345084Sjohnlev 
2355084Sjohnlev #endif /* __xpv */
2365084Sjohnlev 
2375084Sjohnlev 
2383446Smrj /*
2393446Smrj  * Probe the boot time page tables to find the first mapping
2403446Smrj  * including va (or higher) and return non-zero if one is found.
2413446Smrj  * va is updated to the starting address and len to the pagesize.
2423446Smrj  * pp will be set to point to the 1st page_t of the mapped page(s).
2433446Smrj  *
2443446Smrj  * Note that if va is in the middle of a large page, the returned va
2453446Smrj  * will be less than what was asked for.
2463446Smrj  */
2473446Smrj int
kbm_probe(uintptr_t * va,size_t * len,pfn_t * pfn,uint_t * prot)2483446Smrj kbm_probe(uintptr_t *va, size_t *len, pfn_t *pfn, uint_t *prot)
2493446Smrj {
2503446Smrj 	uintptr_t	probe_va;
2513446Smrj 	x86pte_t	*ptep;
2523446Smrj 	paddr_t		pte_physaddr;
2533446Smrj 	x86pte_t	pte_val;
2543446Smrj 	level_t		l;
2553446Smrj 
2563446Smrj 	if (khat_running)
2573446Smrj 		panic("kbm_probe() called too late");
2583446Smrj 	*len = 0;
2593446Smrj 	*pfn = PFN_INVALID;
2603446Smrj 	*prot = 0;
2613446Smrj 	probe_va = *va;
2623446Smrj restart_new_va:
2633446Smrj 	l = top_level;
2643446Smrj 	for (;;) {
2653446Smrj 		if (IN_VA_HOLE(probe_va))
2663446Smrj 			probe_va = mmu.hole_end;
2673446Smrj 
2683446Smrj 		if (IN_HYPERVISOR_VA(probe_va))
2695084Sjohnlev #if defined(__amd64) && defined(__xpv)
2705084Sjohnlev 			probe_va = HYPERVISOR_VIRT_END;
2715084Sjohnlev #else
2723446Smrj 			return (0);
2735084Sjohnlev #endif
2743446Smrj 
2753446Smrj 		/*
2763446Smrj 		 * If we don't have a valid PTP/PTE at this level
2773446Smrj 		 * then we can bump VA by this level's pagesize and try again.
2783446Smrj 		 * When the probe_va wraps around, we are done.
2793446Smrj 		 */
2803446Smrj 		ptep = find_pte(probe_va, &pte_physaddr, l, 1);
2813446Smrj 		if (ptep == NULL)
2823446Smrj 			bop_panic("kbm_probe: find_pte returned NULL");
2833446Smrj 		if (kbm_pae_support)
2843446Smrj 			pte_val = *ptep;
2853446Smrj 		else
2863446Smrj 			pte_val = *((x86pte32_t *)ptep);
2873446Smrj 		if (!PTE_ISVALID(pte_val)) {
2883446Smrj 			probe_va = (probe_va & BOOT_MASK(l)) + BOOT_SZ(l);
2893446Smrj 			if (probe_va <= *va)
2903446Smrj 				return (0);
2913446Smrj 			goto restart_new_va;
2923446Smrj 		}
2933446Smrj 
2943446Smrj 		/*
2953446Smrj 		 * If this entry is a pointer to a lower level page table
2963446Smrj 		 * go down to it.
2973446Smrj 		 */
2983446Smrj 		if (!PTE_ISPAGE(pte_val, l)) {
2993446Smrj 			ASSERT(l > 0);
3003446Smrj 			--l;
3013446Smrj 			continue;
3023446Smrj 		}
3033446Smrj 
3043446Smrj 		/*
3053446Smrj 		 * We found a boot level page table entry
3063446Smrj 		 */
3073446Smrj 		*len = BOOT_SZ(l);
3083446Smrj 		*va = probe_va & ~(*len - 1);
3093446Smrj 		*pfn = PTE2PFN(pte_val, l);
3103446Smrj 
3113446Smrj 
3123446Smrj 		*prot = PROT_READ | PROT_EXEC;
3133446Smrj 		if (PTE_GET(pte_val, PT_WRITABLE))
3143446Smrj 			*prot |= PROT_WRITE;
3153446Smrj 
3163446Smrj 		/*
3173446Smrj 		 * pt_nx is cleared if processor doesn't support NX bit
3183446Smrj 		 */
3193446Smrj 		if (PTE_GET(pte_val, mmu.pt_nx))
3203446Smrj 			*prot &= ~PROT_EXEC;
3213446Smrj 
3223446Smrj 		return (1);
3233446Smrj 	}
3243446Smrj }
3253446Smrj 
3263446Smrj 
3273446Smrj /*
3283446Smrj  * Destroy a boot loader page table 4K mapping.
3293446Smrj  */
3303446Smrj void
kbm_unmap(uintptr_t va)3313446Smrj kbm_unmap(uintptr_t va)
3323446Smrj {
3333446Smrj 	if (khat_running)
3343446Smrj 		panic("kbm_unmap() called too late");
3353446Smrj 	else {
3365084Sjohnlev #ifdef __xpv
3375084Sjohnlev 		(void) HYPERVISOR_update_va_mapping(va, 0,
3385084Sjohnlev 		    UVMF_INVLPG | UVMF_LOCAL);
3395084Sjohnlev #else
3403446Smrj 		x86pte_t *ptep;
3413446Smrj 		level_t	level = 0;
3423446Smrj 		uint_t  probe_only = 1;
3433446Smrj 
3443446Smrj 		ptep = find_pte(va, NULL, level, probe_only);
3453446Smrj 		if (ptep == NULL)
3463446Smrj 			return;
3473446Smrj 
3483446Smrj 		if (kbm_pae_support)
3493446Smrj 			*ptep = 0;
3503446Smrj 		else
3513446Smrj 			*((x86pte32_t *)ptep) = 0;
3523446Smrj 		mmu_tlbflush_entry((caddr_t)va);
3535084Sjohnlev #endif
3543446Smrj 	}
3553446Smrj }
3563446Smrj 
3573446Smrj 
3583446Smrj /*
3593446Smrj  * Change a boot loader page table 4K mapping.
3603446Smrj  * Returns the pfn of the old mapping.
3613446Smrj  */
3623446Smrj pfn_t
kbm_remap(uintptr_t va,pfn_t pfn)3633446Smrj kbm_remap(uintptr_t va, pfn_t pfn)
3643446Smrj {
3653446Smrj 	x86pte_t *ptep;
3663446Smrj 	level_t	level = 0;
3673446Smrj 	uint_t  probe_only = 1;
3683446Smrj 	x86pte_t pte_val = pa_to_ma(pfn_to_pa(pfn)) | PT_WRITABLE |
3693446Smrj 	    PT_NOCONSIST | PT_VALID;
3703446Smrj 	x86pte_t old_pte;
3713446Smrj 
3723446Smrj 	if (khat_running)
3733446Smrj 		panic("kbm_remap() called too late");
3743446Smrj 	ptep = find_pte(va, NULL, level, probe_only);
3753446Smrj 	if (ptep == NULL)
3763446Smrj 		bop_panic("kbm_remap: find_pte returned NULL");
3773446Smrj 
3783446Smrj 	if (kbm_pae_support)
3793446Smrj 		old_pte = *ptep;
3803446Smrj 	else
3813446Smrj 		old_pte = *((x86pte32_t *)ptep);
3823446Smrj 
3835084Sjohnlev #ifdef __xpv
3845084Sjohnlev 	if (HYPERVISOR_update_va_mapping(va, pte_val, UVMF_INVLPG | UVMF_LOCAL))
3855084Sjohnlev 		bop_panic("HYPERVISOR_update_va_mapping() failed");
3865084Sjohnlev #else
3873446Smrj 	if (kbm_pae_support)
3883446Smrj 		*((x86pte_t *)ptep) = pte_val;
3893446Smrj 	else
3903446Smrj 		*((x86pte32_t *)ptep) = pte_val;
3913446Smrj 	mmu_tlbflush_entry((caddr_t)va);
3925084Sjohnlev #endif
3933446Smrj 
3943446Smrj 	if (!(old_pte & PT_VALID) || ma_to_pa(old_pte) == -1)
3953446Smrj 		return (PFN_INVALID);
3963446Smrj 	return (mmu_btop(ma_to_pa(old_pte)));
3973446Smrj }
3983446Smrj 
3993446Smrj 
4003446Smrj /*
4013446Smrj  * Change a boot loader page table 4K mapping to read only.
4023446Smrj  */
4033446Smrj void
kbm_read_only(uintptr_t va,paddr_t pa)4043446Smrj kbm_read_only(uintptr_t va, paddr_t pa)
4053446Smrj {
4063446Smrj 	x86pte_t pte_val = pa_to_ma(pa) |
4073446Smrj 	    PT_NOCONSIST | PT_REF | PT_MOD | PT_VALID;
4085084Sjohnlev 
4095084Sjohnlev #ifdef __xpv
4105084Sjohnlev 	if (HYPERVISOR_update_va_mapping(va, pte_val, UVMF_INVLPG | UVMF_LOCAL))
4115084Sjohnlev 		bop_panic("HYPERVISOR_update_va_mapping() failed");
4125084Sjohnlev #else
4133446Smrj 	x86pte_t *ptep;
4143446Smrj 	level_t	level = 0;
4153446Smrj 
4163446Smrj 	ptep = find_pte(va, NULL, level, 0);
4173446Smrj 	if (ptep == NULL)
4183446Smrj 		bop_panic("kbm_read_only: find_pte returned NULL");
4193446Smrj 
4203446Smrj 	if (kbm_pae_support)
4213446Smrj 		*ptep = pte_val;
4223446Smrj 	else
4233446Smrj 		*((x86pte32_t *)ptep) = pte_val;
4243446Smrj 	mmu_tlbflush_entry((caddr_t)va);
4255084Sjohnlev #endif
4263446Smrj }
4273446Smrj 
4283446Smrj /*
4293446Smrj  * interfaces for kernel debugger to access physical memory
4303446Smrj  */
4313446Smrj static x86pte_t save_pte;
4323446Smrj 
4333446Smrj void *
kbm_push(paddr_t pa)4343446Smrj kbm_push(paddr_t pa)
4353446Smrj {
4363446Smrj 	static int first_time = 1;
4373446Smrj 
4383446Smrj 	if (first_time) {
4393446Smrj 		first_time = 0;
4403446Smrj 		return (window);
4413446Smrj 	}
4423446Smrj 
4433446Smrj 	if (kbm_pae_support)
4443446Smrj 		save_pte = *((x86pte_t *)pte_to_window);
4453446Smrj 	else
4463446Smrj 		save_pte = *((x86pte32_t *)pte_to_window);
4473446Smrj 	return (kbm_remap_window(pa, 0));
4483446Smrj }
4493446Smrj 
4503446Smrj void
kbm_pop(void)4513446Smrj kbm_pop(void)
4523446Smrj {
4535084Sjohnlev #ifdef __xpv
4545084Sjohnlev 	if (HYPERVISOR_update_va_mapping((uintptr_t)window, save_pte,
4555084Sjohnlev 	    UVMF_INVLPG | UVMF_LOCAL) < 0)
4565084Sjohnlev 		bop_panic("HYPERVISOR_update_va_mapping() failed");
4575084Sjohnlev #else
4583446Smrj 	if (kbm_pae_support)
4593446Smrj 		*((x86pte_t *)pte_to_window) = save_pte;
4603446Smrj 	else
4613446Smrj 		*((x86pte32_t *)pte_to_window) = save_pte;
4623446Smrj 	mmu_tlbflush_entry(window);
4635084Sjohnlev #endif
4643446Smrj }
4653446Smrj 
4663446Smrj x86pte_t
get_pteval(paddr_t table,uint_t index)4673446Smrj get_pteval(paddr_t table, uint_t index)
4683446Smrj {
4693446Smrj 	void *table_ptr = kbm_remap_window(table, 0);
4703446Smrj 
4713446Smrj 	if (kbm_pae_support)
4723446Smrj 		return (((x86pte_t *)table_ptr)[index]);
4733446Smrj 	return (((x86pte32_t *)table_ptr)[index]);
4743446Smrj }
4753446Smrj 
4765084Sjohnlev #ifndef __xpv
4773446Smrj void
set_pteval(paddr_t table,uint_t index,uint_t level,x86pte_t pteval)4783446Smrj set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval)
4793446Smrj {
4803446Smrj 	void *table_ptr = kbm_remap_window(table, 0);
4813446Smrj 	if (kbm_pae_support)
4823446Smrj 		((x86pte_t *)table_ptr)[index] = pteval;
4833446Smrj 	else
4843446Smrj 		((x86pte32_t *)table_ptr)[index] = pteval;
4853446Smrj 	if (level == top_level && level == 2)
4863446Smrj 		reload_cr3();
4873446Smrj }
4885084Sjohnlev #endif
4893446Smrj 
4903446Smrj paddr_t
make_ptable(x86pte_t * pteval,uint_t level)4913446Smrj make_ptable(x86pte_t *pteval, uint_t level)
4923446Smrj {
4933446Smrj 	paddr_t new_table;
4943446Smrj 	void *table_ptr;
4953446Smrj 
4963446Smrj 	new_table = do_bop_phys_alloc(MMU_PAGESIZE, MMU_PAGESIZE);
4973446Smrj 	table_ptr = kbm_remap_window(new_table, 1);
4983446Smrj 	bzero(table_ptr, MMU_PAGESIZE);
4995084Sjohnlev #ifdef __xpv
5005084Sjohnlev 	/* Remove write permission to the new page table.  */
5015084Sjohnlev 	(void) kbm_remap_window(new_table, 0);
5025084Sjohnlev #endif
5033446Smrj 
5043446Smrj 	if (level == top_level && level == 2)
5053446Smrj 		*pteval = pa_to_ma(new_table) | PT_VALID;
5063446Smrj 	else
5073446Smrj 		*pteval = pa_to_ma(new_table) |
5083446Smrj 		    PT_VALID | PT_REF | PT_USER | PT_WRITABLE;
5093446Smrj 
5103446Smrj 	return (new_table);
5113446Smrj }
5123446Smrj 
5133446Smrj x86pte_t *
map_pte(paddr_t table,uint_t index)5143446Smrj map_pte(paddr_t table, uint_t index)
5153446Smrj {
5163446Smrj 	void *table_ptr = kbm_remap_window(table, 0);
5173446Smrj 	return ((x86pte_t *)((caddr_t)table_ptr + index * pte_size));
5183446Smrj }
519