1/* 2 * linux/arch/arm/lib/uaccess-armo.S 3 * 4 * Copyright (C) 1998 Russell King 5 * 6 * Note! Some code fragments found in here have a special calling 7 * convention - they are not APCS compliant! 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13#include <linux/linkage.h> 14#include <asm/assembler.h> 15 16 .text 17 18 .globl SYMBOL_NAME(uaccess_user) 19SYMBOL_NAME(uaccess_user): 20 .word uaccess_user_put_byte 21 .word uaccess_user_get_byte 22 .word uaccess_user_put_half 23 .word uaccess_user_get_half 24 .word uaccess_user_put_word 25 .word uaccess_user_get_word 26 .word __arch_copy_from_user 27 .word __arch_copy_to_user 28 .word __arch_clear_user 29 .word __arch_strncpy_from_user 30 .word __arch_strnlen_user 31 32 33@ In : r0 = x, r1 = addr, r2 = error 34@ Out: r2 = error 35uaccess_user_put_byte: 36 stmfd sp!, {lr} 37USER( strbt r0, [r1]) 38 ldmfd sp!, {pc}^ 39 40@ In : r0 = x, r1 = addr, r2 = error 41@ Out: r2 = error 42uaccess_user_put_half: 43 stmfd sp!, {lr} 44USER( strbt r0, [r1], #1) 45 mov r0, r0, lsr #8 46USER( strbt r0, [r1]) 47 ldmfd sp!, {pc}^ 48 49@ In : r0 = x, r1 = addr, r2 = error 50@ Out: r2 = error 51uaccess_user_put_word: 52 stmfd sp!, {lr} 53USER( strt r0, [r1]) 54 ldmfd sp!, {pc}^ 55 569001: mov r2, #-EFAULT 57 ldmfd sp!, {pc}^ 58 59@ In : r0 = addr, r1 = error 60@ Out: r0 = x, r1 = error 61uaccess_user_get_byte: 62 stmfd sp!, {lr} 63USER( ldrbt r0, [r0]) 64 ldmfd sp!, {pc}^ 65 66@ In : r0 = addr, r1 = error 67@ Out: r0 = x, r1 = error 68uaccess_user_get_half: 69 stmfd sp!, {lr} 70USER( ldrt r0, [r0]) 71 mov r0, r0, lsl #16 72 mov r0, r0, lsr #16 73 ldmfd sp!, {pc}^ 74 75@ In : r0 = addr, r1 = error 76@ Out: r0 = x, r1 = error 77uaccess_user_get_word: 78 stmfd sp!, {lr} 79USER( ldrt r0, [r0]) 80 ldmfd sp!, {pc}^ 81 829001: mov r1, #-EFAULT 83 ldmfd sp!, {pc}^ 84 85 86 87 .globl SYMBOL_NAME(uaccess_kernel) 88SYMBOL_NAME(uaccess_kernel): 89 .word uaccess_kernel_put_byte 90 .word uaccess_kernel_get_byte 91 .word uaccess_kernel_put_half 92 .word uaccess_kernel_get_half 93 .word uaccess_kernel_put_word 94 .word uaccess_kernel_get_word 95 .word uaccess_kernel_copy 96 .word uaccess_kernel_copy 97 .word uaccess_kernel_clear 98 .word uaccess_kernel_strncpy_from 99 .word uaccess_kernel_strnlen 100 101@ In : r0 = x, r1 = addr, r2 = error 102@ Out: r2 = error 103uaccess_kernel_put_byte: 104 stmfd sp!, {lr} 105 strb r0, [r1] 106 ldmfd sp!, {pc}^ 107 108@ In : r0 = x, r1 = addr, r2 = error 109@ Out: r2 = error 110uaccess_kernel_put_half: 111 stmfd sp!, {lr} 112 strb r0, [r1] 113 mov r0, r0, lsr #8 114 strb r0, [r1, #1] 115 ldmfd sp!, {pc}^ 116 117@ In : r0 = x, r1 = addr, r2 = error 118@ Out: r2 = error 119uaccess_kernel_put_word: 120 stmfd sp!, {lr} 121 str r0, [r1] 122 ldmfd sp!, {pc}^ 123 124@ In : r0 = addr, r1 = error 125@ Out: r0 = x, r1 = error 126uaccess_kernel_get_byte: 127 stmfd sp!, {lr} 128 ldrb r0, [r0] 129 ldmfd sp!, {pc}^ 130 131@ In : r0 = addr, r1 = error 132@ Out: r0 = x, r1 = error 133uaccess_kernel_get_half: 134 stmfd sp!, {lr} 135 ldr r0, [r0] 136 mov r0, r0, lsl #16 137 mov r0, r0, lsr #16 138 ldmfd sp!, {pc}^ 139 140@ In : r0 = addr, r1 = error 141@ Out: r0 = x, r1 = error 142uaccess_kernel_get_word: 143 stmfd sp!, {lr} 144 ldr r0, [r0] 145 ldmfd sp!, {pc}^ 146 147 148/* Prototype: int uaccess_kernel_copy(void *to, const char *from, size_t n) 149 * Purpose : copy a block to kernel memory from kernel memory 150 * Params : to - kernel memory 151 * : from - kernel memory 152 * : n - number of bytes to copy 153 * Returns : Number of bytes NOT copied. 154 */ 155uaccess_kernel_copy: 156 stmfd sp!, {lr} 157 bl SYMBOL_NAME(memcpy) 158 mov r0, #0 159 ldmfd sp!, {pc}^ 160 161/* Prototype: int uaccess_kernel_clear(void *addr, size_t sz) 162 * Purpose : clear some kernel memory 163 * Params : addr - kernel memory address to clear 164 * : sz - number of bytes to clear 165 * Returns : number of bytes NOT cleared 166 */ 167uaccess_kernel_clear: 168 stmfd sp!, {lr} 169 mov r2, #0 170 cmp r1, #4 171 blt 2f 172 ands ip, r0, #3 173 beq 1f 174 cmp ip, #1 175 strb r2, [r0], #1 176 strleb r2, [r0], #1 177 strltb r2, [r0], #1 178 rsb ip, ip, #4 179 sub r1, r1, ip @ 7 6 5 4 3 2 1 1801: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7 181 bmi 2f 182 str r2, [r0], #4 183 str r2, [r0], #4 184 b 1b 1852: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3 186 strpl r2, [r0], #4 187 tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x 188 strneb r2, [r0], #1 189 strneb r2, [r0], #1 190 tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1 191 strneb r2, [r0], #1 192 mov r0, #0 193 ldmfd sp!, {pc}^ 194 195/* Prototype: size_t uaccess_kernel_strncpy_from(char *dst, char *src, size_t len) 196 * Purpose : copy a string from kernel memory to kernel memory 197 * Params : dst - kernel memory destination 198 * : src - kernel memory source 199 * : len - maximum length of string 200 * Returns : number of characters copied 201 */ 202uaccess_kernel_strncpy_from: 203 stmfd sp!, {lr} 204 mov ip, r2 2051: subs r2, r2, #1 206 bmi 2f 207 ldrb r3, [r1], #1 208 strb r3, [r0], #1 209 teq r3, #0 210 bne 1b 2112: subs r0, ip, r2 212 ldmfd sp!, {pc}^ 213 214/* Prototype: int uaccess_kernel_strlen(char *str, long n) 215 * Purpose : get length of a string in kernel memory 216 * Params : str - address of string in kernel memory 217 * Returns : length of string *including terminator*, 218 * or zero on exception, or n + 1 if too long 219 */ 220uaccess_kernel_strnlen: 221 stmfd sp!, {lr} 222 mov r2, r0 2231: ldrb r1, [r0], #1 224 teq r1, #0 225 beq 2f 226 subs r1, r1, #1 227 bne 1b 228 add r0, r0, #1 2292: sub r0, r0, r2 230 ldmfd sp!, {pc}^ 231 232