xref: /illumos-gate/usr/src/uts/i86pc/boot/boot_mmu.c (revision 2d6eb4a5)
1ae115bc7Smrj /*
2ae115bc7Smrj  * CDDL HEADER START
3ae115bc7Smrj  *
4ae115bc7Smrj  * The contents of this file are subject to the terms of the
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * You may not use this file except in compliance with the License.
7ae115bc7Smrj  *
8ae115bc7Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj  * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj  * See the License for the specific language governing permissions
11ae115bc7Smrj  * and limitations under the License.
12ae115bc7Smrj  *
13ae115bc7Smrj  * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj  * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj  *
19ae115bc7Smrj  * CDDL HEADER END
20ae115bc7Smrj  */
21ae115bc7Smrj 
22ae115bc7Smrj /*
23ae115bc7Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24ae115bc7Smrj  * Use is subject to license terms.
25ae115bc7Smrj  */
26ae115bc7Smrj 
27ae115bc7Smrj /*
28ae115bc7Smrj  * WARNING: This file is used by both dboot and the kernel.
29ae115bc7Smrj  */
30ae115bc7Smrj 
31ae115bc7Smrj #include <sys/param.h>
32ae115bc7Smrj #include <sys/machparam.h>
33ae115bc7Smrj #include <sys/mach_mmu.h>
34*843e1988Sjohnlev #ifdef __xpv
35*843e1988Sjohnlev #include <sys/hypervisor.h>
36*843e1988Sjohnlev #endif
37ae115bc7Smrj 
38ae115bc7Smrj #ifdef _BOOT
39ae115bc7Smrj #include <dboot/dboot_printf.h>
40ae115bc7Smrj #define	bop_panic dboot_panic
41ae115bc7Smrj #else
42ae115bc7Smrj #include <sys/bootconf.h>
43ae115bc7Smrj #endif
44ae115bc7Smrj 
45ae115bc7Smrj uint_t shift_amt_nopae[] = {12, 22};
46ae115bc7Smrj uint_t shift_amt_pae[] = {12, 21, 30, 39};
47ae115bc7Smrj uint_t *shift_amt;
48ae115bc7Smrj uint_t ptes_per_table;
49ae115bc7Smrj uint_t pte_size;
50ae115bc7Smrj uint32_t lpagesize;
51ae115bc7Smrj paddr_t top_page_table;
52ae115bc7Smrj uint_t top_level;
53ae115bc7Smrj 
54ae115bc7Smrj /*
55ae115bc7Smrj  * Return the index corresponding to a virt address at a given page table level.
56ae115bc7Smrj  */
57ae115bc7Smrj static uint_t
vatoindex(uint64_t va,uint_t level)58ae115bc7Smrj vatoindex(uint64_t va, uint_t level)
59ae115bc7Smrj {
60ae115bc7Smrj 	return ((va >> shift_amt[level]) & (ptes_per_table - 1));
61ae115bc7Smrj }
62ae115bc7Smrj 
63ae115bc7Smrj /*
64ae115bc7Smrj  * Return a pointer to the page table entry that maps a virtual address.
65ae115bc7Smrj  * If there is no page table and probe_only is not set, one is created.
66ae115bc7Smrj  */
67ae115bc7Smrj x86pte_t *
find_pte(uint64_t va,paddr_t * pa,uint_t level,uint_t probe_only)68ae115bc7Smrj find_pte(uint64_t va, paddr_t *pa, uint_t level, uint_t probe_only)
69ae115bc7Smrj {
70ae115bc7Smrj 	uint_t l;
71ae115bc7Smrj 	uint_t index;
72ae115bc7Smrj 	paddr_t table;
73ae115bc7Smrj 
74ae115bc7Smrj 	if (pa)
75ae115bc7Smrj 		*pa = 0;
76ae115bc7Smrj 
77ae115bc7Smrj #ifndef _BOOT
78ae115bc7Smrj 	if (IN_HYPERVISOR_VA(va))
79ae115bc7Smrj 		return (NULL);
80ae115bc7Smrj #endif
81ae115bc7Smrj 
82ae115bc7Smrj 	/*
83ae115bc7Smrj 	 * Walk down the page tables creating any needed intermediate tables.
84ae115bc7Smrj 	 */
85ae115bc7Smrj 	table = top_page_table;
86ae115bc7Smrj 	for (l = top_level; l != level; --l) {
87ae115bc7Smrj 		uint64_t pteval;
88ae115bc7Smrj 		paddr_t new_table;
89ae115bc7Smrj 
90ae115bc7Smrj 		index = vatoindex(va, l);
91ae115bc7Smrj 		pteval = get_pteval(table, index);
92ae115bc7Smrj 
93ae115bc7Smrj 		/*
94ae115bc7Smrj 		 * Life is easy if we find the pagetable.  We just use it.
95ae115bc7Smrj 		 */
96ae115bc7Smrj 		if (pteval & PT_VALID) {
97ae115bc7Smrj 			table = ma_to_pa(pteval & MMU_PAGEMASK);
98ae115bc7Smrj 			if (table == -1) {
99ae115bc7Smrj 				if (probe_only)
100ae115bc7Smrj 					return (NULL);
101ae115bc7Smrj 				bop_panic("find_pte(): phys not found!");
102ae115bc7Smrj 			}
103ae115bc7Smrj 			continue;
104ae115bc7Smrj 		}
105ae115bc7Smrj 
106ae115bc7Smrj 		if (probe_only)
107ae115bc7Smrj 			return (NULL);
108ae115bc7Smrj 
109ae115bc7Smrj 		new_table = make_ptable(&pteval, l);
110ae115bc7Smrj 		set_pteval(table, index, l, pteval);
111ae115bc7Smrj 
112ae115bc7Smrj 		table = new_table;
113ae115bc7Smrj 	}
114ae115bc7Smrj 
115ae115bc7Smrj 	/*
116ae115bc7Smrj 	 * Return a pointer into the current pagetable.
117ae115bc7Smrj 	 */
118ae115bc7Smrj 	index = vatoindex(va, l);
119ae115bc7Smrj 	if (pa)
120ae115bc7Smrj 		*pa = table + index * pte_size;
121ae115bc7Smrj 	return (map_pte(table, index));
122ae115bc7Smrj }
123