summaryrefslogtreecommitdiffstats
path: root/sys/amd64/amd64/cpu_switch.S
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2010-07-08 03:35:00 +0000
committeralc <alc@FreeBSD.org>2010-07-08 03:35:00 +0000
commit10f83cdf0a459ed959605be219efd36ff9183a1e (patch)
tree4991a91b654ff72b58c05faf176fb4d6120c703a /sys/amd64/amd64/cpu_switch.S
parent5e2426bc109883c6a0e6cb07e0b07b4c7a78cccf (diff)
downloadFreeBSD-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.S22
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)
OpenPOWER on IntegriCloud