/* * Flush kernel TLB entries in the given range */ void flush_tlb_kernel_range(unsigned long start, unsigned long end) { #ifdef CONFIG_SMP preempt_disable(); smp_call_function(do_flush_tlb_mm_ipi, NULL, 1); _tlbil_pid(0); preempt_enable(); #endif _tlbil_pid(0); }
/* * These are the base non-SMP variants of page and mm flushing */ void local_flush_tlb_mm(struct mm_struct *mm) { unsigned int pid; preempt_disable(); pid = mm->context.id; if (pid != MMU_NO_CONTEXT) _tlbil_pid(pid); preempt_enable(); }
void flush_tlb_mm(struct mm_struct *mm) { unsigned int pid; preempt_disable(); pid = mm->context.id; if (unlikely(pid == MMU_NO_CONTEXT)) goto no_context; if (!cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { struct tlb_flush_param p = { .pid = pid }; /* Ignores smp_processor_id() even if set. */ smp_call_function_many(mm_cpumask(mm), do_flush_tlb_mm_ipi, &p, 1); } _tlbil_pid(pid); no_context: preempt_enable(); }
void flush_tlb_mm(struct mm_struct *mm) { cpumask_t cpu_mask; unsigned int pid; preempt_disable(); pid = mm->context.id; if (unlikely(pid == MMU_NO_CONTEXT)) goto no_context; cpu_mask = mm->cpu_vm_mask; cpu_clear(smp_processor_id(), cpu_mask); if (!cpus_empty(cpu_mask)) { struct tlb_flush_param p = { .pid = pid }; smp_call_function_mask(cpu_mask, do_flush_tlb_mm_ipi, &p, 1); } _tlbil_pid(pid); no_context: preempt_enable(); }
static void do_flush_tlb_mm_ipi(void *param) { struct tlb_flush_param *p = param; _tlbil_pid(p ? p->pid : 0); }