summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-20 23:50:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-20 23:50:27 +0000
commit72919904796333a20c6a5d5c380091b42e407aa9 (patch)
tree0d40300f31cfb7ff67e0e1ea98c1c1058f82d148 /include
parentbe8574a19cef3002c2d9041596bcf8fa3570d218 (diff)
Add {get,put}_user()-style functions that are protected against DBE.
Unlike the IRIX functions they only have one instruction overhead per access, don't involve subroutine calls or any spinlocks, so are implicitly threadsafe. Add PCI infrastructure for SN0 + the necessary fixups for IOC3 brokeness.
Diffstat (limited to 'include')
-rw-r--r--include/asm-mips64/paccess.h92
1 files changed, 92 insertions, 0 deletions
diff --git a/include/asm-mips64/paccess.h b/include/asm-mips64/paccess.h
new file mode 100644
index 000000000..0b97674cf
--- /dev/null
+++ b/include/asm-mips64/paccess.h
@@ -0,0 +1,92 @@
+/* $Id: paccess.h,v 1.1 2000/01/20 22:50:32 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ *
+ * Protected memory access. Used for everything that might take revenge
+ * by sending a DBE error like accessing possibly non-existant memory or
+ * devices.
+ */
+#ifndef _ASM_PACCESS_H
+#define _ASM_PACCESS_H
+
+#include <linux/errno.h>
+
+#define put_dbe(x,ptr) __put_dbe((x),(ptr),sizeof(*(ptr)))
+#define get_dbe(x,ptr) __get_dbe((x),(ptr),sizeof(*(ptr)))
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __get_dbe(x,ptr,size) ({ \
+long __gu_err; \
+__typeof(*(ptr)) __gu_val; \
+long __gu_addr; \
+__asm__("":"=r" (__gu_val)); \
+__gu_addr = (long) (ptr); \
+__asm__("":"=r" (__gu_err)); \
+switch (size) { \
+case 1: __get_dbe_asm("lb"); break; \
+case 2: __get_dbe_asm("lh"); break; \
+case 4: __get_dbe_asm("lw"); break; \
+case 8: __get_dbe_asm("ld"); break; \
+default: __get_dbe_unknown(); break; \
+} x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_dbe_asm(insn) \
+({ \
+__asm__ __volatile__( \
+ "1:\t" insn "\t%1,%2\n\t" \
+ "move\t%0,$0\n" \
+ "2:\n\t" \
+ ".section\t.fixup,\"ax\"\n" \
+ "3:\tli\t%0,%3\n\t" \
+ "move\t%1,$0\n\t" \
+ "j\t2b\n\t" \
+ ".previous\n\t" \
+ ".section\t__dbe_table,\"a\"\n\t" \
+ ".dword\t1b,3b\n\t" \
+ ".previous" \
+ :"=r" (__gu_err), "=r" (__gu_val) \
+ :"o" (__m(__gu_addr)), "i" (-EFAULT)); })
+
+extern void __get_dbe_unknown(void);
+
+#define __put_dbe(x,ptr,size) ({ \
+long __pu_err; \
+__typeof__(*(ptr)) __pu_val; \
+long __pu_addr; \
+__pu_val = (x); \
+__pu_addr = (long) (ptr); \
+__asm__("":"=r" (__pu_err)); \
+switch (size) { \
+case 1: __put_dbe_asm("sb"); break; \
+case 2: __put_dbe_asm("sh"); break; \
+case 4: __put_dbe_asm("sw"); break; \
+case 8: __put_dbe_asm("sd"); break; \
+default: __put_dbe_unknown(); break; \
+} __pu_err; })
+
+#define __put_dbe_asm(insn) \
+({ \
+__asm__ __volatile__( \
+ "1:\t" insn "\t%1,%2\n\t" \
+ "move\t%0,$0\n" \
+ "2:\n\t" \
+ ".section\t.fixup,\"ax\"\n" \
+ "3:\tli\t%0,%3\n\t" \
+ "j\t2b\n\t" \
+ ".previous\n\t" \
+ ".section\t__dbe_table,\"a\"\n\t" \
+ ".dword\t1b,3b\n\t" \
+ ".previous" \
+ :"=r" (__pu_err) \
+ :"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT)); })
+
+extern void __put_dbe_unknown(void);
+
+#endif /* _ASM_PACCESS_H */