* Invalidates any TLB entries that map a virtual page from the specified * address range. If "end" is zero, then every virtual page is considered to * be within the address range's upper bound. */
| 197 | * be within the address range's upper bound. |
| 198 | */ |
| 199 | void |
| 200 | tlb_invalidate_range(pmap_t pmap, vm_offset_t start, vm_offset_t end) |
| 201 | { |
| 202 | register_t asid, end_hi, hi, hi_pagemask, s, save_asid, start_hi; |
| 203 | int i; |
| 204 | |
| 205 | KASSERT(start < end || (end == 0 && start > 0), |
| 206 | ("tlb_invalidate_range: invalid range")); |
| 207 | |
| 208 | /* |
| 209 | * Truncate the virtual address "start" to an even page frame number, |
| 210 | * and round the virtual address "end" to an even page frame number. |
| 211 | */ |
| 212 | start &= ~((1 << TLBMASK_SHIFT) - 1); |
| 213 | end = roundup2(end, 1 << TLBMASK_SHIFT); |
| 214 | |
| 215 | s = intr_disable(); |
| 216 | save_asid = mips_rd_entryhi() & TLBHI_ASID_MASK; |
| 217 | |
| 218 | asid = pmap_asid(pmap); |
| 219 | start_hi = TLBHI_ENTRY(start, asid); |
| 220 | end_hi = TLBHI_ENTRY(end, asid); |
| 221 | |
| 222 | /* |
| 223 | * Select the fastest method for invalidating the TLB entries. |
| 224 | */ |
| 225 | if (end - start < num_tlbentries << TLBMASK_SHIFT || (end == 0 && |
| 226 | start >= -(num_tlbentries << TLBMASK_SHIFT))) { |
| 227 | /* |
| 228 | * The virtual address range is small compared to the size of |
| 229 | * the TLB. Probe the TLB for each even numbered page frame |
| 230 | * within the virtual address range. |
| 231 | */ |
| 232 | for (hi = start_hi; hi != end_hi; hi += 1 << TLBMASK_SHIFT) { |
| 233 | mips_wr_pagemask(0); |
| 234 | mips_wr_entryhi(hi); |
| 235 | tlb_probe(); |
| 236 | i = mips_rd_index(); |
| 237 | if (i >= 0) |
| 238 | tlb_invalidate_one(i); |
| 239 | } |
| 240 | } else { |
| 241 | /* |
| 242 | * The virtual address range is large compared to the size of |
| 243 | * the TLB. Test every non-wired TLB entry. |
| 244 | */ |
| 245 | for (i = mips_rd_wired(); i < num_tlbentries; i++) { |
| 246 | mips_wr_index(i); |
| 247 | tlb_read(); |
| 248 | hi = mips_rd_entryhi(); |
| 249 | if ((hi & TLBHI_ASID_MASK) == asid && (hi < end_hi || |
| 250 | end == 0)) { |
| 251 | /* |
| 252 | * If "hi" is a large page that spans |
| 253 | * "start_hi", then it must be invalidated. |
| 254 | */ |
| 255 | hi_pagemask = mips_rd_pagemask(); |
| 256 | if (hi >= (start_hi & ~(hi_pagemask << |
no test coverage detected