pmap.c (88786) | pmap.c (88826) |
---|---|
1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * Copyright (c) 1994 John S. Dyson 5 * All rights reserved. 6 * Copyright (c) 1994 David Greenman 7 * All rights reserved. 8 * --- 25 unchanged lines hidden (view full) --- 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 | 1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * Copyright (c) 1994 John S. Dyson 5 * All rights reserved. 6 * Copyright (c) 1994 David Greenman 7 * All rights reserved. 8 * --- 25 unchanged lines hidden (view full) --- 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 |
42 * $FreeBSD: head/sys/sparc64/sparc64/pmap.c 88786 2002-01-01 21:14:58Z jake $ | 42 * $FreeBSD: head/sys/sparc64/sparc64/pmap.c 88826 2002-01-02 18:49:20Z tmm $ |
43 */ 44 45/* 46 * Manages physical address maps. 47 * 48 * In addition to hardware address maps, this module is called upon to 49 * provide software-use-only maps which may or may not be stored in the 50 * same form as hardware maps. These pseudo-maps are used to store --- 135 unchanged lines hidden (view full) --- 186static void pmap_context_destroy(u_int i); 187 188/* 189 * Allocate physical memory for use in pmap_bootstrap. 190 */ 191static vm_offset_t pmap_bootstrap_alloc(vm_size_t size); 192 193/* | 43 */ 44 45/* 46 * Manages physical address maps. 47 * 48 * In addition to hardware address maps, this module is called upon to 49 * provide software-use-only maps which may or may not be stored in the 50 * same form as hardware maps. These pseudo-maps are used to store --- 135 unchanged lines hidden (view full) --- 186static void pmap_context_destroy(u_int i); 187 188/* 189 * Allocate physical memory for use in pmap_bootstrap. 190 */ 191static vm_offset_t pmap_bootstrap_alloc(vm_size_t size); 192 193/* |
194 * If user pmap is processed with pmap_remove and with pmap_remove and the 195 * resident count drops to 0, there are no more pages to remove, so we 196 * need not continue. 197 */ 198#define PMAP_REMOVE_DONE(pm) \ 199 ((pm) != kernel_pmap && (pm)->pm_stats.resident_count == 0) 200 201/* 202 * The threshold (in bytes) above which tsb_foreach() is used in pmap_remove() 203 * and pmap_protect() instead of trying each virtual address. 204 */ 205#define PMAP_TSB_THRESH ((TSB_SIZE / 2) * PAGE_SIZE) 206 207/* Callbacks for tsb_foreach. */ 208tsb_callback_t pmap_remove_tte; 209tsb_callback_t pmap_protect_tte; 210 211/* |
|
194 * Quick sort callout for comparing memory regions. 195 */ 196static int mr_cmp(const void *a, const void *b); 197static int om_cmp(const void *a, const void *b); 198static int 199mr_cmp(const void *a, const void *b) 200{ 201 return ((const struct mem_region *)a)->mr_start - --- 356 unchanged lines hidden (view full) --- 558 tlb_page_demap(TLB_DTLB, TLB_CTX_KERNEL, va); 559 *tp = tte; 560} 561 562/* 563 * Map a wired page into kernel virtual address space. This additionally 564 * takes a flag argument wich is or'ed to the TTE data. This is used by 565 * bus_space_map(). | 212 * Quick sort callout for comparing memory regions. 213 */ 214static int mr_cmp(const void *a, const void *b); 215static int om_cmp(const void *a, const void *b); 216static int 217mr_cmp(const void *a, const void *b) 218{ 219 return ((const struct mem_region *)a)->mr_start - --- 356 unchanged lines hidden (view full) --- 576 tlb_page_demap(TLB_DTLB, TLB_CTX_KERNEL, va); 577 *tp = tte; 578} 579 580/* 581 * Map a wired page into kernel virtual address space. This additionally 582 * takes a flag argument wich is or'ed to the TTE data. This is used by 583 * bus_space_map(). |
584 * NOTE: if the mapping is non-cacheable, it's the caller's responsibility 585 * to flush entries that might still be in the cache, if applicable. |
|
566 */ 567void 568pmap_kenter_flags(vm_offset_t va, vm_offset_t pa, u_long flags) 569{ 570 struct tte tte; 571 struct tte *tp; 572 573 tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va); --- 68 unchanged lines hidden (view full) --- 642{ 643 int i; 644 645 for (i = 0; i < count; i++, va += PAGE_SIZE) 646 pmap_kenter(va, VM_PAGE_TO_PHYS(m[i])); 647} 648 649/* | 586 */ 587void 588pmap_kenter_flags(vm_offset_t va, vm_offset_t pa, u_long flags) 589{ 590 struct tte tte; 591 struct tte *tp; 592 593 tte.tte_tag = TT_CTX(TLB_CTX_KERNEL) | TT_VA(va); --- 68 unchanged lines hidden (view full) --- 662{ 663 int i; 664 665 for (i = 0; i < count; i++, va += PAGE_SIZE) 666 pmap_kenter(va, VM_PAGE_TO_PHYS(m[i])); 667} 668 669/* |
670 * As above, but take an additional flags argument and call 671 * pmap_kenter_flags(). 672 */ 673void 674pmap_qenter_flags(vm_offset_t va, vm_page_t *m, int count, u_long fl) 675{ 676 int i; 677 678 for (i = 0; i < count; i++, va += PAGE_SIZE) 679 pmap_kenter_flags(va, VM_PAGE_TO_PHYS(m[i]), fl); 680} 681 682/* |
|
650 * Remove page mappings from kernel virtual address space. Intended for 651 * temporary mappings entered by pmap_qenter. 652 */ 653void 654pmap_qremove(vm_offset_t va, int count) 655{ 656 int i; 657 --- 433 unchanged lines hidden (view full) --- 1091 if (m->wire_count || m->hold_count || m->busy || 1092 (m->flags & (PG_BUSY | PG_UNMANAGED))) 1093 continue; 1094 pv_remove_all(m); 1095 } 1096 pmap_pagedaemon_waken = 0; 1097} 1098 | 683 * Remove page mappings from kernel virtual address space. Intended for 684 * temporary mappings entered by pmap_qenter. 685 */ 686void 687pmap_qremove(vm_offset_t va, int count) 688{ 689 int i; 690 --- 433 unchanged lines hidden (view full) --- 1124 if (m->wire_count || m->hold_count || m->busy || 1125 (m->flags & (PG_BUSY | PG_UNMANAGED))) 1126 continue; 1127 pv_remove_all(m); 1128 } 1129 pmap_pagedaemon_waken = 0; 1130} 1131 |
1132int 1133pmap_remove_tte(struct pmap *pm, struct tte *tp, vm_offset_t va) 1134{ 1135 vm_page_t m; 1136 1137 m = PHYS_TO_VM_PAGE(TD_GET_PA(tp->tte_data)); 1138 if ((tp->tte_data & TD_PV) != 0) { 1139 if ((tp->tte_data & TD_W) != 0 && 1140 pmap_track_modified(pm, va)) 1141 vm_page_dirty(m); 1142 if ((tp->tte_data & TD_REF) != 0) 1143 vm_page_flag_set(m, PG_REFERENCED); 1144 pv_remove(pm, m, va); 1145 pmap_cache_remove(m, va); 1146 } 1147 atomic_clear_long(&tp->tte_data, TD_V); 1148 tp->tte_tag = 0; 1149 tp->tte_data = 0; 1150 tlb_page_demap(TLB_ITLB | TLB_DTLB, 1151 pm->pm_context, va); 1152 if (PMAP_REMOVE_DONE(pm)) 1153 return (0); 1154 return (1); 1155} 1156 |
|
1099/* 1100 * Remove the given range of addresses from the specified map. 1101 */ 1102void 1103pmap_remove(pmap_t pm, vm_offset_t start, vm_offset_t end) 1104{ 1105 struct tte *tp; | 1157/* 1158 * Remove the given range of addresses from the specified map. 1159 */ 1160void 1161pmap_remove(pmap_t pm, vm_offset_t start, vm_offset_t end) 1162{ 1163 struct tte *tp; |
1106 vm_page_t m; | |
1107 1108 CTR3(KTR_PMAP, "pmap_remove: ctx=%#lx start=%#lx end=%#lx", 1109 pm->pm_context, start, end); | 1164 1165 CTR3(KTR_PMAP, "pmap_remove: ctx=%#lx start=%#lx end=%#lx", 1166 pm->pm_context, start, end); |
1110 for (; start < end; start += PAGE_SIZE) { 1111 if ((tp = tsb_tte_lookup(pm, start)) != NULL) { 1112 m = PHYS_TO_VM_PAGE(TD_GET_PA(tp->tte_data)); 1113 if ((tp->tte_data & TD_PV) != 0) { 1114 if ((tp->tte_data & TD_W) != 0 && 1115 pmap_track_modified(pm, start)) 1116 vm_page_dirty(m); 1117 if ((tp->tte_data & TD_REF) != 0) 1118 vm_page_flag_set(m, PG_REFERENCED); 1119 pv_remove(pm, m, start); 1120 pmap_cache_remove(m, start); | 1167 if (PMAP_REMOVE_DONE(pm)) 1168 return; 1169 if (end - start > PMAP_TSB_THRESH) 1170 tsb_foreach(pm, start, end, pmap_remove_tte); 1171 else { 1172 for (; start < end; start += PAGE_SIZE) { 1173 if ((tp = tsb_tte_lookup(pm, start)) != NULL) { 1174 if (!pmap_remove_tte(pm, tp, start)) 1175 break; |
1121 } | 1176 } |
1122 atomic_clear_long(&tp->tte_data, TD_V); 1123 tp->tte_tag = 0; 1124 tp->tte_data = 0; 1125 tlb_page_demap(TLB_ITLB | TLB_DTLB, 1126 pm->pm_context, start); | |
1127 } 1128 } 1129} 1130 | 1177 } 1178 } 1179} 1180 |
1181int 1182pmap_protect_tte(struct pmap *pm, struct tte *tp, vm_offset_t va) 1183{ 1184 vm_page_t m; 1185 u_long data; 1186 1187 data = tp->tte_data; 1188 if ((data & TD_PV) != 0) { 1189 m = PHYS_TO_VM_PAGE(TD_GET_PA(data)); 1190 if ((data & TD_REF) != 0) { 1191 vm_page_flag_set(m, PG_REFERENCED); 1192 data &= ~TD_REF; 1193 } 1194 if ((data & TD_W) != 0 && 1195 pmap_track_modified(pm, va)) { 1196 vm_page_dirty(m); 1197 } 1198 } 1199 1200 data &= ~(TD_W | TD_SW); 1201 1202 CTR2(KTR_PMAP, "pmap_protect: new=%#lx old=%#lx", 1203 data, tp->tte_data); 1204 1205 if (data != tp->tte_data) { 1206 CTR0(KTR_PMAP, "pmap_protect: demap"); 1207 tlb_page_demap(TLB_DTLB | TLB_ITLB, 1208 pm->pm_context, va); 1209 tp->tte_data = data; 1210 } 1211 return (0); 1212} 1213 |
|
1131/* 1132 * Set the physical protection on the specified range of this map as requested. 1133 */ 1134void 1135pmap_protect(pmap_t pm, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) 1136{ 1137 struct tte *tp; | 1214/* 1215 * Set the physical protection on the specified range of this map as requested. 1216 */ 1217void 1218pmap_protect(pmap_t pm, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) 1219{ 1220 struct tte *tp; |
1138 vm_page_t m; 1139 u_long data; | |
1140 1141 CTR4(KTR_PMAP, "pmap_protect: ctx=%#lx sva=%#lx eva=%#lx prot=%#lx", 1142 pm->pm_context, sva, eva, prot); 1143 1144 KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap, 1145 ("pmap_protect: non current pmap")); 1146 1147 if ((prot & VM_PROT_READ) == VM_PROT_NONE) { 1148 pmap_remove(pm, sva, eva); 1149 return; 1150 } 1151 1152 if (prot & VM_PROT_WRITE) 1153 return; 1154 | 1221 1222 CTR4(KTR_PMAP, "pmap_protect: ctx=%#lx sva=%#lx eva=%#lx prot=%#lx", 1223 pm->pm_context, sva, eva, prot); 1224 1225 KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap, 1226 ("pmap_protect: non current pmap")); 1227 1228 if ((prot & VM_PROT_READ) == VM_PROT_NONE) { 1229 pmap_remove(pm, sva, eva); 1230 return; 1231 } 1232 1233 if (prot & VM_PROT_WRITE) 1234 return; 1235 |
1155 for (; sva < eva; sva += PAGE_SIZE) { 1156 if ((tp = tsb_tte_lookup(pm, sva)) != NULL) { 1157 data = tp->tte_data; 1158 if ((data & TD_PV) != 0) { 1159 m = PHYS_TO_VM_PAGE(TD_GET_PA(data)); 1160 if ((data & TD_REF) != 0) { 1161 vm_page_flag_set(m, PG_REFERENCED); 1162 data &= ~TD_REF; 1163 } 1164 if ((data & TD_W) != 0 && 1165 pmap_track_modified(pm, sva)) { 1166 vm_page_dirty(m); 1167 } 1168 } 1169 1170 data &= ~(TD_W | TD_SW); 1171 1172 CTR2(KTR_PMAP, "pmap_protect: new=%#lx old=%#lx", 1173 data, tp->tte_data); 1174 1175 if (data != tp->tte_data) { 1176 CTR0(KTR_PMAP, "pmap_protect: demap"); 1177 tlb_page_demap(TLB_DTLB | TLB_ITLB, 1178 pm->pm_context, sva); 1179 tp->tte_data = data; 1180 } | 1236 if (eva - sva > PMAP_TSB_THRESH) 1237 tsb_foreach(pm, sva, eva, pmap_protect_tte); 1238 else { 1239 for (; sva < eva; sva += PAGE_SIZE) { 1240 if ((tp = tsb_tte_lookup(pm, sva)) != NULL) 1241 pmap_protect_tte(pm, tp, sva); |
1181 } 1182 } 1183} 1184 1185/* 1186 * Map the given physical page at the specified virtual address in the 1187 * target pmap with the protection requested. If specified the page 1188 * will be wired down. --- 123 unchanged lines hidden (view full) --- 1312 tte.tte_data |= TD_W; 1313 } 1314 if (pm->pm_context == TLB_CTX_KERNEL) 1315 tte.tte_data |= TD_P; 1316 if (prot & VM_PROT_WRITE) 1317 tte.tte_data |= TD_SW; 1318 if (prot & VM_PROT_EXECUTE) { 1319 tte.tte_data |= TD_EXEC; | 1242 } 1243 } 1244} 1245 1246/* 1247 * Map the given physical page at the specified virtual address in the 1248 * target pmap with the protection requested. If specified the page 1249 * will be wired down. --- 123 unchanged lines hidden (view full) --- 1373 tte.tte_data |= TD_W; 1374 } 1375 if (pm->pm_context == TLB_CTX_KERNEL) 1376 tte.tte_data |= TD_P; 1377 if (prot & VM_PROT_WRITE) 1378 tte.tte_data |= TD_SW; 1379 if (prot & VM_PROT_EXECUTE) { 1380 tte.tte_data |= TD_EXEC; |
1320#if 0 | |
1321 icache_inval_phys(pa, pa + PAGE_SIZE - 1); | 1381 icache_inval_phys(pa, pa + PAGE_SIZE - 1); |
1322#endif | |
1323 } 1324 1325 if (tp != NULL) 1326 *tp = tte; 1327 else 1328 tsb_tte_enter(pm, m, va, tte); 1329} 1330 --- 290 unchanged lines hidden --- | 1382 } 1383 1384 if (tp != NULL) 1385 *tp = tte; 1386 else 1387 tsb_tte_enter(pm, m, va, tte); 1388} 1389 --- 290 unchanged lines hidden --- |