-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcopy_from_user.S
More file actions
133 lines (115 loc) · 2.99 KB
/
copy_from_user.S
File metadata and controls
133 lines (115 loc) · 2.99 KB
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* linux/arch/arm/lib/copy_from_user.S
*
* Author: Nicolas Pitre
* Created: Sep 29, 2005
* Copyright: MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Prototype:
*
* size_t __copy_from_user(void *to, const void *from, size_t n)
*
* Purpose:
*
* copy a block to kernel memory from user memory
*
* Params:
*
* to = kernel memory
* from = user memory
* n = number of bytes to copy
*
* Return value:
*
* Number of bytes NOT copied.
*/
#ifndef CONFIG_THUMB2_KERNEL
#define LDR1W_SHIFT 0
#else
#define LDR1W_SHIFT 1
#endif
#define STR1W_SHIFT 0
.macro ldr1w ptr reg abort
ldrusr \reg, \ptr, 4, abort=\abort
.endm
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
ldr1w \ptr, \reg1, \abort
ldr1w \ptr, \reg2, \abort
ldr1w \ptr, \reg3, \abort
ldr1w \ptr, \reg4, \abort
.endm
.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
ldr4w \ptr, \reg1, \reg2, \reg3, \reg4, \abort
ldr4w \ptr, \reg5, \reg6, \reg7, \reg8, \abort
.endm
.macro ldr1b ptr reg cond=al abort
ldrusr \reg, \ptr, 1, \cond, abort=\abort
.endm
.macro str1w ptr reg abort
W(str) \reg, [\ptr], #4
.endm
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
.endm
.macro str1b ptr reg cond=al abort
str\cond\()b \reg, [\ptr], #1
.endm
.macro enter reg1 reg2
mov r3, #0
stmdb sp!, {r0, r2, r3, \reg1, \reg2}
#ifdef CONFIG_SCRIBE
@ r0 == kptr, r1 == uptr, those are already setup, but r1 needs to be saved
@ however, we save (again) r2 and r3, because their stack offsets depend
@ on whether reg1 or reg2 happens to be r1. r0 is always at the same offset.
stmfd sp!, {r1, r2, r3, lr}
@ r2 (size) is already setup
@ r3 (flags) needs to be loaded up w/ a constant
mov r3, #SCRIBE_DATA_INPUT
bl scribe_pre_uaccess
ldmfd sp, {r1, r2, r3, lr} @ note: does not update sp, b/c we need those values at exit as well
ldr r0, [sp, #16]
#endif /* CONFIG_SCRIBE */
.endm
.macro exit reg1 reg2
#ifdef CONFIG_SCRIBE
@ save regs that might get clobbered by the call
stmfd sp!, {r1, r2, r3, lr}
@ load up the argument values we saved on entry
ldr r1, [sp, #16]
ldr r2, [sp, #20]
ldr r0, [sp, #32]
mov r3, #SCRIBE_DATA_INPUT
bl scribe_post_uaccess
@ restore regs (not r0, it gets immediately clobbered below)
ldmfd sp!, {r1, r2, r3, lr}
@ get rid of the registers we saved in enter
add sp, sp, #16
#endif /* CONFIG_SCRIBE */
add sp, sp, #8
ldmfd sp!, {r0, \reg1, \reg2}
.endm
.text
ENTRY(__copy_from_user)
#include "copy_template.S"
ENDPROC(__copy_from_user)
.pushsection .fixup,"ax"
.align 0
copy_abort_preamble
#ifdef CONFIG_SCRIBE
add sp, sp, #16
#endif /* CONFIG_SCRIBE */
ldmfd sp!, {r1, r2}
sub r3, r0, r1
rsb r1, r3, r2
str r1, [sp]
bl __memzero
ldr r0, [sp], #4
copy_abort_end
.popsection