|
@@ -1,3 +1,170 @@
|
|
|
#ifndef __ALPHA_UACCESS_H
|
|
|
#define __ALPHA_UACCESS_H
|
|
|
|
|
|
+#include <linux/errno.h>
|
|
|
+#include <linux/sched.h>
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * The fs value determines whether argument validity checking should be
|
|
|
+ * performed or not. If get_fs() == USER_DS, checking is performed, with
|
|
|
+ * get_fs() == KERNEL_DS, checking is bypassed.
|
|
|
+ *
|
|
|
+ * Or at least it did once upon a time. Nowadays it is a mask that
|
|
|
+ * defines which bits of the address space are off limits. This is a
|
|
|
+ * wee bit faster than the above.
|
|
|
+ *
|
|
|
+ * For historical reasons, these macros are grossly misnamed.
|
|
|
+ */
|
|
|
+
|
|
|
+#define KERNEL_DS ((mm_segment_t) { 0UL })
|
|
|
+#define USER_DS ((mm_segment_t) { -0x40000000000UL })
|
|
|
+
|
|
|
+#define VERIFY_READ 0
|
|
|
+#define VERIFY_WRITE 1
|
|
|
+
|
|
|
+#define get_fs() (current_thread_info()->addr_limit)
|
|
|
+#define get_ds() (KERNEL_DS)
|
|
|
+#define set_fs(x) (current_thread_info()->addr_limit = (x))
|
|
|
+
|
|
|
+#define segment_eq(a,b) ((a).seg == (b).seg)
|
|
|
+
|
|
|
+/*
|
|
|
+ * Is a address valid? This does a straightforward calculation rather
|
|
|
+ * than tests.
|
|
|
+ *
|
|
|
+ * Address valid if:
|
|
|
+ * - "addr" doesn't have any high-bits set
|
|
|
+ * - AND "size" doesn't have any high-bits set
|
|
|
+ * - AND "addr+size" doesn't have any high-bits set
|
|
|
+ * - OR we are in kernel mode.
|
|
|
+ */
|
|
|
+#define __access_ok(addr,size,segment) \
|
|
|
+ (((segment).seg & (addr | size | (addr+size))) == 0)
|
|
|
+
|
|
|
+#define access_ok(type,addr,size) \
|
|
|
+({ \
|
|
|
+ __chk_user_ptr(addr); \
|
|
|
+ __access_ok(((unsigned long)(addr)),(size),get_fs()); \
|
|
|
+})
|
|
|
+
|
|
|
+/*
|
|
|
+ * These are the main single-value transfer routines. They automatically
|
|
|
+ * use the right size if we just have the right pointer type.
|
|
|
+ *
|
|
|
+ * As the alpha uses the same address space for kernel and user
|
|
|
+ * data, we can just do these as direct assignments. (Of course, the
|
|
|
+ * exception handling means that it's no longer "just"...)
|
|
|
+ *
|
|
|
+ * Careful to not
|
|
|
+ * (a) re-use the arguments for side effects (sizeof/typeof is ok)
|
|
|
+ * (b) require any knowledge of processes at this stage
|
|
|
+ */
|
|
|
+#define put_user(x,ptr) \
|
|
|
+ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)),get_fs())
|
|
|
+#define get_user(x,ptr) \
|
|
|
+ __get_user_check((x),(ptr),sizeof(*(ptr)),get_fs())
|
|
|
+
|
|
|
+/*
|
|
|
+ * The "__xxx" versions do not do address space checking, useful when
|
|
|
+ * doing multiple accesses to the same area (the programmer has to do the
|
|
|
+ * checks by hand with "access_ok()")
|
|
|
+ */
|
|
|
+#define __put_user(x,ptr) \
|
|
|
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
|
|
|
+#define __get_user(x,ptr) \
|
|
|
+ __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
|
|
|
+
|
|
|
+/*
|
|
|
+ * The "lda %1, 2b-1b(%0)" bits are magic to get the assembler to
|
|
|
+ * encode the bits we need for resolving the exception. See the
|
|
|
+ * more extensive comments with fixup_inline_exception below for
|
|
|
+ * more information.
|
|
|
+ */
|
|
|
+
|
|
|
+extern void __get_user_unknown(void);
|
|
|
+
|
|
|
+#define __get_user_nocheck(x,ptr,size) \
|
|
|
+({ \
|
|
|
+ long __gu_err = 0; \
|
|
|
+ unsigned long __gu_val; \
|
|
|
+ __chk_user_ptr(ptr); \
|
|
|
+ switch (size) { \
|
|
|
+ case 1: __get_user_8(ptr); break; \
|
|
|
+ case 2: __get_user_16(ptr); break; \
|
|
|
+ case 4: __get_user_32(ptr); break; \
|
|
|
+ case 8: __get_user_64(ptr); break; \
|
|
|
+ default: __get_user_unknown(); break; \
|
|
|
+ } \
|
|
|
+ (x) = (__typeof__(*(ptr))) __gu_val; \
|
|
|
+ __gu_err; \
|
|
|
+})
|
|
|
+
|
|
|
+#define __get_user_check(x,ptr,size,segment) \
|
|
|
+({ \
|
|
|
+ long __gu_err = -EFAULT; \
|
|
|
+ unsigned long __gu_val = 0; \
|
|
|
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
|
|
+ if (__access_ok((unsigned long)__gu_addr,size,segment)) { \
|
|
|
+ __gu_err = 0; \
|
|
|
+ switch (size) { \
|
|
|
+ case 1: __get_user_8(__gu_addr); break; \
|
|
|
+ case 2: __get_user_16(__gu_addr); break; \
|
|
|
+ case 4: __get_user_32(__gu_addr); break; \
|
|
|
+ case 8: __get_user_64(__gu_addr); break; \
|
|
|
+ default: __get_user_unknown(); break; \
|
|
|
+ } \
|
|
|
+ } \
|
|
|
+ (x) = (__typeof__(*(ptr))) __gu_val; \
|
|
|
+ __gu_err; \
|
|
|
+})
|
|
|
+
|
|
|
+struct __large_struct { unsigned long buf[100]; };
|
|
|
+#define __m(x) (*(struct __large_struct __user *)(x))
|
|
|
+
|
|
|
+#define __get_user_64(addr) \
|
|
|
+ __asm__("1: ldq %0,%2\n" \
|
|
|
+ "2:\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .long 1b - .\n" \
|
|
|
+ " lda %0, 2b-1b(%1)\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=r"(__gu_val), "=r"(__gu_err) \
|
|
|
+ : "m"(__m(addr)), "1"(__gu_err))
|
|
|
+
|
|
|
+#define __get_user_32(addr) \
|
|
|
+ __asm__("1: ldl %0,%2\n" \
|
|
|
+ "2:\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .long 1b - .\n" \
|
|
|
+ " lda %0, 2b-1b(%1)\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=r"(__gu_val), "=r"(__gu_err) \
|
|
|
+ : "m"(__m(addr)), "1"(__gu_err))
|
|
|
+
|
|
|
+#ifdef __alpha_bwx__
|
|
|
+/* Those lucky bastards with ev56 and later CPUs can do byte/word moves. */
|
|
|
+
|
|
|
+#define __get_user_16(addr) \
|
|
|
+ __asm__("1: ldwu %0,%2\n" \
|
|
|
+ "2:\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .long 1b - .\n" \
|
|
|
+ " lda %0, 2b-1b(%1)\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=r"(__gu_val), "=r"(__gu_err) \
|
|
|
+ : "m"(__m(addr)), "1"(__gu_err))
|
|
|
+
|
|
|
+#define __get_user_8(addr) \
|
|
|
+ __asm__("1: ldbu %0,%2\n" \
|
|
|
+ "2:\n" \
|
|
|
+ ".section __ex_table,\"a\"\n" \
|
|
|
+ " .long 1b - .\n" \
|
|
|
+ " lda %0, 2b-1b(%1)\n" \
|
|
|
+ ".previous" \
|
|
|
+ : "=r"(__gu_val), "=r"(__gu_err) \
|
|
|
+ : "m"(__m(addr)), "1"(__gu_err))
|
|
|
+#else
|
|
|
+/* Unfortunately, we can't get an unaligned access trap for the sub-word
|
|
|
+ load, so we have to do a general unaligned operation. */
|
|
|
+
|