diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sparc64/lib/copy_in_user.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sparc64/lib/copy_in_user.S')
-rw-r--r-- | arch/sparc64/lib/copy_in_user.S | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/arch/sparc64/lib/copy_in_user.S b/arch/sparc64/lib/copy_in_user.S new file mode 100644 index 000000000000..816076c0bc06 --- /dev/null +++ b/arch/sparc64/lib/copy_in_user.S | |||
@@ -0,0 +1,119 @@ | |||
1 | /* copy_in_user.S: Copy from userspace to userspace. | ||
2 | * | ||
3 | * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) | ||
4 | */ | ||
5 | |||
6 | #include <asm/asi.h> | ||
7 | |||
8 | #define XCC xcc | ||
9 | |||
10 | #define EX(x,y) \ | ||
11 | 98: x,y; \ | ||
12 | .section .fixup; \ | ||
13 | .align 4; \ | ||
14 | 99: retl; \ | ||
15 | mov 1, %o0; \ | ||
16 | .section __ex_table; \ | ||
17 | .align 4; \ | ||
18 | .word 98b, 99b; \ | ||
19 | .text; \ | ||
20 | .align 4; | ||
21 | |||
22 | .register %g2,#scratch | ||
23 | .register %g3,#scratch | ||
24 | |||
25 | .text | ||
26 | .align 32 | ||
27 | |||
28 | /* Don't try to get too fancy here, just nice and | ||
29 | * simple. This is predominantly used for well aligned | ||
30 | * small copies in the compat layer. It is also used | ||
31 | * to copy register windows around during thread cloning. | ||
32 | */ | ||
33 | |||
34 | .globl ___copy_in_user | ||
35 | .type ___copy_in_user,#function | ||
36 | ___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ | ||
37 | /* Writing to %asi is _expensive_ so we hardcode it. | ||
38 | * Reading %asi to check for KERNEL_DS is comparatively | ||
39 | * cheap. | ||
40 | */ | ||
41 | rd %asi, %g1 | ||
42 | cmp %g1, ASI_AIUS | ||
43 | bne,pn %icc, memcpy_user_stub | ||
44 | nop | ||
45 | |||
46 | cmp %o2, 0 | ||
47 | be,pn %XCC, 85f | ||
48 | or %o0, %o1, %o3 | ||
49 | cmp %o2, 16 | ||
50 | bleu,a,pn %XCC, 80f | ||
51 | or %o3, %o2, %o3 | ||
52 | |||
53 | /* 16 < len <= 64 */ | ||
54 | andcc %o3, 0x7, %g0 | ||
55 | bne,pn %XCC, 90f | ||
56 | sub %o0, %o1, %o3 | ||
57 | |||
58 | andn %o2, 0x7, %o4 | ||
59 | and %o2, 0x7, %o2 | ||
60 | 1: subcc %o4, 0x8, %o4 | ||
61 | EX(ldxa [%o1] %asi, %o5) | ||
62 | EX(stxa %o5, [%o1 + %o3] ASI_AIUS) | ||
63 | bgu,pt %XCC, 1b | ||
64 | add %o1, 0x8, %o1 | ||
65 | andcc %o2, 0x4, %g0 | ||
66 | be,pt %XCC, 1f | ||
67 | nop | ||
68 | sub %o2, 0x4, %o2 | ||
69 | EX(lduwa [%o1] %asi, %o5) | ||
70 | EX(stwa %o5, [%o1 + %o3] ASI_AIUS) | ||
71 | add %o1, 0x4, %o1 | ||
72 | 1: cmp %o2, 0 | ||
73 | be,pt %XCC, 85f | ||
74 | nop | ||
75 | ba,pt %xcc, 90f | ||
76 | nop | ||
77 | |||
78 | 80: /* 0 < len <= 16 */ | ||
79 | andcc %o3, 0x3, %g0 | ||
80 | bne,pn %XCC, 90f | ||
81 | sub %o0, %o1, %o3 | ||
82 | |||
83 | 82: | ||
84 | subcc %o2, 4, %o2 | ||
85 | EX(lduwa [%o1] %asi, %g1) | ||
86 | EX(stwa %g1, [%o1 + %o3] ASI_AIUS) | ||
87 | bgu,pt %XCC, 82b | ||
88 | add %o1, 4, %o1 | ||
89 | |||
90 | 85: retl | ||
91 | clr %o0 | ||
92 | |||
93 | .align 32 | ||
94 | 90: | ||
95 | subcc %o2, 1, %o2 | ||
96 | EX(lduba [%o1] %asi, %g1) | ||
97 | EX(stba %g1, [%o1 + %o3] ASI_AIUS) | ||
98 | bgu,pt %XCC, 90b | ||
99 | add %o1, 1, %o1 | ||
100 | retl | ||
101 | clr %o0 | ||
102 | |||
103 | .size ___copy_in_user, .-___copy_in_user | ||
104 | |||
105 | /* Act like copy_{to,in}_user(), ie. return zero instead | ||
106 | * of original destination pointer. This is invoked when | ||
107 | * copy_{to,in}_user() finds that %asi is kernel space. | ||
108 | */ | ||
109 | .globl memcpy_user_stub | ||
110 | .type memcpy_user_stub,#function | ||
111 | memcpy_user_stub: | ||
112 | save %sp, -192, %sp | ||
113 | mov %i0, %o0 | ||
114 | mov %i1, %o1 | ||
115 | call memcpy | ||
116 | mov %i2, %o2 | ||
117 | ret | ||
118 | restore %g0, %g0, %o0 | ||
119 | .size memcpy_user_stub, .-memcpy_user_stub | ||