diff options
author | alc <alc@FreeBSD.org> | 2010-07-08 03:35:00 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2010-07-08 03:35:00 +0000 |
commit | 10f83cdf0a459ed959605be219efd36ff9183a1e (patch) | |
tree | 4991a91b654ff72b58c05faf176fb4d6120c703a /sys/amd64/amd64/cpu_switch.S | |
parent | 5e2426bc109883c6a0e6cb07e0b07b4c7a78cccf (diff) | |
download | FreeBSD-src-10f83cdf0a459ed959605be219efd36ff9183a1e.zip FreeBSD-src-10f83cdf0a459ed959605be219efd36ff9183a1e.tar.gz |
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
Diffstat (limited to 'sys/amd64/amd64/cpu_switch.S')
-rw-r--r-- | sys/amd64/amd64/cpu_switch.S | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index c71bcd0..cfb4204 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -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) |