Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.20-rc4 288 lines 10 kB view raw
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#include <asm-generic/uaccess.h> 12 13#define VERIFY_READ 0 14#define VERIFY_WRITE 1 15 16#define KERNEL_DS ((mm_segment_t){0}) 17#define USER_DS ((mm_segment_t){1}) 18 19#define segment_eq(a,b) ((a).seg == (b).seg) 20 21#define get_ds() (KERNEL_DS) 22#define get_fs() (current_thread_info()->addr_limit) 23#define set_fs(x) (current_thread_info()->addr_limit = (x)) 24 25/* 26 * Note that since kernel addresses are in a separate address space on 27 * parisc, we don't need to do anything for access_ok(). 28 * We just let the page fault handler do the right thing. This also means 29 * that put_user is the same as __put_user, etc. 30 */ 31 32extern int __get_kernel_bad(void); 33extern int __get_user_bad(void); 34extern int __put_kernel_bad(void); 35extern int __put_user_bad(void); 36 37static inline long access_ok(int type, const void __user * addr, 38 unsigned long size) 39{ 40 return 1; 41} 42 43#define put_user __put_user 44#define get_user __get_user 45 46#if BITS_PER_LONG == 32 47#define LDD_KERNEL(ptr) __get_kernel_bad(); 48#define LDD_USER(ptr) __get_user_bad(); 49#define STD_KERNEL(x, ptr) __put_kernel_asm64(x,ptr) 50#define STD_USER(x, ptr) __put_user_asm64(x,ptr) 51#else 52#define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr) 53#define LDD_USER(ptr) __get_user_asm("ldd",ptr) 54#define STD_KERNEL(x, ptr) __put_kernel_asm("std",x,ptr) 55#define STD_USER(x, ptr) __put_user_asm("std",x,ptr) 56#endif 57 58/* 59 * The exception table contains two values: the first is an address 60 * for an instruction that is allowed to fault, and the second is 61 * the address to the fixup routine. 62 */ 63 64struct exception_table_entry { 65 unsigned long insn; /* address of insn that is allowed to fault. */ 66 long fixup; /* fixup routine */ 67}; 68 69/* 70 * The page fault handler stores, in a per-cpu area, the following information 71 * if a fixup routine is available. 72 */ 73struct exception_data { 74 unsigned long fault_ip; 75 unsigned long fault_space; 76 unsigned long fault_addr; 77}; 78 79#define __get_user(x,ptr) \ 80({ \ 81 register long __gu_err __asm__ ("r8") = 0; \ 82 register long __gu_val __asm__ ("r9") = 0; \ 83 \ 84 if (segment_eq(get_fs(),KERNEL_DS)) { \ 85 switch (sizeof(*(ptr))) { \ 86 case 1: __get_kernel_asm("ldb",ptr); break; \ 87 case 2: __get_kernel_asm("ldh",ptr); break; \ 88 case 4: __get_kernel_asm("ldw",ptr); break; \ 89 case 8: LDD_KERNEL(ptr); break; \ 90 default: __get_kernel_bad(); break; \ 91 } \ 92 } \ 93 else { \ 94 switch (sizeof(*(ptr))) { \ 95 case 1: __get_user_asm("ldb",ptr); break; \ 96 case 2: __get_user_asm("ldh",ptr); break; \ 97 case 4: __get_user_asm("ldw",ptr); break; \ 98 case 8: LDD_USER(ptr); break; \ 99 default: __get_user_bad(); break; \ 100 } \ 101 } \ 102 \ 103 (x) = (__typeof__(*(ptr))) __gu_val; \ 104 __gu_err; \ 105}) 106 107#ifdef __LP64__ 108#define __get_kernel_asm(ldx,ptr) \ 109 __asm__("\n1:\t" ldx "\t0(%2),%0\n" \ 110 "\t.section __ex_table,\"aw\"\n" \ 111 "\t.dword\t1b,fixup_get_user_skip_1\n" \ 112 "\t.previous" \ 113 : "=r"(__gu_val), "=r"(__gu_err) \ 114 : "r"(ptr), "1"(__gu_err) \ 115 : "r1"); 116 117#define __get_user_asm(ldx,ptr) \ 118 __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \ 119 "\t.section __ex_table,\"aw\"\n" \ 120 "\t.dword\t1b,fixup_get_user_skip_1\n" \ 121 "\t.previous" \ 122 : "=r"(__gu_val), "=r"(__gu_err) \ 123 : "r"(ptr), "1"(__gu_err) \ 124 : "r1"); 125#else 126#define __get_kernel_asm(ldx,ptr) \ 127 __asm__("\n1:\t" ldx "\t0(%2),%0\n" \ 128 "\t.section __ex_table,\"aw\"\n" \ 129 "\t.word\t1b,fixup_get_user_skip_1\n" \ 130 "\t.previous" \ 131 : "=r"(__gu_val), "=r"(__gu_err) \ 132 : "r"(ptr), "1"(__gu_err) \ 133 : "r1"); 134 135#define __get_user_asm(ldx,ptr) \ 136 __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \ 137 "\t.section __ex_table,\"aw\"\n" \ 138 "\t.word\t1b,fixup_get_user_skip_1\n" \ 139 "\t.previous" \ 140 : "=r"(__gu_val), "=r"(__gu_err) \ 141 : "r"(ptr), "1"(__gu_err) \ 142 : "r1"); 143#endif /* !__LP64__ */ 144 145#define __put_user(x,ptr) \ 146({ \ 147 register long __pu_err __asm__ ("r8") = 0; \ 148 __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ 149 \ 150 if (segment_eq(get_fs(),KERNEL_DS)) { \ 151 switch (sizeof(*(ptr))) { \ 152 case 1: __put_kernel_asm("stb",__x,ptr); break; \ 153 case 2: __put_kernel_asm("sth",__x,ptr); break; \ 154 case 4: __put_kernel_asm("stw",__x,ptr); break; \ 155 case 8: STD_KERNEL(__x,ptr); break; \ 156 default: __put_kernel_bad(); break; \ 157 } \ 158 } \ 159 else { \ 160 switch (sizeof(*(ptr))) { \ 161 case 1: __put_user_asm("stb",__x,ptr); break; \ 162 case 2: __put_user_asm("sth",__x,ptr); break; \ 163 case 4: __put_user_asm("stw",__x,ptr); break; \ 164 case 8: STD_USER(__x,ptr); break; \ 165 default: __put_user_bad(); break; \ 166 } \ 167 } \ 168 \ 169 __pu_err; \ 170}) 171 172/* 173 * The "__put_user/kernel_asm()" macros tell gcc they read from memory 174 * instead of writing. This is because they do not write to any memory 175 * gcc knows about, so there are no aliasing issues. These macros must 176 * also be aware that "fixup_put_user_skip_[12]" are executed in the 177 * context of the fault, and any registers used there must be listed 178 * as clobbers. In this case only "r1" is used by the current routines. 179 * r8/r9 are already listed as err/val. 180 */ 181 182#ifdef __LP64__ 183#define __put_kernel_asm(stx,x,ptr) \ 184 __asm__ __volatile__ ( \ 185 "\n1:\t" stx "\t%2,0(%1)\n" \ 186 "\t.section __ex_table,\"aw\"\n" \ 187 "\t.dword\t1b,fixup_put_user_skip_1\n" \ 188 "\t.previous" \ 189 : "=r"(__pu_err) \ 190 : "r"(ptr), "r"(x), "0"(__pu_err) \ 191 : "r1") 192 193#define __put_user_asm(stx,x,ptr) \ 194 __asm__ __volatile__ ( \ 195 "\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \ 196 "\t.section __ex_table,\"aw\"\n" \ 197 "\t.dword\t1b,fixup_put_user_skip_1\n" \ 198 "\t.previous" \ 199 : "=r"(__pu_err) \ 200 : "r"(ptr), "r"(x), "0"(__pu_err) \ 201 : "r1") 202#else 203#define __put_kernel_asm(stx,x,ptr) \ 204 __asm__ __volatile__ ( \ 205 "\n1:\t" stx "\t%2,0(%1)\n" \ 206 "\t.section __ex_table,\"aw\"\n" \ 207 "\t.word\t1b,fixup_put_user_skip_1\n" \ 208 "\t.previous" \ 209 : "=r"(__pu_err) \ 210 : "r"(ptr), "r"(x), "0"(__pu_err) \ 211 : "r1") 212 213#define __put_user_asm(stx,x,ptr) \ 214 __asm__ __volatile__ ( \ 215 "\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \ 216 "\t.section __ex_table,\"aw\"\n" \ 217 "\t.word\t1b,fixup_put_user_skip_1\n" \ 218 "\t.previous" \ 219 : "=r"(__pu_err) \ 220 : "r"(ptr), "r"(x), "0"(__pu_err) \ 221 : "r1") 222 223#define __put_kernel_asm64(__val,ptr) do { \ 224 u64 __val64 = (u64)(__val); \ 225 u32 hi = (__val64) >> 32; \ 226 u32 lo = (__val64) & 0xffffffff; \ 227 __asm__ __volatile__ ( \ 228 "\n1:\tstw %2,0(%1)\n" \ 229 "\n2:\tstw %3,4(%1)\n" \ 230 "\t.section __ex_table,\"aw\"\n" \ 231 "\t.word\t1b,fixup_put_user_skip_2\n" \ 232 "\t.word\t2b,fixup_put_user_skip_1\n" \ 233 "\t.previous" \ 234 : "=r"(__pu_err) \ 235 : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \ 236 : "r1"); \ 237} while (0) 238 239#define __put_user_asm64(__val,ptr) do { \ 240 u64 __val64 = (u64)__val; \ 241 u32 hi = (__val64) >> 32; \ 242 u32 lo = (__val64) & 0xffffffff; \ 243 __asm__ __volatile__ ( \ 244 "\n1:\tstw %2,0(%%sr3,%1)\n" \ 245 "\n2:\tstw %3,4(%%sr3,%1)\n" \ 246 "\t.section __ex_table,\"aw\"\n" \ 247 "\t.word\t1b,fixup_get_user_skip_2\n" \ 248 "\t.word\t2b,fixup_get_user_skip_1\n" \ 249 "\t.previous" \ 250 : "=r"(__pu_err) \ 251 : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \ 252 : "r1"); \ 253} while (0) 254 255#endif /* !__LP64__ */ 256 257 258/* 259 * Complex access routines -- external declarations 260 */ 261 262extern unsigned long lcopy_to_user(void __user *, const void *, unsigned long); 263extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long); 264extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long); 265extern long lstrncpy_from_user(char *, const char __user *, long); 266extern unsigned lclear_user(void __user *,unsigned long); 267extern long lstrnlen_user(const char __user *,long); 268 269/* 270 * Complex access routines -- macros 271 */ 272 273#define strncpy_from_user lstrncpy_from_user 274#define strnlen_user lstrnlen_user 275#define strlen_user(str) lstrnlen_user(str, 0x7fffffffL) 276#define clear_user lclear_user 277#define __clear_user lclear_user 278 279unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); 280#define __copy_to_user copy_to_user 281unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len); 282#define __copy_from_user copy_from_user 283unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); 284#define __copy_in_user copy_in_user 285#define __copy_to_user_inatomic __copy_to_user 286#define __copy_from_user_inatomic __copy_from_user 287 288#endif /* __PARISC_UACCESS_H */