Skip to content

Commit 6710287

Browse files
committed
parisc: Implement __get/put_kernel_nofault()
Remove CONFIG_SET_FS from parisc, so we need to add __get_kernel_nofault() and __put_kernel_nofault(), define HAVE_GET_KERNEL_NOFAULT and remove set_fs(), get_fs(), load_sr2(), thread_info->addr_limit, KERNEL_DS and USER_DS. The nice side-effect of this patch is that we now can directly access userspace via sr3 without the need to use a temporary sr2 which is either copied from sr3 or set to zero (for kernel space). Signed-off-by: Helge Deller <[email protected]> Suggested-by: Arnd Bergmann <[email protected]>
1 parent d97180a commit 6710287

File tree

6 files changed

+62
-86
lines changed

6 files changed

+62
-86
lines changed

arch/parisc/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ config PARISC
6464
select HAVE_KPROBES_ON_FTRACE
6565
select HAVE_DYNAMIC_FTRACE_WITH_REGS
6666
select HAVE_SOFTIRQ_ON_OWN_STACK if IRQSTACKS
67-
select SET_FS
6867
select TRACE_IRQFLAGS_SUPPORT
6968

7069
help

arch/parisc/include/asm/processor.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,6 @@ DECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data);
101101

102102
#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
103103

104-
typedef struct {
105-
int seg;
106-
} mm_segment_t;
107-
108104
#define ARCH_MIN_TASKALIGN 8
109105

