Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * linux/include/asm-arm/proc-armo/uaccess.h |
| 3 | * |
| 4 | * Copyright (C) 1996 Russell King |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as |
| 8 | * published by the Free Software Foundation. |
| 9 | */ |
| 10 | |
| 11 | /* |
| 12 | * The fs functions are implemented on the ARM2 and ARM3 architectures |
| 13 | * manually. |
| 14 | * Use *_user functions to access user memory with faulting behaving |
| 15 | * as though the user is accessing the memory. |
| 16 | * Use set_fs(get_ds()) and then the *_user functions to allow them to |
| 17 | * access kernel memory. |
| 18 | */ |
| 19 | |
| 20 | /* |
| 21 | * These are the values used to represent the user `fs' and the kernel `ds' |
| 22 | * FIXME - the KERNEL_DS should end at 0x03000000 but we want to access ROM at |
| 23 | * 0x03400000. ideally we want to forbid access to the IO space inbetween. |
| 24 | */ |
| 25 | #define KERNEL_DS 0x03FFFFFF |
| 26 | #define USER_DS 0x02000000 |
| 27 | |
| 28 | extern uaccess_t uaccess_user, uaccess_kernel; |
| 29 | |
| 30 | static inline void set_fs (mm_segment_t fs) |
| 31 | { |
| 32 | current_thread_info()->addr_limit = fs; |
| 33 | current->thread.uaccess = (fs == USER_DS ? &uaccess_user : &uaccess_kernel); |
| 34 | } |
| 35 | |
| 36 | #define __range_ok(addr,size) ({ \ |
Tilman Schmidt | 16cf5b3 | 2007-02-10 01:45:41 -0800 | [diff] [blame] | 37 | unsigned long flag, roksum; \ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 38 | __asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \ |
Tilman Schmidt | 16cf5b3 | 2007-02-10 01:45:41 -0800 | [diff] [blame] | 39 | : "=&r" (flag), "=&r" (roksum) \ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 40 | : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \ |
| 41 | : "cc"); \ |
| 42 | flag; }) |
| 43 | |
| 44 | #define __addr_ok(addr) ({ \ |
| 45 | unsigned long flag; \ |
| 46 | __asm__ __volatile__("cmp %2, %0; movlo %0, #0" \ |
| 47 | : "=&r" (flag) \ |
| 48 | : "0" (current_thread_info()->addr_limit), "r" (addr) \ |
| 49 | : "cc"); \ |
| 50 | (flag == 0); }) |
| 51 | |
| 52 | #define __put_user_asm_byte(x,addr,err) \ |
| 53 | __asm__ __volatile__( \ |
| 54 | " mov r0, %1\n" \ |
| 55 | " mov r1, %2\n" \ |
| 56 | " mov r2, %0\n" \ |
| 57 | " mov lr, pc\n" \ |
| 58 | " mov pc, %3\n" \ |
| 59 | " mov %0, r2\n" \ |
| 60 | : "=r" (err) \ |
| 61 | : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_byte), \ |
| 62 | "0" (err) \ |
| 63 | : "r0", "r1", "r2", "lr") |
| 64 | |
| 65 | #define __put_user_asm_half(x,addr,err) \ |
| 66 | __asm__ __volatile__( \ |
| 67 | " mov r0, %1\n" \ |
| 68 | " mov r1, %2\n" \ |
| 69 | " mov r2, %0\n" \ |
| 70 | " mov lr, pc\n" \ |
| 71 | " mov pc, %3\n" \ |
| 72 | " mov %0, r2\n" \ |
| 73 | : "=r" (err) \ |
| 74 | : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_half), \ |
| 75 | "0" (err) \ |
| 76 | : "r0", "r1", "r2", "lr") |
| 77 | |
| 78 | #define __put_user_asm_word(x,addr,err) \ |
| 79 | __asm__ __volatile__( \ |
| 80 | " mov r0, %1\n" \ |
| 81 | " mov r1, %2\n" \ |
| 82 | " mov r2, %0\n" \ |
| 83 | " mov lr, pc\n" \ |
| 84 | " mov pc, %3\n" \ |
| 85 | " mov %0, r2\n" \ |
| 86 | : "=r" (err) \ |
| 87 | : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_word), \ |
| 88 | "0" (err) \ |
| 89 | : "r0", "r1", "r2", "lr") |
| 90 | |
| 91 | #define __put_user_asm_dword(x,addr,err) \ |
| 92 | __asm__ __volatile__( \ |
| 93 | " mov r0, %1\n" \ |
| 94 | " mov r1, %2\n" \ |
| 95 | " mov r2, %0\n" \ |
| 96 | " mov lr, pc\n" \ |
| 97 | " mov pc, %3\n" \ |
| 98 | " mov %0, r2\n" \ |
| 99 | : "=r" (err) \ |
| 100 | : "r" (x), "r" (addr), "r" (current->thread.uaccess->put_dword), \ |
| 101 | "0" (err) \ |
| 102 | : "r0", "r1", "r2", "lr") |
| 103 | |
| 104 | #define __get_user_asm_byte(x,addr,err) \ |
| 105 | __asm__ __volatile__( \ |
| 106 | " mov r0, %2\n" \ |
| 107 | " mov r1, %0\n" \ |
| 108 | " mov lr, pc\n" \ |
| 109 | " mov pc, %3\n" \ |
| 110 | " mov %0, r1\n" \ |
| 111 | " mov %1, r0\n" \ |
| 112 | : "=r" (err), "=r" (x) \ |
| 113 | : "r" (addr), "r" (current->thread.uaccess->get_byte), "0" (err) \ |
| 114 | : "r0", "r1", "r2", "lr") |
| 115 | |
| 116 | #define __get_user_asm_half(x,addr,err) \ |
| 117 | __asm__ __volatile__( \ |
| 118 | " mov r0, %2\n" \ |
| 119 | " mov r1, %0\n" \ |
| 120 | " mov lr, pc\n" \ |
| 121 | " mov pc, %3\n" \ |
| 122 | " mov %0, r1\n" \ |
| 123 | " mov %1, r0\n" \ |
| 124 | : "=r" (err), "=r" (x) \ |
| 125 | : "r" (addr), "r" (current->thread.uaccess->get_half), "0" (err) \ |
| 126 | : "r0", "r1", "r2", "lr") |
| 127 | |
| 128 | #define __get_user_asm_word(x,addr,err) \ |
| 129 | __asm__ __volatile__( \ |
| 130 | " mov r0, %2\n" \ |
| 131 | " mov r1, %0\n" \ |
| 132 | " mov lr, pc\n" \ |
| 133 | " mov pc, %3\n" \ |
| 134 | " mov %0, r1\n" \ |
| 135 | " mov %1, r0\n" \ |
| 136 | : "=r" (err), "=r" (x) \ |
| 137 | : "r" (addr), "r" (current->thread.uaccess->get_word), "0" (err) \ |
| 138 | : "r0", "r1", "r2", "lr") |
| 139 | |
| 140 | #define __do_copy_from_user(to,from,n) \ |
| 141 | (n) = current->thread.uaccess->copy_from_user((to),(from),(n)) |
| 142 | |
| 143 | #define __do_copy_to_user(to,from,n) \ |
| 144 | (n) = current->thread.uaccess->copy_to_user((to),(from),(n)) |
| 145 | |
| 146 | #define __do_clear_user(addr,sz) \ |
| 147 | (sz) = current->thread.uaccess->clear_user((addr),(sz)) |
| 148 | |
| 149 | #define __do_strncpy_from_user(dst,src,count,res) \ |
| 150 | (res) = current->thread.uaccess->strncpy_from_user(dst,src,count) |
| 151 | |
| 152 | #define __do_strnlen_user(s,n,res) \ |
| 153 | (res) = current->thread.uaccess->strnlen_user(s,n) |