blob: 192ad9e11b25d8db07804051d649f407a4ca5af3 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002#ifndef __PARISC_UACCESS_H
3#define __PARISC_UACCESS_H
4
5/*
6 * User space memory access functions
7 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#include <asm/page.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <asm/cache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
Helge Deller8dd95c62014-10-21 21:29:09 +020011#include <linux/bug.h>
Al Viroaace8802016-08-20 19:03:37 -040012#include <linux/string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013
Linus Torvalds1da177e2005-04-16 15:20:36 -070014/*
15 * Note that since kernel addresses are in a separate address space on
Jesper Juhle49332b2005-05-01 08:59:08 -070016 * parisc, we don't need to do anything for access_ok().
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 * We just let the page fault handler do the right thing. This also means
18 * that put_user is the same as __put_user, etc.
19 */
20
Linus Torvalds96d4f262019-01-03 18:57:57 -080021#define access_ok(uaddr, size) \
Helge Deller186ecf12017-03-15 21:48:42 +010022 ( (uaddr) == (uaddr) )
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#define put_user __put_user
25#define get_user __get_user
26
Helge Dellerca72a222006-12-20 00:35:57 +010027#if !defined(CONFIG_64BIT)
Helge Deller67102872021-09-09 12:47:00 +020028#define LDD_USER(sr, val, ptr) __get_user_asm64(sr, val, ptr)
29#define STD_USER(sr, x, ptr) __put_user_asm64(sr, x, ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#else
Helge Deller67102872021-09-09 12:47:00 +020031#define LDD_USER(sr, val, ptr) __get_user_asm(sr, val, "ldd", ptr)
32#define STD_USER(sr, x, ptr) __put_user_asm(sr, "std", x, ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#endif
34
35/*
Helge Dellercb910c12016-04-08 21:36:06 +020036 * The exception table contains two values: the first is the relative offset to
37 * the address of the instruction that is allowed to fault, and the second is
38 * the relative offset to the address of the fixup routine. Since relative
39 * addresses are used, 32bit values are sufficient even on 64bit kernel.
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 */
41
Helge Deller0de79852016-03-23 16:00:46 +010042#define ARCH_HAS_RELATIVE_EXTABLE
Linus Torvalds1da177e2005-04-16 15:20:36 -070043struct exception_table_entry {
Helge Deller0de79852016-03-23 16:00:46 +010044 int insn; /* relative address of insn that is allowed to fault. */
45 int fixup; /* relative address of fixup routine */
Linus Torvalds1da177e2005-04-16 15:20:36 -070046};
47
Helge Deller0b3d6432007-01-28 14:52:57 +010048#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
49 ".section __ex_table,\"aw\"\n" \
Helge Deller0de79852016-03-23 16:00:46 +010050 ".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \
Helge Deller0b3d6432007-01-28 14:52:57 +010051 ".previous\n"
52
Linus Torvalds1da177e2005-04-16 15:20:36 -070053/*
Helge Dellerd19f5e42017-03-25 11:59:15 +010054 * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry
55 * (with lowest bit set) for which the fault handler in fixup_exception() will
56 * load -EFAULT into %r8 for a read or write fault, and zeroes the target
57 * register in case of a read fault in get_user().
58 */
59#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\
60 ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1)
61
Helge Deller67102872021-09-09 12:47:00 +020062#define __get_user_internal(sr, val, ptr) \
Helge Deller3f795ce2017-04-16 10:00:14 +020063({ \
64 register long __gu_err __asm__ ("r8") = 0; \
65 \
66 switch (sizeof(*(ptr))) { \
Helge Deller67102872021-09-09 12:47:00 +020067 case 1: __get_user_asm(sr, val, "ldb", ptr); break; \
68 case 2: __get_user_asm(sr, val, "ldh", ptr); break; \
69 case 4: __get_user_asm(sr, val, "ldw", ptr); break; \
70 case 8: LDD_USER(sr, val, ptr); break; \
Helge Deller3f795ce2017-04-16 10:00:14 +020071 default: BUILD_BUG(); \
72 } \
73 \
74 __gu_err; \
Linus Torvalds1da177e2005-04-16 15:20:36 -070075})
76
Helge Deller3f795ce2017-04-16 10:00:14 +020077#define __get_user(val, ptr) \
78({ \
Helge Deller67102872021-09-09 12:47:00 +020079 __get_user_internal("%%sr3,", val, ptr); \
Helge Deller3f795ce2017-04-16 10:00:14 +020080})
81
Helge Deller67102872021-09-09 12:47:00 +020082#define __get_user_asm(sr, val, ldx, ptr) \
Helge Deller3f795ce2017-04-16 10:00:14 +020083{ \
84 register long __gu_val; \
85 \
Helge Deller67102872021-09-09 12:47:00 +020086 __asm__("1: " ldx " 0(" sr "%2),%0\n" \
Helge Dellerd19f5e42017-03-25 11:59:15 +010087 "9:\n" \
88 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 : "=r"(__gu_val), "=r"(__gu_err) \
Helge Deller3f795ce2017-04-16 10:00:14 +020090 : "r"(ptr), "1"(__gu_err)); \
91 \
92 (val) = (__force __typeof__(*(ptr))) __gu_val; \
93}
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Helge Deller67102872021-09-09 12:47:00 +020095#define HAVE_GET_KERNEL_NOFAULT
96#define __get_kernel_nofault(dst, src, type, err_label) \
97{ \
98 type __z; \
99 long __err; \
100 __err = __get_user_internal("%%sr0,", __z, (type *)(src)); \
101 if (unlikely(__err)) \
102 goto err_label; \
103 else \
104 *(type *)(dst) = __z; \
105}
106
107
Helge Dellerd2ad8242016-04-09 08:27:08 +0200108#if !defined(CONFIG_64BIT)
109
Helge Deller67102872021-09-09 12:47:00 +0200110#define __get_user_asm64(sr, val, ptr) \
Helge Deller3f795ce2017-04-16 10:00:14 +0200111{ \
112 union { \
113 unsigned long long l; \
114 __typeof__(*(ptr)) t; \
115 } __gu_tmp; \
116 \
Helge Dellerd19f5e42017-03-25 11:59:15 +0100117 __asm__(" copy %%r0,%R0\n" \
Helge Deller67102872021-09-09 12:47:00 +0200118 "1: ldw 0(" sr "%2),%0\n" \
119 "2: ldw 4(" sr "%2),%R0\n" \
Helge Dellerd19f5e42017-03-25 11:59:15 +0100120 "9:\n" \
121 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
122 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
Helge Deller3f795ce2017-04-16 10:00:14 +0200123 : "=&r"(__gu_tmp.l), "=r"(__gu_err) \
124 : "r"(ptr), "1"(__gu_err)); \
125 \
126 (val) = __gu_tmp.t; \
127}
Helge Dellerd2ad8242016-04-09 08:27:08 +0200128
129#endif /* !defined(CONFIG_64BIT) */
130
131
Helge Deller67102872021-09-09 12:47:00 +0200132#define __put_user_internal(sr, x, ptr) \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133({ \
134 register long __pu_err __asm__ ("r8") = 0; \
135 __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
136 \
Helge Deller06bff6b2016-04-09 08:26:14 +0200137 switch (sizeof(*(ptr))) { \
Helge Deller67102872021-09-09 12:47:00 +0200138 case 1: __put_user_asm(sr, "stb", __x, ptr); break; \
139 case 2: __put_user_asm(sr, "sth", __x, ptr); break; \
140 case 4: __put_user_asm(sr, "stw", __x, ptr); break; \
141 case 8: STD_USER(sr, __x, ptr); break; \
Helge Deller3f795ce2017-04-16 10:00:14 +0200142 default: BUILD_BUG(); \
143 } \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 \
145 __pu_err; \
146})
147
Helge Deller3f795ce2017-04-16 10:00:14 +0200148#define __put_user(x, ptr) \
149({ \
Helge Deller67102872021-09-09 12:47:00 +0200150 __put_user_internal("%%sr3,", x, ptr); \
Helge Deller3f795ce2017-04-16 10:00:14 +0200151})
152
Helge Deller67102872021-09-09 12:47:00 +0200153#define __put_kernel_nofault(dst, src, type, err_label) \
154{ \
155 type __z = *(type *)(src); \
156 long __err; \
157 __err = __put_user_internal("%%sr0,", __z, (type *)(dst)); \
158 if (unlikely(__err)) \
159 goto err_label; \
160}
161
162
163
Helge Deller3f795ce2017-04-16 10:00:14 +0200164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165/*
166 * The "__put_user/kernel_asm()" macros tell gcc they read from memory
167 * instead of writing. This is because they do not write to any memory
Carlos O'Donell3fd3a742006-04-22 14:47:21 -0600168 * gcc knows about, so there are no aliasing issues. These macros must
Helge Dellerd19f5e42017-03-25 11:59:15 +0100169 * also be aware that fixups are executed in the context of the fault,
170 * and any registers used there must be listed as clobbers.
171 * r8 is already listed as err.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 */
173
Helge Deller67102872021-09-09 12:47:00 +0200174#define __put_user_asm(sr, stx, x, ptr) \
175 __asm__ __volatile__ ( \
176 "1: " stx " %2,0(" sr "%1)\n" \
177 "9:\n" \
178 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
179 : "=r"(__pu_err) \
Helge Dellerd19f5e42017-03-25 11:59:15 +0100180 : "r"(ptr), "r"(x), "0"(__pu_err))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Helge Dellerca72a222006-12-20 00:35:57 +0100183#if !defined(CONFIG_64BIT)
Helge Deller94a19812006-12-19 22:33:58 +0100184
Helge Deller67102872021-09-09 12:47:00 +0200185#define __put_user_asm64(sr, __val, ptr) do { \
186 __asm__ __volatile__ ( \
187 "1: stw %2,0(" sr "%1)\n" \
188 "2: stw %R2,4(" sr "%1)\n" \
189 "9:\n" \
190 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
191 ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
192 : "=r"(__pu_err) \
193 : "r"(ptr), "r"(__val), "0"(__pu_err)); \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194} while (0)
195
Helge Dellerca72a222006-12-20 00:35:57 +0100196#endif /* !defined(CONFIG_64BIT) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
198
199/*
200 * Complex access routines -- external declarations
201 */
202
James Bottomleyb1195c02012-05-26 09:48:19 +0100203extern long strncpy_from_user(char *, const char __user *, long);
Helge Deller67102872021-09-09 12:47:00 +0200204extern __must_check unsigned lclear_user(void __user *, unsigned long);
Helge Deller1260dea2021-09-04 23:49:26 +0200205extern __must_check long strnlen_user(const char __user *src, long n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206/*
207 * Complex access routines -- macros
208 */
209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210#define clear_user lclear_user
211#define __clear_user lclear_user
212
Al Virof64fd182017-03-24 23:11:26 -0400213unsigned long __must_check raw_copy_to_user(void __user *dst, const void *src,
214 unsigned long len);
215unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src,
216 unsigned long len);
Al Virof64fd182017-03-24 23:11:26 -0400217#define INLINE_COPY_TO_USER
218#define INLINE_COPY_FROM_USER
Helge Deller888c31f2010-02-01 19:56:33 +0000219
Helge Dellere4483722009-01-13 20:52:46 +0100220struct pt_regs;
Kyle McMartinc61c25e2008-12-20 02:29:06 +0000221int fixup_exception(struct pt_regs *regs);
222
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223#endif /* __PARISC_UACCESS_H */