yuezonghe | 824eb0c | 2024-06-27 02:32:26 -0700 | [diff] [blame^] | 1 | /* Copyright (C) 2000 Free Software Foundation, Inc. |
| 2 | This file is part of the GNU C Library. |
| 3 | |
| 4 | The GNU C Library is free software; you can redistribute it and/or |
| 5 | modify it under the terms of the GNU Lesser General Public |
| 6 | License as published by the Free Software Foundation; either |
| 7 | version 2.1 of the License, or (at your option) any later version. |
| 8 | |
| 9 | The GNU C Library is distributed in the hope that it will be useful, |
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | Lesser General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU Lesser General Public |
| 15 | License along with the GNU C Library; if not, write to the Free |
| 16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 17 | 02111-1307 USA. */ |
| 18 | |
| 19 | #include <features.h> |
| 20 | #define _ERRNO_H |
| 21 | #include <bits/errno.h> |
| 22 | #include <sys/syscall.h> |
| 23 | #include <bits/arm_asm.h> |
| 24 | |
| 25 | #if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 |
| 26 | |
| 27 | /* The mmap2 system call takes six arguments, all in registers. */ |
| 28 | .text |
| 29 | .global mmap64 |
| 30 | .type mmap64,%function |
| 31 | .align 2 |
| 32 | |
| 33 | #ifdef __ARM_EABI__ |
| 34 | #if defined(THUMB1_ONLY) |
| 35 | .thumb_func |
| 36 | mmap64: |
| 37 | #ifdef __ARMEB__ |
| 38 | /* Offsets are after pushing 3 words. */ |
| 39 | # define LOW_OFFSET 12 + 8 + 4 |
| 40 | # define HIGH_OFFSET 12 + 8 + 0 |
| 41 | #else |
| 42 | # define LOW_OFFSET 12 + 8 + 0 |
| 43 | # define HIGH_OFFSET 12 + 8 + 4 |
| 44 | #endif |
| 45 | push {r4, r5, r6} |
| 46 | ldr r6, [sp, $LOW_OFFSET] |
| 47 | ldr r5, [sp, $HIGH_OFFSET] |
| 48 | lsl r4, r6, #20 @ check that offset is page-aligned |
| 49 | bne .Linval |
| 50 | lsr r4, r5, #12 @ check for overflow |
| 51 | bne .Linval |
| 52 | @ compose page offset |
| 53 | lsr r6, r6, #12 |
| 54 | lsl r5, r5, #20 |
| 55 | orr r5, r5, r6 |
| 56 | ldr r4, [sp, #8] @ load fd |
| 57 | DO_CALL (mmap2) |
| 58 | ldr r1, =0xfffff000 |
| 59 | cmp r0, r1 |
| 60 | bcs .Lerror |
| 61 | bx lr |
| 62 | .Linval: |
| 63 | ldr r0, =-EINVAL |
| 64 | pop {r4, r5, r6} |
| 65 | .Lerror: |
| 66 | push {r3, lr} |
| 67 | bl __syscall_error |
| 68 | POP_RET |
| 69 | .pool |
| 70 | #else /* !THUMB1_ONLY */ |
| 71 | mmap64: |
| 72 | #ifdef __ARMEB__ |
| 73 | # define LOW_OFFSET 8 + 4 |
| 74 | /* The initial + 4 is for the stack postdecrement. */ |
| 75 | # define HIGH_OFFSET 4 + 8 + 0 |
| 76 | #else |
| 77 | # define LOW_OFFSET 8 + 0 |
| 78 | # define HIGH_OFFSET 4 + 8 + 4 |
| 79 | #endif |
| 80 | ldr ip, [sp, $LOW_OFFSET] |
| 81 | str r5, [sp, #-4]! |
| 82 | ldr r5, [sp, $HIGH_OFFSET] |
| 83 | str r4, [sp, #-4]! |
| 84 | movs r4, ip, lsl $20 @ check that offset is page-aligned |
| 85 | mov ip, ip, lsr $12 |
| 86 | IT(t, eq) |
| 87 | moveqs r4, r5, lsr $12 @ check for overflow |
| 88 | bne .Linval |
| 89 | ldr r4, [sp, $8] @ load fd |
| 90 | orr r5, ip, r5, lsl $20 @ compose page offset |
| 91 | DO_CALL (mmap2) |
| 92 | cmn r0, $4096 |
| 93 | ldmfd sp!, {r4, r5} |
| 94 | IT(t, cc) |
| 95 | #if defined(__USE_BX__) |
| 96 | bxcc lr |
| 97 | #else |
| 98 | movcc pc, lr |
| 99 | #endif |
| 100 | b __syscall_error |
| 101 | .Linval: |
| 102 | mov r0, $-EINVAL |
| 103 | ldmfd sp!, {r4, r5} |
| 104 | b __syscall_error |
| 105 | #endif |
| 106 | #else /* !__ARM_EABI__ */ |
| 107 | mmap64: |
| 108 | stmfd sp!, {r4, r5, lr} |
| 109 | ldr r5, [sp, $16] |
| 110 | ldr r4, [sp, $12] |
| 111 | movs ip, r5, lsl $20 @ check that offset is page-aligned |
| 112 | bne .Linval |
| 113 | ldr ip, [sp, $20] |
| 114 | mov r5, r5, lsr $12 |
| 115 | orr r5, r5, ip, lsl $20 @ compose page offset |
| 116 | movs ip, ip, lsr $12 |
| 117 | bne .Linval @ check for overflow |
| 118 | mov ip, r0 |
| 119 | DO_CALL (mmap2) |
| 120 | cmn r0, $4096 |
| 121 | ldmccfd sp!, {r4, r5, pc} |
| 122 | cmn r0, $ENOSYS |
| 123 | ldmnefd sp!, {r4, r5, lr} |
| 124 | bne __error |
| 125 | /* The current kernel does not support mmap2. Fall back to plain |
| 126 | mmap if the offset is small enough. */ |
| 127 | ldr r5, [sp, $20] |
| 128 | mov r0, ip @ first arg was clobbered |
| 129 | teq r5, $0 |
| 130 | ldmeqfd sp!, {r4, r5, lr} |
| 131 | beq HIDDEN_JUMPTARGET(mmap) |
| 132 | .Linval: |
| 133 | mov r0, $-EINVAL |
| 134 | ldmfd sp!, {r4, r5, lr} |
| 135 | b __error |
| 136 | |
| 137 | __error: |
| 138 | b __syscall_error |
| 139 | #endif |
| 140 | .size mmap64,.-mmap64 |
| 141 | |
| 142 | #endif |