110106
struct thread_struct {

arch/parisc/include/asm/thread_info.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
struct thread_info {
1212
struct task_struct *task; /* main task structure */
1313
unsigned long flags; /* thread_info flags (see TIF_*) */
14-
mm_segment_t addr_limit; /* user-level address space limit */
1514
__u32 cpu; /* current CPU */
1615
int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
1716
};
@@ -21,7 +20,6 @@ struct thread_info {
2120
.task = &tsk, \
2221
.flags = 0, \
2322
.cpu = 0, \
24-
.addr_limit = KERNEL_DS, \
2523
.preempt_count = INIT_PREEMPT_COUNT, \
2624
}
2725

arch/parisc/include/asm/uaccess.h

Lines changed: 61 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@
1111
#include <linux/bug.h>
1212
#include <linux/string.h>
1313

14-
#define KERNEL_DS ((mm_segment_t){0})
15-
#define USER_DS ((mm_segment_t){1})
16-
17-
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
18-
19-
#define get_fs() (current_thread_info()->addr_limit)
20-
#define set_fs(x) (current_thread_info()->addr_limit = (x))
21-
2214
/*
2315
* Note that since kernel addresses are in a separate address space on
2416
* parisc, we don't need to do anything for access_ok().
@@ -33,11 +25,11 @@
3325
#define get_user __get_user
3426

3527
#if !defined(CONFIG_64BIT)
36-
#define LDD_USER(val, ptr) __get_user_asm64(val, ptr)
37-
#define STD_USER(x, ptr) __put_user_asm64(x, ptr)
28+
#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)
3830
#else
39-
#define LDD_USER(val, ptr) __get_user_asm(val, "ldd", ptr)
40-
#define STD_USER(x, ptr) __put_user_asm("std", x, ptr)
31+
#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)
4133
#endif
4234

4335
/*
@@ -67,28 +59,15 @@ struct exception_table_entry {
6759
#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\
6860
ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1)
6961

70-
/*
71-
* load_sr2() preloads the space register %%sr2 - based on the value of
72-
* get_fs() - with either a value of 0 to access kernel space (KERNEL_DS which
73-
* is 0), or with the current value of %%sr3 to access user space (USER_DS)
74-
* memory. The following __get_user_asm() and __put_user_asm() functions have
75-
* %%sr2 hard-coded to access the requested memory.
76-
*/
77-
#define load_sr2() \
78-
__asm__(" or,= %0,%%r0,%%r0\n\t" \
79-
" mfsp %%sr3,%0\n\t" \
80-
" mtsp %0,%%sr2\n\t" \
81-
: : "r"(get_fs()) : )
82-
83-
#define __get_user_internal(val, ptr) \
62+
#define __get_user_internal(sr, val, ptr) \
8463
({ \
8564
register long __gu_err __asm__ ("r8") = 0; \
8665
\
8766
switch (sizeof(*(ptr))) { \
88-
case 1: __get_user_asm(val, "ldb", ptr); break; \
89-
case 2: __get_user_asm(val, "ldh", ptr); break; \
90-
case 4: __get_user_asm(val, "ldw", ptr); break; \
91-
case 8: LDD_USER(val, ptr); break; \
67+
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; \
9271
default: BUILD_BUG(); \
9372
} \
9473
\
@@ -97,15 +76,14 @@ struct exception_table_entry {
9776

9877
#define __get_user(val, ptr) \
9978
({ \
100-
load_sr2(); \
101-
__get_user_internal(val, ptr); \
79+
__get_user_internal("%%sr3,", val, ptr); \
10280
})
10381

104-
#define __get_user_asm(val, ldx, ptr) \
82+
#define __get_user_asm(sr, val, ldx, ptr) \
10583
{ \
10684
register long __gu_val; \
10785
\
108-
__asm__("1: " ldx " 0(%%sr2,%2),%0\n" \
86+
__asm__("1: " ldx " 0(" sr "%2),%0\n" \
10987
"9:\n" \
11088
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
11189
: "=r"(__gu_val), "=r"(__gu_err) \
@@ -114,18 +92,31 @@ struct exception_table_entry {
11492
(val) = (__force __typeof__(*(ptr))) __gu_val; \
11593
}
11694

95+
#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+
117108
#if !defined(CONFIG_64BIT)
118109

119-
#define __get_user_asm64(val, ptr) \
110+
#define __get_user_asm64(sr, val, ptr) \
120111
{ \
121112
union { \
122113
unsigned long long l; \
123114
__typeof__(*(ptr)) t; \
124115
} __gu_tmp; \
125116
\
126117
__asm__(" copy %%r0,%R0\n" \
127-
"1: ldw 0(%%sr2,%2),%0\n" \
128-
"2: ldw 4(%%sr2,%2),%R0\n" \
118+
"1: ldw 0(" sr "%2),%0\n" \
119+
"2: ldw 4(" sr "%2),%R0\n" \
129120
"9:\n" \
130121
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
131122
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
@@ -138,16 +129,16 @@ struct exception_table_entry {
138129
#endif /* !defined(CONFIG_64BIT) */
139130

140131

141-
#define __put_user_internal(x, ptr) \
132+
#define __put_user_internal(sr, x, ptr) \
142133
({ \
143134
register long __pu_err __asm__ ("r8") = 0; \
144135
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
145136
\
146137
switch (sizeof(*(ptr))) { \
147-
case 1: __put_user_asm("stb", __x, ptr); break; \
148-
case 2: __put_user_asm("sth", __x, ptr); break; \
149-
case 4: __put_user_asm("stw", __x, ptr); break; \
150-
case 8: STD_USER(__x, ptr); break; \
138+
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; \
151142
default: BUILD_BUG(); \
152143
} \
153144
\
@@ -156,10 +147,20 @@ struct exception_table_entry {
156147

157148
#define __put_user(x, ptr) \
158149
({ \
159-
load_sr2(); \
160-
__put_user_internal(x, ptr); \
150+
__put_user_internal("%%sr3,", x, ptr); \
161151
})
162152

153+
#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+
163164

164165
/*
165166
* The "__put_user/kernel_asm()" macros tell gcc they read from memory
@@ -170,26 +171,26 @@ struct exception_table_entry {
170171
* r8 is already listed as err.
171172
*/
172173

173-
#define __put_user_asm(stx, x, ptr) \
174-
__asm__ __volatile__ ( \
175-
"1: " stx " %2,0(%%sr2,%1)\n" \
176-
"9:\n" \
177-
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
178-
: "=r"(__pu_err) \
174+
#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) \
179180
: "r"(ptr), "r"(x), "0"(__pu_err))
180181

181182

182183
#if !defined(CONFIG_64BIT)
183184

184-
#define __put_user_asm64(__val, ptr) do { \
185-
__asm__ __volatile__ ( \
186-
"1: stw %2,0(%%sr2,%1)\n" \
187-
"2: stw %R2,4(%%sr2,%1)\n" \
188-
"9:\n" \
189-
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
190-
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
191-
: "=r"(__pu_err) \
192-
: "r"(ptr), "r"(__val), "0"(__pu_err)); \
185+
#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)); \
193194
} while (0)
194195

195196
#endif /* !defined(CONFIG_64BIT) */
@@ -200,12 +201,11 @@ struct exception_table_entry {
200201
*/
201202

202203
extern long strncpy_from_user(char *, const char __user *, long);
203-
extern unsigned lclear_user(void __user *, unsigned long);
204+
extern __must_check unsigned lclear_user(void __user *, unsigned long);
204205
extern __must_check long strnlen_user(const char __user *src, long n);
205206
/*
206207
* Complex access routines -- macros
207208
*/
208-
#define user_addr_max() (~0UL)
209209

210210
#define clear_user lclear_user
211211
#define __clear_user lclear_user

arch/parisc/kernel/asm-offsets.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ int main(void)
230230
DEFINE(TI_TASK, offsetof(struct thread_info, task));
231231
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
232232
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
233-
DEFINE(TI_SEGMENT, offsetof(struct thread_info, addr_limit));
234233
DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
235234
DEFINE(THREAD_SZ, sizeof(struct thread_info));
236235
/* THREAD_SZ_ALGN includes space for a stack frame. */

arch/parisc/lib/lusercopy.S

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,6 @@
2727
#include <asm/errno.h>
2828
#include <linux/linkage.h>
2929

30-
/*
31-
* get_sr gets the appropriate space value into
32-
* sr1 for kernel/user space access, depending
33-
* on the flag stored in the task structure.
34-
*/
35-
36-
.macro get_sr
37-
mfctl %cr30,%r1
38-
ldw TI_SEGMENT(%r1),%r22
39-
mfsp %sr3,%r1
40-
or,<> %r22,%r0,%r0
41-
copy %r0,%r1
42-
mtsp %r1,%sr1
43-
.endm
44-
4530
/*
4631
* unsigned long lclear_user(void *to, unsigned long n)
4732
*
@@ -51,10 +36,9 @@
5136

5237
ENTRY_CFI(lclear_user)
5338
comib,=,n 0,%r25,$lclu_done
54-
get_sr
5539
$lclu_loop:
5640
addib,<> -1,%r25,$lclu_loop
57-
1: stbs,ma %r0,1(%sr1,%r26)
41+
1: stbs,ma %r0,1(%sr3,%r26)
5842

5943
$lclu_done:
6044
bv %r0(%r2)

0 commit comments

Comments
 (0)