blob: f33fdd2558e8ef74a56b2693e454e976f7c8cdbc [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Paul Mundt3eeffb32007-11-19 18:57:03 +09002 * arch/sh/mm/tlb-flush_64.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 2000, 2001 Paolo Alberelli
5 * Copyright (C) 2003 Richard Curnow (/proc/tlb, bug fixes)
Paul Mundta1e20302012-04-11 12:44:50 +09006 * Copyright (C) 2003 - 2012 Paul Mundt
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
Paul Mundt3eeffb32007-11-19 18:57:03 +09008 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/signal.h>
13#include <linux/rwsem.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/string.h>
18#include <linux/types.h>
19#include <linux/ptrace.h>
20#include <linux/mman.h>
21#include <linux/mm.h>
22#include <linux/smp.h>
Ingo Molnarcdd6c482009-09-21 12:02:48 +020023#include <linux/perf_event.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <asm/io.h>
26#include <asm/tlb.h>
27#include <asm/uaccess.h>
28#include <asm/pgalloc.h>
29#include <asm/mmu_context.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Paul Mundt3eeffb32007-11-19 18:57:03 +090031void local_flush_tlb_one(unsigned long asid, unsigned long page)
Linus Torvalds1da177e2005-04-16 15:20:36 -070032{
33 unsigned long long match, pteh=0, lpage;
34 unsigned long tlb;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36 /*
37 * Sign-extend based on neff.
38 */
Paul Mundtc7914832009-08-04 17:14:39 +090039 lpage = neff_sign_extend(page);
Paul Mundt3eeffb32007-11-19 18:57:03 +090040 match = (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 match |= lpage;
42
Paul Mundt3eeffb32007-11-19 18:57:03 +090043 for_each_itlb_entry(tlb) {
44 asm volatile ("getcfg %1, 0, %0"
45 : "=r" (pteh)
46 : "r" (tlb) );
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Paul Mundt3eeffb32007-11-19 18:57:03 +090048 if (pteh == match) {
49 __flush_tlb_slot(tlb);
50 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 }
52 }
53
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 for_each_dtlb_entry(tlb) {
55 asm volatile ("getcfg %1, 0, %0"
56 : "=r" (pteh)
57 : "r" (tlb) );
58
59 if (pteh == match) {
60 __flush_tlb_slot(tlb);
61 break;
62 }
63
64 }
65}
66
Paul Mundt3eeffb32007-11-19 18:57:03 +090067void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068{
69 unsigned long flags;
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 if (vma->vm_mm) {
72 page &= PAGE_MASK;
73 local_irq_save(flags);
Paul Mundt3eeffb32007-11-19 18:57:03 +090074 local_flush_tlb_one(get_asid(), page);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 local_irq_restore(flags);
76 }
77}
78
Paul Mundt3eeffb32007-11-19 18:57:03 +090079void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
80 unsigned long end)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
82 unsigned long flags;
83 unsigned long long match, pteh=0, pteh_epn, pteh_low;
84 unsigned long tlb;
Paul Mundt3eeffb32007-11-19 18:57:03 +090085 unsigned int cpu = smp_processor_id();
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 struct mm_struct *mm;
87
88 mm = vma->vm_mm;
Paul Mundt3eeffb32007-11-19 18:57:03 +090089 if (cpu_context(cpu, mm) == NO_CONTEXT)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 return;
91
92 local_irq_save(flags);
93
94 start &= PAGE_MASK;
95 end &= PAGE_MASK;
96
Paul Mundt3eeffb32007-11-19 18:57:03 +090097 match = (cpu_asid(cpu, mm) << PTEH_ASID_SHIFT) | PTEH_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
99 /* Flush ITLB */
100 for_each_itlb_entry(tlb) {
101 asm volatile ("getcfg %1, 0, %0"
102 : "=r" (pteh)
103 : "r" (tlb) );
104
105 pteh_epn = pteh & PAGE_MASK;
106 pteh_low = pteh & ~PAGE_MASK;
107
108 if (pteh_low == match && pteh_epn >= start && pteh_epn <= end)
109 __flush_tlb_slot(tlb);
110 }
111
112 /* Flush DTLB */
113 for_each_dtlb_entry(tlb) {
114 asm volatile ("getcfg %1, 0, %0"
115 : "=r" (pteh)
116 : "r" (tlb) );
117
118 pteh_epn = pteh & PAGE_MASK;
119 pteh_low = pteh & ~PAGE_MASK;
120
121 if (pteh_low == match && pteh_epn >= start && pteh_epn <= end)
122 __flush_tlb_slot(tlb);
123 }
124
125 local_irq_restore(flags);
126}
127
Paul Mundt3eeffb32007-11-19 18:57:03 +0900128void local_flush_tlb_mm(struct mm_struct *mm)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
130 unsigned long flags;
Paul Mundt3eeffb32007-11-19 18:57:03 +0900131 unsigned int cpu = smp_processor_id();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Paul Mundt3eeffb32007-11-19 18:57:03 +0900133 if (cpu_context(cpu, mm) == NO_CONTEXT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 return;
135
136 local_irq_save(flags);
137
Paul Mundt3eeffb32007-11-19 18:57:03 +0900138 cpu_context(cpu, mm) = NO_CONTEXT;
139 if (mm == current->mm)
140 activate_context(mm, cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
142 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143}
144
Paul Mundt3eeffb32007-11-19 18:57:03 +0900145void local_flush_tlb_all(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
147 /* Invalidate all, including shared pages, excluding fixed TLBs */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 unsigned long flags, tlb;
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 local_irq_save(flags);
151
152 /* Flush each ITLB entry */
Paul Mundt3eeffb32007-11-19 18:57:03 +0900153 for_each_itlb_entry(tlb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 __flush_tlb_slot(tlb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156 /* Flush each DTLB entry */
Paul Mundt3eeffb32007-11-19 18:57:03 +0900157 for_each_dtlb_entry(tlb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 __flush_tlb_slot(tlb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 local_irq_restore(flags);
161}
162
Paul Mundt3eeffb32007-11-19 18:57:03 +0900163void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164{
165 /* FIXME: Optimize this later.. */
166 flush_tlb_all();
167}
Paul Mundt9cef7492009-07-29 00:12:17 +0900168
Paul Mundt59615ec2010-07-02 15:44:09 +0900169void __flush_tlb_global(void)
170{
171 flush_tlb_all();
172}