Rev 4339 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4339 | Rev 4348 | ||
|---|---|---|---|
| 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 | } |