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 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 * 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