Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usercopy.c
Go to the documentation of this file.
1 /* MN10300 Userspace accessor functions
2  *
3  * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells ([email protected])
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public Licence
9  * as published by the Free Software Foundation; either version
10  * 2 of the Licence, or (at your option) any later version.
11  */
12 #include <asm/uaccess.h>
13 
14 unsigned long
15 __generic_copy_to_user(void *to, const void *from, unsigned long n)
16 {
17  if (access_ok(VERIFY_WRITE, to, n))
18  __copy_user(to, from, n);
19  return n;
20 }
21 
22 unsigned long
23 __generic_copy_from_user(void *to, const void *from, unsigned long n)
24 {
25  if (access_ok(VERIFY_READ, from, n))
26  __copy_user_zeroing(to, from, n);
27  return n;
28 }
29 
30 /*
31  * Copy a null terminated string from userspace.
32  */
33 #define __do_strncpy_from_user(dst, src, count, res) \
34 do { \
35  int w; \
36  asm volatile( \
37  " mov %1,%0\n" \
38  " cmp 0,%1\n" \
39  " beq 2f\n" \
40  "0:\n" \
41  " movbu (%5),%2\n" \
42  "1:\n" \
43  " movbu %2,(%6)\n" \
44  " inc %5\n" \
45  " inc %6\n" \
46  " cmp 0,%2\n" \
47  " beq 2f\n" \
48  " add -1,%1\n" \
49  " bne 0b\n" \
50  "2:\n" \
51  " sub %1,%0\n" \
52  "3:\n" \
53  " .section .fixup,\"ax\"\n" \
54  "4:\n" \
55  " mov %3,%0\n" \
56  " jmp 3b\n" \
57  " .previous\n" \
58  " .section __ex_table,\"a\"\n" \
59  " .balign 4\n" \
60  " .long 0b,4b\n" \
61  " .long 1b,4b\n" \
62  " .previous" \
63  :"=&r"(res), "=r"(count), "=&r"(w) \
64  :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
65  : "memory", "cc"); \
66 } while (0)
67 
68 long
69 __strncpy_from_user(char *dst, const char *src, long count)
70 {
71  long res;
72  __do_strncpy_from_user(dst, src, count, res);
73  return res;
74 }
75 
76 long
77 strncpy_from_user(char *dst, const char *src, long count)
78 {
79  long res = -EFAULT;
80  if (access_ok(VERIFY_READ, src, 1))
81  __do_strncpy_from_user(dst, src, count, res);
82  return res;
83 }
84 
85 
86 /*
87  * Clear a userspace memory
88  */
89 #define __do_clear_user(addr, size) \
90 do { \
91  int w; \
92  asm volatile( \
93  " cmp 0,%0\n" \
94  " beq 1f\n" \
95  " clr %1\n" \
96  "0: movbu %1,(%3,%2)\n" \
97  " inc %3\n" \
98  " cmp %0,%3\n" \
99  " bne 0b\n" \
100  "1:\n" \
101  " sub %3,%0\n" \
102  "2:\n" \
103  ".section .fixup,\"ax\"\n" \
104  "3: jmp 2b\n" \
105  ".previous\n" \
106  ".section __ex_table,\"a\"\n" \
107  " .balign 4\n" \
108  " .long 0b,3b\n" \
109  ".previous\n" \
110  : "+r"(size), "=&r"(w) \
111  : "a"(addr), "d"(0) \
112  : "memory", "cc"); \
113 } while (0)
114 
115 unsigned long
116 __clear_user(void *to, unsigned long n)
117 {
118  __do_clear_user(to, n);
119  return n;
120 }
121 
122 unsigned long
123 clear_user(void *to, unsigned long n)
124 {
125  if (access_ok(VERIFY_WRITE, to, n))
126  __do_clear_user(to, n);
127  return n;
128 }
129 
130 /*
131  * Return the size of a string (including the ending 0)
132  *
133  * Return 0 on exception, a value greater than N if too long
134  */
135 long strnlen_user(const char *s, long n)
136 {
137  unsigned long res, w;
138 
139  if (!__addr_ok(s))
140  return 0;
141 
142  if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
143  n = current_thread_info()->addr_limit.seg - (u_long)s;
144 
145  asm volatile(
146  "0: cmp %4,%0\n"
147  " beq 2f\n"
148  "1: movbu (%0,%3),%1\n"
149  " inc %0\n"
150  " cmp 0,%1\n"
151  " beq 3f\n"
152  " bra 0b\n"
153  "2: clr %0\n"
154  "3:\n"
155  ".section .fixup,\"ax\"\n"
156  "4: jmp 2b\n"
157  ".previous\n"
158  ".section __ex_table,\"a\"\n"
159  " .balign 4\n"
160  " .long 1b,4b\n"
161  ".previous\n"
162  :"=d"(res), "=&r"(w)
163  :"0"(0), "a"(s), "r"(n)
164  : "memory", "cc");
165  return res;
166 }