summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-06-27 21:50:52 +0000
committerpeter <peter@FreeBSD.org>2003-06-27 21:50:52 +0000
commit88fbf8d0cfbc81ef77d00c5b31316561bfe6e2ab (patch)
treed9bd01f5e26f62bc28ed820d4bd4410f46dab13b
parent546c8585afe295c59f6ebc668aa2474f04f0e853 (diff)
downloadFreeBSD-src-88fbf8d0cfbc81ef77d00c5b31316561bfe6e2ab.zip
FreeBSD-src-88fbf8d0cfbc81ef77d00c5b31316561bfe6e2ab.tar.gz
Fix the false IPIs on smp when using LAZY_SWITCH caused by pmap_activate()
not releasing the pm_active bit in the old pmap.
-rw-r--r--sys/i386/i386/genassym.c1
-rw-r--r--sys/i386/i386/pmap.c7
-rw-r--r--sys/i386/i386/swtch.s18
-rw-r--r--sys/i386/include/pcpu.h1
4 files changed, 18 insertions, 9 deletions
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 675f80a..54e2ec2 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -201,6 +201,7 @@ ASSYM(PC_COMMON_TSSD, offsetof(struct pcpu, pc_common_tssd));
ASSYM(PC_TSS_GDT, offsetof(struct pcpu, pc_tss_gdt));
ASSYM(PC_CURRENTLDT, offsetof(struct pcpu, pc_currentldt));
ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid));
+ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
#ifdef SMP
ASSYM(LA_VER, offsetof(struct LAPIC, version));
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index a2401c1..1e45a97 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -1073,6 +1073,7 @@ pmap_pinit0(pmap)
pmap->pm_pdpt = (pdpt_entry_t *)(KERNBASE + (vm_offset_t)IdlePDPT);
#endif
pmap->pm_active = 0;
+ PCPU_SET(curpmap, pmap);
TAILQ_INIT(&pmap->pm_pvlist);
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
mtx_lock_spin(&allpmaps_lock);
@@ -3240,14 +3241,17 @@ void
pmap_activate(struct thread *td)
{
struct proc *p = td->td_proc;
- pmap_t pmap;
+ pmap_t pmap, oldpmap;
u_int32_t cr3;
critical_enter();
pmap = vmspace_pmap(td->td_proc->p_vmspace);
+ oldpmap = PCPU_GET(curpmap);
#if defined(SMP)
+ atomic_clear_int(&oldpmap->pm_active, PCPU_GET(cpumask));
atomic_set_int(&pmap->pm_active, PCPU_GET(cpumask));
#else
+ oldpmap->pm_active &= ~1;
pmap->pm_active |= 1;
#endif
#ifdef PAE
@@ -3271,6 +3275,7 @@ pmap_activate(struct thread *td)
#ifdef SWTCH_OPTIM_STATS
tlb_flush_count++;
#endif
+ PCPU_SET(curpmap, pmap);
critical_exit();
}
diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s
index a19baa7..810d82e 100644
--- a/sys/i386/i386/swtch.s
+++ b/sys/i386/i386/swtch.s
@@ -67,12 +67,11 @@ ENTRY(cpu_throw)
testl %ecx,%ecx /* no thread? */
jz 1f
/* release bit from old pm_active */
- movl TD_PROC(%ecx), %eax /* thread->td_proc */
- movl P_VMSPACE(%eax), %ebx /* proc->p_vmspace */
+ movl PCPU(CURPMAP), %ebx
#ifdef SMP
lock
#endif
- btrl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* clear old */
+ btrl %esi, PM_ACTIVE(%ebx) /* clear old */
1:
movl 8(%esp),%ecx /* New thread */
movl TD_PCB(%ecx),%edx
@@ -84,10 +83,12 @@ ENTRY(cpu_throw)
/* set bit in new pm_active */
movl TD_PROC(%ecx),%eax
movl P_VMSPACE(%eax), %ebx
+ addl $VM_PMAP, %ebx
+ movl %ebx, PCPU(CURPMAP)
#ifdef SMP
lock
#endif
- btsl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* set new */
+ btsl %esi, PM_ACTIVE(%ebx) /* set new */
jmp sw1
/*
@@ -188,20 +189,21 @@ ENTRY(cpu_switch)
movl %eax,%cr3 /* new address space */
/* Release bit from old pmap->pm_active */
- movl TD_PROC(%edi), %eax /* oldproc */
- movl P_VMSPACE(%eax), %ebx
+ movl PCPU(CURPMAP), %ebx
#ifdef SMP
lock
#endif
- btrl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* clear old */
+ btrl %esi, PM_ACTIVE(%ebx) /* clear old */
/* Set bit in new pmap->pm_active */
movl TD_PROC(%ecx),%eax /* newproc */
movl P_VMSPACE(%eax), %ebx
+ addl $VM_PMAP, %ebx
+ movl %ebx, PCPU(CURPMAP)
#ifdef SMP
lock
#endif
- btsl %esi, VM_PMAP+PM_ACTIVE(%ebx) /* set new */
+ btsl %esi, PM_ACTIVE(%ebx) /* set new */
#ifdef LAZY_SWITCH
#ifdef SWTCH_OPTIM_STATS
diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
index a680645..799eefb 100644
--- a/sys/i386/include/pcpu.h
+++ b/sys/i386/include/pcpu.h
@@ -43,6 +43,7 @@
*/
#define PCPU_MD_FIELDS \
struct pcpu *pc_prvspace; /* Self-reference */ \
+ struct pmap *pc_curpmap; \
struct i386tss pc_common_tss; \
struct segment_descriptor pc_common_tssd; \
struct segment_descriptor *pc_tss_gdt; \
OpenPOWER on IntegriCloud