aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-blackfin/uaccess.h
diff options
context:
space:
mode:
authorBryan Wu <bryan.wu@analog.com>2007-05-06 17:50:22 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:58 -0400
commit1394f03221790a988afc3e4b3cb79f2e477246a9 (patch)
tree2c1963c9a4f2d84a5e021307fde240c5d567cf70 /include/asm-blackfin/uaccess.h
parent73243284463a761e04d69d22c7516b2be7de096c (diff)
blackfin architecture
This adds support for the Analog Devices Blackfin processor architecture, and currently supports the BF533, BF532, BF531, BF537, BF536, BF534, and BF561 (Dual Core) devices, with a variety of development platforms including those avaliable from Analog Devices (BF533-EZKit, BF533-STAMP, BF537-STAMP, BF561-EZKIT), and Bluetechnix! Tinyboards. The Blackfin architecture was jointly developed by Intel and Analog Devices Inc. (ADI) as the Micro Signal Architecture (MSA) core and introduced it in December of 2000. Since then ADI has put this core into its Blackfin processor family of devices. The Blackfin core has the advantages of a clean, orthogonal,RISC-like microprocessor instruction set. It combines a dual-MAC (Multiply/Accumulate), state-of-the-art signal processing engine and single-instruction, multiple-data (SIMD) multimedia capabilities into a single instruction-set architecture. The Blackfin architecture, including the instruction set, is described by the ADSP-BF53x/BF56x Blackfin Processor Programming Reference http://blackfin.uclinux.org/gf/download/frsrelease/29/2549/Blackfin_PRM.pdf The Blackfin processor is already supported by major releases of gcc, and there are binary and source rpms/tarballs for many architectures at: http://blackfin.uclinux.org/gf/project/toolchain/frs There is complete documentation, including "getting started" guides available at: http://docs.blackfin.uclinux.org/ which provides links to the sources and patches you will need in order to set up a cross-compiling environment for bfin-linux-uclibc This patch, as well as the other patches (toolchain, distribution, uClibc) are actively supported by Analog Devices Inc, at: http://blackfin.uclinux.org/ We have tested this on LTP, and our test plan (including pass/fails) can be found at: http://docs.blackfin.uclinux.org/doku.php?id=testing_the_linux_kernel [m.kozlowski@tuxland.pl: balance parenthesis in blackfin header files] Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: Aubrey Li <aubrey.li@analog.com> Signed-off-by: Jie Zhang <jie.zhang@analog.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/asm-blackfin/uaccess.h')
-rw-r--r--include/asm-blackfin/uaccess.h271
1 files changed, 271 insertions, 0 deletions
diff --git a/include/asm-blackfin/uaccess.h b/include/asm-blackfin/uaccess.h
new file mode 100644
index 000000000000..bfcb6794c672
--- /dev/null
+++ b/include/asm-blackfin/uaccess.h
@@ -0,0 +1,271 @@
1/* Changes made by Lineo Inc. May 2001
2 *
3 * Based on: include/asm-m68knommu/uaccess.h
4 */
5
6#ifndef __BLACKFIN_UACCESS_H
7#define __BLACKFIN_UACCESS_H
8
9/*
10 * User space memory access functions
11 */
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/string.h>
15
16#include <asm/segment.h>
17#ifndef CONFIG_NO_ACCESS_CHECK
18# include <asm/bfin-global.h>
19#endif
20
21#define get_ds() (KERNEL_DS)
22#define get_fs() (current_thread_info()->addr_limit)
23
24static inline void set_fs(mm_segment_t fs)
25{
26 current_thread_info()->addr_limit = fs;
27}
28
29#define segment_eq(a,b) ((a) == (b))
30
31#define VERIFY_READ 0
32#define VERIFY_WRITE 1
33
34#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
35
36static inline int is_in_rom(unsigned long addr)
37{
38 /*
39 * What we are really trying to do is determine if addr is
40 * in an allocated kernel memory region. If not then assume
41 * we cannot free it or otherwise de-allocate it. Ideally
42 * we could restrict this to really being in a ROM or flash,
43 * but that would need to be done on a board by board basis,
44 * not globally.
45 */
46 if ((addr < _ramstart) || (addr >= _ramend))
47 return (1);
48
49 /* Default case, not in ROM */
50 return (0);
51}
52
53/*
54 * The fs value determines whether argument validity checking should be
55 * performed or not. If get_fs() == USER_DS, checking is performed, with
56 * get_fs() == KERNEL_DS, checking is bypassed.
57 */
58
59#ifdef CONFIG_NO_ACCESS_CHECK
60static inline int _access_ok(unsigned long addr, unsigned long size) { return 1; }
61#else
62#ifdef CONFIG_ACCESS_OK_L1
63extern int _access_ok(unsigned long addr, unsigned long size)__attribute__((l1_text));
64#else
65extern int _access_ok(unsigned long addr, unsigned long size);
66#endif
67#endif
68
69/*
70 * The exception table consists of pairs of addresses: the first is the
71 * address of an instruction that is allowed to fault, and the second is
72 * the address at which the program should continue. No registers are
73 * modified, so it is entirely up to the continuation code to figure out
74 * what to do.
75 *
76 * All the routines below use bits of fixup code that are out of line
77 * with the main instruction path. This means when everything is well,
78 * we don't even have to jump over them. Further, they do not intrude
79 * on our cache or tlb entries.
80 */
81
82struct exception_table_entry {
83 unsigned long insn, fixup;
84};
85
86/* Returns 0 if exception not found and fixup otherwise. */
87extern unsigned long search_exception_table(unsigned long);
88
89/*
90 * These are the main single-value transfer routines. They automatically
91 * use the right size if we just have the right pointer type.
92 */
93
94#define put_user(x,p) \
95 ({ \
96 int _err = 0; \
97 typeof(*(p)) _x = (x); \
98 typeof(*(p)) *_p = (p); \
99 if (!access_ok(VERIFY_WRITE, _p, sizeof(*(_p)))) {\
100 _err = -EFAULT; \
101 } \
102 else { \
103 switch (sizeof (*(_p))) { \
104 case 1: \
105 __put_user_asm(_x, _p, B); \
106 break; \
107 case 2: \
108 __put_user_asm(_x, _p, W); \
109 break; \
110 case 4: \
111 __put_user_asm(_x, _p, ); \
112 break; \
113 case 8: { \
114 long _xl, _xh; \
115 _xl = ((long *)&_x)[0]; \
116 _xh = ((long *)&_x)[1]; \
117 __put_user_asm(_xl, ((long *)_p)+0, ); \
118 __put_user_asm(_xh, ((long *)_p)+1, ); \
119 } break; \
120 default: \
121 _err = __put_user_bad(); \
122 break; \
123 } \
124 } \
125 _err; \
126 })
127
128#define __put_user(x,p) put_user(x,p)
129static inline int bad_user_access_length(void)
130{
131 panic("bad_user_access_length");
132 return -1;
133}
134
135#define __put_user_bad() (printk(KERN_INFO "put_user_bad %s:%d %s\n",\
136 __FILE__, __LINE__, __FUNCTION__),\
137 bad_user_access_length(), (-EFAULT))
138
139/*
140 * Tell gcc we read from memory instead of writing: this is because
141 * we do not write to any memory gcc knows about, so there are no
142 * aliasing issues.
143 */
144
145#define __ptr(x) ((unsigned long *)(x))
146
147#define __put_user_asm(x,p,bhw) \
148 __asm__ (#bhw"[%1] = %0;\n\t" \
149 : /* no outputs */ \
150 :"d" (x),"a" (__ptr(p)) : "memory")
151
152#define get_user(x,p) \
153 ({ \
154 int _err = 0; \
155 typeof(*(p)) *_p = (p); \
156 if (!access_ok(VERIFY_READ, _p, sizeof(*(_p)))) { \
157 _err = -EFAULT; \
158 } \
159 else { \
160 switch (sizeof(*(_p))) { \
161 case 1: \
162 __get_user_asm(x, _p, B,(Z)); \
163 break; \
164 case 2: \
165 __get_user_asm(x, _p, W,(Z)); \
166 break; \
167 case 4: \
168 __get_user_asm(x, _p, , ); \
169 break; \
170 case 8: { \
171 unsigned long _xl, _xh; \
172 __get_user_asm(_xl, ((unsigned long *)_p)+0, , ); \
173 __get_user_asm(_xh, ((unsigned long *)_p)+1, , ); \
174 ((unsigned long *)&x)[0] = _xl; \
175 ((unsigned long *)&x)[1] = _xh; \
176 } break; \
177 default: \
178 x = 0; \
179 printk(KERN_INFO "get_user_bad: %s:%d %s\n", \
180 __FILE__, __LINE__, __FUNCTION__); \
181 _err = __get_user_bad(); \
182 break; \
183 } \
184 } \
185 _err; \
186 })
187
188#define __get_user(x,p) get_user(x,p)
189
190#define __get_user_bad() (bad_user_access_length(), (-EFAULT))
191
192#define __get_user_asm(x,p,bhw,option) \
193 { \
194 unsigned long _tmp; \
195 __asm__ ("%0 =" #bhw "[%1]"#option";\n\t" \
196 : "=d" (_tmp) \
197 : "a" (__ptr(p))); \
198 (x) = (__typeof__(*(p))) _tmp; \
199 }
200
201#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
202#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
203#define __copy_to_user_inatomic __copy_to_user
204#define __copy_from_user_inatomic __copy_from_user
205
206#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n))\
207 return retval; })
208
209#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n))\
210 return retval; })
211
212static inline long copy_from_user(void *to,
213 const void __user * from, unsigned long n)
214{
215 if (access_ok(VERIFY_READ, from, n))
216 memcpy(to, from, n);
217 else
218 return n;
219 return 0;
220}
221
222static inline long copy_to_user(void *to,
223 const void __user * from, unsigned long n)
224{
225 if (access_ok(VERIFY_WRITE, to, n))
226 memcpy(to, from, n);
227 else
228 return n;
229 return 0;
230}
231
232/*
233 * Copy a null terminated string from userspace.
234 */
235
236static inline long strncpy_from_user(char *dst,
237 const char *src, long count)
238{
239 char *tmp;
240 if (!access_ok(VERIFY_READ, src, 1))
241 return -EFAULT;
242 strncpy(dst, src, count);
243 for (tmp = dst; *tmp && count > 0; tmp++, count--) ;
244 return (tmp - dst);
245}
246
247/*
248 * Return the size of a string (including the ending 0)
249 *
250 * Return 0 on exception, a value greater than N if too long
251 */
252static inline long strnlen_user(const char *src, long n)
253{
254 return (strlen(src) + 1);
255}
256
257#define strlen_user(str) strnlen_user(str, 32767)
258
259/*
260 * Zero Userspace
261 */
262
263static inline unsigned long __clear_user(void *to, unsigned long n)
264{
265 memset(to, 0, n);
266 return 0;
267}
268
269#define clear_user(to, n) __clear_user(to, n)
270
271#endif /* _BLACKFIN_UACCESS_H */