]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 LT |
2 | /* |
3 | * linux/arch/m32r/mm/mmu.S | |
4 | * | |
5 | * Copyright (C) 2001 by Hiroyuki Kondo | |
6 | */ | |
7 | ||
1da177e4 LT |
8 | #include <linux/linkage.h> |
9 | #include <asm/assembler.h> | |
10 | #include <asm/smp.h> | |
11 | ||
12 | .text | |
13 | #ifdef CONFIG_MMU | |
14 | ||
15 | #include <asm/mmu_context.h> | |
16 | #include <asm/page.h> | |
17 | #include <asm/pgtable.h> | |
18 | #include <asm/m32r.h> | |
19 | ||
20 | /* | |
21 | * TLB Miss Exception handler | |
22 | */ | |
23 | .balign 16 | |
24 | ENTRY(tme_handler) | |
25 | .global tlb_entry_i_dat | |
26 | .global tlb_entry_d_dat | |
27 | ||
28 | SWITCH_TO_KERNEL_STACK | |
29 | ||
30 | #if defined(CONFIG_ISA_M32R2) | |
31 | st r0, @-sp | |
32 | st r1, @-sp | |
33 | st r2, @-sp | |
34 | st r3, @-sp | |
35 | ||
36 | seth r3, #high(MMU_REG_BASE) | |
37 | ld r1, @(MESTS_offset, r3) ; r1: status (MESTS reg.) | |
38 | ld r0, @(MDEVP_offset, r3) ; r0: PFN + ASID (MDEVP reg.) | |
39 | st r1, @(MESTS_offset, r3) ; clear status (MESTS reg.) | |
40 | and3 r1, r1, #(MESTS_IT) | |
41 | bnez r1, 1f ; instruction TLB miss? | |
42 | ||
43 | ;; data TLB miss | |
44 | ;; input | |
45 | ;; r0: PFN + ASID (MDEVP reg.) | |
46 | ;; r1 - r3: free | |
47 | ;; output | |
48 | ;; r0: PFN + ASID | |
49 | ;; r1: TLB entry base address | |
50 | ;; r2: &tlb_entry_{i|d}_dat | |
51 | ;; r3: free | |
52 | ||
53 | #ifndef CONFIG_SMP | |
54 | seth r2, #high(tlb_entry_d_dat) | |
55 | or3 r2, r2, #low(tlb_entry_d_dat) | |
56 | #else /* CONFIG_SMP */ | |
57 | ldi r1, #-8192 | |
58 | seth r2, #high(tlb_entry_d_dat) | |
59 | or3 r2, r2, #low(tlb_entry_d_dat) | |
60 | and r1, sp | |
61 | ld r1, @(16, r1) ; current_thread_info->cpu | |
62 | slli r1, #2 | |
63 | add r2, r1 | |
64 | #endif /* !CONFIG_SMP */ | |
65 | seth r1, #high(DTLB_BASE) | |
66 | or3 r1, r1, #low(DTLB_BASE) | |
67 | bra 2f | |
68 | ||
69 | .balign 16 | |
70 | .fillinsn | |
71 | 1: | |
72 | ;; instrucntion TLB miss | |
73 | ;; input | |
74 | ;; r0: MDEVP reg. (included ASID) | |
75 | ;; r1 - r3: free | |
76 | ;; output | |
77 | ;; r0: PFN + ASID | |
78 | ;; r1: TLB entry base address | |
79 | ;; r2: &tlb_entry_{i|d}_dat | |
80 | ;; r3: free | |
81 | ldi r3, #-4096 | |
82 | and3 r0, r0, #(MMU_CONTEXT_ASID_MASK) | |
83 | mvfc r1, bpc | |
84 | and r1, r3 | |
85 | or r0, r1 ; r0: PFN + ASID | |
86 | #ifndef CONFIG_SMP | |
87 | seth r2, #high(tlb_entry_i_dat) | |
88 | or3 r2, r2, #low(tlb_entry_i_dat) | |
89 | #else /* CONFIG_SMP */ | |
90 | ldi r1, #-8192 | |
91 | seth r2, #high(tlb_entry_i_dat) | |
92 | or3 r2, r2, #low(tlb_entry_i_dat) | |
93 | and r1, sp | |
94 | ld r1, @(16, r1) ; current_thread_info->cpu | |
95 | slli r1, #2 | |
96 | add r2, r1 | |
97 | #endif /* !CONFIG_SMP */ | |
98 | seth r1, #high(ITLB_BASE) | |
99 | or3 r1, r1, #low(ITLB_BASE) | |
100 | ||
101 | .fillinsn | |
102 | 2: | |
103 | ;; select TLB entry | |
104 | ;; input | |
105 | ;; r0: PFN + ASID | |
106 | ;; r1: TLB entry base address | |
107 | ;; r2: &tlb_entry_{i|d}_dat | |
108 | ;; r3: free | |
109 | ;; output | |
110 | ;; r0: PFN + ASID | |
111 | ;; r1: TLB entry address | |
112 | ;; r2, r3: free | |
113 | #ifdef CONFIG_ISA_DUAL_ISSUE | |
114 | ld r3, @r2 || srli r1, #3 | |
115 | #else | |
116 | ld r3, @r2 | |
117 | srli r1, #3 | |
118 | #endif | |
119 | add r1, r3 | |
120 | ; tlb_entry_{d|i}_dat++; | |
121 | addi r3, #1 | |
122 | and3 r3, r3, #(NR_TLB_ENTRIES - 1) | |
123 | #ifdef CONFIG_ISA_DUAL_ISSUE | |
124 | st r3, @r2 || slli r1, #3 | |
125 | #else | |
126 | st r3, @r2 | |
127 | slli r1, #3 | |
128 | #endif | |
129 | ||
130 | ;; load pte | |
131 | ;; input | |
132 | ;; r0: PFN + ASID | |
133 | ;; r1: TLB entry address | |
134 | ;; r2, r3: free | |
135 | ;; output | |
136 | ;; r0: PFN + ASID | |
137 | ;; r1: TLB entry address | |
138 | ;; r2: pte_data | |
139 | ;; r3: free | |
140 | ; pgd = *(unsigned long *)MPTB; | |
141 | ld24 r2, #(-MPTB - 1) | |
142 | srl3 r3, r0, #22 | |
143 | #ifdef CONFIG_ISA_DUAL_ISSUE | |
144 | not r2, r2 || slli r3, #2 ; r3: pgd offset | |
145 | #else | |
146 | not r2, r2 | |
147 | slli r3, #2 | |
148 | #endif | |
149 | ld r2, @r2 ; r2: pgd base addr (MPTB reg.) | |
150 | or r3, r2 ; r3: pmd addr | |
151 | ||
152 | ; pmd = pmd_offset(pgd, address); | |
153 | ld r3, @r3 ; r3: pmd data | |
1da177e4 LT |
154 | beqz r3, 3f ; pmd_none(*pmd) ? |
155 | ||
2cff5e1a HT |
156 | and3 r2, r3, #0xfff |
157 | add3 r2, r2, #-355 ; _KERNPG_TABLE(=0x163) | |
158 | bnez r2, 3f ; pmd_bad(*pmd) ? | |
159 | ldi r2, #-4096 | |
160 | ||
1da177e4 LT |
161 | ; pte = pte_offset(pmd, address); |
162 | and r2, r3 ; r2: pte base addr | |
163 | srl3 r3, r0, #10 | |
164 | and3 r3, r3, #0xffc ; r3: pte offset | |
165 | or r3, r2 | |
166 | seth r2, #0x8000 | |
167 | or r3, r2 ; r3: pte addr | |
168 | ||
169 | ; pte_data = (unsigned long)pte_val(*pte); | |
170 | ld r2, @r3 ; r2: pte data | |
0d4f6468 HT |
171 | and3 r3, r2, #2 ; _PAGE_PRESENT(=2) check |
172 | beqz r3, 3f | |
1da177e4 LT |
173 | |
174 | .fillinsn | |
175 | 5: | |
176 | ;; set tlb | |
177 | ;; input | |
178 | ;; r0: PFN + ASID | |
179 | ;; r1: TLB entry address | |
180 | ;; r2: pte_data | |
181 | ;; r3: free | |
182 | st r0, @r1 ; set_tlb_tag(entry++, address); | |
183 | st r2, @+r1 ; set_tlb_data(entry, pte_data); | |
184 | ||
185 | .fillinsn | |
186 | 6: | |
187 | ld r3, @sp+ | |
188 | ld r2, @sp+ | |
189 | ld r1, @sp+ | |
190 | ld r0, @sp+ | |
191 | rte | |
192 | ||
193 | .fillinsn | |
194 | 3: | |
195 | ;; error | |
196 | ;; input | |
197 | ;; r0: PFN + ASID | |
198 | ;; r1: TLB entry address | |
199 | ;; r2, r3: free | |
200 | ;; output | |
201 | ;; r0: PFN + ASID | |
202 | ;; r1: TLB entry address | |
203 | ;; r2: pte_data | |
204 | ;; r3: free | |
205 | #ifdef CONFIG_ISA_DUAL_ISSUE | |
206 | bra 5b || ldi r2, #2 | |
207 | #else | |
208 | ldi r2, #2 ; r2: pte_data = 0 | _PAGE_PRESENT(=2) | |
209 | bra 5b | |
210 | #endif | |
211 | ||
212 | #elif defined (CONFIG_ISA_M32R) | |
213 | ||
214 | st sp, @-sp | |
215 | st r0, @-sp | |
216 | st r1, @-sp | |
217 | st r2, @-sp | |
218 | st r3, @-sp | |
219 | st r4, @-sp | |
220 | ||
221 | seth r3, #high(MMU_REG_BASE) | |
222 | ld r0, @(MDEVA_offset,r3) ; r0: address (MDEVA reg.) | |
223 | mvfc r2, bpc ; r2: bpc | |
224 | ld r1, @(MESTS_offset,r3) ; r1: status (MESTS reg.) | |
225 | st r1, @(MESTS_offset,r3) ; clear status (MESTS reg.) | |
226 | and3 r1, r1, #(MESTS_IT) | |
227 | beqz r1, 1f ; data TLB miss? | |
228 | ||
229 | ;; instrucntion TLB miss | |
230 | mv r0, r2 ; address = bpc; | |
231 | ; entry = (unsigned long *)ITLB_BASE+tlb_entry_i*2; | |
232 | seth r3, #shigh(tlb_entry_i_dat) | |
233 | ld r4, @(low(tlb_entry_i_dat),r3) | |
234 | sll3 r2, r4, #3 | |
235 | seth r1, #high(ITLB_BASE) | |
236 | or3 r1, r1, #low(ITLB_BASE) | |
237 | add r2, r1 ; r2: entry | |
238 | addi r4, #1 ; tlb_entry_i++; | |
239 | and3 r4, r4, #(NR_TLB_ENTRIES-1) | |
240 | st r4, @(low(tlb_entry_i_dat),r3) | |
241 | bra 2f | |
242 | .fillinsn | |
243 | 1: | |
244 | ;; data TLB miss | |
245 | ; entry = (unsigned long *)DTLB_BASE+tlb_entry_d*2; | |
246 | seth r3, #shigh(tlb_entry_d_dat) | |
247 | ld r4, @(low(tlb_entry_d_dat),r3) | |
248 | sll3 r2, r4, #3 | |
249 | seth r1, #high(DTLB_BASE) | |
250 | or3 r1, r1, #low(DTLB_BASE) | |
251 | add r2, r1 ; r2: entry | |
252 | addi r4, #1 ; tlb_entry_d++; | |
253 | and3 r4, r4, #(NR_TLB_ENTRIES-1) | |
254 | st r4, @(low(tlb_entry_d_dat),r3) | |
255 | .fillinsn | |
256 | 2: | |
257 | ;; load pte | |
258 | ; r0: address, r2: entry | |
259 | ; r1,r3,r4: (free) | |
260 | ; pgd = *(unsigned long *)MPTB; | |
261 | ld24 r1, #(-MPTB-1) | |
262 | not r1, r1 | |
263 | ld r1, @r1 | |
264 | srl3 r4, r0, #22 | |
265 | sll3 r3, r4, #2 | |
266 | add r3, r1 ; r3: pgd | |
267 | ; pmd = pmd_offset(pgd, address); | |
268 | ld r1, @r3 ; r1: pmd | |
269 | beqz r1, 3f ; pmd_none(*pmd) ? | |
270 | ; | |
2cff5e1a HT |
271 | and3 r1, r1, #0x3ff |
272 | ldi r4, #0x163 ; _KERNPG_TABLE(=0x163) | |
273 | bne r1, r4, 3f ; pmd_bad(*pmd) ? | |
0d4f6468 | 274 | |
1da177e4 LT |
275 | .fillinsn |
276 | 4: | |
277 | ; pte = pte_offset(pmd, address); | |
278 | ld r4, @r3 ; r4: pte | |
279 | ldi r3, #-4096 | |
280 | and r4, r3 | |
281 | srl3 r3, r0, #10 | |
282 | and3 r3, r3, #0xffc | |
283 | add r4, r3 | |
284 | seth r3, #0x8000 | |
285 | add r4, r3 ; r4: pte | |
286 | ; pte_data = (unsigned long)pte_val(*pte); | |
287 | ld r1, @r4 ; r1: pte_data | |
0d4f6468 HT |
288 | and3 r3, r1, #2 ; _PAGE_PRESENT(=2) check |
289 | beqz r3, 3f | |
1da177e4 | 290 | |
0d4f6468 | 291 | .fillinsn |
1da177e4 LT |
292 | ;; set tlb |
293 | ; r0: address, r1: pte_data, r2: entry | |
294 | ; r3,r4: (free) | |
295 | 5: | |
296 | ldi r3, #-4096 ; set_tlb_tag(entry++, address); | |
297 | and r3, r0 | |
298 | seth r4, #shigh(MASID) | |
299 | ld r4, @(low(MASID),r4) ; r4: MASID | |
300 | and3 r4, r4, #(MMU_CONTEXT_ASID_MASK) | |
301 | or r3, r4 | |
302 | st r3, @r2 | |
0d4f6468 | 303 | st r1, @(4,r2) ; set_tlb_data(entry, pte_data); |
1da177e4 LT |
304 | |
305 | ld r4, @sp+ | |
306 | ld r3, @sp+ | |
307 | ld r2, @sp+ | |
308 | ld r1, @sp+ | |
309 | ld r0, @sp+ | |
310 | ld sp, @sp+ | |
311 | rte | |
312 | ||
0d4f6468 HT |
313 | .fillinsn |
314 | 3: | |
315 | ldi r1, #2 ; r1: pte_data = 0 | _PAGE_PRESENT(=2) | |
316 | bra 5b | |
317 | ||
1da177e4 LT |
318 | #else |
319 | #error unknown isa configuration | |
320 | #endif | |
321 | ||
322 | ENTRY(init_tlb) | |
323 | ;; Set MMU Register | |
324 | seth r0, #high(MMU_REG_BASE) ; Set MMU_REG_BASE higher | |
325 | or3 r0, r0, #low(MMU_REG_BASE) ; Set MMU_REG_BASE lower | |
326 | ldi r1, #0 | |
327 | st r1, @(MPSZ_offset,r0) ; Set MPSZ Reg(Page size 4KB:0 16KB:1 64KB:2) | |
328 | ldi r1, #0 | |
329 | st r1, @(MASID_offset,r0) ; Set ASID Zero | |
330 | ||
331 | ;; Set TLB | |
332 | seth r0, #high(ITLB_BASE) ; Set ITLB_BASE higher | |
333 | or3 r0, r0, #low(ITLB_BASE) ; Set ITLB_BASE lower | |
334 | seth r1, #high(DTLB_BASE) ; Set DTLB_BASE higher | |
335 | or3 r1, r1, #low(DTLB_BASE) ; Set DTLB_BASE lower | |
336 | ldi r2, #0 | |
337 | ldi r3, #NR_TLB_ENTRIES | |
338 | addi r0, #-4 | |
339 | addi r1, #-4 | |
340 | clear_tlb: | |
341 | st r2, @+r0 ; VPA <- 0 | |
342 | st r2, @+r0 ; PPA <- 0 | |
343 | st r2, @+r1 ; VPA <- 0 | |
344 | st r2, @+r1 ; PPA <- 0 | |
345 | addi r3, #-1 | |
346 | bnez r3, clear_tlb | |
347 | ;; | |
348 | jmp r14 | |
349 | ||
350 | ENTRY(m32r_itlb_entrys) | |
351 | ENTRY(m32r_otlb_entrys) | |
352 | ||
353 | #endif /* CONFIG_MMU */ | |
354 | ||
fabb626a | 355 | .end |