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