1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * viking.S: High speed Viking cache/mmu operations
4  *
5  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
6  * Copyright (C) 1997,1998,1999  Jakub Jelinek  (jj@ultra.linux.cz)
7  * Copyright (C) 1999  Pavel Semerad  (semerad@ss1000.ms.mff.cuni.cz)
8  */
9 
10 #include <asm/ptrace.h>
11 #include <asm/psr.h>
12 #include <asm/asm-offsets.h>
13 #include <asm/asi.h>
14 #include <asm/mxcc.h>
15 #include <asm/page.h>
16 #include <asm/pgtable.h>
17 #include <asm/pgtsrmmu.h>
18 #include <asm/viking.h>
19 
20 #ifdef CONFIG_SMP
21 	.data
22 	.align	4
23 sun4dsmp_flush_tlb_spin:
24 	.word	0
25 #endif
26 
27 	.text
28 	.align	4
29 
30 	.globl	viking_flush_cache_all, viking_flush_cache_mm
31 	.globl	viking_flush_cache_range, viking_flush_cache_page
32 	.globl	viking_flush_page, viking_mxcc_flush_page
33 	.globl	viking_flush_page_for_dma, viking_flush_page_to_ram
34 	.globl	viking_flush_sig_insns
35 	.globl	viking_flush_tlb_all, viking_flush_tlb_mm
36 	.globl	viking_flush_tlb_range, viking_flush_tlb_page
37 
38 viking_flush_page:
39 	sethi	%hi(PAGE_OFFSET), %g2
40 	sub	%o0, %g2, %g3
41 	srl	%g3, 12, %g1		! ppage >> 12
42 
43 	clr	%o1			! set counter, 0 - 127
44 	sethi	%hi(PAGE_OFFSET + PAGE_SIZE - 0x80000000), %o3
45 	sethi	%hi(0x80000000), %o4
46 	sethi	%hi(VIKING_PTAG_VALID), %o5
47 	sethi	%hi(2*PAGE_SIZE), %o0
48 	sethi	%hi(PAGE_SIZE), %g7
49 	clr	%o2			! block counter, 0 - 3
50 5:
51 	sll	%o1, 5, %g4
52 	or	%g4, %o4, %g4		! 0x80000000 | (set << 5)
53 
54 	sll	%o2, 26, %g5		! block << 26
55 6:
56 	or	%g5, %g4, %g5
57 	ldda	[%g5] ASI_M_DATAC_TAG, %g2
58 	cmp	%g3, %g1		! ptag == ppage?
59 	bne	7f
60 	 inc	%o2
61 
62 	andcc	%g2, %o5, %g0		! ptag VALID?
63 	be	7f
64 	 add	%g4, %o3, %g2		! (PAGE_OFFSET + PAGE_SIZE) | (set << 5)
65 	ld	[%g2], %g3
66 	ld	[%g2 + %g7], %g3
67 	add	%g2, %o0, %g2
68 	ld	[%g2], %g3
69 	ld	[%g2 + %g7], %g3
70 	add	%g2, %o0, %g2
71 	ld	[%g2], %g3
72 	ld	[%g2 + %g7], %g3
73 	add	%g2, %o0, %g2
74 	ld	[%g2], %g3
75 	b	8f
76 	 ld	[%g2 + %g7], %g3
77 
78 7:
79 	cmp	%o2, 3
80 	ble	6b
81 	 sll	%o2, 26, %g5			! block << 26
82 
83 8:	inc	%o1
84 	cmp	%o1, 0x7f
85 	ble	5b
86 	 clr	%o2
87 
88 9:	retl
89 	 nop
90 
91 viking_mxcc_flush_page:
92 	sethi	%hi(PAGE_OFFSET), %g2
93 	sub	%o0, %g2, %g3
94 	sub	%g3, -PAGE_SIZE, %g3		! ppage + PAGE_SIZE
95 	sethi	%hi(MXCC_SRCSTREAM), %o3	! assume %hi(MXCC_SRCSTREAM) == %hi(MXCC_DESTSTREAM)
96 	mov	0x10, %g2			! set cacheable bit
97 	or	%o3, %lo(MXCC_SRCSTREAM), %o2
98 	or	%o3, %lo(MXCC_DESSTREAM), %o3
99 	sub	%g3, MXCC_STREAM_SIZE, %g3
100 6:
101 	stda	%g2, [%o2] ASI_M_MXCC
102 	stda	%g2, [%o3] ASI_M_MXCC
103 	andncc	%g3, PAGE_MASK, %g0
104 	bne	6b
105 	 sub	%g3, MXCC_STREAM_SIZE, %g3
106 
107 9:	retl
108 	 nop
109 
110 viking_flush_cache_page:
111 viking_flush_cache_range:
112 #ifndef CONFIG_SMP
113 	ld	[%o0 + VMA_VM_MM], %o0
114 #endif
115 viking_flush_cache_mm:
116 #ifndef CONFIG_SMP
117 	ld	[%o0 + AOFF_mm_context], %g1
118 	cmp	%g1, -1
119 	bne	viking_flush_cache_all
120 	 nop
121 	b,a	viking_flush_cache_out
122 #endif
123 viking_flush_cache_all:
124 	WINDOW_FLUSH(%g4, %g5)
125 viking_flush_cache_out:
126 	retl
127 	 nop
128 
129 viking_flush_tlb_all:
130 	mov	0x400, %g1
131 	retl
132 	 sta	%g0, [%g1] ASI_M_FLUSH_PROBE
133 
134 viking_flush_tlb_mm:
135 	mov	SRMMU_CTX_REG, %g1
136 	ld	[%o0 + AOFF_mm_context], %o1
137 	lda	[%g1] ASI_M_MMUREGS, %g5
138 #ifndef CONFIG_SMP
139 	cmp	%o1, -1
140 	be	1f
141 #endif
142 	mov	0x300, %g2
143 	sta	%o1, [%g1] ASI_M_MMUREGS
144 	sta	%g0, [%g2] ASI_M_FLUSH_PROBE
145 	retl
146 	 sta	%g5, [%g1] ASI_M_MMUREGS
147 #ifndef CONFIG_SMP
148 1:	retl
149 	 nop
150 #endif
151 
152 viking_flush_tlb_range:
153 	ld	[%o0 + VMA_VM_MM], %o0
154 	mov	SRMMU_CTX_REG, %g1
155 	ld	[%o0 + AOFF_mm_context], %o3
156 	lda	[%g1] ASI_M_MMUREGS, %g5
157 #ifndef CONFIG_SMP
158 	cmp	%o3, -1
159 	be	2f
160 #endif
161 	sethi	%hi(~((1 << PGDIR_SHIFT) - 1)), %o4
162 	sta	%o3, [%g1] ASI_M_MMUREGS
163 	and	%o1, %o4, %o1
164 	add	%o1, 0x200, %o1
165 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
166 1:	sub	%o1, %o4, %o1
167 	cmp	%o1, %o2
168 	blu,a	1b
169 	 sta	%g0, [%o1] ASI_M_FLUSH_PROBE
170 	retl
171 	 sta	%g5, [%g1] ASI_M_MMUREGS
172 #ifndef CONFIG_SMP
173 2:	retl
174 	 nop
175 #endif
176 
177 viking_flush_tlb_page:
178 	ld	[%o0 + VMA_VM_MM], %o0
179 	mov	SRMMU_CTX_REG, %g1
180 	ld	[%o0 + AOFF_mm_context], %o3
181 	lda	[%g1] ASI_M_MMUREGS, %g5
182 #ifndef CONFIG_SMP
183 	cmp	%o3, -1
184 	be	1f
185 #endif
186 	and	%o1, PAGE_MASK, %o1
187 	sta	%o3, [%g1] ASI_M_MMUREGS
188 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
189 	retl
190 	 sta	%g5, [%g1] ASI_M_MMUREGS
191 #ifndef CONFIG_SMP
192 1:	retl
193 	 nop
194 #endif
195 
196 viking_flush_page_to_ram:
197 viking_flush_page_for_dma:
198 viking_flush_sig_insns:
199 	retl
200 	 nop
201 
202 #ifdef CONFIG_SMP
203 	.globl	sun4dsmp_flush_tlb_all, sun4dsmp_flush_tlb_mm
204 	.globl	sun4dsmp_flush_tlb_range, sun4dsmp_flush_tlb_page
205 sun4dsmp_flush_tlb_all:
206 	sethi	%hi(sun4dsmp_flush_tlb_spin), %g3
207 1:	ldstub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
208 	tst	%g5
209 	bne	2f
210 	 mov	0x400, %g1
211 	sta	%g0, [%g1] ASI_M_FLUSH_PROBE
212 	retl
213 	 stb	%g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
214 2:	tst	%g5
215 	bne,a	2b
216 	 ldub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
217 	b,a	1b
218 
219 sun4dsmp_flush_tlb_mm:
220 	sethi	%hi(sun4dsmp_flush_tlb_spin), %g3
221 1:	ldstub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
222 	tst	%g5
223 	bne	2f
224 	 mov	SRMMU_CTX_REG, %g1
225 	ld	[%o0 + AOFF_mm_context], %o1
226 	lda	[%g1] ASI_M_MMUREGS, %g5
227 	mov	0x300, %g2
228 	sta	%o1, [%g1] ASI_M_MMUREGS
229 	sta	%g0, [%g2] ASI_M_FLUSH_PROBE
230 	sta	%g5, [%g1] ASI_M_MMUREGS
231 	retl
232 	 stb	%g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
233 2:	tst	%g5
234 	bne,a	2b
235 	 ldub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
236 	b,a	1b
237 
238 sun4dsmp_flush_tlb_range:
239 	sethi	%hi(sun4dsmp_flush_tlb_spin), %g3
240 1:	ldstub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
241 	tst	%g5
242 	bne	3f
243 	 mov	SRMMU_CTX_REG, %g1
244 	ld	[%o0 + VMA_VM_MM], %o0
245 	ld	[%o0 + AOFF_mm_context], %o3
246 	lda	[%g1] ASI_M_MMUREGS, %g5
247 	sethi	%hi(~((1 << PGDIR_SHIFT) - 1)), %o4
248 	sta	%o3, [%g1] ASI_M_MMUREGS
249 	and	%o1, %o4, %o1
250 	add	%o1, 0x200, %o1
251 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
252 2:	sub	%o1, %o4, %o1
253 	cmp	%o1, %o2
254 	blu,a	2b
255 	 sta	%g0, [%o1] ASI_M_FLUSH_PROBE
256 	sta	%g5, [%g1] ASI_M_MMUREGS
257 	retl
258 	 stb	%g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
259 3:	tst	%g5
260 	bne,a	3b
261 	 ldub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
262 	b,a	1b
263 
264 sun4dsmp_flush_tlb_page:
265 	sethi	%hi(sun4dsmp_flush_tlb_spin), %g3
266 1:	ldstub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
267 	tst	%g5
268 	bne	2f
269 	 mov	SRMMU_CTX_REG, %g1
270 	ld	[%o0 + VMA_VM_MM], %o0
271 	ld	[%o0 + AOFF_mm_context], %o3
272 	lda	[%g1] ASI_M_MMUREGS, %g5
273 	and	%o1, PAGE_MASK, %o1
274 	sta	%o3, [%g1] ASI_M_MMUREGS
275 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
276 	sta	%g5, [%g1] ASI_M_MMUREGS
277 	retl
278 	 stb	%g0, [%g3 + %lo(sun4dsmp_flush_tlb_spin)]
279 2:	tst	%g5
280 	bne,a	2b
281 	 ldub	[%g3 + %lo(sun4dsmp_flush_tlb_spin)], %g5
282 	b,a	1b
283 	 nop
284 #endif
285