162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/arch/arm/lib/copy_to_user.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Nicolas Pitre 662306a36Sopenharmony_ci * Created: Sep 29, 2005 762306a36Sopenharmony_ci * Copyright: MontaVista Software, Inc. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/linkage.h> 1162306a36Sopenharmony_ci#include <asm/assembler.h> 1262306a36Sopenharmony_ci#include <asm/unwind.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * Prototype: 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * size_t arm_copy_to_user(void *to, const void *from, size_t n) 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Purpose: 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * copy a block to user memory from kernel memory 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Params: 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * to = user memory 2662306a36Sopenharmony_ci * from = kernel memory 2762306a36Sopenharmony_ci * n = number of bytes to copy 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Return value: 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * Number of bytes NOT copied. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define LDR1W_SHIFT 0 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci .macro ldr1w ptr reg abort 3762306a36Sopenharmony_ci W(ldr) \reg, [\ptr], #4 3862306a36Sopenharmony_ci .endm 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci .macro ldr4w ptr reg1 reg2 reg3 reg4 abort 4162306a36Sopenharmony_ci ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4} 4262306a36Sopenharmony_ci .endm 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 4562306a36Sopenharmony_ci ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} 4662306a36Sopenharmony_ci .endm 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci .macro ldr1b ptr reg cond=al abort 4962306a36Sopenharmony_ci ldrb\cond \reg, [\ptr], #1 5062306a36Sopenharmony_ci .endm 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#ifdef CONFIG_CPU_USE_DOMAINS 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#ifndef CONFIG_THUMB2_KERNEL 5562306a36Sopenharmony_ci#define STR1W_SHIFT 0 5662306a36Sopenharmony_ci#else 5762306a36Sopenharmony_ci#define STR1W_SHIFT 1 5862306a36Sopenharmony_ci#endif 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci .macro str1w ptr reg abort 6162306a36Sopenharmony_ci strusr \reg, \ptr, 4, abort=\abort 6262306a36Sopenharmony_ci .endm 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 6562306a36Sopenharmony_ci str1w \ptr, \reg1, \abort 6662306a36Sopenharmony_ci str1w \ptr, \reg2, \abort 6762306a36Sopenharmony_ci str1w \ptr, \reg3, \abort 6862306a36Sopenharmony_ci str1w \ptr, \reg4, \abort 6962306a36Sopenharmony_ci str1w \ptr, \reg5, \abort 7062306a36Sopenharmony_ci str1w \ptr, \reg6, \abort 7162306a36Sopenharmony_ci str1w \ptr, \reg7, \abort 7262306a36Sopenharmony_ci str1w \ptr, \reg8, \abort 7362306a36Sopenharmony_ci .endm 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#else 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define STR1W_SHIFT 0 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci .macro str1w ptr reg abort 8062306a36Sopenharmony_ci USERL(\abort, W(str) \reg, [\ptr], #4) 8162306a36Sopenharmony_ci .endm 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort 8462306a36Sopenharmony_ci USERL(\abort, stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}) 8562306a36Sopenharmony_ci .endm 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci#endif /* CONFIG_CPU_USE_DOMAINS */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci .macro str1b ptr reg cond=al abort 9062306a36Sopenharmony_ci strusr \reg, \ptr, 1, \cond, abort=\abort 9162306a36Sopenharmony_ci .endm 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci .macro enter regs:vararg 9462306a36Sopenharmony_ci mov r3, #0 9562306a36Sopenharmony_ciUNWIND( .save {r0, r2, r3, \regs} ) 9662306a36Sopenharmony_ci stmdb sp!, {r0, r2, r3, \regs} 9762306a36Sopenharmony_ci .endm 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci .macro exit regs:vararg 10062306a36Sopenharmony_ci add sp, sp, #8 10162306a36Sopenharmony_ci ldmfd sp!, {r0, \regs} 10262306a36Sopenharmony_ci .endm 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci .text 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ciENTRY(__copy_to_user_std) 10762306a36Sopenharmony_ciWEAK(arm_copy_to_user) 10862306a36Sopenharmony_ci#ifdef CONFIG_CPU_SPECTRE 10962306a36Sopenharmony_ci ldr r3, =TASK_SIZE 11062306a36Sopenharmony_ci uaccess_mask_range_ptr r0, r2, r3, ip 11162306a36Sopenharmony_ci#endif 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#include "copy_template.S" 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciENDPROC(arm_copy_to_user) 11662306a36Sopenharmony_ciENDPROC(__copy_to_user_std) 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci .pushsection .text.fixup,"ax" 11962306a36Sopenharmony_ci .align 0 12062306a36Sopenharmony_ci copy_abort_preamble 12162306a36Sopenharmony_ci ldmfd sp!, {r1, r2, r3} 12262306a36Sopenharmony_ci sub r0, r0, r1 12362306a36Sopenharmony_ci rsb r0, r0, r2 12462306a36Sopenharmony_ci copy_abort_end 12562306a36Sopenharmony_ci .popsection 126