Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/m32r/mm/mmu.S
10817 views
1
/*
2
* linux/arch/m32r/mm/mmu.S
3
*
4
* Copyright (C) 2001 by Hiroyuki Kondo
5
*/
6
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
153
beqz r3, 3f ; pmd_none(*pmd) ?
154
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
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
170
and3 r3, r2, #2 ; _PAGE_PRESENT(=2) check
171
beqz r3, 3f
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
;
270
and3 r1, r1, #0x3ff
271
ldi r4, #0x163 ; _KERNPG_TABLE(=0x163)
272
bne r1, r4, 3f ; pmd_bad(*pmd) ?
273
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
287
and3 r3, r1, #2 ; _PAGE_PRESENT(=2) check
288
beqz r3, 3f
289
290
.fillinsn
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
302
st r1, @(4,r2) ; set_tlb_data(entry, pte_data);
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
312
.fillinsn
313
3:
314
ldi r1, #2 ; r1: pte_data = 0 | _PAGE_PRESENT(=2)
315
bra 5b
316
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
354
.end
355
356