1/* 2 * linux/arch/arm/lib/copy_to_user.S 3 * 4 * Author: Nicolas Pitre 5 * Created: Sep 29, 2005 6 * Copyright: MontaVista Software, Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/linkage.h> 14#include <asm/assembler.h> 15#include <asm/unwind.h> 16 17/* 18 * Prototype: 19 * 20 * size_t arm_copy_to_user(void *to, const void *from, size_t n) 21 * 22 * Purpose: 23 * 24 * copy a block to user memory from kernel memory 25 * 26 * Params: 27 * 28 * to = user memory 29 * from = kernel memory 30 * n = number of bytes to copy 31 * 32 * Return value: 33 * 34 * Number of bytes NOT copied. 35 */ 36 37#define LDR1W_SHIFT 0 38 39 .macro ldr1w ptr reg abort 40 W(ldr) \reg, [\ptr], #4 41 .endm 42 43 .macro ldr4w ptr reg1 reg2 reg3 reg4 abort 44 ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4} 45 .endm 46 47 .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 48 ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} 49 .endm 50 51 .macro ldr1b ptr reg cond=al abort 52 ldr\cond\()b \reg, [\ptr], #1 53 .endm 54 55#ifdef CONFIG_CPU_USE_DOMAINS 56 57#ifndef CONFIG_THUMB2_KERNEL 58#define STR1W_SHIFT 0 59#else 60#define STR1W_SHIFT 1 61#endif 62 63 .macro str1w ptr reg abort 64 strusr \reg, \ptr, 4, abort=\abort 65 .endm 66 67 .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 68 str1w \ptr, \reg1, \abort 69 str1w \ptr, \reg2, \abort 70 str1w \ptr, \reg3, \abort 71 str1w \ptr, \reg4, \abort 72 str1w \ptr, \reg5, \abort 73 str1w \ptr, \reg6, \abort 74 str1w \ptr, \reg7, \abort 75 str1w \ptr, \reg8, \abort 76 .endm 77 78#else 79 80#define STR1W_SHIFT 0 81 82 .macro str1w ptr reg abort 83 USERL(\abort, W(str) \reg, [\ptr], #4) 84 .endm 85 86 .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 87 USERL(\abort, stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}) 88 .endm 89 90#endif /* CONFIG_CPU_USE_DOMAINS */ 91 92 .macro str1b ptr reg cond=al abort 93 strusr \reg, \ptr, 1, \cond, abort=\abort 94 .endm 95 96 .macro enter reg1 reg2 97 mov r3, #0 98 stmdb sp!, {r0, r2, r3, \reg1, \reg2} 99 .endm 100 101 .macro usave reg1 reg2 102 UNWIND( .save {r0, r2, r3, \reg1, \reg2} ) 103 .endm 104 105 .macro exit reg1 reg2 106 add sp, sp, #8 107 ldmfd sp!, {r0, \reg1, \reg2} 108 .endm 109 110 .text 111 112ENTRY(__copy_to_user_std) 113WEAK(arm_copy_to_user) 114#ifdef CONFIG_CPU_SPECTRE 115 get_thread_info r3 116 ldr r3, [r3, #TI_ADDR_LIMIT] 117 uaccess_mask_range_ptr r0, r2, r3, ip 118#endif 119 120#include "copy_template.S" 121 122ENDPROC(arm_copy_to_user) 123ENDPROC(__copy_to_user_std) 124 125 .pushsection .text.fixup,"ax" 126 .align 0 127 copy_abort_preamble 128 ldmfd sp!, {r1, r2, r3} 129 sub r0, r0, r1 130 rsb r0, r0, r2 131 copy_abort_end 132 .popsection 133