10aea86a2SCatalin Marinas/* 20aea86a2SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 30aea86a2SCatalin Marinas * 40aea86a2SCatalin Marinas * This program is free software; you can redistribute it and/or modify 50aea86a2SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 60aea86a2SCatalin Marinas * published by the Free Software Foundation. 70aea86a2SCatalin Marinas * 80aea86a2SCatalin Marinas * This program is distributed in the hope that it will be useful, 90aea86a2SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 100aea86a2SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 110aea86a2SCatalin Marinas * GNU General Public License for more details. 120aea86a2SCatalin Marinas * 130aea86a2SCatalin Marinas * You should have received a copy of the GNU General Public License 140aea86a2SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 150aea86a2SCatalin Marinas */ 160aea86a2SCatalin Marinas 170aea86a2SCatalin Marinas#include <linux/linkage.h> 18338d4f49SJames Morse 19338d4f49SJames Morse#include <asm/alternative.h> 200aea86a2SCatalin Marinas#include <asm/assembler.h> 2140426882SFeng Kan#include <asm/cache.h> 22338d4f49SJames Morse#include <asm/cpufeature.h> 23338d4f49SJames Morse#include <asm/sysreg.h> 240aea86a2SCatalin Marinas 250aea86a2SCatalin Marinas/* 260aea86a2SCatalin Marinas * Copy from user space to a kernel buffer (alignment handled by the hardware) 270aea86a2SCatalin Marinas * 280aea86a2SCatalin Marinas * Parameters: 290aea86a2SCatalin Marinas * x0 - to 300aea86a2SCatalin Marinas * x1 - from 310aea86a2SCatalin Marinas * x2 - n 320aea86a2SCatalin Marinas * Returns: 330aea86a2SCatalin Marinas * x0 - bytes not copied 340aea86a2SCatalin Marinas */ 3540426882SFeng Kan 3640426882SFeng Kan .macro ldrb1 ptr, regB, val 3757f4959bSJames Morse uao_user_alternative 9998f, ldrb, ldtrb, \ptr, \regB, \val 3840426882SFeng Kan .endm 3940426882SFeng Kan 4040426882SFeng Kan .macro strb1 ptr, regB, val 4140426882SFeng Kan strb \ptr, [\regB], \val 4240426882SFeng Kan .endm 4340426882SFeng Kan 4440426882SFeng Kan .macro ldrh1 ptr, regB, val 4557f4959bSJames Morse uao_user_alternative 9998f, ldrh, ldtrh, \ptr, \regB, \val 4640426882SFeng Kan .endm 4740426882SFeng Kan 4840426882SFeng Kan .macro strh1 ptr, regB, val 4940426882SFeng Kan strh \ptr, [\regB], \val 5040426882SFeng Kan .endm 5140426882SFeng Kan 5240426882SFeng Kan .macro ldr1 ptr, regB, val 5357f4959bSJames Morse uao_user_alternative 9998f, ldr, ldtr, \ptr, \regB, \val 5440426882SFeng Kan .endm 5540426882SFeng Kan 5640426882SFeng Kan .macro str1 ptr, regB, val 5740426882SFeng Kan str \ptr, [\regB], \val 5840426882SFeng Kan .endm 5940426882SFeng Kan 6040426882SFeng Kan .macro ldp1 ptr, regB, regC, val 6157f4959bSJames Morse uao_ldp 9998f, \ptr, \regB, \regC, \val 6240426882SFeng Kan .endm 6340426882SFeng Kan 6440426882SFeng Kan .macro stp1 ptr, regB, regC, val 6540426882SFeng Kan stp \ptr, \regB, [\regC], \val 6640426882SFeng Kan .endm 6740426882SFeng Kan 6840426882SFeng Kanend .req x5 690aea86a2SCatalin MarinasENTRY(__copy_from_user) 7070544196SJames MorseALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \ 71338d4f49SJames Morse CONFIG_ARM64_PAN) 7240426882SFeng Kan add end, x0, x2 7340426882SFeng Kan#include "copy_template.S" 7470544196SJames MorseALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \ 75338d4f49SJames Morse CONFIG_ARM64_PAN) 7640426882SFeng Kan mov x0, #0 // Nothing to copy 770aea86a2SCatalin Marinas ret 780aea86a2SCatalin MarinasENDPROC(__copy_from_user) 790aea86a2SCatalin Marinas 800aea86a2SCatalin Marinas .section .fixup,"ax" 810aea86a2SCatalin Marinas .align 2 8240426882SFeng Kan9998: 8340426882SFeng Kan sub x0, end, dst 8440426882SFeng Kan9999: 8540426882SFeng Kan strb wzr, [dst], #1 // zero remaining buffer space 8640426882SFeng Kan cmp dst, end 8740426882SFeng Kan b.lo 9999b 880aea86a2SCatalin Marinas ret 890aea86a2SCatalin Marinas .previous 90