Rev 830 | Rev 958 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 830 | Rev 831 | ||
|---|---|---|---|
| Line 43... | Line 43... | ||
| 43 | static void tlb_invalid_fail(struct exception_regdump *pstate); |
43 | static void tlb_invalid_fail(struct exception_regdump *pstate); |
| 44 | static void tlb_modified_fail(struct exception_regdump *pstate); |
44 | static void tlb_modified_fail(struct exception_regdump *pstate); |
| 45 | 45 | ||
| 46 | static pte_t *find_mapping_and_check(__address badvaddr); |
46 | static pte_t *find_mapping_and_check(__address badvaddr); |
| 47 | 47 | ||
| 48 | static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn); |
48 | static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn); |
| 49 | static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
49 | static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
| 50 | 50 | ||
| 51 | /** Initialize TLB |
51 | /** Initialize TLB |
| 52 | * |
52 | * |
| 53 | * Initialize TLB. |
53 | * Initialize TLB. |
| Line 102... | Line 102... | ||
| 102 | * Record access to PTE. |
102 | * Record access to PTE. |
| 103 | */ |
103 | */ |
| 104 | pte->a = 1; |
104 | pte->a = 1; |
| 105 | 105 | ||
| 106 | prepare_entry_hi(&hi, AS->asid, badvaddr); |
106 | prepare_entry_hi(&hi, AS->asid, badvaddr); |
| 107 | prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->lo.d, pte->lo.c, pte->lo.pfn); |
107 | prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
| 108 | 108 | ||
| 109 | /* |
109 | /* |
| 110 | * New entry is to be inserted into TLB |
110 | * New entry is to be inserted into TLB |
| 111 | */ |
111 | */ |
| 112 | cp0_entry_hi_write(hi.value); |
112 | cp0_entry_hi_write(hi.value); |
| Line 176... | Line 176... | ||
| 176 | /* |
176 | /* |
| 177 | * Record access to PTE. |
177 | * Record access to PTE. |
| 178 | */ |
178 | */ |
| 179 | pte->a = 1; |
179 | pte->a = 1; |
| 180 | 180 | ||
| 181 | prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->lo.d, pte->lo.c, pte->lo.pfn); |
181 | prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
| 182 | 182 | ||
| 183 | /* |
183 | /* |
| 184 | * The entry is to be updated in TLB. |
184 | * The entry is to be updated in TLB. |
| 185 | */ |
185 | */ |
| 186 | if ((badvaddr/PAGE_SIZE) % 2 == 0) |
186 | if ((badvaddr/PAGE_SIZE) % 2 == 0) |
| Line 250... | Line 250... | ||
| 250 | 250 | ||
| 251 | /* |
251 | /* |
| 252 | * Record access and write to PTE. |
252 | * Record access and write to PTE. |
| 253 | */ |
253 | */ |
| 254 | pte->a = 1; |
254 | pte->a = 1; |
| 255 | pte->lo.d = 1; |
255 | pte->d = 1; |
| 256 | 256 | ||
| 257 | prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->w, pte->lo.c, pte->lo.pfn); |
257 | prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn); |
| 258 | 258 | ||
| 259 | /* |
259 | /* |
| 260 | * The entry is to be updated in TLB. |
260 | * The entry is to be updated in TLB. |
| 261 | */ |
261 | */ |
| 262 | if ((badvaddr/PAGE_SIZE) % 2 == 0) |
262 | if ((badvaddr/PAGE_SIZE) % 2 == 0) |
| Line 335... | Line 335... | ||
| 335 | 335 | ||
| 336 | /* |
336 | /* |
| 337 | * Check if the mapping exists in page tables. |
337 | * Check if the mapping exists in page tables. |
| 338 | */ |
338 | */ |
| 339 | pte = page_mapping_find(AS, badvaddr); |
339 | pte = page_mapping_find(AS, badvaddr); |
| 340 | if (pte && pte->lo.v) { |
340 | if (pte && pte->p) { |
| 341 | /* |
341 | /* |
| 342 | * Mapping found in page tables. |
342 | * Mapping found in page tables. |
| 343 | * Immediately succeed. |
343 | * Immediately succeed. |
| 344 | */ |
344 | */ |
| 345 | return pte; |
345 | return pte; |
| Line 352... | Line 352... | ||
| 352 | /* |
352 | /* |
| 353 | * The higher-level page fault handler succeeded, |
353 | * The higher-level page fault handler succeeded, |
| 354 | * The mapping ought to be in place. |
354 | * The mapping ought to be in place. |
| 355 | */ |
355 | */ |
| 356 | pte = page_mapping_find(AS, badvaddr); |
356 | pte = page_mapping_find(AS, badvaddr); |
| 357 | ASSERT(pte && pte->lo.v); |
357 | ASSERT(pte && pte->p); |
| 358 | return pte; |
358 | return pte; |
| 359 | } |
359 | } |
| 360 | } |
360 | } |
| 361 | 361 | ||
| 362 | /* |
362 | /* |
| Line 368... | Line 368... | ||
| 368 | } |
368 | } |
| 369 | 369 | ||
| 370 | /* |
370 | /* |
| 371 | * Handler cannot succeed if the mapping is marked as invalid. |
371 | * Handler cannot succeed if the mapping is marked as invalid. |
| 372 | */ |
372 | */ |
| 373 | if (!pte->lo.v) { |
373 | if (!pte->p) { |
| 374 | printf("Invalid mapping.\n"); |
374 | printf("Invalid mapping.\n"); |
| 375 | return NULL; |
375 | return NULL; |
| 376 | } |
376 | } |
| 377 | 377 | ||
| 378 | return pte; |
378 | return pte; |
| 379 | } |
379 | } |
| 380 | 380 | ||
| 381 | void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn) |
381 | void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn) |
| 382 | { |
382 | { |
| 383 | lo->value = 0; |
383 | lo->value = 0; |
| 384 | lo->g = g; |
384 | lo->g = g; |
| 385 | lo->v = v; |
385 | lo->v = v; |
| 386 | lo->d = d; |
386 | lo->d = d; |
| 387 | lo->c = c; |
387 | lo->c = cacheable ? PAGE_CACHEABLE_EXC_WRITE : PAGE_UNCACHED; |
| 388 | lo->pfn = pfn; |
388 | lo->pfn = pfn; |
| 389 | } |
389 | } |
| 390 | 390 | ||
| 391 | void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr) |
391 | void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr) |
| 392 | { |
392 | { |