diff options
author | peter <peter@FreeBSD.org> | 2003-06-27 21:50:52 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-06-27 21:50:52 +0000 |
commit | 88fbf8d0cfbc81ef77d00c5b31316561bfe6e2ab (patch) | |
tree | d9bd01f5e26f62bc28ed820d4bd4410f46dab13b | |
parent | 546c8585afe295c59f6ebc668aa2474f04f0e853 (diff) | |
download | FreeBSD-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.c | 1 | ||||
-rw-r--r-- | sys/i386/i386/pmap.c | 7 | ||||
-rw-r--r-- | sys/i386/i386/swtch.s | 18 | ||||
-rw-r--r-- | sys/i386/include/pcpu.h | 1 |
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; \ |