PageRenderTime 32ms CodeModel.GetById 10ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/m32r/mm/mmu.S

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