diff options
Diffstat (limited to 'include/asm-sh/uaccess.h')
-rw-r--r-- | include/asm-sh/uaccess.h | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h index 2cb01861e7c5..5c49ed6715f2 100644 --- a/include/asm-sh/uaccess.h +++ b/include/asm-sh/uaccess.h | |||
@@ -16,21 +16,9 @@ | |||
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | 18 | ||
19 | /* | ||
20 | * NOTE: Macro/functions in this file depends on threads_info.h implementation. | ||
21 | * Assumes: | ||
22 | * TI_FLAGS == 8 | ||
23 | * TIF_USERSPACE == 31 | ||
24 | * USER_ADDR_LIMIT == 0x80000000 | ||
25 | */ | ||
26 | |||
27 | #define VERIFY_READ 0 | 19 | #define VERIFY_READ 0 |
28 | #define VERIFY_WRITE 1 | 20 | #define VERIFY_WRITE 1 |
29 | 21 | ||
30 | typedef struct { | ||
31 | unsigned int is_user_space; | ||
32 | } mm_segment_t; | ||
33 | |||
34 | /* | 22 | /* |
35 | * The fs value determines whether argument validity checking should be | 23 | * The fs value determines whether argument validity checking should be |
36 | * performed or not. If get_fs() == USER_DS, checking is performed, with | 24 | * performed or not. If get_fs() == USER_DS, checking is performed, with |
@@ -40,16 +28,18 @@ typedef struct { | |||
40 | */ | 28 | */ |
41 | 29 | ||
42 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) | 30 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) |
43 | #define segment_eq(a,b) ((a).is_user_space == (b).is_user_space) | ||
44 | 31 | ||
45 | #define USER_ADDR_LIMIT 0x80000000 | 32 | #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL) |
33 | #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) | ||
46 | 34 | ||
47 | #define KERNEL_DS MAKE_MM_SEG(0) | 35 | #define segment_eq(a,b) ((a).seg == (b).seg) |
48 | #define USER_DS MAKE_MM_SEG(1) | ||
49 | 36 | ||
50 | #define get_ds() (KERNEL_DS) | 37 | #define get_ds() (KERNEL_DS) |
51 | 38 | ||
52 | #if !defined(CONFIG_MMU) | 39 | #if !defined(CONFIG_MMU) |
40 | /* NOMMU is always true */ | ||
41 | #define __addr_ok(addr) (1) | ||
42 | |||
53 | static inline mm_segment_t get_fs(void) | 43 | static inline mm_segment_t get_fs(void) |
54 | { | 44 | { |
55 | return USER_DS; | 45 | return USER_DS; |
@@ -76,31 +66,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size) | |||
76 | return ((addr >= memory_start) && ((addr + size) < memory_end)); | 66 | return ((addr >= memory_start) && ((addr + size) < memory_end)); |
77 | } | 67 | } |
78 | #else /* CONFIG_MMU */ | 68 | #else /* CONFIG_MMU */ |
79 | static inline mm_segment_t get_fs(void) | 69 | #define __addr_ok(addr) \ |
80 | { | 70 | ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) |
81 | return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE)); | ||
82 | } | ||
83 | 71 | ||
84 | static inline void set_fs(mm_segment_t s) | 72 | #define get_fs() (current_thread_info()->addr_limit) |
85 | { | 73 | #define set_fs(x) (current_thread_info()->addr_limit = (x)) |
86 | unsigned long ti, flag; | ||
87 | __asm__ __volatile__( | ||
88 | "stc r7_bank, %0\n\t" | ||
89 | "mov.l @(8,%0), %1\n\t" | ||
90 | "shal %1\n\t" | ||
91 | "cmp/pl %2\n\t" | ||
92 | "rotcr %1\n\t" | ||
93 | "mov.l %1, @(8,%0)" | ||
94 | : "=&r" (ti), "=&r" (flag) | ||
95 | : "r" (s.is_user_space) | ||
96 | : "t"); | ||
97 | /**** | ||
98 | if (s.is_user_space) | ||
99 | set_thread_flag(TIF_USERSPACE); | ||
100 | else | ||
101 | clear_thread_flag(TIF_USERSPACE); | ||
102 | ****/ | ||
103 | } | ||
104 | 74 | ||
105 | /* | 75 | /* |
106 | * __access_ok: Check if address with size is OK or not. | 76 | * __access_ok: Check if address with size is OK or not. |
@@ -108,7 +78,7 @@ static inline void set_fs(mm_segment_t s) | |||
108 | * We do three checks: | 78 | * We do three checks: |
109 | * (1) is it user space? | 79 | * (1) is it user space? |
110 | * (2) addr + size --> carry? | 80 | * (2) addr + size --> carry? |
111 | * (3) addr + size >= 0x80000000 (USER_ADDR_LIMIT) | 81 | * (3) addr + size >= 0x80000000 (PAGE_OFFSET) |
112 | * | 82 | * |
113 | * (1) (2) (3) | RESULT | 83 | * (1) (2) (3) | RESULT |
114 | * 0 0 0 | ok | 84 | * 0 0 0 | ok |
@@ -201,6 +171,7 @@ do { \ | |||
201 | __gu_err; \ | 171 | __gu_err; \ |
202 | }) | 172 | }) |
203 | 173 | ||
174 | #ifdef CONFIG_MMU | ||
204 | #define __get_user_check(x,ptr,size) \ | 175 | #define __get_user_check(x,ptr,size) \ |
205 | ({ \ | 176 | ({ \ |
206 | long __gu_err, __gu_val; \ | 177 | long __gu_err, __gu_val; \ |
@@ -290,6 +261,18 @@ __asm__("stc r7_bank, %1\n\t" \ | |||
290 | : "r" (addr) \ | 261 | : "r" (addr) \ |
291 | : "t"); \ | 262 | : "t"); \ |
292 | }) | 263 | }) |
264 | #else /* CONFIG_MMU */ | ||
265 | #define __get_user_check(x,ptr,size) \ | ||
266 | ({ \ | ||
267 | long __gu_err, __gu_val; \ | ||
268 | if (__access_ok((unsigned long)(ptr), (size))) { \ | ||
269 | __get_user_size(__gu_val, (ptr), (size), __gu_err); \ | ||
270 | (x) = (__typeof__(*(ptr)))__gu_val; \ | ||
271 | } else \ | ||
272 | __gu_err = -EFAULT; \ | ||
273 | __gu_err; \ | ||
274 | }) | ||
275 | #endif | ||
293 | 276 | ||
294 | #define __get_user_asm(x, addr, err, insn) \ | 277 | #define __get_user_asm(x, addr, err, insn) \ |
295 | ({ \ | 278 | ({ \ |
@@ -541,7 +524,7 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n) | |||
541 | "3:\n\t" | 524 | "3:\n\t" |
542 | "mov.l 4f, %1\n\t" | 525 | "mov.l 4f, %1\n\t" |
543 | "jmp @%1\n\t" | 526 | "jmp @%1\n\t" |
544 | " mov %5, %0\n" | 527 | " mov #0, %0\n" |
545 | ".balign 4\n" | 528 | ".balign 4\n" |
546 | "4: .long 2b\n" | 529 | "4: .long 2b\n" |
547 | ".previous\n" | 530 | ".previous\n" |
@@ -550,26 +533,20 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n) | |||
550 | " .long 1b,3b\n" | 533 | " .long 1b,3b\n" |
551 | ".previous" | 534 | ".previous" |
552 | : "=z" (res), "=&r" (__dummy) | 535 | : "=z" (res), "=&r" (__dummy) |
553 | : "0" (0), "r" (__s), "r" (__n), "i" (-EFAULT) | 536 | : "0" (0), "r" (__s), "r" (__n) |
554 | : "t"); | 537 | : "t"); |
555 | return res; | 538 | return res; |
556 | } | 539 | } |
557 | 540 | ||
558 | static __inline__ long strnlen_user(const char __user *s, long n) | 541 | static __inline__ long strnlen_user(const char __user *s, long n) |
559 | { | 542 | { |
560 | if (!access_ok(VERIFY_READ, s, n)) | 543 | if (!__addr_ok(s)) |
561 | return 0; | 544 | return 0; |
562 | else | 545 | else |
563 | return __strnlen_user(s, n); | 546 | return __strnlen_user(s, n); |
564 | } | 547 | } |
565 | 548 | ||
566 | static __inline__ long strlen_user(const char __user *s) | 549 | #define strlen_user(str) strnlen_user(str, ~0UL >> 1) |
567 | { | ||
568 | if (!access_ok(VERIFY_READ, s, 0)) | ||
569 | return 0; | ||
570 | else | ||
571 | return __strnlen_user(s, ~0UL >> 1); | ||
572 | } | ||
573 | 550 | ||
574 | /* | 551 | /* |
575 | * The exception table consists of pairs of addresses: the first is the | 552 | * The exception table consists of pairs of addresses: the first is the |