* Update kernel pte1 on all pmaps. * * The following function is called only on one cpu with disabled interrupts. * In SMP case, smp_rendezvous_cpus() is used to stop other cpus. This way * nobody can invoke explicit hardware table walk during the update of pte1. * Unsolicited hardware table walk can still happen, invoked by speculative * data or instruction prefetch or even by specula
| 3277 | * itself unexpectedly but voluntarily. |
| 3278 | */ |
| 3279 | static void |
| 3280 | pmap_update_pte1_kernel(vm_offset_t va, pt1_entry_t npte1) |
| 3281 | { |
| 3282 | pmap_t pmap; |
| 3283 | pt1_entry_t *pte1p; |
| 3284 | |
| 3285 | /* |
| 3286 | * Get current pmap. Interrupts should be disabled here |
| 3287 | * so PCPU_GET() is done atomically. |
| 3288 | */ |
| 3289 | pmap = PCPU_GET(curpmap); |
| 3290 | if (pmap == NULL) |
| 3291 | pmap = kernel_pmap; |
| 3292 | |
| 3293 | /* |
| 3294 | * (1) Change pte1 on current pmap. |
| 3295 | * (2) Flush all obsolete TLB entries on current CPU. |
| 3296 | * (3) Change pte1 on all pmaps. |
| 3297 | * (4) Flush all obsolete TLB entries on all CPUs in SMP case. |
| 3298 | */ |
| 3299 | |
| 3300 | pte1p = pmap_pte1(pmap, va); |
| 3301 | pte1_store(pte1p, npte1); |
| 3302 | |
| 3303 | /* Kill all the small mappings or the big one only. */ |
| 3304 | if (pte1_is_section(npte1)) { |
| 3305 | pmap_pte1_kern_promotions++; |
| 3306 | tlb_flush_range_local(pte1_trunc(va), PTE1_SIZE); |
| 3307 | } else { |
| 3308 | pmap_pte1_kern_demotions++; |
| 3309 | tlb_flush_local(pte1_trunc(va)); |
| 3310 | } |
| 3311 | |
| 3312 | /* |
| 3313 | * In SMP case, this function is called when all cpus are at smp |
| 3314 | * rendezvous, so there is no need to use 'allpmaps_lock' lock here. |
| 3315 | * In UP case, the function is called with this lock locked. |
| 3316 | */ |
| 3317 | LIST_FOREACH(pmap, &allpmaps, pm_list) { |
| 3318 | pte1p = pmap_pte1(pmap, va); |
| 3319 | pte1_store(pte1p, npte1); |
| 3320 | } |
| 3321 | |
| 3322 | #ifdef SMP |
| 3323 | /* Kill all the small mappings or the big one only. */ |
| 3324 | if (pte1_is_section(npte1)) |
| 3325 | tlb_flush_range(pte1_trunc(va), PTE1_SIZE); |
| 3326 | else |
| 3327 | tlb_flush(pte1_trunc(va)); |
| 3328 | #endif |
| 3329 | } |
| 3330 | |
| 3331 | #ifdef SMP |
| 3332 | struct pte1_action { |
no test coverage detected