Annotation of src/sys/arch/amd64/amd64/copy.S, Revision 1.4.10.1
1.4.10.1! matt 1: /* $NetBSD: copy.S,v 1.5 2007/05/17 14:51:13 yamt Exp $ */
1.1 fvdl 2:
3: /*
4: * Copyright (c) 2001 Wasabi Systems, Inc.
5: * All rights reserved.
6: *
7: * Written by Frank van der Linden for Wasabi Systems, Inc.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed for the NetBSD Project by
20: * Wasabi Systems, Inc.
21: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
23: * written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35: * POSSIBILITY OF SUCH DAMAGE.
36: */
37:
38: #include "assym.h"
39:
40: #include <sys/errno.h>
41: #include <sys/syscall.h>
42:
43: #include <machine/param.h>
44: #include <machine/asm.h>
45:
1.4.10.1! matt 46: #define GET_CURPCB(reg) \
! 47: movq CPUVAR(CURLWP), reg; \
! 48: movq L_ADDR(reg), reg
! 49:
1.1 fvdl 50: /*
51: * Copy routines from and to userland, plus a few more. See the
52: * section 9 manpages for info. Some cases can be optimized more.
53: *
54: * I wonder if it's worthwhile to make these use SSE2 registers.
55: */
56:
57: /*
58: * XXXfvdl appears only to be used by pccons.
59: *
1.4 christos 60: * fillw(short pattern, void *addr, size_t len);
1.1 fvdl 61: * Write len copies of pattern at addr.
62: * appears to be used by pccons.
63: */
64: ENTRY(fillw)
65: movl %edi,%eax
66: movq %rsi,%rdi
67: movw %ax,%cx
68: rorl $16,%eax
69: movw %cx,%ax
70: cld
71: movq %rdx,%rcx
72: shrq %rcx
73: rep
74: stosl
75: movq %rdx,%rcx
76: andq $1,%rcx
77: rep
78: stosw
79: ret
80:
81: ENTRY(kcopy)
1.4.10.1! matt 82: GET_CURPCB(%rax)
1.1 fvdl 83: pushq PCB_ONFAULT(%rax)
84: leaq _C_LABEL(copy_fault)(%rip),%r11
85: movq %r11, PCB_ONFAULT(%rax)
86:
87: xchgq %rdi,%rsi
88: movq %rdx,%rcx
89:
90: movq %rdi,%rax
91: subq %rsi,%rax
92: cmpq %rcx,%rax # overlapping?
93: jb 1f
94: cld # nope, copy forward
95: shrq $3,%rcx # copy by 64-bit words
96: rep
97: movsq
98:
99: movq %rdx,%rcx
100: andl $7,%ecx # any bytes left?
101: rep
102: movsb
103:
1.4.10.1! matt 104: GET_CURPCB(%rdx)
1.1 fvdl 105: popq PCB_ONFAULT(%rdx)
106: xorq %rax,%rax
107: ret
108:
109: 1: addq %rcx,%rdi # copy backward
110: addq %rcx,%rsi
111: std
112: andq $7,%rcx # any fractional bytes?
113: decq %rdi
114: decq %rsi
115: rep
116: movsb
117: movq %rdx,%rcx # copy remainder by 64-bit words
118: shrq $3,%rcx
119: subq $7,%rsi
120: subq $7,%rdi
121: rep
122: movsq
123: cld
124:
1.4.10.1! matt 125: GET_CURPCB(%rdx)
1.1 fvdl 126: popq PCB_ONFAULT(%rdx)
127: xorq %rax,%rax
128: ret
129:
130: ENTRY(copyout)
131: pushq $0
132:
133: xchgq %rdi,%rsi
134: movq %rdx,%rax
135:
136: movq %rdi,%rdx
137: addq %rax,%rdx
138: jc _C_LABEL(copy_efault)
139: movq $VM_MAXUSER_ADDRESS,%r8
140: cmpq %r8,%rdx
141: ja _C_LABEL(copy_efault)
142:
1.4.10.1! matt 143: GET_CURPCB(%rdx)
1.1 fvdl 144: leaq _C_LABEL(copy_fault)(%rip),%r11
145: movq %r11,PCB_ONFAULT(%rdx)
146:
147: cld
148: movq %rax,%rcx
149: shrq $3,%rcx
150: rep
151: movsq
152: movb %al,%cl
153: andb $7,%cl
154: rep
155: movsb
156:
157: popq PCB_ONFAULT(%rdx)
158: xorl %eax,%eax
159: ret
160:
161: ENTRY(copyin)
1.4.10.1! matt 162: GET_CURPCB(%rax)
1.1 fvdl 163: pushq $0
164: leaq _C_LABEL(copy_fault)(%rip),%r11
165: movq %r11,PCB_ONFAULT(%rax)
166:
167: xchgq %rdi,%rsi
168: movq %rdx,%rax
169:
170: movq %rsi,%rdx
171: addq %rax,%rdx
172: jc _C_LABEL(copy_efault)
173: movq $VM_MAXUSER_ADDRESS,%r8
174: cmpq %r8,%rdx
175: ja _C_LABEL(copy_efault)
176:
177: 3: /* bcopy(%rsi, %rdi, %rax); */
178: cld
179: movq %rax,%rcx
180: shrq $3,%rcx
181: rep
182: movsq
183: movb %al,%cl
184: andb $7,%cl
185: rep
186: movsb
187:
1.4.10.1! matt 188: GET_CURPCB(%rdx)
1.1 fvdl 189: popq PCB_ONFAULT(%rdx)
190: xorl %eax,%eax
191: ret
192:
193: NENTRY(copy_efault)
194: movq $EFAULT,%rax
195:
196: NENTRY(copy_fault)
1.4.10.1! matt 197: GET_CURPCB(%rdx)
1.1 fvdl 198: popq PCB_ONFAULT(%rdx)
199: ret
200:
201: ENTRY(copyoutstr)
202: xchgq %rdi,%rsi
203: movq %rdx,%r8
204: movq %rcx,%r9
205:
1.4.10.1! matt 206: 5: GET_CURPCB(%rax)
1.1 fvdl 207: leaq _C_LABEL(copystr_fault)(%rip),%r11
208: movq %r11,PCB_ONFAULT(%rax)
209: /*
210: * Get min(%rdx, VM_MAXUSER_ADDRESS-%rdi).
211: */
212: movq $VM_MAXUSER_ADDRESS,%rax
213: subq %rdi,%rax
1.2 fvdl 214: jc _C_LABEL(copystr_efault)
1.1 fvdl 215: cmpq %rdx,%rax
216: jae 1f
217: movq %rax,%rdx
218: movq %rax,%r8
219:
220: 1: incq %rdx
221: cld
222:
223: 1: decq %rdx
224: jz 2f
225: lodsb
226: stosb
227: testb %al,%al
228: jnz 1b
229:
230: /* Success -- 0 byte reached. */
231: decq %rdx
232: xorq %rax,%rax
233: jmp copystr_return
234:
235: 2: /* rdx is zero -- return EFAULT or ENAMETOOLONG. */
236: movq $VM_MAXUSER_ADDRESS,%r11
237: cmpq %r11,%rdi
238: jae _C_LABEL(copystr_efault)
239: movq $ENAMETOOLONG,%rax
240: jmp copystr_return
241:
242: ENTRY(copyinstr)
243: xchgq %rdi,%rsi
244: movq %rdx,%r8
245: movq %rcx,%r9
246:
1.4.10.1! matt 247: GET_CURPCB(%rcx)
1.1 fvdl 248: leaq _C_LABEL(copystr_fault)(%rip),%r11
249: movq %r11,PCB_ONFAULT(%rcx)
250:
251: /*
252: * Get min(%rdx, VM_MAXUSER_ADDRESS-%rsi).
253: */
254: movq $VM_MAXUSER_ADDRESS,%rax
255: subq %rsi,%rax
1.2 fvdl 256: jc _C_LABEL(copystr_efault)
1.1 fvdl 257: cmpq %rdx,%rax
258: jae 1f
259: movq %rax,%rdx
260: movq %rax,%r8
261:
262: 1: incq %rdx
263: cld
264:
265: 1: decq %rdx
266: jz 2f
267: lodsb
268: stosb
269: testb %al,%al
270: jnz 1b
271:
272: /* Success -- 0 byte reached. */
273: decq %rdx
274: xorq %rax,%rax
275: jmp copystr_return
276:
277: 2: /* edx is zero -- return EFAULT or ENAMETOOLONG. */
278: movq $VM_MAXUSER_ADDRESS,%r11
279: cmpq %r11,%rsi
280: jae _C_LABEL(copystr_efault)
281: movq $ENAMETOOLONG,%rax
282: jmp copystr_return
283:
284: ENTRY(copystr_efault)
285: movl $EFAULT,%eax
286:
287: ENTRY(copystr_fault)
288: copystr_return:
289: /* Set *lencopied and return %eax. */
1.4.10.1! matt 290: GET_CURPCB(%rcx)
1.1 fvdl 291: movq $0,PCB_ONFAULT(%rcx)
292: testq %r9,%r9
293: jz 8f
294: subq %rdx,%r8
295: movq %r8,(%r9)
296:
297: 8: ret
298:
299: ENTRY(copystr)
300: xchgq %rdi,%rsi
301: movq %rdx,%r8
302:
303: incq %rdx
304: cld
305:
306: 1: decq %rdx
307: jz 4f
308: lodsb
309: stosb
310: testb %al,%al
311: jnz 1b
312:
313: /* Success -- 0 byte reached. */
314: decq %rdx
315: xorl %eax,%eax
316: jmp 6f
317:
318: 4: /* edx is zero -- return ENAMETOOLONG. */
319: movl $ENAMETOOLONG,%eax
320:
321: 6: /* Set *lencopied and return %eax. */
322: testq %rcx,%rcx
323: jz 7f
324: subq %rdx,%r8
325: movq %r8,(%rcx)
326:
327: 7: ret
328:
329: ENTRY(fuword)
330: movq $VM_MAXUSER_ADDRESS-4,%r11
331: cmpq %r11,%rdi
332: ja _C_LABEL(fusuaddrfault)
1.4.10.1! matt 333: GET_CURPCB(%rcx)
1.1 fvdl 334: leaq _C_LABEL(fusufailure)(%rip),%r11
335: movq %r11,PCB_ONFAULT(%rcx)
336: movl (%rdi),%eax
337: movq $0,PCB_ONFAULT(%rcx)
338: ret
339:
340: ENTRY(fusword)
341: movq $VM_MAXUSER_ADDRESS-2,%r11
342: cmpq %r11,%rdi
343: ja _C_LABEL(fusuaddrfault)
1.4.10.1! matt 344: GET_CURPCB(%rcx)
1.1 fvdl 345: leaq _C_LABEL(fusufailure)(%rip),%r11
346: movq %r11,PCB_ONFAULT(%rcx)
347: movzwl (%rdi),%eax
348: movq $0,PCB_ONFAULT(%rcx)
349: ret
350:
351: ENTRY(fuswintr)
352: movq $VM_MAXUSER_ADDRESS-2,%r11
353: cmpq %r11,%rdi
354: ja _C_LABEL(fusuaddrfault)
1.4.10.1! matt 355: GET_CURPCB(%rcx)
1.1 fvdl 356: leaq _C_LABEL(fusuintrfailure)(%rip),%r11
357: movq %r11,PCB_ONFAULT(%rcx)
358: movzwl (%rdi),%eax
359: movq $0,PCB_ONFAULT(%rcx)
360: ret
361:
362: ENTRY(fubyte)
363: movq $VM_MAXUSER_ADDRESS-1,%r11
364: cmpq %r11,%rdi
365: ja _C_LABEL(fusuaddrfault)
1.4.10.1! matt 366: GET_CURPCB(%rcx)
1.1 fvdl 367: leaq _C_LABEL(fusuintrfailure)(%rip),%r11
368: movq %r11,PCB_ONFAULT(%rcx)
369: movzbl (%rdi),%eax
370: movq $0,PCB_ONFAULT(%rcx)
371: ret
372:
373: /*
374: * These are the same, but must reside at different addresses,
375: * because trap.c checks for them.
376: */
377: ENTRY(fusuintrfailure)
378: movq $0,PCB_ONFAULT(%rcx)
379: movl $-1,%eax
380: ret
381:
382: ENTRY(fusufailure)
383: movq $0,PCB_ONFAULT(%rcx)
384: movl $-1,%eax
385: ret
386:
387: ENTRY(fusuaddrfault)
388: movl $-1,%eax
389: ret
390:
391: ENTRY(suword)
392: movq $VM_MAXUSER_ADDRESS-4,%r11
393: cmpq %r11,%rdi
394: ja _C_LABEL(fusuaddrfault)
395:
1.4.10.1! matt 396: GET_CURPCB(%rcx)
1.1 fvdl 397: leaq _C_LABEL(fusufailure)(%rip),%r11
398: movq %r11,PCB_ONFAULT(%rcx)
399:
400: movq %rsi,(%rdi)
401: xorq %rax,%rax
402: movq %rax,PCB_ONFAULT(%rcx)
403: ret
404:
405: ENTRY(susword)
406: movq $VM_MAXUSER_ADDRESS-2,%r11
407: cmpq %r11,%rdi
408: ja _C_LABEL(fusuaddrfault)
409:
1.4.10.1! matt 410: GET_CURPCB(%rcx)
1.1 fvdl 411: leaq _C_LABEL(fusufailure)(%rip),%r11
412: movq %r11,PCB_ONFAULT(%rcx)
413:
414: movw %si,(%rdi)
415: xorq %rax,%rax
416: movq %rax,PCB_ONFAULT(%rcx)
417: ret
418:
419: ENTRY(suswintr)
420: movq $VM_MAXUSER_ADDRESS-2,%r11
421: cmpq %r11,%rdi
422: ja _C_LABEL(fusuaddrfault)
1.4.10.1! matt 423: GET_CURPCB(%rcx)
1.1 fvdl 424: leaq _C_LABEL(fusuintrfailure)(%rip),%r11
425: movq %r11,PCB_ONFAULT(%rcx)
426:
427: movw %si,(%rdi)
428: xorq %rax,%rax
429: movq %rax,PCB_ONFAULT(%rcx)
430: ret
431:
432: ENTRY(subyte)
433: movq $VM_MAXUSER_ADDRESS-1,%r11
434: cmpq %r11,%rdi
435: ja _C_LABEL(fusuaddrfault)
436:
1.4.10.1! matt 437: GET_CURPCB(%rcx)
1.1 fvdl 438: leaq _C_LABEL(fusufailure)(%rip),%r11
439: movq %r11,PCB_ONFAULT(%rcx)
440:
441: movb %sil,(%rdi)
442: xorq %rax,%rax
443: movq %rax,PCB_ONFAULT(%rcx)
444: ret
CVSweb <webmaster@jp.NetBSD.org>