FreeBSD/sys/i386/i386/pmap.c
/*
 * For SMP, these functions have to use the IPI mechanism for coherence.
 *
 * N.B.: Before calling any of the following TLB invalidation functions,
 * the calling processor must ensure that all stores updating a non-
 * kernel page table are globally performed.  Otherwise, another
 * processor could cache an old, pre-update entry without being
 * invalidated.  This can happen one of two ways: (1) The pmap becomes
 * active on another processor after its pm_active field is checked by
 * one of the following functions but before a store updating the page
 * table is globally performed. (2) The pmap becomes active on another
 * processor before its pm_active field is checked but due to
 * speculative loads one of the following functions stills reads the
 * pmap as inactive on the other processor.
 * 
 * The kernel page table is exempt because its pm_active field is
 * immutable.  The kernel page table is always active on every
 * processor.
 */
For SMP, these functions have to use the IPI mechanism for coherence.
N.B.: Before calling any of the following TLB invalidation functions,
the calling processor must ensure that all stores updating a non
kernel page table are globally performed.  Otherwise, another
processor could cache an old, pre-update entry without being
invalidated.  This can happen one of two ways: (1) The pmap becomes
active on another processor after its pm_active field is checked by
one of the following functions but before a store updating the page
table is globally performed. (2) The pmap becomes active on another
processor before its pm_active field is checked but due to
speculative loads one of the following functions stills reads the
pmap as inactive on the other processor.

The kernel page table is exempt because its pm_active field is
immutable.  The kernel page table is always active on every
processor.
For SMP these functions have to use the IPI mechanism for coherence . N . B . : Before calling any of the following TLB invalidation functions the calling processor must ensure that all stores updating a non kernel page table are globally performed . Otherwise another processor could cache an old pre - update entry without being invalidated . This can happen one of two ways : ( 1 ) The pmap becomes active on another processor after its pm_active field is checked by one of the following functions but before a store updating the page table is globally performed . ( 2 ) The pmap becomes active on another processor before its pm_active field is checked but due to speculative loads one of the following functions stills reads the pmap as inactive on the other processor . The kernel page table is exempt because its pm_active field is immutable . The kernel page table is always active on every processor .
void
pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
{
	cpuset_t *mask, other_cpus;
	u_int cpuid;
	sched_pin();
	if (pmap == kernel_pmap || !CPU_CMP(&pmap->pm_active, &all_cpus)) {
		invlpg(va);
		mask = &all_cpus;
	} else {
		cpuid = PCPU_GET(cpuid);
		other_cpus = all_cpus;
		CPU_CLR(cpuid, &other_cpus);
		if (CPU_ISSET(cpuid, &pmap->pm_active))
			invlpg(va);
		CPU_AND(&other_cpus, &pmap->pm_active);
		mask = &other_cpus;
	}
	smp_masked_invlpg(*mask, va);
	sched_unpin();
}
void pmap_invalidate_page ( pmap_t pmap , vm_offset_t va ) { cpuset_t * mask , other_cpus ; u_int cpuid ; sched_pin ( ) ; if ( pmap == kernel_pmap || ! CPU_CMP ( & pmap -> pm_active , & all_cpus ) ) { invlpg ( va ) ; mask = & all_cpus ; } else { cpuid = PCPU_GET ( cpuid ) ; other_cpus = all_cpus ; CPU_CLR ( cpuid , & other_cpus ) ; if ( CPU_ISSET ( cpuid , & pmap -> pm_active ) ) invlpg ( va ) ; CPU_AND ( & other_cpus , & pmap -> pm_active ) ; mask = & other_cpus ; } smp_masked_invlpg ( * mask , va ) ; sched_unpin ( ) ; }
For SMP, these functions have to use the IPI mechanism for coherence.
For SMP these functions have to use the IPI mechanism for coherence .