FreeBSD/sys/arm/arm/pmap-v6.c
/*
 *  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 speculative hardware table walk.
 *
 *  The break-before-make approach should be implemented here. However, it's
 *  not so easy to do that for kernel mappings as it would be unhappy to unmap
 *  itself unexpectedly but voluntarily.
 */
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 speculative hardware table walk.

The break-before-make approach should be implemented here. However, it's
not so easy to do that for kernel mappings as it would be unhappy to unmap
itself unexpectedly but voluntarily.
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 speculative hardware table walk . The break - before - make approach should be implemented here . However it ' s not so easy to do that for kernel mappings as it would be unhappy to unmap itself unexpectedly but voluntarily .
static void
pmap_update_pte1_kernel(vm_offset_t va, pt1_entry_t npte1)
{
	pmap_t pmap;
	pt1_entry_t *pte1p;
	pmap = PCPU_GET(curpmap);
	if (pmap == NULL)
		pmap = kernel_pmap;
	pte1p = pmap_pte1(pmap, va);
	pte1_store(pte1p, npte1);
	if (pte1_is_section(npte1)) {
		pmap_pte1_kern_promotions++;
		tlb_flush_range_local(pte1_trunc(va), PTE1_SIZE);
	} else {
		pmap_pte1_kern_demotions++;
		tlb_flush_local(pte1_trunc(va));
	}
	LIST_FOREACH(pmap, &allpmaps, pm_list) {
		pte1p = pmap_pte1(pmap, va);
		pte1_store(pte1p, npte1);
	}
#ifdef SMP
	if (pte1_is_section(npte1))
		tlb_flush_range(pte1_trunc(va), PTE1_SIZE);
	else
		tlb_flush(pte1_trunc(va));
#endif
}
static void pmap_update_pte1_kernel ( vm_offset_t va , pt1_entry_t npte1 ) { pmap_t pmap ; pt1_entry_t * pte1p ; pmap = PCPU_GET ( curpmap ) ; if ( pmap == NULL ) pmap = kernel_pmap ; pte1p = pmap_pte1 ( pmap , va ) ; pte1_store ( pte1p , npte1 ) ; if ( pte1_is_section ( npte1 ) ) { pmap_pte1_kern_promotions ++ ; tlb_flush_range_local ( pte1_trunc ( va ) , PTE1_SIZE ) ; } else { pmap_pte1_kern_demotions ++ ; tlb_flush_local ( pte1_trunc ( va ) ) ; } LIST_FOREACH ( pmap , & allpmaps , pm_list ) { pte1p = pmap_pte1 ( pmap , va ) ; pte1_store ( pte1p , npte1 ) ; } #ifdef SMP if ( pte1_is_section ( npte1 ) ) tlb_flush_range ( pte1_trunc ( va ) , PTE1_SIZE ) ; else tlb_flush ( pte1_trunc ( va ) ) ; #endif }
Update kernel pte1 on all pmaps.
Update kernel pte1 on all pmaps .
/*
	 * Get current pmap. Interrupts should be disabled here
	 * so PCPU_GET() is done atomically.
	 */ /*
	 * (1) Change pte1 on current pmap.
	 * (2) Flush all obsolete TLB entries on current CPU.
	 * (3) Change pte1 on all pmaps.
	 * (4) Flush all obsolete TLB entries on all CPUs in SMP case.
	 */ /* Kill all the small mappings or the big one only. */ /*
	 * In SMP case, this function is called when all cpus are at smp
	 * rendezvous, so there is no need to use 'allpmaps_lock' lock here.
	 * In UP case, the function is called with this lock locked.
	 */ /* Kill all the small mappings or the big one only. */