18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _PARISC_TLBFLUSH_H
38c2ecf20Sopenharmony_ci#define _PARISC_TLBFLUSH_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/* TLB flushing routines.... */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/mm.h>
88c2ecf20Sopenharmony_ci#include <linux/sched.h>
98c2ecf20Sopenharmony_ci#include <asm/mmu_context.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciextern void flush_tlb_all(void);
128c2ecf20Sopenharmony_ciextern void flush_tlb_all_local(void *);
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define smp_flush_tlb_all()	flush_tlb_all()
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciint __flush_tlb_range(unsigned long sid,
178c2ecf20Sopenharmony_ci	unsigned long start, unsigned long end);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define flush_tlb_range(vma, start, end) \
208c2ecf20Sopenharmony_ci	__flush_tlb_range((vma)->vm_mm->context, start, end)
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define flush_tlb_kernel_range(start, end) \
238c2ecf20Sopenharmony_ci	__flush_tlb_range(0, start, end)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * flush_tlb_mm()
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * The code to switch to a new context is NOT valid for processes
298c2ecf20Sopenharmony_ci * which play with the space id's.  Thus, we have to preserve the
308c2ecf20Sopenharmony_ci * space and just flush the entire tlb.  However, the compilers,
318c2ecf20Sopenharmony_ci * dynamic linker, etc, do not manipulate space id's, so there
328c2ecf20Sopenharmony_ci * could be a significant performance benefit in switching contexts
338c2ecf20Sopenharmony_ci * and not flushing the whole tlb.
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic inline void flush_tlb_mm(struct mm_struct *mm)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	BUG_ON(mm == &init_mm); /* Should never happen */
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#if 1 || defined(CONFIG_SMP)
418c2ecf20Sopenharmony_ci	/* Except for very small threads, flushing the whole TLB is
428c2ecf20Sopenharmony_ci	 * faster than using __flush_tlb_range.  The pdtlb and pitlb
438c2ecf20Sopenharmony_ci	 * instructions are very slow because of the TLB broadcast.
448c2ecf20Sopenharmony_ci	 * It might be faster to do local range flushes on all CPUs
458c2ecf20Sopenharmony_ci	 * on PA 2.0 systems.
468c2ecf20Sopenharmony_ci	 */
478c2ecf20Sopenharmony_ci	flush_tlb_all();
488c2ecf20Sopenharmony_ci#else
498c2ecf20Sopenharmony_ci	/* FIXME: currently broken, causing space id and protection ids
508c2ecf20Sopenharmony_ci	 * to go out of sync, resulting in faults on userspace accesses.
518c2ecf20Sopenharmony_ci	 * This approach needs further investigation since running many
528c2ecf20Sopenharmony_ci	 * small applications (e.g., GCC testsuite) is faster on HP-UX.
538c2ecf20Sopenharmony_ci	 */
548c2ecf20Sopenharmony_ci	if (mm) {
558c2ecf20Sopenharmony_ci		if (mm->context != 0)
568c2ecf20Sopenharmony_ci			free_sid(mm->context);
578c2ecf20Sopenharmony_ci		mm->context = alloc_sid();
588c2ecf20Sopenharmony_ci		if (mm == current->active_mm)
598c2ecf20Sopenharmony_ci			load_context(mm->context);
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic inline void flush_tlb_page(struct vm_area_struct *vma,
658c2ecf20Sopenharmony_ci	unsigned long addr)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	purge_tlb_entries(vma->vm_mm, addr);
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci#endif
70