1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _VM_HAT_PTE_H 27 #define _VM_HAT_PTE_H 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 #include <sys/types.h> 36 #include <sys/mach_mmu.h> 37 38 /* 39 * macros to get/set/clear the PTE fields 40 */ 41 #define PTE_SET(p, f) ((p) |= (f)) 42 #define PTE_CLR(p, f) ((p) &= ~(x86pte_t)(f)) 43 #define PTE_GET(p, f) ((p) & (f)) 44 45 /* 46 * Handy macro to check if a pagetable entry or pointer is valid 47 */ 48 #define PTE_ISVALID(p) PTE_GET(p, PT_VALID) 49 50 /* 51 * Does a PTE map a large page. 52 */ 53 #define PTE_IS_LGPG(p, l) ((l) > 0 && PTE_GET((p), PT_PAGESIZE)) 54 55 /* 56 * does this PTE represent a page (not a pointer to another page table)? 57 */ 58 #define PTE_ISPAGE(p, l) \ 59 (PTE_ISVALID(p) && ((l) == 0 || PTE_GET(p, PT_PAGESIZE))) 60 61 /* 62 * Handy macro to check if 2 PTE's are the same - ignores REF/MOD bits 63 */ 64 #define PTE_EQUIV(a, b) (((a) | PT_REF | PT_MOD) == ((b) | PT_REF | PT_MOD)) 65 66 /* 67 * Shorthand for converting a PTE to it's pfn. 68 */ 69 #define PTE2MFN(p, l) \ 70 mmu_btop(PTE_GET((p), PTE_IS_LGPG((p), (l)) ? PT_PADDR_LGPG : PT_PADDR)) 71 #define PTE2PFN(p, l) PTE2MFN(p, l) 72 73 #define PT_NX (0x8000000000000000ull) 74 #define PT_PADDR (0x000ffffffffff000ull) 75 #define PT_PADDR_LGPG (0x000fffffffffe000ull) /* phys addr for large pages */ 76 77 /* 78 * Macros to create a PTP or PTE from the pfn and level 79 */ 80 #define MAKEPTP(pfn, l) \ 81 (pfn_to_pa(pfn) | mmu.ptp_bits[(l) + 1]) 82 #define MAKEPTE(pfn, l) \ 83 (pfn_to_pa(pfn) | mmu.pte_bits[l]) 84 85 /* 86 * The idea of "level" refers to the level where the page table is used in the 87 * the hardware address translation steps. The level values correspond to the 88 * following names of tables used in AMD/Intel architecture documents: 89 * 90 * AMD/INTEL name Level # 91 * ---------------------- ------- 92 * Page Map Level 4 3 93 * Page Directory Pointer 2 94 * Page Directory 1 95 * Page Table 0 96 * 97 * The numbering scheme is such that the values of 0 and 1 can correspond to 98 * the pagesize codes used for MPSS support. For now the Maximum level at 99 * which you can have a large page is a constant, that may change in 100 * future processors. 101 * 102 * The type of "level_t" is signed so that it can be used like: 103 * level_t l; 104 * ... 105 * while (--l >= 0) 106 * ... 107 */ 108 #define MAX_NUM_LEVEL 4 109 #define MAX_PAGE_LEVEL 1 /* for now.. sigh */ 110 typedef int8_t level_t; 111 #define LEVEL_SHIFT(l) (mmu.level_shift[l]) 112 #define LEVEL_SIZE(l) (mmu.level_size[l]) 113 #define LEVEL_OFFSET(l) (mmu.level_offset[l]) 114 #define LEVEL_MASK(l) (mmu.level_mask[l]) 115 116 /* 117 * Macros to: 118 * Check for a PFN above 4Gig and 64Gig for 32 bit PAE support 119 */ 120 #define PFN_4G (4ull * (1024 * 1024 * 1024 / MMU_PAGESIZE)) 121 #define PFN_64G (64ull * (1024 * 1024 * 1024 / MMU_PAGESIZE)) 122 #define PFN_ABOVE4G(pfn) ((pfn) >= PFN_4G) 123 #define PFN_ABOVE64G(pfn) ((pfn) >= PFN_64G) 124 125 /* 126 * The CR3 register holds the physical address of the top level page table. 127 */ 128 #define MAKECR3(pfn) mmu_ptob(pfn) 129 130 /* 131 * HAT/MMU parameters that depend on kernel mode and/or processor type 132 */ 133 struct htable; 134 struct hat_mmu_info { 135 x86pte_t pt_nx; /* either 0 or PT_NX */ 136 x86pte_t pt_global; /* either 0 or PT_GLOBAL */ 137 138 pfn_t highest_pfn; 139 140 uint_t num_level; /* number of page table levels in use */ 141 uint_t max_level; /* just num_level - 1 */ 142 uint_t max_page_level; /* maximum level at which we can map a page */ 143 uint_t ptes_per_table; /* # of entries in lower level page tables */ 144 uint_t top_level_count; /* # of entries in top most level page table */ 145 uint_t inval_nonleaf; /* invlpg after invalidates in inner tables */ 146 147 uint_t hash_cnt; /* cnt of entries in htable_hash_cache */ 148 uint_t vlp_hash_cnt; /* cnt of entries in vlp htable_hash_cache */ 149 150 uint_t pae_hat; /* either 0 or 1 */ 151 152 uintptr_t hole_start; /* start of VA hole (or -1 if none) */ 153 uintptr_t hole_end; /* end of VA hole (or 0 if none) */ 154 155 struct htable **kmap_htables; /* htables for segmap + 32 bit heap */ 156 x86pte_t *kmap_ptes; /* mapping of pagetables that map kmap */ 157 uintptr_t kmap_addr; /* start addr of kmap */ 158 uintptr_t kmap_eaddr; /* end addr of kmap */ 159 160 uint_t pte_size; /* either 4 or 8 */ 161 uint_t pte_size_shift; /* either 2 or 3 */ 162 x86pte_t ptp_bits[MAX_NUM_LEVEL]; /* bits set for interior PTP */ 163 x86pte_t pte_bits[MAX_NUM_LEVEL]; /* bits set for leaf PTE */ 164 165 /* 166 * A range of VA used to window pages in the i86pc/vm code. 167 * See PWIN_XXX macros. 168 */ 169 caddr_t pwin_base; 170 caddr_t pwin_pte_va; 171 paddr_t pwin_pte_pa; 172 173 /* 174 * The following tables are equivalent to PAGEXXXXX at different levels 175 * in the page table hierarchy. 176 */ 177 uint_t level_shift[MAX_NUM_LEVEL]; /* PAGESHIFT for given level */ 178 uintptr_t level_size[MAX_NUM_LEVEL]; /* PAGESIZE for given level */ 179 uintptr_t level_offset[MAX_NUM_LEVEL]; /* PAGEOFFSET for given level */ 180 uintptr_t level_mask[MAX_NUM_LEVEL]; /* PAGEMASK for given level */ 181 }; 182 183 184 #if defined(_KERNEL) 185 186 /* 187 * Macros to access the HAT's private page windows. They're used for 188 * accessing pagetables, ppcopy() and page_zero(). 189 * The 1st two macros are used to get an index for the particular use. 190 * The next three give you: 191 * - the virtual address of the window 192 * - the virtual address of the pte that maps the window 193 * - the physical address of the pte that map the window 194 */ 195 #define PWIN_TABLE(cpuid) ((cpuid) * 2) 196 #define PWIN_SRC(cpuid) ((cpuid) * 2 + 1) /* for x86pte_copy() */ 197 #define PWIN_VA(x) (mmu.pwin_base + ((x) << MMU_PAGESHIFT)) 198 #define PWIN_PTE_VA(x) (mmu.pwin_pte_va + ((x) << mmu.pte_size_shift)) 199 #define PWIN_PTE_PA(x) (mmu.pwin_pte_pa + ((x) << mmu.pte_size_shift)) 200 201 /* 202 * The concept of a VA hole exists in AMD64. This might need to be made 203 * model specific eventually. 204 * 205 * In the 64 bit kernel PTE loads are atomic, but need cas64 on 32 bit kernel. 206 */ 207 #if defined(__amd64) 208 209 #ifdef lint 210 #define IN_VA_HOLE(va) (__lintzero) 211 #else 212 #define IN_VA_HOLE(va) (mmu.hole_start <= (va) && (va) < mmu.hole_end) 213 #endif 214 215 #define FMT_PTE "0x%lx" 216 #define GET_PTE(ptr) (*(x86pte_t *)(ptr)) 217 #define SET_PTE(ptr, pte) (*(x86pte_t *)(ptr) = pte) 218 #define CAS_PTE(ptr, x, y) cas64(ptr, x, y) 219 220 #elif defined(__i386) 221 222 #define IN_VA_HOLE(va) (__lintzero) 223 224 #define FMT_PTE "0x%llx" 225 226 /* on 32 bit kernels, 64 bit loads aren't atomic, use get_pte64() */ 227 extern x86pte_t get_pte64(x86pte_t *ptr); 228 #define GET_PTE(ptr) (mmu.pae_hat ? get_pte64(ptr) : *(x86pte32_t *)(ptr)) 229 #define SET_PTE(ptr, pte) \ 230 ((mmu.pae_hat ? ((x86pte32_t *)(ptr))[1] = (pte >> 32) : 0), \ 231 *(x86pte32_t *)(ptr) = pte) 232 #define CAS_PTE(ptr, x, y) \ 233 (mmu.pae_hat ? cas64(ptr, x, y) : \ 234 cas32((uint32_t *)(ptr), (uint32_t)(x), (uint32_t)(y))) 235 236 #endif /* __i386 */ 237 238 /* 239 * Return a pointer to the pte entry at the given index within a page table. 240 */ 241 #define PT_INDEX_PTR(p, x) \ 242 ((x86pte_t *)((uintptr_t)(p) + ((x) << mmu.pte_size_shift))) 243 244 /* 245 * Return the physical address of the pte entry at the given index within a 246 * page table. 247 */ 248 #define PT_INDEX_PHYSADDR(p, x) \ 249 ((paddr_t)(p) + ((x) << mmu.pte_size_shift)) 250 251 /* 252 * From pfn to bytes, careful not to lose bits on PAE. 253 */ 254 #define pfn_to_pa(pfn) (mmu_ptob((paddr_t)(pfn))) 255 256 extern struct hat_mmu_info mmu; 257 258 #endif /* _KERNEL */ 259 260 261 #ifdef __cplusplus 262 } 263 #endif 264 265 #endif /* _VM_HAT_PTE_H */ 266