Rev 1196 | Rev 1411 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1196 | Rev 1288 | ||
|---|---|---|---|
| Line 42... | Line 42... | ||
| 42 | 42 | ||
| 43 | static void tlb_refill_fail(istate_t *istate); |
43 | static void tlb_refill_fail(istate_t *istate); |
| 44 | static void tlb_invalid_fail(istate_t *istate); |
44 | static void tlb_invalid_fail(istate_t *istate); |
| 45 | static void tlb_modified_fail(istate_t *istate); |
45 | static void tlb_modified_fail(istate_t *istate); |
| 46 | 46 | ||
| 47 | static pte_t *find_mapping_and_check(__address badvaddr); |
47 | static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc); |
| 48 | 48 | ||
| 49 | static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn); |
49 | static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn); |
| 50 | static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
50 | static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr); |
| 51 | 51 | ||
| 52 | /** Initialize TLB |
52 | /** Initialize TLB |
| Line 89... | Line 89... | ||
| 89 | entry_lo_t lo; |
89 | entry_lo_t lo; |
| 90 | entry_hi_t hi; |
90 | entry_hi_t hi; |
| 91 | asid_t asid; |
91 | asid_t asid; |
| 92 | __address badvaddr; |
92 | __address badvaddr; |
| 93 | pte_t *pte; |
93 | pte_t *pte; |
| - | 94 | int pfrc; |
|
| 94 | 95 | ||
| 95 | badvaddr = cp0_badvaddr_read(); |
96 | badvaddr = cp0_badvaddr_read(); |
| 96 | 97 | ||
| 97 | spinlock_lock(&AS->lock); |
98 | spinlock_lock(&AS->lock); |
| 98 | asid = AS->asid; |
99 | asid = AS->asid; |
| 99 | spinlock_unlock(&AS->lock); |
100 | spinlock_unlock(&AS->lock); |
| 100 | 101 | ||
| 101 | page_table_lock(AS, true); |
102 | page_table_lock(AS, true); |
| 102 | 103 | ||
| 103 | pte = find_mapping_and_check(badvaddr); |
104 | pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
| 104 | if (!pte) |
105 | if (!pte) { |
| - | 106 | switch (pfrc) { |
|
| - | 107 | case AS_PF_FAULT: |
|
| 105 | goto fail; |
108 | goto fail; |
| - | 109 | break; |
|
| - | 110 | case AS_PF_DEFER: |
|
| - | 111 | /* |
|
| - | 112 | * The page fault came during copy_from_uspace() |
|
| - | 113 | * or copy_to_uspace(). |
|
| - | 114 | */ |
|
| - | 115 | page_table_unlock(AS, true); |
|
| - | 116 | return; |
|
| - | 117 | default: |
|
| - | 118 | panic("unexpected pfrc (%d)\n", pfrc); |
|
| - | 119 | } |
|
| - | 120 | } |
|
| 106 | 121 | ||
| 107 | /* |
122 | /* |
| 108 | * Record access to PTE. |
123 | * Record access to PTE. |
| 109 | */ |
124 | */ |
| 110 | pte->a = 1; |
125 | pte->a = 1; |
| Line 146... | Line 161... | ||
| 146 | tlb_index_t index; |
161 | tlb_index_t index; |
| 147 | __address badvaddr; |
162 | __address badvaddr; |
| 148 | entry_lo_t lo; |
163 | entry_lo_t lo; |
| 149 | entry_hi_t hi; |
164 | entry_hi_t hi; |
| 150 | pte_t *pte; |
165 | pte_t *pte; |
| - | 166 | int pfrc; |
|
| 151 | 167 | ||
| 152 | badvaddr = cp0_badvaddr_read(); |
168 | badvaddr = cp0_badvaddr_read(); |
| 153 | 169 | ||
| 154 | /* |
170 | /* |
| 155 | * Locate the faulting entry in TLB. |
171 | * Locate the faulting entry in TLB. |
| Line 168... | Line 184... | ||
| 168 | if (index.p) { |
184 | if (index.p) { |
| 169 | printf("TLB entry not found.\n"); |
185 | printf("TLB entry not found.\n"); |
| 170 | goto fail; |
186 | goto fail; |
| 171 | } |
187 | } |
| 172 | 188 | ||
| 173 | pte = find_mapping_and_check(badvaddr); |
189 | pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
| 174 | if (!pte) |
190 | if (!pte) { |
| - | 191 | switch (pfrc) { |
|
| - | 192 | case AS_PF_FAULT: |
|
| 175 | goto fail; |
193 | goto fail; |
| - | 194 | break; |
|
| - | 195 | case AS_PF_DEFER: |
|
| - | 196 | /* |
|
| - | 197 | * The page fault came during copy_from_uspace() |
|
| - | 198 | * or copy_to_uspace(). |
|
| - | 199 | */ |
|
| - | 200 | page_table_unlock(AS, true); |
|
| - | 201 | return; |
|
| - | 202 | default: |
|
| - | 203 | panic("unexpected pfrc (%d)\n", pfrc); |
|
| - | 204 | } |
|
| - | 205 | } |
|
| 176 | 206 | ||
| 177 | /* |
207 | /* |
| 178 | * Read the faulting TLB entry. |
208 | * Read the faulting TLB entry. |
| 179 | */ |
209 | */ |
| 180 | tlbr(); |
210 | tlbr(); |
| Line 215... | Line 245... | ||
| 215 | tlb_index_t index; |
245 | tlb_index_t index; |
| 216 | __address badvaddr; |
246 | __address badvaddr; |
| 217 | entry_lo_t lo; |
247 | entry_lo_t lo; |
| 218 | entry_hi_t hi; |
248 | entry_hi_t hi; |
| 219 | pte_t *pte; |
249 | pte_t *pte; |
| - | 250 | int pfrc; |
|
| 220 | 251 | ||
| 221 | badvaddr = cp0_badvaddr_read(); |
252 | badvaddr = cp0_badvaddr_read(); |
| 222 | 253 | ||
| 223 | /* |
254 | /* |
| 224 | * Locate the faulting entry in TLB. |
255 | * Locate the faulting entry in TLB. |
| Line 237... | Line 268... | ||
| 237 | if (index.p) { |
268 | if (index.p) { |
| 238 | printf("TLB entry not found.\n"); |
269 | printf("TLB entry not found.\n"); |
| 239 | goto fail; |
270 | goto fail; |
| 240 | } |
271 | } |
| 241 | 272 | ||
| 242 | pte = find_mapping_and_check(badvaddr); |
273 | pte = find_mapping_and_check(badvaddr, istate, &pfrc); |
| 243 | if (!pte) |
274 | if (!pte) { |
| - | 275 | switch (pfrc) { |
|
| - | 276 | case AS_PF_FAULT: |
|
| 244 | goto fail; |
277 | goto fail; |
| - | 278 | break; |
|
| - | 279 | case AS_PF_DEFER: |
|
| - | 280 | /* |
|
| - | 281 | * The page fault came during copy_from_uspace() |
|
| - | 282 | * or copy_to_uspace(). |
|
| - | 283 | */ |
|
| - | 284 | page_table_unlock(AS, true); |
|
| - | 285 | return; |
|
| - | 286 | default: |
|
| - | 287 | panic("unexpected pfrc (%d)\n", pfrc); |
|
| - | 288 | } |
|
| - | 289 | } |
|
| 245 | 290 | ||
| 246 | /* |
291 | /* |
| 247 | * Fail if the page is not writable. |
292 | * Fail if the page is not writable. |
| 248 | */ |
293 | */ |
| 249 | if (!pte->w) |
294 | if (!pte->w) |
| Line 319... | Line 364... | ||
| 319 | * |
364 | * |
| 320 | * Try to find PTE for faulting address. |
365 | * Try to find PTE for faulting address. |
| 321 | * The AS->lock must be held on entry to this function. |
366 | * The AS->lock must be held on entry to this function. |
| 322 | * |
367 | * |
| 323 | * @param badvaddr Faulting virtual address. |
368 | * @param badvaddr Faulting virtual address. |
| - | 369 | * @param istate Pointer to interrupted state. |
|
| - | 370 | * @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
|
| 324 | * |
371 | * |
| 325 | * @return PTE on success, NULL otherwise. |
372 | * @return PTE on success, NULL otherwise. |
| 326 | */ |
373 | */ |
| 327 | pte_t *find_mapping_and_check(__address badvaddr) |
374 | pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc) |
| 328 | { |
375 | { |
| 329 | entry_hi_t hi; |
376 | entry_hi_t hi; |
| 330 | pte_t *pte; |
377 | pte_t *pte; |
| 331 | 378 | ||
| 332 | hi.value = cp0_entry_hi_read(); |
379 | hi.value = cp0_entry_hi_read(); |
| Line 348... | Line 395... | ||
| 348 | * Mapping found in page tables. |
395 | * Mapping found in page tables. |
| 349 | * Immediately succeed. |
396 | * Immediately succeed. |
| 350 | */ |
397 | */ |
| 351 | return pte; |
398 | return pte; |
| 352 | } else { |
399 | } else { |
| - | 400 | int rc; |
|
| - | 401 | ||
| 353 | /* |
402 | /* |
| 354 | * Mapping not found in page tables. |
403 | * Mapping not found in page tables. |
| 355 | * Resort to higher-level page fault handler. |
404 | * Resort to higher-level page fault handler. |
| 356 | */ |
405 | */ |
| 357 | page_table_unlock(AS, true); |
406 | page_table_unlock(AS, true); |
| 358 | if (as_page_fault(badvaddr)) { |
407 | switch (rc = as_page_fault(badvaddr, istate)) { |
| - | 408 | case AS_PF_OK: |
|
| 359 | /* |
409 | /* |
| 360 | * The higher-level page fault handler succeeded, |
410 | * The higher-level page fault handler succeeded, |
| 361 | * The mapping ought to be in place. |
411 | * The mapping ought to be in place. |
| 362 | */ |
412 | */ |
| 363 | page_table_lock(AS, true); |
413 | page_table_lock(AS, true); |
| 364 | pte = page_mapping_find(AS, badvaddr); |
414 | pte = page_mapping_find(AS, badvaddr); |
| 365 | ASSERT(pte && pte->p); |
415 | ASSERT(pte && pte->p); |
| 366 | return pte; |
416 | return pte; |
| - | 417 | break; |
|
| - | 418 | case AS_PF_DEFER: |
|
| - | 419 | page_table_lock(AS, true); |
|
| - | 420 | *pfrc = AS_PF_DEFER; |
|
| - | 421 | return NULL; |
|
| 367 | } else { |
422 | break; |
| - | 423 | case AS_PF_FAULT: |
|
| 368 | page_table_lock(AS, true); |
424 | page_table_lock(AS, true); |
| 369 | printf("Page fault.\n"); |
425 | printf("Page fault.\n"); |
| - | 426 | *pfrc = AS_PF_FAULT; |
|
| 370 | return NULL; |
427 | return NULL; |
| - | 428 | break; |
|
| - | 429 | default: |
|
| - | 430 | panic("unexpected rc (%d)\n", rc); |
|
| 371 | } |
431 | } |
| 372 | 432 | ||
| 373 | } |
433 | } |
| 374 | } |
434 | } |
| 375 | 435 | ||