Rev 4055 | Rev 4420 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4055 | Rev 4296 | ||
---|---|---|---|
Line 197... | Line 197... | ||
197 | } |
197 | } |
198 | 198 | ||
199 | /** ITLB miss handler. */ |
199 | /** ITLB miss handler. */ |
200 | void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate) |
200 | void fast_instruction_access_mmu_miss(unative_t unused, istate_t *istate) |
201 | { |
201 | { |
202 | uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
202 | uintptr_t page_16k = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
203 | index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
203 | index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
204 | pte_t *t; |
204 | pte_t *t; |
205 | 205 | ||
206 | page_table_lock(AS, true); |
206 | page_table_lock(AS, true); |
207 | t = page_mapping_find(AS, va); |
207 | t = page_mapping_find(AS, page_16k); |
208 | if (t && PTE_EXECUTABLE(t)) { |
208 | if (t && PTE_EXECUTABLE(t)) { |
209 | /* |
209 | /* |
210 | * The mapping was found in the software page hash table. |
210 | * The mapping was found in the software page hash table. |
211 | * Insert it into ITLB. |
211 | * Insert it into ITLB. |
212 | */ |
212 | */ |
Line 220... | Line 220... | ||
220 | /* |
220 | /* |
221 | * Forward the page fault to the address space page fault |
221 | * Forward the page fault to the address space page fault |
222 | * handler. |
222 | * handler. |
223 | */ |
223 | */ |
224 | page_table_unlock(AS, true); |
224 | page_table_unlock(AS, true); |
225 | if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) { |
225 | if (as_page_fault(page_16k, PF_ACCESS_EXEC, istate) == |
- | 226 | AS_PF_FAULT) { |
|
226 | do_fast_instruction_access_mmu_miss_fault(istate, |
227 | do_fast_instruction_access_mmu_miss_fault(istate, |
227 | __func__); |
228 | __func__); |
228 | } |
229 | } |
229 | } |
230 | } |
230 | } |
231 | } |
Line 240... | Line 241... | ||
240 | * DTLB miss. |
241 | * DTLB miss. |
241 | * @param istate Interrupted state saved on the stack. |
242 | * @param istate Interrupted state saved on the stack. |
242 | */ |
243 | */ |
243 | void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
244 | void fast_data_access_mmu_miss(tlb_tag_access_reg_t tag, istate_t *istate) |
244 | { |
245 | { |
245 | uintptr_t va; |
246 | uintptr_t page_8k; |
- | 247 | uintptr_t page_16k; |
|
246 | index_t index; |
248 | index_t index; |
247 | pte_t *t; |
249 | pte_t *t; |
248 | 250 | ||
249 | va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
251 | page_8k = (uint64_t) tag.vpn << MMU_PAGE_WIDTH; |
- | 252 | page_16k = ALIGN_DOWN(page_8k, PAGE_SIZE); |
|
250 | index = tag.vpn % MMU_PAGES_PER_PAGE; |
253 | index = tag.vpn % MMU_PAGES_PER_PAGE; |
251 | 254 | ||
252 | if (tag.context == ASID_KERNEL) { |
255 | if (tag.context == ASID_KERNEL) { |
253 | if (!tag.vpn) { |
256 | if (!tag.vpn) { |
254 | /* NULL access in kernel */ |
257 | /* NULL access in kernel */ |
255 | do_fast_data_access_mmu_miss_fault(istate, tag, |
258 | do_fast_data_access_mmu_miss_fault(istate, tag, |
256 | __func__); |
259 | __func__); |
- | 260 | } else if (page_8k >= end_of_identity) { |
|
- | 261 | /* |
|
- | 262 | * The kernel is accessing the I/O space. |
|
- | 263 | * We still do identity mapping for I/O, |
|
- | 264 | * but without caching. |
|
- | 265 | */ |
|
- | 266 | dtlb_insert_mapping(page_8k, KA2PA(page_8k), |
|
- | 267 | PAGESIZE_8K, false, false); |
|
- | 268 | return; |
|
257 | } |
269 | } |
258 | do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected " |
270 | do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected " |
259 | "kernel page fault."); |
271 | "kernel page fault."); |
260 | } |
272 | } |
261 | 273 | ||
262 | page_table_lock(AS, true); |
274 | page_table_lock(AS, true); |
263 | t = page_mapping_find(AS, va); |
275 | t = page_mapping_find(AS, page_16k); |
264 | if (t) { |
276 | if (t) { |
265 | /* |
277 | /* |
266 | * The mapping was found in the software page hash table. |
278 | * The mapping was found in the software page hash table. |
267 | * Insert it into DTLB. |
279 | * Insert it into DTLB. |
268 | */ |
280 | */ |
Line 276... | Line 288... | ||
276 | /* |
288 | /* |
277 | * Forward the page fault to the address space page fault |
289 | * Forward the page fault to the address space page fault |
278 | * handler. |
290 | * handler. |
279 | */ |
291 | */ |
280 | page_table_unlock(AS, true); |
292 | page_table_unlock(AS, true); |
281 | if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
293 | if (as_page_fault(page_16k, PF_ACCESS_READ, istate) == |
- | 294 | AS_PF_FAULT) { |
|
282 | do_fast_data_access_mmu_miss_fault(istate, tag, |
295 | do_fast_data_access_mmu_miss_fault(istate, tag, |
283 | __func__); |
296 | __func__); |
284 | } |
297 | } |
285 | } |
298 | } |
286 | } |
299 | } |
Line 293... | Line 306... | ||
293 | * DTLB miss. |
306 | * DTLB miss. |
294 | * @param istate Interrupted state saved on the stack. |
307 | * @param istate Interrupted state saved on the stack. |
295 | */ |
308 | */ |
296 | void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
309 | void fast_data_access_protection(tlb_tag_access_reg_t tag, istate_t *istate) |
297 | { |
310 | { |
298 | uintptr_t va; |
311 | uintptr_t page_16k; |
299 | index_t index; |
312 | index_t index; |
300 | pte_t *t; |
313 | pte_t *t; |
301 | 314 | ||
302 | va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
315 | page_16k = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
303 | index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
316 | index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
304 | 317 | ||
305 | page_table_lock(AS, true); |
318 | page_table_lock(AS, true); |
306 | t = page_mapping_find(AS, va); |
319 | t = page_mapping_find(AS, page_16k); |
307 | if (t && PTE_WRITABLE(t)) { |
320 | if (t && PTE_WRITABLE(t)) { |
308 | /* |
321 | /* |
309 | * The mapping was found in the software page hash table and is |
322 | * The mapping was found in the software page hash table and is |
310 | * writable. Demap the old mapping and insert an updated mapping |
323 | * writable. Demap the old mapping and insert an updated mapping |
311 | * into DTLB. |
324 | * into DTLB. |
312 | */ |
325 | */ |
313 | t->a = true; |
326 | t->a = true; |
314 | t->d = true; |
327 | t->d = true; |
315 | dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, |
328 | dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, |
316 | va + index * MMU_PAGE_SIZE); |
329 | page_16k + index * MMU_PAGE_SIZE); |
317 | dtlb_pte_copy(t, index, false); |
330 | dtlb_pte_copy(t, index, false); |
318 | #ifdef CONFIG_TSB |
331 | #ifdef CONFIG_TSB |
319 | dtsb_pte_copy(t, index, false); |
332 | dtsb_pte_copy(t, index, false); |
320 | #endif |
333 | #endif |
321 | page_table_unlock(AS, true); |
334 | page_table_unlock(AS, true); |
Line 323... | Line 336... | ||
323 | /* |
336 | /* |
324 | * Forward the page fault to the address space page fault |
337 | * Forward the page fault to the address space page fault |
325 | * handler. |
338 | * handler. |
326 | */ |
339 | */ |
327 | page_table_unlock(AS, true); |
340 | page_table_unlock(AS, true); |
328 | if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) { |
341 | if (as_page_fault(page_16k, PF_ACCESS_WRITE, istate) == |
- | 342 | AS_PF_FAULT) { |
|
329 | do_fast_data_access_protection_fault(istate, tag, |
343 | do_fast_data_access_protection_fault(istate, tag, |
330 | __func__); |
344 | __func__); |
331 | } |
345 | } |
332 | } |
346 | } |
333 | } |
347 | } |