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; |