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
133
134
135
136
137
138
139
140
141
142
|
/* Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <features.h>
#define _ERRNO_H
#include <bits/errno.h>
#include <sys/syscall.h>
#include <bits/arm_asm.h>
#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2
/* The mmap2 system call takes six arguments, all in registers. */
.text
.global mmap64
.type mmap64,%function
.align 2
#ifdef __ARM_EABI__
#if defined(THUMB1_ONLY)
.thumb_func
mmap64:
#ifdef __ARMEB__
/* Offsets are after pushing 3 words. */
# define LOW_OFFSET 12 + 8 + 4
# define HIGH_OFFSET 12 + 8 + 0
#else
# define LOW_OFFSET 12 + 8 + 0
# define HIGH_OFFSET 12 + 8 + 4
#endif
push {r4, r5, r6}
ldr r6, [sp, $LOW_OFFSET]
ldr r5, [sp, $HIGH_OFFSET]
lsl r4, r6, #20 @ check that offset is page-aligned
bne .Linval
lsr r4, r5, #12 @ check for overflow
bne .Linval
@ compose page offset
lsr r6, r6, #12
lsl r5, r5, #20
orr r5, r5, r6
ldr r4, [sp, #8] @ load fd
DO_CALL (mmap2)
ldr r1, =0xfffff000
cmp r0, r1
bcs .Lerror
bx lr
.Linval:
ldr r0, =-EINVAL
pop {r4, r5, r6}
.Lerror:
push {r3, lr}
bl __syscall_error
POP_RET
.pool
#else /* !THUMB1_ONLY */
mmap64:
#ifdef __ARMEB__
# define LOW_OFFSET 8 + 4
/* The initial + 4 is for the stack postdecrement. */
# define HIGH_OFFSET 4 + 8 + 0
#else
# define LOW_OFFSET 8 + 0
# define HIGH_OFFSET 4 + 8 + 4
#endif
ldr ip, [sp, $LOW_OFFSET]
str r5, [sp, #-4]!
ldr r5, [sp, $HIGH_OFFSET]
str r4, [sp, #-4]!
movs r4, ip, lsl $20 @ check that offset is page-aligned
mov ip, ip, lsr $12
IT(t, eq)
moveqs r4, r5, lsr $12 @ check for overflow
bne .Linval
ldr r4, [sp, $8] @ load fd
orr r5, ip, r5, lsl $20 @ compose page offset
DO_CALL (mmap2)
cmn r0, $4096
ldmfd sp!, {r4, r5}
IT(t, cc)
#if defined(__USE_BX__)
bxcc lr
#else
movcc pc, lr
#endif
b __syscall_error
.Linval:
mov r0, $-EINVAL
ldmfd sp!, {r4, r5}
b __syscall_error
#endif
#else /* !__ARM_EABI__ */
mmap64:
stmfd sp!, {r4, r5, lr}
ldr r5, [sp, $16]
ldr r4, [sp, $12]
movs ip, r5, lsl $20 @ check that offset is page-aligned
bne .Linval
ldr ip, [sp, $20]
mov r5, r5, lsr $12
orr r5, r5, ip, lsl $20 @ compose page offset
movs ip, ip, lsr $12
bne .Linval @ check for overflow
mov ip, r0
DO_CALL (mmap2)
cmn r0, $4096
ldmccfd sp!, {r4, r5, pc}
cmn r0, $ENOSYS
ldmnefd sp!, {r4, r5, lr}
bne __error
/* The current kernel does not support mmap2. Fall back to plain
mmap if the offset is small enough. */
ldr r5, [sp, $20]
mov r0, ip @ first arg was clobbered
teq r5, $0
ldmeqfd sp!, {r4, r5, lr}
beq HIDDEN_JUMPTARGET(mmap)
.Linval:
mov r0, $-EINVAL
ldmfd sp!, {r4, r5, lr}
b __error
__error:
b __syscall_error
#endif
.size mmap64,.-mmap64
#endif
|