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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _VM_HAT_I86_H 28 #define _VM_HAT_I86_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 /* 37 * VM - Hardware Address Translation management. 38 * 39 * This file describes the contents of the x86_64 HAT data structures. 40 */ 41 #include <sys/types.h> 42 #include <sys/t_lock.h> 43 #include <sys/cpuvar.h> 44 #include <sys/x_call.h> 45 #include <vm/seg.h> 46 #include <vm/page.h> 47 #include <sys/vmparam.h> 48 #include <sys/vm_machparam.h> 49 #include <sys/promif.h> 50 #include <vm/hat_pte.h> 51 #include <vm/htable.h> 52 #include <vm/hment.h> 53 54 /* 55 * The essential data types involved: 56 * 57 * htable_t - There is one of these for each page table and it is used 58 * by the HAT to manage the page table. 59 * 60 * hment_t - Links together multiple PTEs to a single page. 61 */ 62 63 /* 64 * VLP processes have a 32 bit address range, so their top level is 2 and 65 * with only 4 PTEs in that table. 66 */ 67 #define VLP_LEVEL (2) 68 #define VLP_NUM_PTES (4) 69 #define VLP_SIZE (VLP_NUM_PTES * sizeof (x86pte_t)) 70 #define TOP_LEVEL(h) (((h)->hat_flags & HAT_VLP) ? VLP_LEVEL : mmu.max_level) 71 #define VLP_COPY(fromptep, toptep) { \ 72 toptep[0] = fromptep[0]; \ 73 toptep[1] = fromptep[1]; \ 74 toptep[2] = fromptep[2]; \ 75 toptep[3] = fromptep[3]; \ 76 } 77 78 /* 79 * The hat struct exists for each address space. 80 */ 81 struct hat { 82 kmutex_t hat_mutex; 83 kmutex_t hat_switch_mutex; 84 struct as *hat_as; 85 uint_t hat_stats; 86 pgcnt_t hat_pages_mapped[MAX_PAGE_LEVEL + 1]; 87 cpuset_t hat_cpus; 88 uint16_t hat_flags; 89 htable_t *hat_htable; /* top level htable */ 90 struct hat *hat_next; 91 struct hat *hat_prev; 92 uint_t hat_num_hash; /* number of htable hash buckets */ 93 htable_t **hat_ht_hash; /* htable hash buckets */ 94 htable_t *hat_ht_cached; /* cached free htables */ 95 x86pte_t hat_vlp_ptes[VLP_NUM_PTES]; 96 }; 97 typedef struct hat hat_t; 98 99 #define PGCNT_INC(hat, level) \ 100 atomic_add_long(&(hat)->hat_pages_mapped[level], 1); 101 #define PGCNT_DEC(hat, level) \ 102 atomic_add_long(&(hat)->hat_pages_mapped[level], -1); 103 104 /* 105 * Flags for the hat_flags field 106 * 107 * HAT_FREEING - set when HAT is being destroyed - mostly used to detect that 108 * demap()s can be avoided. 109 * 110 * HAT_VLP - indicates a 32 bit process has a virtual address range less than 111 * the hardware's physical address range. (VLP->Virtual Less-than Physical) 112 * 113 * HAT_VICTIM - This is set while a hat is being examined for page table 114 * stealing and prevents it from being freed. 115 * 116 * HAT_SHARED - The hat has exported it's page tables via hat_share() 117 */ 118 #define HAT_FREEING (0x0001) 119 #define HAT_VLP (0x0002) 120 #define HAT_VICTIM (0x0004) 121 #define HAT_SHARED (0x0008) 122 123 /* 124 * Additional platform attribute for hat_devload() to force no caching. 125 */ 126 #define HAT_PLAT_NOCACHE (0x100000) 127 128 /* 129 * Simple statistics for the HAT. These are just counters that are 130 * atomically incremented. They can be reset directly from the kernel 131 * debugger. 132 */ 133 struct hatstats { 134 uint64_t hs_reap_attempts; 135 uint64_t hs_reaped; 136 uint64_t hs_steals; 137 uint64_t hs_ptable_allocs; 138 uint64_t hs_ptable_frees; 139 uint64_t hs_htable_rgets; /* allocs from reserve */ 140 uint64_t hs_htable_rputs; /* putbacks to reserve */ 141 uint64_t hs_htable_shared; /* number of htables shared */ 142 uint64_t hs_htable_unshared; /* number of htables unshared */ 143 uint64_t hs_hm_alloc; 144 uint64_t hs_hm_free; 145 uint64_t hs_hm_put_reserve; 146 uint64_t hs_hm_get_reserve; 147 uint64_t hs_hm_steals; 148 uint64_t hs_hm_steal_exam; 149 }; 150 extern struct hatstats hatstat; 151 #define HATSTAT_INC(x) (atomic_add_64(&hatstat.x, 1)) 152 153 #if defined(_KERNEL) 154 155 /* 156 * Useful macro to align hat_XXX() address arguments to a page boundary 157 */ 158 #define ALIGN2PAGE(a) ((uintptr_t)(a) & MMU_PAGEMASK) 159 #define IS_PAGEALIGNED(a) (((uintptr_t)(a) & MMU_PAGEOFFSET) == 0) 160 161 extern uint_t khat_running; /* set at end of hat_kern_setup() */ 162 extern cpuset_t khat_cpuset; /* cpuset for kernal address demap Xcalls */ 163 extern kmutex_t hat_list_lock; 164 extern kcondvar_t hat_list_cv; 165 166 167 168 /* 169 * Interfaces to setup a cpu private mapping (ie. preemption disabled). 170 * The attr and flags arguments are the same as for hat_devload(). 171 * setup() must be called once, then any number of calls to remap(), 172 * followed by a final call to release() 173 * 174 * Used by ppcopy(), page_zero(), the memscrubber, and the kernel debugger. 175 */ 176 extern void *hat_mempte_kern_setup(caddr_t addr, void *); 177 extern void *hat_mempte_setup(caddr_t addr); 178 extern void hat_mempte_remap(pfn_t, caddr_t, void *, uint_t attr, uint_t flags); 179 extern void hat_mempte_release(caddr_t addr, void *); 180 181 /* 182 * interfaces to manage which thread has access to htable and hment reserves 183 */ 184 extern uint_t can_steal_post_boot; 185 extern uint_t use_boot_reserve; 186 extern kthread_t *hat_reserves_thread; 187 188 /* 189 * initialization stuff needed by by startup, mp_startup... 190 */ 191 extern void hat_cpu_online(struct cpu *); 192 extern void setup_vaddr_for_ppcopy(struct cpu *); 193 extern void clear_boot_mappings(uintptr_t, uintptr_t); 194 extern int hat_boot_probe(uintptr_t *va, size_t *len, pfn_t *pfn, uint_t *prot); 195 196 /* 197 * magic value to indicate that all TLB entries should be demapped. 198 */ 199 #define DEMAP_ALL_ADDR (~(uintptr_t)0) 200 201 /* 202 * not in any include file??? 203 */ 204 extern void halt(char *fmt); 205 206 /* 207 * x86 specific routines for use online in setup or i86pc/vm files 208 */ 209 extern void hat_kern_alloc(void); 210 extern void hati_kern_setup_load(uintptr_t, size_t, pfn_t, pgcnt_t, uint_t); 211 extern void hat_demap(struct hat *hat, uintptr_t va); 212 extern void hat_pte_unmap(htable_t *ht, uint_t entry, uint_t flags, 213 x86pte_t old_pte, void *pte_ptr); 214 extern void hat_init_finish(void); 215 extern void hat_kmap_init(uintptr_t base, size_t len); 216 extern caddr_t hat_kpm_pfn2va(pfn_t pfn); 217 extern pfn_t hat_kpm_va2pfn(caddr_t); 218 extern page_t *hat_kpm_vaddr2page(caddr_t); 219 extern uintptr_t hat_kernelbase(uintptr_t); 220 221 extern pfn_t hat_boot_remap(uintptr_t, pfn_t); 222 extern void hat_boot_demap(uintptr_t); 223 extern hment_t *hati_page_unmap(page_t *pp, htable_t *ht, uint_t entry); 224 /* 225 * Hat switch function invoked to load a new context into %cr3 226 */ 227 extern void hat_switch(struct hat *hat); 228 229 230 #endif /* _KERNEL */ 231 232 #ifdef __cplusplus 233 } 234 #endif 235 236 #endif /* _VM_HAT_I86_H */ 237