blob: c5e420750c48d70374b216a70d3078add0fc0eb5 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * linux/arch/arm/lib/getuser.S
4 *
5 * Copyright (C) 2001 Russell King
6 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
8 *
9 * These functions have a non-standard call interface to make them more
10 * efficient, especially as they return an error value in addition to
11 * the "real" return value.
12 *
13 * __get_user_X
14 *
15 * Inputs: r0 contains the address
Russell King84046632012-09-07 18:22:28 +010016 * r1 contains the address limit, which must be preserved
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 * Outputs: r0 is the error code
Daniel Thompsone38361d2014-07-10 20:58:08 +010018 * r2, r3 contains the zero-extended value
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 * lr corrupted
20 *
Russell King4baa9922008-08-02 10:55:55 +010021 * No other registers must be altered. (see <asm/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 * for specific ASM register usage).
23 *
24 * Note that ADDR_LIMIT is either 0 or 0xc0000000.
25 * Note also that it is intended that __get_user_bad is not global.
26 */
Catalin Marinas93ed3972008-08-28 11:22:32 +010027#include <linux/linkage.h>
Russell King84046632012-09-07 18:22:28 +010028#include <asm/assembler.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <asm/errno.h>
Catalin Marinas247055a2010-09-13 16:03:21 +010030#include <asm/domain.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
Catalin Marinas93ed3972008-08-28 11:22:32 +010032ENTRY(__get_user_1)
Russell King84046632012-09-07 18:22:28 +010033 check_uaccess r0, 1, r1, r2, __get_user_bad
Catalin Marinas4e7682d2012-01-25 11:38:13 +0100341: TUSER(ldrb) r2, [r0]
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 mov r0, #0
Russell King6ebbf2c2014-06-30 16:29:12 +010036 ret lr
Catalin Marinas93ed3972008-08-28 11:22:32 +010037ENDPROC(__get_user_1)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +010038_ASM_NOKPROBE(__get_user_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Catalin Marinas93ed3972008-08-28 11:22:32 +010040ENTRY(__get_user_2)
Russell King84046632012-09-07 18:22:28 +010041 check_uaccess r0, 2, r1, r2, __get_user_bad
Vincent Whitchurch344eb5532018-11-09 10:12:30 +010042#if __LINUX_ARM_ARCH__ >= 6
43
442: TUSER(ldrh) r2, [r0]
45
46#else
47
Russell King84046632012-09-07 18:22:28 +010048#ifdef CONFIG_CPU_USE_DOMAINS
49rb .req ip
502: ldrbt r2, [r0], #1
513: ldrbt rb, [r0], #0
Catalin Marinas8b592782009-07-24 12:32:57 +010052#else
Russell King84046632012-09-07 18:22:28 +010053rb .req r0
542: ldrb r2, [r0]
553: ldrb rb, [r0, #1]
Catalin Marinas8b592782009-07-24 12:32:57 +010056#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#ifndef __ARMEB__
Russell King84046632012-09-07 18:22:28 +010058 orr r2, r2, rb, lsl #8
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#else
Russell King84046632012-09-07 18:22:28 +010060 orr r2, rb, r2, lsl #8
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#endif
Vincent Whitchurch344eb5532018-11-09 10:12:30 +010062
63#endif /* __LINUX_ARM_ARCH__ >= 6 */
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 mov r0, #0
Russell King6ebbf2c2014-06-30 16:29:12 +010066 ret lr
Catalin Marinas93ed3972008-08-28 11:22:32 +010067ENDPROC(__get_user_2)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +010068_ASM_NOKPROBE(__get_user_2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Catalin Marinas93ed3972008-08-28 11:22:32 +010070ENTRY(__get_user_4)
Russell King84046632012-09-07 18:22:28 +010071 check_uaccess r0, 4, r1, r2, __get_user_bad
Catalin Marinas4e7682d2012-01-25 11:38:13 +0100724: TUSER(ldr) r2, [r0]
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 mov r0, #0
Russell King6ebbf2c2014-06-30 16:29:12 +010074 ret lr
Catalin Marinas93ed3972008-08-28 11:22:32 +010075ENDPROC(__get_user_4)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +010076_ASM_NOKPROBE(__get_user_4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Daniel Thompsone38361d2014-07-10 20:58:08 +010078ENTRY(__get_user_8)
Kees Cook9e344042017-02-16 01:44:37 +010079 check_uaccess r0, 8, r1, r2, __get_user_bad8
Daniel Thompsone38361d2014-07-10 20:58:08 +010080#ifdef CONFIG_THUMB2_KERNEL
815: TUSER(ldr) r2, [r0]
826: TUSER(ldr) r3, [r0, #4]
83#else
845: TUSER(ldr) r2, [r0], #4
856: TUSER(ldr) r3, [r0]
86#endif
87 mov r0, #0
88 ret lr
89ENDPROC(__get_user_8)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +010090_ASM_NOKPROBE(__get_user_8)
Daniel Thompsone38361d2014-07-10 20:58:08 +010091
92#ifdef __ARMEB__
Victor Kamenskyd9981382014-09-04 06:07:33 +010093ENTRY(__get_user_32t_8)
Daniel Thompsone38361d2014-07-10 20:58:08 +010094 check_uaccess r0, 8, r1, r2, __get_user_bad
95#ifdef CONFIG_CPU_USE_DOMAINS
96 add r0, r0, #4
977: ldrt r2, [r0]
98#else
997: ldr r2, [r0, #4]
100#endif
101 mov r0, #0
102 ret lr
Victor Kamenskyd9981382014-09-04 06:07:33 +0100103ENDPROC(__get_user_32t_8)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +0100104_ASM_NOKPROBE(__get_user_32t_8)
Victor Kamenskyd9981382014-09-04 06:07:33 +0100105
106ENTRY(__get_user_64t_1)
107 check_uaccess r0, 1, r1, r2, __get_user_bad8
1088: TUSER(ldrb) r3, [r0]
109 mov r0, #0
110 ret lr
111ENDPROC(__get_user_64t_1)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +0100112_ASM_NOKPROBE(__get_user_64t_1)
Victor Kamenskyd9981382014-09-04 06:07:33 +0100113
114ENTRY(__get_user_64t_2)
115 check_uaccess r0, 2, r1, r2, __get_user_bad8
116#ifdef CONFIG_CPU_USE_DOMAINS
117rb .req ip
1189: ldrbt r3, [r0], #1
11910: ldrbt rb, [r0], #0
120#else
121rb .req r0
1229: ldrb r3, [r0]
12310: ldrb rb, [r0, #1]
124#endif
125 orr r3, rb, r3, lsl #8
126 mov r0, #0
127 ret lr
128ENDPROC(__get_user_64t_2)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +0100129_ASM_NOKPROBE(__get_user_64t_2)
Victor Kamenskyd9981382014-09-04 06:07:33 +0100130
131ENTRY(__get_user_64t_4)
132 check_uaccess r0, 4, r1, r2, __get_user_bad8
13311: TUSER(ldr) r3, [r0]
134 mov r0, #0
135 ret lr
136ENDPROC(__get_user_64t_4)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +0100137_ASM_NOKPROBE(__get_user_64t_4)
Daniel Thompsone38361d2014-07-10 20:58:08 +0100138#endif
139
140__get_user_bad8:
141 mov r3, #0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142__get_user_bad:
143 mov r2, #0
144 mov r0, #-EFAULT
Russell King6ebbf2c2014-06-30 16:29:12 +0100145 ret lr
Catalin Marinas93ed3972008-08-28 11:22:32 +0100146ENDPROC(__get_user_bad)
Daniel Thompsone38361d2014-07-10 20:58:08 +0100147ENDPROC(__get_user_bad8)
Masami Hiramatsu0d73c3f2018-05-13 05:04:29 +0100148_ASM_NOKPROBE(__get_user_bad)
149_ASM_NOKPROBE(__get_user_bad8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Russell King42604152010-04-19 10:15:03 +0100151.pushsection __ex_table, "a"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 .long 1b, __get_user_bad
153 .long 2b, __get_user_bad
Vincent Whitchurch344eb5532018-11-09 10:12:30 +0100154#if __LINUX_ARM_ARCH__ < 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 .long 3b, __get_user_bad
Vincent Whitchurch344eb5532018-11-09 10:12:30 +0100156#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 .long 4b, __get_user_bad
Daniel Thompsone38361d2014-07-10 20:58:08 +0100158 .long 5b, __get_user_bad8
159 .long 6b, __get_user_bad8
160#ifdef __ARMEB__
161 .long 7b, __get_user_bad
Victor Kamenskyd9981382014-09-04 06:07:33 +0100162 .long 8b, __get_user_bad8
163 .long 9b, __get_user_bad8
164 .long 10b, __get_user_bad8
165 .long 11b, __get_user_bad8
Daniel Thompsone38361d2014-07-10 20:58:08 +0100166#endif
Russell King42604152010-04-19 10:15:03 +0100167.popsection