Fix the false IPIs on smp when using LAZY_SWITCH caused by pmap_activate()
not releasing the pm_active bit in the old pmap.
This commit is contained in:
parent
546c8585af
commit
88fbf8d0cf
@ -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));
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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; \
|
||||
|
Loading…
x
Reference in New Issue
Block a user