File: /usr/src/linux/include/asm-parisc/uaccess.h

1     #ifndef __PARISC_UACCESS_H
2     #define __PARISC_UACCESS_H
3     
4     /*
5      * User space memory access functions
6      */
7     #include <linux/sched.h>
8     #include <asm/page.h>
9     #include <asm/system.h>
10     #include <asm/cache.h>
11     
12     #define VERIFY_READ 0
13     #define VERIFY_WRITE 1
14     
15     #define KERNEL_DS	((mm_segment_t){0})
16     #define USER_DS 	((mm_segment_t){1})
17     
18     #define segment_eq(a,b)	((a).seg == (b).seg)
19     
20     #define get_ds()	(KERNEL_DS)
21     #define get_fs()	(current->addr_limit)
22     #define set_fs(x)	(current->addr_limit = (x))
23     
24     /*
25      * Note that since kernel addresses are in a separate address space on
26      * parisc, we don't need to do anything for access_ok() or verify_area().
27      * We just let the page fault handler do the right thing. This also means
28      * that put_user is the same as __put_user, etc.
29      */
30     
31     #define access_ok(type,addr,size)   (1)
32     #define verify_area(type,addr,size) (0)
33     
34     #define put_user __put_user
35     #define get_user __get_user
36     
37     /*
38      * The exception table contains two values: the first is an address
39      * for an instruction that is allowed to fault, and the second is
40      * the number of bytes to skip if a fault occurs. We also support in
41      * two bit flags: 0x2 tells the exception handler to clear register
42      * r9 and 0x1 tells the exception handler to put -EFAULT in r8.
43      * This allows us to handle the simple cases for put_user and
44      * get_user without having to have .fixup sections.
45      */
46     
47     struct exception_table_entry {
48     	unsigned long addr;  /* address of insn that is allowed to fault.   */
49     	int skip;            /* pcoq skip | r9 clear flag | r8 -EFAULT flag */
50     };
51     
52     extern const struct exception_table_entry 
53         *search_exception_table(unsigned long addr);
54     
55     #define __get_user(x,ptr)                               \
56     ({                                                      \
57     	register long __gu_err __asm__ ("r8") = 0;      \
58     	register long __gu_val __asm__ ("r9") = 0;      \
59     							\
60     	if (segment_eq(get_fs(),KERNEL_DS)) {           \
61     	    switch (sizeof(*(ptr))) {                   \
62     	    case 1: __get_kernel_asm("ldb",ptr); break; \
63     	    case 2: __get_kernel_asm("ldh",ptr); break; \
64     	    case 4: __get_kernel_asm("ldw",ptr); break; \
65     	    case 8: __get_kernel_asm("ldd",ptr); break; \
66     	    default: BUG(); break;                      \
67     	    }                                           \
68     	}                                               \
69     	else {                                          \
70     	    switch (sizeof(*(ptr))) {                   \
71     	    case 1: __get_user_asm("ldb",ptr); break;   \
72     	    case 2: __get_user_asm("ldh",ptr); break;   \
73     	    case 4: __get_user_asm("ldw",ptr); break;   \
74     	    case 8: __get_user_asm("ldd",ptr); break;   \
75     	    default: BUG(); break;                      \
76     	    }                                           \
77     	}                                               \
78     							\
79     	(x) = (__typeof__(*(ptr))) __gu_val;            \
80     	__gu_err;                                       \
81     })
82     
83     #define __get_kernel_asm(ldx,ptr)                       \
84     	__asm__("\n1:\t" ldx "\t0(%2),%0\n"             \
85     		"2:\n"					\
86     		"\t.section __ex_table,\"a\"\n"         \
87     		 "\t.word\t1b\n"                        \
88     		 "\t.word\t(2b-1b)+3\n"                 \
89     		 "\t.previous"                          \
90     		: "=r"(__gu_val), "=r"(__gu_err)        \
91     		: "r"(ptr), "1"(__gu_err));
92     
93     #define __get_user_asm(ldx,ptr)                         \
94     	__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n"       \
95     		"2:\n"					\
96     		"\t.section __ex_table,\"a\"\n"         \
97     		 "\t.word\t1b\n"                        \
98     		 "\t.word\t(2b-1b)+3\n"                 \
99     		 "\t.previous"                          \
100     		: "=r"(__gu_val), "=r"(__gu_err)        \
101     		: "r"(ptr), "1"(__gu_err));
102     
103     
104     #define __put_user(x,ptr)                                       \
105     ({								\
106     	register long __pu_err __asm__ ("r8") = 0;		\
107     								\
108     	if (segment_eq(get_fs(),KERNEL_DS)) {                   \
109     	    switch (sizeof(*(ptr))) {                           \
110     	    case 1: __put_kernel_asm("stb",x,ptr); break;       \
111     	    case 2: __put_kernel_asm("sth",x,ptr); break;       \
112     	    case 4: __put_kernel_asm("stw",x,ptr); break;       \
113     	    case 8: __put_kernel_asm("std",x,ptr); break;       \
114     	    default: BUG(); break;                              \
115     	    }                                                   \
116     	}                                                       \
117     	else {                                                  \
118     	    switch (sizeof(*(ptr))) {                           \
119     	    case 1: __put_user_asm("stb",x,ptr); break;         \
120     	    case 2: __put_user_asm("sth",x,ptr); break;         \
121     	    case 4: __put_user_asm("stw",x,ptr); break;         \
122     	    case 8: __put_user_asm("std",x,ptr); break;         \
123     	    default: BUG(); break;                              \
124     	    }                                                   \
125     	}                                                       \
126     								\
127     	__pu_err;						\
128     })
129     
130     /*
131      * The "__put_user/kernel_asm()" macros tell gcc they read from memory
132      * instead of writing. This is because they do not write to any memory
133      * gcc knows about, so there are no aliasing issues.
134      */
135     
136     #define __put_kernel_asm(stx,x,ptr)                         \
137     	__asm__ __volatile__ (                              \
138     		"\n1:\t" stx "\t%2,0(%1)\n"                 \
139     		"2:\n"					    \
140     		"\t.section __ex_table,\"a\"\n"             \
141     		 "\t.word\t1b\n"                            \
142     		 "\t.word\t(2b-1b)+1\n"                     \
143     		 "\t.previous"                              \
144     		: "=r"(__pu_err)                            \
145     		: "r"(ptr), "r"(x), "0"(__pu_err))
146     
147     #define __put_user_asm(stx,x,ptr)                           \
148     	__asm__ __volatile__ (                              \
149     		"\n1:\t" stx "\t%2,0(%%sr3,%1)\n"           \
150     		"2:\n"					    \
151     		"\t.section __ex_table,\"a\"\n"             \
152     		 "\t.word\t1b\n"                            \
153     		 "\t.word\t(2b-1b)+1\n"                     \
154     		 "\t.previous"                              \
155     		: "=r"(__pu_err)                            \
156     		: "r"(ptr), "r"(x), "0"(__pu_err))
157     
158     
159     /*
160      * Complex access routines -- external declarations
161      */
162     
163     extern unsigned long lcopy_to_user(void *, const void *, unsigned long);
164     extern unsigned long lcopy_from_user(void *, const void *, unsigned long);
165     extern long lstrncpy_from_user(char *, const char *, long);
166     extern unsigned lclear_user(void *,unsigned long);
167     extern long lstrnlen_user(const char *,long);
168     
169     /*
170      * Complex access routines -- macros
171      */
172     
173     #define strncpy_from_user lstrncpy_from_user
174     #define strnlen_user lstrnlen_user
175     #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
176     #define clear_user lclear_user
177     
178     #define copy_from_user lcopy_from_user
179     #define __copy_from_user lcopy_from_user
180     #define copy_to_user lcopy_to_user
181     #define __copy_to_user lcopy_to_user
182     
183     #define copy_to_user_ret(to,from,n,retval) \
184         ({ if (lcopy_to_user(to,from,n)) return retval; })
185     
186     #define copy_from_user_ret(to,from,n,retval) \
187         ({ if (lcopy_from_user(to,from,n)) return retval; })
188     
189     #endif /* __PARISC_UACCESS_H */
190