Rev 1270 | Rev 1328 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1270 | Rev 1288 | ||
|---|---|---|---|
| Line 66... | Line 66... | ||
| 66 | * |
66 | * |
| 67 | * Try to find PTE for faulting address. |
67 | * Try to find PTE for faulting address. |
| 68 | * The AS->lock must be held on entry to this function. |
68 | * The AS->lock must be held on entry to this function. |
| 69 | * |
69 | * |
| 70 | * @param badvaddr Faulting virtual address. |
70 | * @param badvaddr Faulting virtual address. |
| - | 71 | * @param istate Pointer to interrupted state. |
|
| - | 72 | * @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
|
| 71 | * @return PTE on success, NULL otherwise. |
73 | * @return PTE on success, NULL otherwise. |
| 72 | * |
74 | * |
| 73 | */ |
75 | */ |
| 74 | static pte_t *find_mapping_and_check(__address badvaddr) |
76 | static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfcr) |
| 75 | { |
77 | { |
| 76 | /* |
78 | /* |
| 77 | * Check if the mapping exists in page tables. |
79 | * Check if the mapping exists in page tables. |
| 78 | */ |
80 | */ |
| 79 | pte_t *pte = page_mapping_find(AS, badvaddr); |
81 | pte_t *pte = page_mapping_find(AS, badvaddr); |
| Line 82... | Line 84... | ||
| 82 | * Mapping found in page tables. |
84 | * Mapping found in page tables. |
| 83 | * Immediately succeed. |
85 | * Immediately succeed. |
| 84 | */ |
86 | */ |
| 85 | return pte; |
87 | return pte; |
| 86 | } else { |
88 | } else { |
| - | 89 | int rc; |
|
| - | 90 | ||
| 87 | /* |
91 | /* |
| 88 | * Mapping not found in page tables. |
92 | * Mapping not found in page tables. |
| 89 | * Resort to higher-level page fault handler. |
93 | * Resort to higher-level page fault handler. |
| 90 | */ |
94 | */ |
| 91 | page_table_unlock(AS, true); |
95 | page_table_unlock(AS, true); |
| 92 | if (as_page_fault(badvaddr)) { |
96 | switch (rc = as_page_fault(badvaddr, istate)) { |
| - | 97 | case AS_PF_OK: |
|
| 93 | /* |
98 | /* |
| 94 | * The higher-level page fault handler succeeded, |
99 | * The higher-level page fault handler succeeded, |
| 95 | * The mapping ought to be in place. |
100 | * The mapping ought to be in place. |
| 96 | */ |
101 | */ |
| 97 | page_table_lock(AS, true); |
102 | page_table_lock(AS, true); |
| 98 | pte = page_mapping_find(AS, badvaddr); |
103 | pte = page_mapping_find(AS, badvaddr); |
| 99 | ASSERT((pte) && (pte->p)); |
104 | ASSERT((pte) && (pte->p)); |
| 100 | return pte; |
105 | return pte; |
| - | 106 | break; |
|
| - | 107 | case AS_PF_DEFER: |
|
| - | 108 | page_table_lock(AS, true); |
|
| - | 109 | *pfcr = rc; |
|
| - | 110 | return NULL; |
|
| 101 | } else { |
111 | break; |
| - | 112 | case AS_PF_FAULT: |
|
| 102 | page_table_lock(AS, true); |
113 | page_table_lock(AS, true); |
| 103 | printf("Page fault.\n"); |
114 | printf("Page fault.\n"); |
| - | 115 | *pfcr = rc; |
|
| 104 | return NULL; |
116 | return NULL; |
| - | 117 | break; |
|
| - | 118 | default: |
|
| - | 119 | panic("unexpected rc (%d)\n", rc); |
|
| 105 | } |
120 | break; |
| 106 | 121 | } |
|
| 107 | } |
122 | } |
| 108 | } |
123 | } |
| 109 | 124 | ||
| 110 | 125 | ||
| 111 | static void pht_refill_fail(__address badvaddr, istate_t *istate) |
126 | static void pht_refill_fail(__address badvaddr, istate_t *istate) |
| Line 137... | Line 152... | ||
| 137 | __u32 page; |
152 | __u32 page; |
| 138 | __u32 api; |
153 | __u32 api; |
| 139 | __u32 vsid; |
154 | __u32 vsid; |
| 140 | __u32 hash; |
155 | __u32 hash; |
| 141 | __u32 i; |
156 | __u32 i; |
| - | 157 | int pfcr; |
|
| 142 | 158 | ||
| 143 | if (data) { |
159 | if (data) { |
| 144 | asm volatile ( |
160 | asm volatile ( |
| 145 | "mfdar %0\n" |
161 | "mfdar %0\n" |
| 146 | : "=r" (badvaddr) |
162 | : "=r" (badvaddr) |
| Line 152... | Line 168... | ||
| 152 | asid = AS->asid; |
168 | asid = AS->asid; |
| 153 | spinlock_unlock(&AS->lock); |
169 | spinlock_unlock(&AS->lock); |
| 154 | 170 | ||
| 155 | page_table_lock(AS, true); |
171 | page_table_lock(AS, true); |
| 156 | 172 | ||
| 157 | pte = find_mapping_and_check(badvaddr); |
173 | pte = find_mapping_and_check(badvaddr, istate, &pfcr); |
| 158 | if (!pte) |
174 | if (!pte) { |
| - | 175 | switch (pfcr) { |
|
| - | 176 | case AS_PF_FAULT: |
|
| 159 | goto fail; |
177 | goto fail; |
| - | 178 | break; |
|
| - | 179 | case AS_PF_DEFER: |
|
| - | 180 | /* |
|
| - | 181 | * The page fault came during copy_from_uspace() |
|
| - | 182 | * or copy_to_uspace(). |
|
| - | 183 | */ |
|
| - | 184 | page_table_unlock(AS, true); |
|
| - | 185 | return; |
|
| - | 186 | default: |
|
| - | 187 | panic("Unexpected pfrc (%d)\n", pfcr); |
|
| - | 188 | break; |
|
| - | 189 | } |
|
| - | 190 | } |
|
| 160 | 191 | ||
| 161 | /* Record access to PTE */ |
192 | /* Record access to PTE */ |
| 162 | pte->a = 1; |
193 | pte->a = 1; |
| 163 | 194 | ||
| 164 | page = (badvaddr >> 12) & 0xffff; |
195 | page = (badvaddr >> 12) & 0xffff; |