xref: /titanic_41/usr/src/uts/i86pc/boot/boot_mmu.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32ae115bc7Smrj 
33ae115bc7Smrj #include <sys/param.h>
34ae115bc7Smrj #include <sys/machparam.h>
35ae115bc7Smrj #include <sys/mach_mmu.h>
36*843e1988Sjohnlev #ifdef __xpv
37*843e1988Sjohnlev #include <sys/hypervisor.h>
38*843e1988Sjohnlev #endif
39ae115bc7Smrj 
40ae115bc7Smrj #ifdef _BOOT
41ae115bc7Smrj #include <dboot/dboot_printf.h>
42ae115bc7Smrj #define	bop_panic dboot_panic
43ae115bc7Smrj #else
44ae115bc7Smrj #include <sys/bootconf.h>
45ae115bc7Smrj #endif
46ae115bc7Smrj 
47ae115bc7Smrj uint_t shift_amt_nopae[] = {12, 22};
48ae115bc7Smrj uint_t shift_amt_pae[] = {12, 21, 30, 39};
49ae115bc7Smrj uint_t *shift_amt;
50ae115bc7Smrj uint_t ptes_per_table;
51ae115bc7Smrj uint_t pte_size;
52ae115bc7Smrj uint32_t lpagesize;
53ae115bc7Smrj paddr_t top_page_table;
54ae115bc7Smrj uint_t top_level;
55ae115bc7Smrj 
56ae115bc7Smrj /*
57ae115bc7Smrj  * Return the index corresponding to a virt address at a given page table level.
58ae115bc7Smrj  */
59ae115bc7Smrj static uint_t
vatoindex(uint64_t va,uint_t level)60ae115bc7Smrj vatoindex(uint64_t va, uint_t level)
61ae115bc7Smrj {
62ae115bc7Smrj 	return ((va >> shift_amt[level]) & (ptes_per_table - 1));
63ae115bc7Smrj }
64ae115bc7Smrj 
65ae115bc7Smrj /*
66ae115bc7Smrj  * Return a pointer to the page table entry that maps a virtual address.
67ae115bc7Smrj  * If there is no page table and probe_only is not set, one is created.
68ae115bc7Smrj  */
69ae115bc7Smrj x86pte_t *
find_pte(uint64_t va,paddr_t * pa,uint_t level,uint_t probe_only)70ae115bc7Smrj find_pte(uint64_t va, paddr_t *pa, uint_t level, uint_t probe_only)
71ae115bc7Smrj {
72ae115bc7Smrj 	uint_t l;
73ae115bc7Smrj 	uint_t index;
74ae115bc7Smrj 	paddr_t table;
75ae115bc7Smrj 
76ae115bc7Smrj 	if (pa)
77ae115bc7Smrj 		*pa = 0;
78ae115bc7Smrj 
79ae115bc7Smrj #ifndef _BOOT
80ae115bc7Smrj 	if (IN_HYPERVISOR_VA(va))
81ae115bc7Smrj 		return (NULL);
82ae115bc7Smrj #endif
83ae115bc7Smrj 
84ae115bc7Smrj 	/*
85ae115bc7Smrj 	 * Walk down the page tables creating any needed intermediate tables.
86ae115bc7Smrj 	 */
87ae115bc7Smrj 	table = top_page_table;
88ae115bc7Smrj 	for (l = top_level; l != level; --l) {
89ae115bc7Smrj 		uint64_t pteval;
90ae115bc7Smrj 		paddr_t new_table;
91ae115bc7Smrj 
92ae115bc7Smrj 		index = vatoindex(va, l);
93ae115bc7Smrj 		pteval = get_pteval(table, index);
94ae115bc7Smrj 
95ae115bc7Smrj 		/*
96ae115bc7Smrj 		 * Life is easy if we find the pagetable.  We just use it.
97ae115bc7Smrj 		 */
98ae115bc7Smrj 		if (pteval & PT_VALID) {
99ae115bc7Smrj 			table = ma_to_pa(pteval & MMU_PAGEMASK);
100ae115bc7Smrj 			if (table == -1) {
101ae115bc7Smrj 				if (probe_only)
102ae115bc7Smrj 					return (NULL);
103ae115bc7Smrj 				bop_panic("find_pte(): phys not found!");
104ae115bc7Smrj 			}
105ae115bc7Smrj 			continue;
106ae115bc7Smrj 		}
107ae115bc7Smrj 
108ae115bc7Smrj 		if (probe_only)
109ae115bc7Smrj 			return (NULL);
110ae115bc7Smrj 
111ae115bc7Smrj 		new_table = make_ptable(&pteval, l);
112ae115bc7Smrj 		set_pteval(table, index, l, pteval);
113ae115bc7Smrj 
114ae115bc7Smrj 		table = new_table;
115ae115bc7Smrj 	}
116ae115bc7Smrj 
117ae115bc7Smrj 	/*
118ae115bc7Smrj 	 * Return a pointer into the current pagetable.
119ae115bc7Smrj 	 */
120ae115bc7Smrj 	index = vatoindex(va, l);
121ae115bc7Smrj 	if (pa)
122ae115bc7Smrj 		*pa = table + index * pte_size;
123ae115bc7Smrj 	return (map_pte(table, index));
124ae115bc7Smrj }
125