xref: /netbsd/sys/arch/arm/arm/cpufunc_asm_sa1.S (revision c4a72b64)
1/*	$NetBSD: cpufunc_asm_sa1.S,v 1.8 2002/08/17 16:36:32 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1997,1998 Mark Brinicombe.
5 * Copyright (c) 1997 Causality Limited
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by Causality Limited.
19 * 4. The name of Causality Limited may not be used to endorse or promote
20 *    products derived from this software without specific prior written
21 *    permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * SA-1 assembly functions for CPU / MMU / TLB specific operations
36 */
37
38#include <machine/cpu.h>
39#include <machine/asm.h>
40
41.Lblock_userspace_access:
42	.word	_C_LABEL(block_userspace_access)
43
44/*
45 * Functions to set the MMU Translation Table Base register
46 *
47 * We need to clean and flush the cache as it uses virtual
48 * addresses that are about to change.
49 */
50ENTRY(sa1_setttb)
51#ifdef CACHE_CLEAN_BLOCK_INTR
52	mrs	r3, cpsr_all
53	orr	r1, r3, #(I32_bit | F32_bit)
54	msr	cpsr_all, r1
55#else
56	ldr	r3, .Lblock_userspace_access
57	ldr	r2, [r3]
58	orr	r1, r2, #1
59	str	r1, [r3]
60#endif
61	stmfd	sp!, {r0-r3, lr}
62	bl	_C_LABEL(sa1_cache_cleanID)
63	ldmfd	sp!, {r0-r3, lr}
64	mcr	p15, 0, r0, c7, c5, 0	/* invalidate I$ and BTB */
65	mcr	p15, 0, r0, c7, c10, 4	/* drain write and fill buffer */
66
67	/* Write the TTB */
68	mcr	p15, 0, r0, c2, c0, 0
69
70	/* If we have updated the TTB we must flush the TLB */
71	mcr	p15, 0, r0, c8, c7, 0	/* invalidate I+D TLB */
72
73	/* The cleanID above means we only need to flush the I cache here */
74	mcr	p15, 0, r0, c7, c5, 0	/* invalidate I$ and BTB */
75
76	/* Make sure that pipeline is emptied */
77	mov	r0, r0
78	mov	r0, r0
79#ifdef CACHE_CLEAN_BLOCK_INTR
80	msr	cpsr_all, r3
81#else
82	str	r2, [r3]
83#endif
84	mov	pc, lr
85
86/*
87 * TLB functions
88 */
89ENTRY(sa1_tlb_flushID_SE)
90	mcr	p15, 0, r0, c8, c6, 1	/* flush D tlb single entry */
91	mcr	p15, 0, r0, c8, c5, 0	/* flush I tlb */
92	mov	pc, lr
93
94/*
95 * Cache functions
96 */
97ENTRY(sa1_cache_flushID)
98	mcr	p15, 0, r0, c7, c7, 0	/* flush I+D cache */
99	mov	pc, lr
100
101ENTRY(sa1_cache_flushI)
102	mcr	p15, 0, r0, c7, c5, 0	/* flush I cache */
103	mov	pc, lr
104
105ENTRY(sa1_cache_flushD)
106	mcr	p15, 0, r0, c7, c6, 0	/* flush D cache */
107	mov	pc, lr
108
109ENTRY(sa1_cache_flushD_SE)
110	mcr	p15, 0, r0, c7, c6, 1	/* flush D cache single entry */
111	mov	pc, lr
112
113ENTRY(sa1_cache_cleanD_E)
114	mcr	p15, 0, r0, c7, c10, 1	/* clean D cache entry */
115	mov	pc, lr
116
117/*
118 * Information for the SA-1 cache clean/purge functions:
119 *
120 *	* Virtual address of the memory region to use
121 *	* Size of memory region
122 */
123	.data
124
125	.global	_C_LABEL(sa1_cache_clean_addr)
126_C_LABEL(sa1_cache_clean_addr):
127	.word	0xf0000000
128
129	.global	_C_LABEL(sa1_cache_clean_size)
130_C_LABEL(sa1_cache_clean_size):
131#if defined(CPU_SA1100) || defined(CPU_SA1110)
132	.word	0x00004000
133#else
134	.word	0x00008000
135#endif
136
137	.text
138
139.Lsa1_cache_clean_addr:
140	.word	_C_LABEL(sa1_cache_clean_addr)
141.Lsa1_cache_clean_size:
142	.word	_C_LABEL(sa1_cache_clean_size)
143
144#ifdef CACHE_CLEAN_BLOCK_INTR
145#define	SA1_CACHE_CLEAN_BLOCK						\
146	mrs	r3, cpsr_all					;	\
147	orr	r0, r3, #(I32_bit | F32_bit)			;	\
148	msr	cpsr_all, r0
149
150#define	SA1_CACHE_CLEAN_UNBLOCK						\
151	msr	cpsr_all, r3
152#else
153#define	SA1_CACHE_CLEAN_BLOCK						\
154	ldr	r3, .Lblock_userspace_access			;	\
155	ldr	ip, [r3]					;	\
156	orr	r0, ip, #1					;	\
157	str	r0, [r3]
158
159#define	SA1_CACHE_CLEAN_UNBLOCK						\
160	str	ip, [r3]
161#endif /* CACHE_CLEAN_BLOCK_INTR */
162
163#ifdef DOUBLE_CACHE_CLEAN_BANK
164#define	SA1_DOUBLE_CACHE_CLEAN_BANK					\
165	eor	r0, r0, r1					;	\
166	str	r0, [r2]
167#else
168#define	SA1_DOUBLE_CACHE_CLEAN_BANK	/* nothing */
169#endif /* DOUBLE_CACHE_CLEAN_BANK */
170
171#define	SA1_CACHE_CLEAN_PROLOGUE					\
172	SA1_CACHE_CLEAN_BLOCK					;	\
173	ldr	r2, .Lsa1_cache_clean_addr			;	\
174	ldmia	r2, {r0, r1}					;	\
175	SA1_DOUBLE_CACHE_CLEAN_BANK
176
177#define	SA1_CACHE_CLEAN_EPILOGUE					\
178	SA1_CACHE_CLEAN_UNBLOCK
179
180ENTRY_NP(sa1_cache_syncI)
181ENTRY_NP(sa1_cache_purgeID)
182	mcr	p15, 0, r0, c7, c5, 0	/* flush I cache (D cleaned below) */
183ENTRY_NP(sa1_cache_cleanID)
184ENTRY_NP(sa1_cache_purgeD)
185ENTRY(sa1_cache_cleanD)
186	SA1_CACHE_CLEAN_PROLOGUE
187
1881:	ldr	r2, [r0], #32
189	subs	r1, r1, #32
190	bne	1b
191
192	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
193
194	SA1_CACHE_CLEAN_EPILOGUE
195	mov	pc, lr
196
197ENTRY(sa1_cache_purgeID_E)
198	mcr	p15, 0, r0, c7, c10, 1	/* clean dcache entry */
199	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
200	mcr	p15, 0, r0, c7, c5, 0	/* flush I cache */
201	mcr	p15, 0, r0, c7, c6, 1	/* flush D cache single entry */
202	mov	pc, lr
203
204ENTRY(sa1_cache_purgeD_E)
205	mcr	p15, 0, r0, c7, c10, 1	/* clean dcache entry */
206	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
207	mcr	p15, 0, r0, c7, c6, 1	/* flush D cache single entry */
208	mov	pc, lr
209
210/*
211 * Soft functions
212 */
213/* sa1_cache_syncI is identical to sa1_cache_purgeID */
214
215ENTRY(sa1_cache_cleanID_rng)
216ENTRY(sa1_cache_cleanD_rng)
217	cmp	r1, #0x4000
218	bcs	_C_LABEL(sa1_cache_cleanID)
219
220	and	r2, r0, #0x1f
221	add	r1, r1, r2
222	bic	r0, r0, #0x1f
223
2241:	mcr	p15, 0, r0, c7, c10, 1	/* clean D cache entry */
225	add	r0, r0, #32
226	subs	r1, r1, #32
227	bhi	1b
228
229	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
230	mov	pc, lr
231
232ENTRY(sa1_cache_purgeID_rng)
233	cmp	r1, #0x4000
234	bcs	_C_LABEL(sa1_cache_purgeID)
235
236	and	r2, r0, #0x1f
237	add	r1, r1, r2
238	bic	r0, r0, #0x1f
239
2401:	mcr	p15, 0, r0, c7, c10, 1	/* clean D cache entry */
241	mcr	p15, 0, r0, c7, c6, 1	/* flush D cache single entry */
242	add	r0, r0, #32
243	subs	r1, r1, #32
244	bhi	1b
245
246	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
247	mcr	p15, 0, r0, c7, c5, 0	/* flush I cache */
248	mov	pc, lr
249
250ENTRY(sa1_cache_purgeD_rng)
251	cmp	r1, #0x4000
252	bcs	_C_LABEL(sa1_cache_purgeD)
253
254	and	r2, r0, #0x1f
255	add	r1, r1, r2
256	bic	r0, r0, #0x1f
257
2581:	mcr	p15, 0, r0, c7, c10, 1	/* clean D cache entry */
259	mcr	p15, 0, r0, c7, c6, 1	/* flush D cache single entry */
260	add	r0, r0, #32
261	subs	r1, r1, #32
262	bhi	1b
263
264	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
265	mov	pc, lr
266
267ENTRY(sa1_cache_syncI_rng)
268	cmp	r1, #0x4000
269	bcs	_C_LABEL(sa1_cache_syncI)
270
271	and	r2, r0, #0x1f
272	add	r1, r1, r2
273	bic	r0, r0, #0x1f
274
2751:	mcr	p15, 0, r0, c7, c10, 1	/* clean D cache entry */
276	add	r0, r0, #32
277	subs	r1, r1, #32
278	bhi	1b
279
280	mcr	p15, 0, r0, c7, c10, 4	/* drain write buffer */
281	mcr	p15, 0, r0, c7, c5, 0	/* flush I cache */
282
283	mov	pc, lr
284
285/*
286 * Context switch.
287 *
288 * These is the CPU-specific parts of the context switcher cpu_switch()
289 * These functions actually perform the TTB reload.
290 *
291 * NOTE: Special calling convention
292 *	r1, r4-r13 must be preserved
293 */
294#if defined(CPU_SA110)
295ENTRY(sa110_context_switch)
296	/*
297	 * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this.
298	 * Thus the data cache will contain only kernel data and the
299	 * instruction cache will contain only kernel code, and all
300	 * kernel mappings are shared by all processes.
301	 */
302
303	/* Write the TTB */
304	mcr	p15, 0, r0, c2, c0, 0
305
306	/* If we have updated the TTB we must flush the TLB */
307	mcr	p15, 0, r0, c8, c7, 0	/* flush the I+D tlb */
308
309	/* Make sure that pipeline is emptied */
310	mov	r0, r0
311	mov	r0, r0
312	mov	pc, lr
313#endif
314