Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/csky/mm/tlb.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4
#include <linux/init.h>
5
#include <linux/mm.h>
6
#include <linux/module.h>
7
#include <linux/sched.h>
8
9
#include <asm/mmu_context.h>
10
#include <asm/setup.h>
11
12
/*
13
* One C-SKY MMU TLB entry contain two PFN/page entry, ie:
14
* 1VPN -> 2PFN
15
*/
16
#define TLB_ENTRY_SIZE (PAGE_SIZE * 2)
17
#define TLB_ENTRY_SIZE_MASK (PAGE_MASK << 1)
18
19
void flush_tlb_all(void)
20
{
21
tlb_invalid_all();
22
}
23
24
void flush_tlb_mm(struct mm_struct *mm)
25
{
26
#ifdef CONFIG_CPU_HAS_TLBI
27
sync_is();
28
asm volatile(
29
"tlbi.asids %0 \n"
30
"sync.i \n"
31
:
32
: "r" (cpu_asid(mm))
33
: "memory");
34
#else
35
tlb_invalid_all();
36
#endif
37
}
38
39
/*
40
* MMU operation regs only could invalid tlb entry in jtlb and we
41
* need change asid field to invalid I-utlb & D-utlb.
42
*/
43
#ifndef CONFIG_CPU_HAS_TLBI
44
#define restore_asid_inv_utlb(oldpid, newpid) \
45
do { \
46
if (oldpid == newpid) \
47
write_mmu_entryhi(oldpid + 1); \
48
write_mmu_entryhi(oldpid); \
49
} while (0)
50
#endif
51
52
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
53
unsigned long end)
54
{
55
unsigned long newpid = cpu_asid(vma->vm_mm);
56
57
start &= TLB_ENTRY_SIZE_MASK;
58
end += TLB_ENTRY_SIZE - 1;
59
end &= TLB_ENTRY_SIZE_MASK;
60
61
#ifdef CONFIG_CPU_HAS_TLBI
62
sync_is();
63
while (start < end) {
64
asm volatile(
65
"tlbi.vas %0 \n"
66
:
67
: "r" (start | newpid)
68
: "memory");
69
70
start += 2*PAGE_SIZE;
71
}
72
asm volatile("sync.i\n");
73
#else
74
{
75
unsigned long flags, oldpid;
76
77
local_irq_save(flags);
78
oldpid = read_mmu_entryhi() & ASID_MASK;
79
while (start < end) {
80
int idx;
81
82
write_mmu_entryhi(start | newpid);
83
start += 2*PAGE_SIZE;
84
tlb_probe();
85
idx = read_mmu_index();
86
if (idx >= 0)
87
tlb_invalid_indexed();
88
}
89
restore_asid_inv_utlb(oldpid, newpid);
90
local_irq_restore(flags);
91
}
92
#endif
93
}
94
95
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
96
{
97
start &= TLB_ENTRY_SIZE_MASK;
98
end += TLB_ENTRY_SIZE - 1;
99
end &= TLB_ENTRY_SIZE_MASK;
100
101
#ifdef CONFIG_CPU_HAS_TLBI
102
sync_is();
103
while (start < end) {
104
asm volatile(
105
"tlbi.vaas %0 \n"
106
:
107
: "r" (start)
108
: "memory");
109
110
start += 2*PAGE_SIZE;
111
}
112
asm volatile("sync.i\n");
113
#else
114
{
115
unsigned long flags, oldpid;
116
117
local_irq_save(flags);
118
oldpid = read_mmu_entryhi() & ASID_MASK;
119
while (start < end) {
120
int idx;
121
122
write_mmu_entryhi(start | oldpid);
123
start += 2*PAGE_SIZE;
124
tlb_probe();
125
idx = read_mmu_index();
126
if (idx >= 0)
127
tlb_invalid_indexed();
128
}
129
restore_asid_inv_utlb(oldpid, oldpid);
130
local_irq_restore(flags);
131
}
132
#endif
133
}
134
135
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
136
{
137
int newpid = cpu_asid(vma->vm_mm);
138
139
addr &= TLB_ENTRY_SIZE_MASK;
140
141
#ifdef CONFIG_CPU_HAS_TLBI
142
sync_is();
143
asm volatile(
144
"tlbi.vas %0 \n"
145
"sync.i \n"
146
:
147
: "r" (addr | newpid)
148
: "memory");
149
#else
150
{
151
int oldpid, idx;
152
unsigned long flags;
153
154
local_irq_save(flags);
155
oldpid = read_mmu_entryhi() & ASID_MASK;
156
write_mmu_entryhi(addr | newpid);
157
tlb_probe();
158
idx = read_mmu_index();
159
if (idx >= 0)
160
tlb_invalid_indexed();
161
162
restore_asid_inv_utlb(oldpid, newpid);
163
local_irq_restore(flags);
164
}
165
#endif
166
}
167
168
void flush_tlb_one(unsigned long addr)
169
{
170
addr &= TLB_ENTRY_SIZE_MASK;
171
172
#ifdef CONFIG_CPU_HAS_TLBI
173
sync_is();
174
asm volatile(
175
"tlbi.vaas %0 \n"
176
"sync.i \n"
177
:
178
: "r" (addr)
179
: "memory");
180
#else
181
{
182
int oldpid, idx;
183
unsigned long flags;
184
185
local_irq_save(flags);
186
oldpid = read_mmu_entryhi() & ASID_MASK;
187
write_mmu_entryhi(addr | oldpid);
188
tlb_probe();
189
idx = read_mmu_index();
190
if (idx >= 0)
191
tlb_invalid_indexed();
192
193
restore_asid_inv_utlb(oldpid, oldpid);
194
local_irq_restore(flags);
195
}
196
#endif
197
}
198
EXPORT_SYMBOL(flush_tlb_one);
199
200