1*0aea86a2SCatalin Marinas/* 2*0aea86a2SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 3*0aea86a2SCatalin Marinas * 4*0aea86a2SCatalin Marinas * This program is free software; you can redistribute it and/or modify 5*0aea86a2SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 6*0aea86a2SCatalin Marinas * published by the Free Software Foundation. 7*0aea86a2SCatalin Marinas * 8*0aea86a2SCatalin Marinas * This program is distributed in the hope that it will be useful, 9*0aea86a2SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 10*0aea86a2SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11*0aea86a2SCatalin Marinas * GNU General Public License for more details. 12*0aea86a2SCatalin Marinas * 13*0aea86a2SCatalin Marinas * You should have received a copy of the GNU General Public License 14*0aea86a2SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 15*0aea86a2SCatalin Marinas */ 16*0aea86a2SCatalin Marinas 17*0aea86a2SCatalin Marinas#include <linux/linkage.h> 18*0aea86a2SCatalin Marinas#include <asm/assembler.h> 19*0aea86a2SCatalin Marinas 20*0aea86a2SCatalin Marinas/* 21*0aea86a2SCatalin Marinas * Copy from user space to a kernel buffer (alignment handled by the hardware) 22*0aea86a2SCatalin Marinas * 23*0aea86a2SCatalin Marinas * Parameters: 24*0aea86a2SCatalin Marinas * x0 - to 25*0aea86a2SCatalin Marinas * x1 - from 26*0aea86a2SCatalin Marinas * x2 - n 27*0aea86a2SCatalin Marinas * Returns: 28*0aea86a2SCatalin Marinas * x0 - bytes not copied 29*0aea86a2SCatalin Marinas */ 30*0aea86a2SCatalin MarinasENTRY(__copy_from_user) 31*0aea86a2SCatalin Marinas add x4, x1, x2 // upper user buffer boundary 32*0aea86a2SCatalin Marinas subs x2, x2, #8 33*0aea86a2SCatalin Marinas b.mi 2f 34*0aea86a2SCatalin Marinas1: 35*0aea86a2SCatalin MarinasUSER(9f, ldr x3, [x1], #8 ) 36*0aea86a2SCatalin Marinas subs x2, x2, #8 37*0aea86a2SCatalin Marinas str x3, [x0], #8 38*0aea86a2SCatalin Marinas b.pl 1b 39*0aea86a2SCatalin Marinas2: adds x2, x2, #4 40*0aea86a2SCatalin Marinas b.mi 3f 41*0aea86a2SCatalin MarinasUSER(9f, ldr w3, [x1], #4 ) 42*0aea86a2SCatalin Marinas sub x2, x2, #4 43*0aea86a2SCatalin Marinas str w3, [x0], #4 44*0aea86a2SCatalin Marinas3: adds x2, x2, #2 45*0aea86a2SCatalin Marinas b.mi 4f 46*0aea86a2SCatalin MarinasUSER(9f, ldrh w3, [x1], #2 ) 47*0aea86a2SCatalin Marinas sub x2, x2, #2 48*0aea86a2SCatalin Marinas strh w3, [x0], #2 49*0aea86a2SCatalin Marinas4: adds x2, x2, #1 50*0aea86a2SCatalin Marinas b.mi 5f 51*0aea86a2SCatalin MarinasUSER(9f, ldrb w3, [x1] ) 52*0aea86a2SCatalin Marinas strb w3, [x0] 53*0aea86a2SCatalin Marinas5: mov x0, #0 54*0aea86a2SCatalin Marinas ret 55*0aea86a2SCatalin MarinasENDPROC(__copy_from_user) 56*0aea86a2SCatalin Marinas 57*0aea86a2SCatalin Marinas .section .fixup,"ax" 58*0aea86a2SCatalin Marinas .align 2 59*0aea86a2SCatalin Marinas9: sub x2, x4, x1 60*0aea86a2SCatalin Marinas mov x3, x2 61*0aea86a2SCatalin Marinas10: strb wzr, [x0], #1 // zero remaining buffer space 62*0aea86a2SCatalin Marinas subs x3, x3, #1 63*0aea86a2SCatalin Marinas b.ne 10b 64*0aea86a2SCatalin Marinas mov x0, x2 // bytes not copied 65*0aea86a2SCatalin Marinas ret 66*0aea86a2SCatalin Marinas .previous 67