|
@@ -192,6 +192,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|
static void flush_tlb_func_common(const struct flush_tlb_info *f,
|
|
static void flush_tlb_func_common(const struct flush_tlb_info *f,
|
|
bool local, enum tlb_flush_reason reason)
|
|
bool local, enum tlb_flush_reason reason)
|
|
{
|
|
{
|
|
|
|
+ /* This code cannot presently handle being reentered. */
|
|
|
|
+ VM_WARN_ON(!irqs_disabled());
|
|
|
|
+
|
|
if (this_cpu_read(cpu_tlbstate.state) != TLBSTATE_OK) {
|
|
if (this_cpu_read(cpu_tlbstate.state) != TLBSTATE_OK) {
|
|
leave_mm(smp_processor_id());
|
|
leave_mm(smp_processor_id());
|
|
return;
|
|
return;
|
|
@@ -297,8 +300,13 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
|
|
info.end = TLB_FLUSH_ALL;
|
|
info.end = TLB_FLUSH_ALL;
|
|
}
|
|
}
|
|
|
|
|
|
- if (mm == this_cpu_read(cpu_tlbstate.loaded_mm))
|
|
|
|
|
|
+ if (mm == this_cpu_read(cpu_tlbstate.loaded_mm)) {
|
|
|
|
+ VM_WARN_ON(irqs_disabled());
|
|
|
|
+ local_irq_disable();
|
|
flush_tlb_func_local(&info, TLB_LOCAL_MM_SHOOTDOWN);
|
|
flush_tlb_func_local(&info, TLB_LOCAL_MM_SHOOTDOWN);
|
|
|
|
+ local_irq_enable();
|
|
|
|
+ }
|
|
|
|
+
|
|
if (cpumask_any_but(mm_cpumask(mm), cpu) < nr_cpu_ids)
|
|
if (cpumask_any_but(mm_cpumask(mm), cpu) < nr_cpu_ids)
|
|
flush_tlb_others(mm_cpumask(mm), &info);
|
|
flush_tlb_others(mm_cpumask(mm), &info);
|
|
put_cpu();
|
|
put_cpu();
|
|
@@ -354,8 +362,13 @@ void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
|
|
|
|
|
|
int cpu = get_cpu();
|
|
int cpu = get_cpu();
|
|
|
|
|
|
- if (cpumask_test_cpu(cpu, &batch->cpumask))
|
|
|
|
|
|
+ if (cpumask_test_cpu(cpu, &batch->cpumask)) {
|
|
|
|
+ VM_WARN_ON(irqs_disabled());
|
|
|
|
+ local_irq_disable();
|
|
flush_tlb_func_local(&info, TLB_LOCAL_SHOOTDOWN);
|
|
flush_tlb_func_local(&info, TLB_LOCAL_SHOOTDOWN);
|
|
|
|
+ local_irq_enable();
|
|
|
|
+ }
|
|
|
|
+
|
|
if (cpumask_any_but(&batch->cpumask, cpu) < nr_cpu_ids)
|
|
if (cpumask_any_but(&batch->cpumask, cpu) < nr_cpu_ids)
|
|
flush_tlb_others(&batch->cpumask, &info);
|
|
flush_tlb_others(&batch->cpumask, &info);
|
|
cpumask_clear(&batch->cpumask);
|
|
cpumask_clear(&batch->cpumask);
|