| 623 | |
| 624 | #ifdef SMP |
| 625 | static __inline void |
| 626 | pmap_call_on_active_cpus(pmap_t pmap, void (*fn)(void *), void *arg) |
| 627 | { |
| 628 | int cpuid, cpu, self; |
| 629 | cpuset_t active_cpus; |
| 630 | |
| 631 | sched_pin(); |
| 632 | if (is_kernel_pmap(pmap)) { |
| 633 | smp_rendezvous(NULL, fn, NULL, arg); |
| 634 | goto out; |
| 635 | } |
| 636 | /* Force ASID update on inactive CPUs */ |
| 637 | CPU_FOREACH(cpu) { |
| 638 | if (!CPU_ISSET(cpu, &pmap->pm_active)) |
| 639 | pmap->pm_asid[cpu].gen = 0; |
| 640 | } |
| 641 | cpuid = PCPU_GET(cpuid); |
| 642 | /* |
| 643 | * XXX: barrier/locking for active? |
| 644 | * |
| 645 | * Take a snapshot of active here, any further changes are ignored. |
| 646 | * tlb update/invalidate should be harmless on inactive CPUs |
| 647 | */ |
| 648 | active_cpus = pmap->pm_active; |
| 649 | self = CPU_ISSET(cpuid, &active_cpus); |
| 650 | CPU_CLR(cpuid, &active_cpus); |
| 651 | /* Optimize for the case where this cpu is the only active one */ |
| 652 | if (CPU_EMPTY(&active_cpus)) { |
| 653 | if (self) |
| 654 | fn(arg); |
| 655 | } else { |
| 656 | if (self) |
| 657 | CPU_SET(cpuid, &active_cpus); |
| 658 | smp_rendezvous_cpus(active_cpus, NULL, fn, NULL, arg); |
| 659 | } |
| 660 | out: |
| 661 | sched_unpin(); |
| 662 | } |
| 663 | #else /* !SMP */ |
| 664 | static __inline void |
| 665 | pmap_call_on_active_cpus(pmap_t pmap, void (*fn)(void *), void *arg) |
no test coverage detected