tlb flush: further bugs? (2.3.12-9)
PATCH 1/1 tlb flush: further bugs? (2.3.12-9)
I think I found 2 minor bugs in the current tlb flush code:
- during crossing TLB flushes, mm->cpu_mask is not set.
- flush_tlb_current_task() contains a race between flush_tlb_other_cpus(the IPI could set mm->cpu_mask) & the next line.
effectively, my patch means that flush_tlb_current_task() is identical to flush_tlb_mm(current->mm), perhaps this should be replaced with a #define.
I've attached a patch (untested) against 2.3.12-9,
Manfred
SMP.C renamed from smp.c.old +8 -4
@@ -1617,6 +1617,8 @@ if (test_bit(cpu, &smp_invalidate_needed)) { clear_bit(cpu, &smp_invalidate_needed); local_flush_tlb(); + if(current->mm) + atomic_set_mask(1 << cpu, ¤t->mm->cpu_vm_mask); } --stuck; if (!stuck) {
@@ -1637,14 +1639,16 @@ */ void flush_tlb_current_task(void) { - unsigned long vm_mask = 1 << current->processor; struct mm_struct *mm = current->mm; + unsigned long vm_mask = 1 << current->processor; + unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask; - if (mm->cpu_vm_mask != vm_mask) { - flush_tlb_others(mm->cpu_vm_mask & ~vm_mask); + mm->cpu_vm_mask = 0; + if (current->active_mm == mm) { mm->cpu_vm_mask = vm_mask; + local_flush_tlb(); } - local_flush_tlb(); + flush_tlb_others(cpu_mask); } void flush_tlb_mm(struct mm_struct * mm)