blob: 14668bd52d6065e41d4b8b446ba984453af9a201 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002#ifndef _PARISC_TLBFLUSH_H
3#define _PARISC_TLBFLUSH_H
4
5/* TLB flushing routines.... */
6
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include <linux/mm.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +04008#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <asm/mmu_context.h>
10
Grant Grundler04d472d2005-10-21 22:40:24 -040011
12/* This is for the serialisation of PxTLB broadcasts. At least on the
13 * N class systems, only one PxTLB inter processor broadcast can be
14 * active at any one time on the Merced bus. This tlb purge
15 * synchronisation is fairly lightweight and harmless so we activate
Helge Dellere82a3b72009-06-16 20:51:48 +000016 * it on all systems not just the N class.
John David Anglin01ab6052015-07-01 17:18:37 -040017
18 * It is also used to ensure PTE updates are atomic and consistent
19 * with the TLB.
Matthew Wilcox29a622d2005-11-17 16:44:14 -050020 */
Grant Grundler04d472d2005-10-21 22:40:24 -040021extern spinlock_t pa_tlb_lock;
22
Helge Dellere82a3b72009-06-16 20:51:48 +000023#define purge_tlb_start(flags) spin_lock_irqsave(&pa_tlb_lock, flags)
24#define purge_tlb_end(flags) spin_unlock_irqrestore(&pa_tlb_lock, flags)
Grant Grundler04d472d2005-10-21 22:40:24 -040025
Linus Torvalds1da177e2005-04-16 15:20:36 -070026extern void flush_tlb_all(void);
Matthew Wilcox1b2425e2006-01-10 20:47:49 -050027extern void flush_tlb_all_local(void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Helge Deller0fc537d2013-05-07 21:42:47 +000029#define smp_flush_tlb_all() flush_tlb_all()
30
John David Anglin01ab6052015-07-01 17:18:37 -040031int __flush_tlb_range(unsigned long sid,
32 unsigned long start, unsigned long end);
33
34#define flush_tlb_range(vma, start, end) \
35 __flush_tlb_range((vma)->vm_mm->context, start, end)
36
37#define flush_tlb_kernel_range(start, end) \
38 __flush_tlb_range(0, start, end)
39
Linus Torvalds1da177e2005-04-16 15:20:36 -070040/*
41 * flush_tlb_mm()
42 *
John David Anglin01ab6052015-07-01 17:18:37 -040043 * The code to switch to a new context is NOT valid for processes
44 * which play with the space id's. Thus, we have to preserve the
45 * space and just flush the entire tlb. However, the compilers,
46 * dynamic linker, etc, do not manipulate space id's, so there
47 * could be a significant performance benefit in switching contexts
48 * and not flushing the whole tlb.
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 */
50
51static inline void flush_tlb_mm(struct mm_struct *mm)
52{
Kyle McMartin04532c42007-02-18 19:35:45 +000053 BUG_ON(mm == &init_mm); /* Should never happen */
54
Kyle McMartin5289f462008-12-23 08:44:30 -050055#if 1 || defined(CONFIG_SMP)
John David Anglin01ab6052015-07-01 17:18:37 -040056 /* Except for very small threads, flushing the whole TLB is
57 * faster than using __flush_tlb_range. The pdtlb and pitlb
58 * instructions are very slow because of the TLB broadcast.
59 * It might be faster to do local range flushes on all CPUs
60 * on PA 2.0 systems.
61 */
Kyle McMartin04532c42007-02-18 19:35:45 +000062 flush_tlb_all();
63#else
Kyle McMartin5289f462008-12-23 08:44:30 -050064 /* FIXME: currently broken, causing space id and protection ids
John David Anglin01ab6052015-07-01 17:18:37 -040065 * to go out of sync, resulting in faults on userspace accesses.
66 * This approach needs further investigation since running many
67 * small applications (e.g., GCC testsuite) is faster on HP-UX.
Kyle McMartin5289f462008-12-23 08:44:30 -050068 */
Kyle McMartin04532c42007-02-18 19:35:45 +000069 if (mm) {
70 if (mm->context != 0)
71 free_sid(mm->context);
72 mm->context = alloc_sid();
73 if (mm == current->active_mm)
74 load_context(mm->context);
75 }
76#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070077}
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079static inline void flush_tlb_page(struct vm_area_struct *vma,
80 unsigned long addr)
81{
John David Angline8d8fc22013-06-29 16:42:12 -040082 unsigned long flags, sid;
Helge Dellere82a3b72009-06-16 20:51:48 +000083
John David Angline8d8fc22013-06-29 16:42:12 -040084 sid = vma->vm_mm->context;
Helge Dellere82a3b72009-06-16 20:51:48 +000085 purge_tlb_start(flags);
John David Angline8d8fc22013-06-29 16:42:12 -040086 mtsp(sid, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 pdtlb(addr);
John David Anglin01ab6052015-07-01 17:18:37 -040088 if (unlikely(split_tlb))
89 pitlb(addr);
Helge Dellere82a3b72009-06-16 20:51:48 +000090 purge_tlb_end(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091}
Linus Torvalds1da177e2005-04-16 15:20:36 -070092#endif