xref: /openbmc/linux/arch/sparc/lib/copy_page.S (revision 478b8fec)
1478b8fecSSam Ravnborg/* clear_page.S: UltraSparc optimized copy page.
2478b8fecSSam Ravnborg *
3478b8fecSSam Ravnborg * Copyright (C) 1996, 1998, 1999, 2000, 2004 David S. Miller (davem@redhat.com)
4478b8fecSSam Ravnborg * Copyright (C) 1997 Jakub Jelinek (jakub@redhat.com)
5478b8fecSSam Ravnborg */
6478b8fecSSam Ravnborg
7478b8fecSSam Ravnborg#include <asm/visasm.h>
8478b8fecSSam Ravnborg#include <asm/thread_info.h>
9478b8fecSSam Ravnborg#include <asm/page.h>
10478b8fecSSam Ravnborg#include <asm/pgtable.h>
11478b8fecSSam Ravnborg#include <asm/spitfire.h>
12478b8fecSSam Ravnborg#include <asm/head.h>
13478b8fecSSam Ravnborg
14478b8fecSSam Ravnborg	/* What we used to do was lock a TLB entry into a specific
15478b8fecSSam Ravnborg	 * TLB slot, clear the page with interrupts disabled, then
16478b8fecSSam Ravnborg	 * restore the original TLB entry.  This was great for
17478b8fecSSam Ravnborg	 * disturbing the TLB as little as possible, but it meant
18478b8fecSSam Ravnborg	 * we had to keep interrupts disabled for a long time.
19478b8fecSSam Ravnborg	 *
20478b8fecSSam Ravnborg	 * Now, we simply use the normal TLB loading mechanism,
21478b8fecSSam Ravnborg	 * and this makes the cpu choose a slot all by itself.
22478b8fecSSam Ravnborg	 * Then we do a normal TLB flush on exit.  We need only
23478b8fecSSam Ravnborg	 * disable preemption during the clear.
24478b8fecSSam Ravnborg	 */
25478b8fecSSam Ravnborg
26478b8fecSSam Ravnborg#define	DCACHE_SIZE	(PAGE_SIZE * 2)
27478b8fecSSam Ravnborg
28478b8fecSSam Ravnborg#if (PAGE_SHIFT == 13)
29478b8fecSSam Ravnborg#define PAGE_SIZE_REM	0x80
30478b8fecSSam Ravnborg#elif (PAGE_SHIFT == 16)
31478b8fecSSam Ravnborg#define PAGE_SIZE_REM	0x100
32478b8fecSSam Ravnborg#else
33478b8fecSSam Ravnborg#error Wrong PAGE_SHIFT specified
34478b8fecSSam Ravnborg#endif
35478b8fecSSam Ravnborg
36478b8fecSSam Ravnborg#define TOUCH(reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7)	\
37478b8fecSSam Ravnborg	fmovd	%reg0, %f48; 	fmovd	%reg1, %f50;		\
38478b8fecSSam Ravnborg	fmovd	%reg2, %f52; 	fmovd	%reg3, %f54;		\
39478b8fecSSam Ravnborg	fmovd	%reg4, %f56; 	fmovd	%reg5, %f58;		\
40478b8fecSSam Ravnborg	fmovd	%reg6, %f60; 	fmovd	%reg7, %f62;
41478b8fecSSam Ravnborg
42478b8fecSSam Ravnborg	.text
43478b8fecSSam Ravnborg
44478b8fecSSam Ravnborg	.align		32
45478b8fecSSam Ravnborg	.globl		copy_user_page
46478b8fecSSam Ravnborg	.type		copy_user_page,#function
47478b8fecSSam Ravnborgcopy_user_page:		/* %o0=dest, %o1=src, %o2=vaddr */
48478b8fecSSam Ravnborg	lduw		[%g6 + TI_PRE_COUNT], %o4
49478b8fecSSam Ravnborg	sethi		%uhi(PAGE_OFFSET), %g2
50478b8fecSSam Ravnborg	sethi		%hi(PAGE_SIZE), %o3
51478b8fecSSam Ravnborg
52478b8fecSSam Ravnborg	sllx		%g2, 32, %g2
53478b8fecSSam Ravnborg	sethi		%hi(PAGE_KERNEL_LOCKED), %g3
54478b8fecSSam Ravnborg
55478b8fecSSam Ravnborg	ldx		[%g3 + %lo(PAGE_KERNEL_LOCKED)], %g3
56478b8fecSSam Ravnborg	sub		%o0, %g2, %g1		! dest paddr
57478b8fecSSam Ravnborg
58478b8fecSSam Ravnborg	sub		%o1, %g2, %g2		! src paddr
59478b8fecSSam Ravnborg
60478b8fecSSam Ravnborg	and		%o2, %o3, %o0		! vaddr D-cache alias bit
61478b8fecSSam Ravnborg	or		%g1, %g3, %g1		! dest TTE data
62478b8fecSSam Ravnborg
63478b8fecSSam Ravnborg	or		%g2, %g3, %g2		! src TTE data
64478b8fecSSam Ravnborg	sethi		%hi(TLBTEMP_BASE), %o3
65478b8fecSSam Ravnborg
66478b8fecSSam Ravnborg	sethi		%hi(DCACHE_SIZE), %o1
67478b8fecSSam Ravnborg	add		%o0, %o3, %o0		! dest TTE vaddr
68478b8fecSSam Ravnborg
69478b8fecSSam Ravnborg	add		%o4, 1, %o2
70478b8fecSSam Ravnborg	add		%o0, %o1, %o1		! src TTE vaddr
71478b8fecSSam Ravnborg
72478b8fecSSam Ravnborg	/* Disable preemption.  */
73478b8fecSSam Ravnborg	mov		TLB_TAG_ACCESS, %g3
74478b8fecSSam Ravnborg	stw		%o2, [%g6 + TI_PRE_COUNT]
75478b8fecSSam Ravnborg
76478b8fecSSam Ravnborg	/* Load TLB entries.  */
77478b8fecSSam Ravnborg	rdpr		%pstate, %o2
78478b8fecSSam Ravnborg	wrpr		%o2, PSTATE_IE, %pstate
79478b8fecSSam Ravnborg	stxa		%o0, [%g3] ASI_DMMU
80478b8fecSSam Ravnborg	stxa		%g1, [%g0] ASI_DTLB_DATA_IN
81478b8fecSSam Ravnborg	membar		#Sync
82478b8fecSSam Ravnborg	stxa		%o1, [%g3] ASI_DMMU
83478b8fecSSam Ravnborg	stxa		%g2, [%g0] ASI_DTLB_DATA_IN
84478b8fecSSam Ravnborg	membar		#Sync
85478b8fecSSam Ravnborg	wrpr		%o2, 0x0, %pstate
86478b8fecSSam Ravnborg
87478b8fecSSam Ravnborgcheetah_copy_page_insn:
88478b8fecSSam Ravnborg	ba,pt		%xcc, 9f
89478b8fecSSam Ravnborg	 nop
90478b8fecSSam Ravnborg
91478b8fecSSam Ravnborg1:
92478b8fecSSam Ravnborg	VISEntryHalf
93478b8fecSSam Ravnborg	membar		#StoreLoad | #StoreStore | #LoadStore
94478b8fecSSam Ravnborg	sethi		%hi((PAGE_SIZE/64)-2), %o2
95478b8fecSSam Ravnborg	mov		%o0, %g1
96478b8fecSSam Ravnborg	prefetch	[%o1 + 0x000], #one_read
97478b8fecSSam Ravnborg	or		%o2, %lo((PAGE_SIZE/64)-2), %o2
98478b8fecSSam Ravnborg	prefetch	[%o1 + 0x040], #one_read
99478b8fecSSam Ravnborg	prefetch	[%o1 + 0x080], #one_read
100478b8fecSSam Ravnborg	prefetch	[%o1 + 0x0c0], #one_read
101478b8fecSSam Ravnborg	ldd		[%o1 + 0x000], %f0
102478b8fecSSam Ravnborg	prefetch	[%o1 + 0x100], #one_read
103478b8fecSSam Ravnborg	ldd		[%o1 + 0x008], %f2
104478b8fecSSam Ravnborg	prefetch	[%o1 + 0x140], #one_read
105478b8fecSSam Ravnborg	ldd		[%o1 + 0x010], %f4
106478b8fecSSam Ravnborg	prefetch	[%o1 + 0x180], #one_read
107478b8fecSSam Ravnborg	fmovd		%f0, %f16
108478b8fecSSam Ravnborg	ldd		[%o1 + 0x018], %f6
109478b8fecSSam Ravnborg	fmovd		%f2, %f18
110478b8fecSSam Ravnborg	ldd		[%o1 + 0x020], %f8
111478b8fecSSam Ravnborg	fmovd		%f4, %f20
112478b8fecSSam Ravnborg	ldd		[%o1 + 0x028], %f10
113478b8fecSSam Ravnborg	fmovd		%f6, %f22
114478b8fecSSam Ravnborg	ldd		[%o1 + 0x030], %f12
115478b8fecSSam Ravnborg	fmovd		%f8, %f24
116478b8fecSSam Ravnborg	ldd		[%o1 + 0x038], %f14
117478b8fecSSam Ravnborg	fmovd		%f10, %f26
118478b8fecSSam Ravnborg	ldd		[%o1 + 0x040], %f0
119478b8fecSSam Ravnborg1:	ldd		[%o1 + 0x048], %f2
120478b8fecSSam Ravnborg	fmovd		%f12, %f28
121478b8fecSSam Ravnborg	ldd		[%o1 + 0x050], %f4
122478b8fecSSam Ravnborg	fmovd		%f14, %f30
123478b8fecSSam Ravnborg	stda		%f16, [%o0] ASI_BLK_P
124478b8fecSSam Ravnborg	ldd		[%o1 + 0x058], %f6
125478b8fecSSam Ravnborg	fmovd		%f0, %f16
126478b8fecSSam Ravnborg	ldd		[%o1 + 0x060], %f8
127478b8fecSSam Ravnborg	fmovd		%f2, %f18
128478b8fecSSam Ravnborg	ldd		[%o1 + 0x068], %f10
129478b8fecSSam Ravnborg	fmovd		%f4, %f20
130478b8fecSSam Ravnborg	ldd		[%o1 + 0x070], %f12
131478b8fecSSam Ravnborg	fmovd		%f6, %f22
132478b8fecSSam Ravnborg	ldd		[%o1 + 0x078], %f14
133478b8fecSSam Ravnborg	fmovd		%f8, %f24
134478b8fecSSam Ravnborg	ldd		[%o1 + 0x080], %f0
135478b8fecSSam Ravnborg	prefetch	[%o1 + 0x180], #one_read
136478b8fecSSam Ravnborg	fmovd		%f10, %f26
137478b8fecSSam Ravnborg	subcc		%o2, 1, %o2
138478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
139478b8fecSSam Ravnborg	bne,pt		%xcc, 1b
140478b8fecSSam Ravnborg	 add		%o1, 0x40, %o1
141478b8fecSSam Ravnborg
142478b8fecSSam Ravnborg	ldd		[%o1 + 0x048], %f2
143478b8fecSSam Ravnborg	fmovd		%f12, %f28
144478b8fecSSam Ravnborg	ldd		[%o1 + 0x050], %f4
145478b8fecSSam Ravnborg	fmovd		%f14, %f30
146478b8fecSSam Ravnborg	stda		%f16, [%o0] ASI_BLK_P
147478b8fecSSam Ravnborg	ldd		[%o1 + 0x058], %f6
148478b8fecSSam Ravnborg	fmovd		%f0, %f16
149478b8fecSSam Ravnborg	ldd		[%o1 + 0x060], %f8
150478b8fecSSam Ravnborg	fmovd		%f2, %f18
151478b8fecSSam Ravnborg	ldd		[%o1 + 0x068], %f10
152478b8fecSSam Ravnborg	fmovd		%f4, %f20
153478b8fecSSam Ravnborg	ldd		[%o1 + 0x070], %f12
154478b8fecSSam Ravnborg	fmovd		%f6, %f22
155478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
156478b8fecSSam Ravnborg	ldd		[%o1 + 0x078], %f14
157478b8fecSSam Ravnborg	fmovd		%f8, %f24
158478b8fecSSam Ravnborg	fmovd		%f10, %f26
159478b8fecSSam Ravnborg	fmovd		%f12, %f28
160478b8fecSSam Ravnborg	fmovd		%f14, %f30
161478b8fecSSam Ravnborg	stda		%f16, [%o0] ASI_BLK_P
162478b8fecSSam Ravnborg	membar		#Sync
163478b8fecSSam Ravnborg	VISExitHalf
164478b8fecSSam Ravnborg	ba,pt		%xcc, 5f
165478b8fecSSam Ravnborg	 nop
166478b8fecSSam Ravnborg
167478b8fecSSam Ravnborg9:
168478b8fecSSam Ravnborg	VISEntry
169478b8fecSSam Ravnborg	ldub		[%g6 + TI_FAULT_CODE], %g3
170478b8fecSSam Ravnborg	mov		%o0, %g1
171478b8fecSSam Ravnborg	cmp		%g3, 0
172478b8fecSSam Ravnborg	rd		%asi, %g3
173478b8fecSSam Ravnborg	be,a,pt		%icc, 1f
174478b8fecSSam Ravnborg	 wr		%g0, ASI_BLK_P, %asi
175478b8fecSSam Ravnborg	wr		%g0, ASI_BLK_COMMIT_P, %asi
176478b8fecSSam Ravnborg1:	ldda		[%o1] ASI_BLK_P, %f0
177478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
178478b8fecSSam Ravnborg	ldda		[%o1] ASI_BLK_P, %f16
179478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
180478b8fecSSam Ravnborg	sethi		%hi(PAGE_SIZE), %o2
181478b8fecSSam Ravnborg1:	TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
182478b8fecSSam Ravnborg	ldda		[%o1] ASI_BLK_P, %f32
183478b8fecSSam Ravnborg	stda		%f48, [%o0] %asi
184478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
185478b8fecSSam Ravnborg	sub		%o2, 0x40, %o2
186478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
187478b8fecSSam Ravnborg	TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
188478b8fecSSam Ravnborg	ldda		[%o1] ASI_BLK_P, %f0
189478b8fecSSam Ravnborg	stda		%f48, [%o0] %asi
190478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
191478b8fecSSam Ravnborg	sub		%o2, 0x40, %o2
192478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
193478b8fecSSam Ravnborg	TOUCH(f32, f34, f36, f38, f40, f42, f44, f46)
194478b8fecSSam Ravnborg	ldda		[%o1] ASI_BLK_P, %f16
195478b8fecSSam Ravnborg	stda		%f48, [%o0] %asi
196478b8fecSSam Ravnborg	sub		%o2, 0x40, %o2
197478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
198478b8fecSSam Ravnborg	cmp		%o2, PAGE_SIZE_REM
199478b8fecSSam Ravnborg	bne,pt		%xcc, 1b
200478b8fecSSam Ravnborg	 add		%o0, 0x40, %o0
201478b8fecSSam Ravnborg#if (PAGE_SHIFT == 16)
202478b8fecSSam Ravnborg	TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
203478b8fecSSam Ravnborg	ldda		[%o1] ASI_BLK_P, %f32
204478b8fecSSam Ravnborg	stda		%f48, [%o0] %asi
205478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
206478b8fecSSam Ravnborg	sub		%o2, 0x40, %o2
207478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
208478b8fecSSam Ravnborg	TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
209478b8fecSSam Ravnborg	ldda		[%o1] ASI_BLK_P, %f0
210478b8fecSSam Ravnborg	stda		%f48, [%o0] %asi
211478b8fecSSam Ravnborg	add		%o1, 0x40, %o1
212478b8fecSSam Ravnborg	sub		%o2, 0x40, %o2
213478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
214478b8fecSSam Ravnborg	membar		#Sync
215478b8fecSSam Ravnborg	stda		%f32, [%o0] %asi
216478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
217478b8fecSSam Ravnborg	stda		%f0, [%o0] %asi
218478b8fecSSam Ravnborg#else
219478b8fecSSam Ravnborg	membar		#Sync
220478b8fecSSam Ravnborg	stda		%f0, [%o0] %asi
221478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
222478b8fecSSam Ravnborg	stda		%f16, [%o0] %asi
223478b8fecSSam Ravnborg#endif
224478b8fecSSam Ravnborg	membar		#Sync
225478b8fecSSam Ravnborg	wr		%g3, 0x0, %asi
226478b8fecSSam Ravnborg	VISExit
227478b8fecSSam Ravnborg
228478b8fecSSam Ravnborg5:
229478b8fecSSam Ravnborg	stxa		%g0, [%g1] ASI_DMMU_DEMAP
230478b8fecSSam Ravnborg	membar		#Sync
231478b8fecSSam Ravnborg
232478b8fecSSam Ravnborg	sethi		%hi(DCACHE_SIZE), %g2
233478b8fecSSam Ravnborg	stxa		%g0, [%g1 + %g2] ASI_DMMU_DEMAP
234478b8fecSSam Ravnborg	membar		#Sync
235478b8fecSSam Ravnborg
236478b8fecSSam Ravnborg	retl
237478b8fecSSam Ravnborg	 stw		%o4, [%g6 + TI_PRE_COUNT]
238478b8fecSSam Ravnborg
239478b8fecSSam Ravnborg	.size		copy_user_page, .-copy_user_page
240478b8fecSSam Ravnborg
241478b8fecSSam Ravnborg	.globl		cheetah_patch_copy_page
242478b8fecSSam Ravnborgcheetah_patch_copy_page:
243478b8fecSSam Ravnborg	sethi		%hi(0x01000000), %o1	! NOP
244478b8fecSSam Ravnborg	sethi		%hi(cheetah_copy_page_insn), %o0
245478b8fecSSam Ravnborg	or		%o0, %lo(cheetah_copy_page_insn), %o0
246478b8fecSSam Ravnborg	stw		%o1, [%o0]
247478b8fecSSam Ravnborg	membar		#StoreStore
248478b8fecSSam Ravnborg	flush		%o0
249478b8fecSSam Ravnborg	retl
250478b8fecSSam Ravnborg	 nop
251