Correctly maintain the per-cpu field "curpmap" on amd64 just like we
do on i386. The consequences of not doing so on amd64 became apparent with the introduction of the COUNT_IPIS and COUNT_XINVLTLB_HITS options. Specifically, single-threaded applications were generating unnecessary IPIs to shoot-down the TLB on other processors. However, this is clearly nonsensical because a single-threaded application is only running on the current processor. The reason that this happens is that pmap_activate() is unable to properly update the old pmap's field "pm_active" without the correct "curpmap". So, in effect, stale bits in "pm_active" were leading pmap_protect(), pmap_remove(), pmap_remove_pages(), etc. to flush the TLB contents on some arbitrary processor that wasn't even running the same application. Reviewed by: kib MFC after: 3 weeks
This commit is contained in:
parent
2d7cef1612
commit
77cb6e6f8d
@ -69,16 +69,13 @@
|
||||
* %rsi = newtd
|
||||
*/
|
||||
ENTRY(cpu_throw)
|
||||
movl PCPU(CPUID),%eax
|
||||
testq %rdi,%rdi
|
||||
jnz 1f
|
||||
movq PCPU(IDLETHREAD),%rdi
|
||||
1:
|
||||
movq TD_PCB(%rdi),%r8 /* Old pcb */
|
||||
movl PCPU(CPUID), %eax
|
||||
jz 1f
|
||||
/* release bit from old pm_active */
|
||||
movq TD_PROC(%rdi), %rdx /* oldtd->td_proc */
|
||||
movq P_VMSPACE(%rdx), %rdx /* proc->p_vmspace */
|
||||
LK btrl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* clear old */
|
||||
movq PCPU(CURPMAP),%rdx
|
||||
LK btrl %eax,PM_ACTIVE(%rdx) /* clear old */
|
||||
1:
|
||||
movq TD_PCB(%rsi),%r8 /* newtd->td_proc */
|
||||
movq PCB_CR3(%r8),%rdx
|
||||
movq %rdx,%cr3 /* new address space */
|
||||
@ -140,15 +137,16 @@ swinact:
|
||||
movq %rcx,%cr3 /* new address space */
|
||||
movl PCPU(CPUID), %eax
|
||||
/* Release bit from old pmap->pm_active */
|
||||
movq TD_PROC(%rdi), %rcx /* oldproc */
|
||||
movq P_VMSPACE(%rcx), %rcx
|
||||
LK btrl %eax, VM_PMAP+PM_ACTIVE(%rcx) /* clear old */
|
||||
movq PCPU(CURPMAP),%rcx
|
||||
LK btrl %eax,PM_ACTIVE(%rcx) /* clear old */
|
||||
SETLK %rdx, TD_LOCK(%rdi) /* Release the old thread */
|
||||
swact:
|
||||
/* Set bit in new pmap->pm_active */
|
||||
movq TD_PROC(%rsi),%rdx /* newproc */
|
||||
movq P_VMSPACE(%rdx), %rdx
|
||||
LK btsl %eax, VM_PMAP+PM_ACTIVE(%rdx) /* set new */
|
||||
addq $VM_PMAP,%rdx
|
||||
LK btsl %eax,PM_ACTIVE(%rdx) /* set new */
|
||||
movq %rdx,PCPU(CURPMAP)
|
||||
|
||||
sw1:
|
||||
#if defined(SCHED_ULE) && defined(SMP)
|
||||
|
@ -1574,6 +1574,7 @@ pmap_pinit0(pmap_t pmap)
|
||||
pmap->pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys);
|
||||
pmap->pm_root = NULL;
|
||||
pmap->pm_active = 0;
|
||||
PCPU_SET(curpmap, pmap);
|
||||
TAILQ_INIT(&pmap->pm_pvchunk);
|
||||
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
|
||||
}
|
||||
@ -5008,6 +5009,7 @@ if (oldpmap) /* XXX FIXME */
|
||||
cr3 = DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4);
|
||||
td->td_pcb->pcb_cr3 = cr3;
|
||||
load_cr3(cr3);
|
||||
PCPU_SET(curpmap, pmap);
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user