Changeset e05b956 in mainline
- Timestamp:
- 2013-02-16T23:26:55Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 192a23f0
- Parents:
- d5b9e8d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/mm/tlb.c
rd5b9e8d re05b956 48 48 #include <symtab.h> 49 49 50 #define VPN_SHIFT 12 51 #define ADDR2VPN(a) ((a) >> VPN_SHIFT) 52 #define ADDR2VPN2(a) (ADDR2VPN((a)) >> 1) 53 #define VPN2ADDR(vpn) ((vpn) << VPN_SHIFT) 54 #define VPN22ADDR(vpn2) (VPN2ADDR(vpn2) << 1) 55 56 #define BANK_SELECT_BIT(a) (((a) >> PAGE_WIDTH) & 1) 57 58 50 59 static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *); 51 60 … … 77 86 } 78 87 88 /** Verify the TLB still contains / does not contain a given entry after the 89 * current thread possibly blocked. 90 * 91 * @param hi Remembered contents of the EntryHi register. 92 * @param should_exist Flag saying whether the caller expect the entry to exist 93 * or not to exist. 94 * @returns True if the TLB contains or does not contain the mapping 95 * according to the caller's expectation. 96 * @returns False otherwise. 97 */ 98 static bool tlb_recheck_entry(entry_hi_t hi, bool should_exist) 99 { 100 tlb_index_t index; 101 102 cp0_entry_hi_write(hi.value); 103 tlbp(); 104 index.value = cp0_index_read(); 105 106 if (!(should_exist ^ index.p)) { 107 /* The old entry disappeared or the new entry already exists. */ 108 return false; 109 } 110 111 return true; 112 } 113 79 114 /** Process TLB Refill Exception. 80 115 * … … 83 118 void tlb_refill(istate_t *istate) 84 119 { 120 entry_hi_t hi; 85 121 entry_lo_t lo; 86 entry_hi_t hi;87 asid_t asid;88 122 uintptr_t badvaddr; 89 123 pte_t *pte; 90 124 91 125 badvaddr = cp0_badvaddr_read(); 92 asid = AS->asid; 93 126 hi.value = cp0_entry_hi_read(); 127 128 /* We may block in find_mapping_and_check(). */ 94 129 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 95 130 if (pte) { 131 if (!tlb_recheck_entry(hi, false)) 132 return; 133 96 134 /* 97 135 * Record access to PTE. … … 99 137 pte->a = 1; 100 138 101 tlb_prepare_entry_hi(&hi, asid, badvaddr);102 139 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, 103 140 pte->cacheable, pte->pfn); … … 106 143 * New entry is to be inserted into TLB 107 144 */ 108 cp0_entry_hi_write(hi.value); 109 if ((badvaddr / PAGE_SIZE) % 2 == 0) { 145 if (BANK_SELECT_BIT(badvaddr) == 0) { 110 146 cp0_entry_lo0_write(lo.value); 111 147 cp0_entry_lo1_write(0); … … 125 161 void tlb_invalid(istate_t *istate) 126 162 { 163 entry_hi_t hi; 164 entry_lo_t lo; 127 165 tlb_index_t index; 128 166 uintptr_t badvaddr; 129 entry_lo_t lo;130 entry_hi_t hi;131 167 pte_t *pte; 132 168 133 badvaddr = cp0_badvaddr_read();134 135 169 /* 136 170 * Locate the faulting entry in TLB. 137 171 */ 138 hi.value = cp0_entry_hi_read();139 tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);140 cp0_entry_hi_write(hi.value);141 172 tlbp(); 142 173 index.value = cp0_index_read(); … … 156 187 ASSERT(!index.p); 157 188 189 badvaddr = cp0_badvaddr_read(); 190 hi.value = cp0_entry_hi_read(); 191 192 /* We may block in find_mapping_and_check(). */ 158 193 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 159 194 if (pte) { 195 if (!tlb_recheck_entry(hi, true)) 196 return; 197 160 198 /* 161 199 * Read the faulting TLB entry. … … 174 212 * The entry is to be updated in TLB. 175 213 */ 176 if ( (badvaddr / PAGE_SIZE) % 2== 0)214 if (BANK_SELECT_BIT(badvaddr) == 0) 177 215 cp0_entry_lo0_write(lo.value); 178 216 else 179 217 cp0_entry_lo1_write(lo.value); 180 cp0_pagemask_write(TLB_PAGE_MASK_16K);181 218 tlbwi(); 182 219 } … … 189 226 void tlb_modified(istate_t *istate) 190 227 { 228 entry_hi_t hi; 229 entry_lo_t lo; 191 230 tlb_index_t index; 192 231 uintptr_t badvaddr; 193 entry_lo_t lo;194 entry_hi_t hi;195 232 pte_t *pte; 196 233 197 badvaddr = cp0_badvaddr_read();198 199 234 /* 200 235 * Locate the faulting entry in TLB. 201 236 */ 202 hi.value = cp0_entry_hi_read();203 tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);204 cp0_entry_hi_write(hi.value);205 237 tlbp(); 206 238 index.value = cp0_index_read(); … … 211 243 ASSERT(!index.p); 212 244 245 badvaddr = cp0_badvaddr_read(); 246 hi.value = cp0_entry_hi_read(); 247 248 /* We may block in find_mapping_and_check(). */ 213 249 pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate); 214 250 if (pte) { 251 if (!tlb_recheck_entry(hi, true)) 252 return; 253 215 254 /* 216 255 * Read the faulting TLB entry. … … 230 269 * The entry is to be updated in TLB. 231 270 */ 232 if ( (badvaddr / PAGE_SIZE) % 2== 0)271 if (BANK_SELECT_BIT(badvaddr) == 0) 233 272 cp0_entry_lo0_write(lo.value); 234 273 else 235 274 cp0_entry_lo1_write(lo.value); 236 cp0_pagemask_write(TLB_PAGE_MASK_16K);237 275 tlbwi(); 238 276 } … … 296 334 void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr) 297 335 { 298 hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2); 336 hi->value = 0; 337 hi->vpn2 = ADDR2VPN2(ALIGN_DOWN(addr, PAGE_SIZE)); 299 338 hi->asid = asid; 300 339 } … … 303 342 void tlb_print(void) 304 343 { 305 page_mask_t mask ;306 entry_lo_t lo0, lo 1;344 page_mask_t mask, mask_save; 345 entry_lo_t lo0, lo0_save, lo1, lo1_save; 307 346 entry_hi_t hi, hi_save; 308 347 unsigned int i; 309 348 310 349 hi_save.value = cp0_entry_hi_read(); 311 312 printf("[nr] [asid] [vpn2] [mask] [gvdc] [pfn ]\n"); 350 lo0_save.value = cp0_entry_lo0_read(); 351 lo1_save.value = cp0_entry_lo1_read(); 352 mask_save.value = cp0_pagemask_read(); 353 354 printf("[nr] [asid] [vpn2 ] [mask] [gvdc] [pfn ]\n"); 313 355 314 356 for (i = 0; i < TLB_ENTRY_COUNT; i++) { … … 321 363 lo1.value = cp0_entry_lo1_read(); 322 364 323 printf("%-4u %-6u % #6x %#6x %1u%1u%1u%1u %#6x\n",324 i, hi.asid, hi.vpn2, mask.mask,325 lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn );326 printf(" %1u%1u%1u%1u %#6x\n",327 lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn );365 printf("%-4u %-6u %0#10x %-#6x %1u%1u%1u%1u %0#10x\n", 366 i, hi.asid, VPN22ADDR(hi.vpn2), mask.mask, 367 lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn << FRAME_WIDTH); 368 printf(" %1u%1u%1u%1u %0#10x\n", 369 lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn << FRAME_WIDTH); 328 370 } 329 371 330 372 cp0_entry_hi_write(hi_save.value); 373 cp0_entry_lo0_write(lo0_save.value); 374 cp0_entry_lo1_write(lo1_save.value); 375 cp0_pagemask_write(mask_save.value); 331 376 } 332 377 … … 334 379 void tlb_invalidate_all(void) 335 380 { 336 ipl_t ipl;337 381 entry_lo_t lo0, lo1; 338 382 entry_hi_t hi_save; 339 383 int i; 340 384 385 ASSERT(interrupts_disabled()); 386 341 387 hi_save.value = cp0_entry_hi_read(); 342 ipl = interrupts_disable();343 388 344 389 for (i = TLB_WIRED; i < TLB_ENTRY_COUNT; i++) { … … 358 403 } 359 404 360 interrupts_restore(ipl);361 405 cp0_entry_hi_write(hi_save.value); 362 406 } … … 368 412 void tlb_invalidate_asid(asid_t asid) 369 413 { 370 ipl_t ipl;371 414 entry_lo_t lo0, lo1; 372 415 entry_hi_t hi, hi_save; 373 416 int i; 374 417 418 ASSERT(interrupts_disabled()); 375 419 ASSERT(asid != ASID_INVALID); 376 420 377 421 hi_save.value = cp0_entry_hi_read(); 378 ipl = interrupts_disable();379 422 380 423 for (i = 0; i < TLB_ENTRY_COUNT; i++) { … … 398 441 } 399 442 400 interrupts_restore(ipl);401 443 cp0_entry_hi_write(hi_save.value); 402 444 } … … 412 454 { 413 455 unsigned int i; 414 ipl_t ipl;415 456 entry_lo_t lo0, lo1; 416 457 entry_hi_t hi, hi_save; 417 458 tlb_index_t index; 459 460 ASSERT(interrupts_disabled()); 418 461 419 462 if (asid == ASID_INVALID) … … 421 464 422 465 hi_save.value = cp0_entry_hi_read(); 423 ipl = interrupts_disable();424 466 425 467 for (i = 0; i < cnt + 1; i += 2) { 426 hi.value = 0;427 468 tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE); 428 469 cp0_entry_hi_write(hi.value); … … 451 492 } 452 493 453 interrupts_restore(ipl);454 494 cp0_entry_hi_write(hi_save.value); 455 495 }
Note:
See TracChangeset
for help on using the changeset viewer.