1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * This routine clears to zero a linear memory buffer in user space.
4  *
5  * Inputs:
6  *	in0:	address of buffer
7  *	in1:	length of buffer in bytes
8  * Outputs:
9  *	r8:	number of bytes that didn't get cleared due to a fault
10  *
11  * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
12  *	Stephane Eranian <eranian@hpl.hp.com>
13  */
14 
15 #include <asm/asmmacro.h>
16 #include <asm/export.h>
17 
18 //
19 // arguments
20 //
21 #define buf		r32
22 #define len		r33
23 
24 //
25 // local registers
26 //
27 #define cnt		r16
28 #define buf2		r17
29 #define saved_lc	r18
30 #define saved_pfs	r19
31 #define tmp		r20
32 #define len2		r21
33 #define len3		r22
34 
35 //
36 // Theory of operations:
37 //	- we check whether or not the buffer is small, i.e., less than 17
38 //	  in which case we do the byte by byte loop.
39 //
40 //	- Otherwise we go progressively from 1 byte store to 8byte store in
41 //	  the head part, the body is a 16byte store loop and we finish we the
42 //	  tail for the last 15 bytes.
43 //	  The good point about this breakdown is that the long buffer handling
44 //	  contains only 2 branches.
45 //
46 //	The reason for not using shifting & masking for both the head and the
47 //	tail is to stay semantically correct. This routine is not supposed
48 //	to write bytes outside of the buffer. While most of the time this would
49 //	be ok, we can't tolerate a mistake. A classical example is the case
50 //	of multithreaded code were to the extra bytes touched is actually owned
51 //	by another thread which runs concurrently to ours. Another, less likely,
52 //	example is with device drivers where reading an I/O mapped location may
53 //	have side effects (same thing for writing).
54 //
55 
56 GLOBAL_ENTRY(__do_clear_user)
57 	.prologue
58 	.save ar.pfs, saved_pfs
59 	alloc	saved_pfs=ar.pfs,2,0,0,0
60 	cmp.eq p6,p0=r0,len		// check for zero length
61 	.save ar.lc, saved_lc
62 	mov saved_lc=ar.lc		// preserve ar.lc (slow)
63 	.body
64 	;;				// avoid WAW on CFM
65 	adds tmp=-1,len			// br.ctop is repeat/until
66 	mov ret0=len			// return value is length at this point
67 (p6)	br.ret.spnt.many rp
68 	;;
69 	cmp.lt p6,p0=16,len		// if len > 16 then long memset
70 	mov ar.lc=tmp			// initialize lc for small count
71 (p6)	br.cond.dptk .long_do_clear
72 	;;				// WAR on ar.lc
73 	//
74 	// worst case 16 iterations, avg 8 iterations
75 	//
76 	// We could have played with the predicates to use the extra
77 	// M slot for 2 stores/iteration but the cost the initialization
78 	// the various counters compared to how long the loop is supposed
79 	// to last on average does not make this solution viable.
80 	//
81 1:
82 	EX( .Lexit1, st1 [buf]=r0,1 )
83 	adds len=-1,len			// countdown length using len
84 	br.cloop.dptk 1b
85 	;;				// avoid RAW on ar.lc
86 	//
87 	// .Lexit4: comes from byte by byte loop
88 	//	    len contains bytes left
89 .Lexit1:
90 	mov ret0=len			// faster than using ar.lc
91 	mov ar.lc=saved_lc
92 	br.ret.sptk.many rp		// end of short clear_user
93 
94 
95 	//
96 	// At this point we know we have more than 16 bytes to copy
97 	// so we focus on alignment (no branches required)
98 	//
99 	// The use of len/len2 for countdown of the number of bytes left
100 	// instead of ret0 is due to the fact that the exception code
101 	// changes the values of r8.
102 	//
103 .long_do_clear:
104 	tbit.nz p6,p0=buf,0		// odd alignment (for long_do_clear)
105 	;;
106 	EX( .Lexit3, (p6) st1 [buf]=r0,1 )	// 1-byte aligned
107 (p6)	adds len=-1,len;;		// sync because buf is modified
108 	tbit.nz p6,p0=buf,1
109 	;;
110 	EX( .Lexit3, (p6) st2 [buf]=r0,2 )	// 2-byte aligned
111 (p6)	adds len=-2,len;;
112 	tbit.nz p6,p0=buf,2
113 	;;
114 	EX( .Lexit3, (p6) st4 [buf]=r0,4 )	// 4-byte aligned
115 (p6)	adds len=-4,len;;
116 	tbit.nz p6,p0=buf,3
117 	;;
118 	EX( .Lexit3, (p6) st8 [buf]=r0,8 )	// 8-byte aligned
119 (p6)	adds len=-8,len;;
120 	shr.u cnt=len,4		// number of 128-bit (2x64bit) words
121 	;;
122 	cmp.eq p6,p0=r0,cnt
123 	adds tmp=-1,cnt
124 (p6)	br.cond.dpnt .dotail		// we have less than 16 bytes left
125 	;;
126 	adds buf2=8,buf			// setup second base pointer
127 	mov ar.lc=tmp
128 	;;
129 
130 	//
131 	// 16bytes/iteration core loop
132 	//
133 	// The second store can never generate a fault because
134 	// we come into the loop only when we are 16-byte aligned.
135 	// This means that if we cross a page then it will always be
136 	// in the first store and never in the second.
137 	//
138 	//
139 	// We need to keep track of the remaining length. A possible (optimistic)
140 	// way would be to use ar.lc and derive how many byte were left by
141 	// doing : left= 16*ar.lc + 16.  this would avoid the addition at
142 	// every iteration.
143 	// However we need to keep the synchronization point. A template
144 	// M;;MB does not exist and thus we can keep the addition at no
145 	// extra cycle cost (use a nop slot anyway). It also simplifies the
146 	// (unlikely)  error recovery code
147 	//
148 
149 2:	EX(.Lexit3, st8 [buf]=r0,16 )
150 	;;				// needed to get len correct when error
151 	st8 [buf2]=r0,16
152 	adds len=-16,len
153 	br.cloop.dptk 2b
154 	;;
155 	mov ar.lc=saved_lc
156 	//
157 	// tail correction based on len only
158 	//
159 	// We alternate the use of len3,len2 to allow parallelism and correct
160 	// error handling. We also reuse p6/p7 to return correct value.
161 	// The addition of len2/len3 does not cost anything more compared to
162 	// the regular memset as we had empty slots.
163 	//
164 .dotail:
165 	mov len2=len			// for parallelization of error handling
166 	mov len3=len
167 	tbit.nz p6,p0=len,3
168 	;;
169 	EX( .Lexit2, (p6) st8 [buf]=r0,8 )	// at least 8 bytes
170 (p6)	adds len3=-8,len2
171 	tbit.nz p7,p6=len,2
172 	;;
173 	EX( .Lexit2, (p7) st4 [buf]=r0,4 )	// at least 4 bytes
174 (p7)	adds len2=-4,len3
175 	tbit.nz p6,p7=len,1
176 	;;
177 	EX( .Lexit2, (p6) st2 [buf]=r0,2 )	// at least 2 bytes
178 (p6)	adds len3=-2,len2
179 	tbit.nz p7,p6=len,0
180 	;;
181 	EX( .Lexit2, (p7) st1 [buf]=r0 )	// only 1 byte left
182 	mov ret0=r0				// success
183 	br.ret.sptk.many rp			// end of most likely path
184 
185 	//
186 	// Outlined error handling code
187 	//
188 
189 	//
190 	// .Lexit3: comes from core loop, need restore pr/lc
191 	//	    len contains bytes left
192 	//
193 	//
194 	// .Lexit2:
195 	//	if p6 -> coming from st8 or st2 : len2 contains what's left
196 	//	if p7 -> coming from st4 or st1 : len3 contains what's left
197 	// We must restore lc/pr even though might not have been used.
198 .Lexit2:
199 	.pred.rel "mutex", p6, p7
200 (p6)	mov len=len2
201 (p7)	mov len=len3
202 	;;
203 	//
204 	// .Lexit4: comes from head, need not restore pr/lc
205 	//	    len contains bytes left
206 	//
207 .Lexit3:
208 	mov ret0=len
209 	mov ar.lc=saved_lc
210 	br.ret.sptk.many rp
211 END(__do_clear_user)
212 EXPORT_SYMBOL(__do_clear_user)
213