blob: 03a540a80e7ff881da37d3b58bc7c1a99298f743 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
/*
* This routine copies a linear memory buffer across the user/kernel boundary. When
* reading a byte from the source causes a fault, the remainder of the destination
* buffer is zeroed out. Note that this can happen only when copying from user
* to kernel memory and we do this to absolutely guarantee that the
* kernel doesn't operate on random data.
*
* This file is derived from arch/alpha/lib/copy_user.S.
*
* Inputs:
* in0: address of destination buffer
* in1: address of source buffer
* in2: length of buffer in bytes
* Outputs:
* r8: number of bytes that didn't get copied due to a fault
*
* Copyright (C) 1999 Hewlett-Packard Co
* Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
*/
#define EXI(x...) \
99: x; \
.section __ex_table,"a"; \
data4 @gprel(99b); \
data4 .Lexit_in-99b; \
.previous
#define EXO(x...) \
99: x; \
.section __ex_table,"a"; \
data4 @gprel(99b); \
data4 .Lexit_out-99b; \
.previous
.text
.psr abi64
.psr lsb
.lsb
.align 32
.global __copy_user
.proc __copy_user
__copy_user:
alloc r10=ar.pfs,3,0,0,0
mov r9=ar.lc // save ar.lc
mov ar.lc=in2 // set ar.lc to length of buffer
br.sptk.few .Lentr
// XXX braindead copy loop---this needs to be optimized
.Loop1:
EXI(ld1 r8=[in1],1)
;;
EXO(st1 [in0]=r8,1)
.Lentr: br.cloop.dptk.few .Loop1 // repeat unless ar.lc--==0
;; // avoid RAW on ar.lc
.Lexit_out:
mov r8=ar.lc // return how many bytes we _didn't_ copy
mov ar.lc=r9
br.ret.sptk.few rp
.Lexit_in:
// clear the remainder of the buffer:
mov r8=ar.lc // return how many bytes we _didn't_ copy
.Loop2:
st1 [in0]=r0,1 // this cannot fault because we get here only on user->kernel copies
br.cloop.dptk.few .Loop2
;; // avoid RAW on ar.lc
mov ar.lc=r9
br.ret.sptk.few rp
.endp __copy_user
|