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