0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef _ASM_PACCESS_H
0014 #define _ASM_PACCESS_H
0015
0016 #include <linux/errno.h>
0017
0018 #ifdef CONFIG_32BIT
0019 #define __PA_ADDR ".word"
0020 #endif
0021 #ifdef CONFIG_64BIT
0022 #define __PA_ADDR ".dword"
0023 #endif
0024
0025 extern asmlinkage void handle_ibe(void);
0026 extern asmlinkage void handle_dbe(void);
0027
0028 #define put_dbe(x, ptr) __put_dbe((x), (ptr), sizeof(*(ptr)))
0029 #define get_dbe(x, ptr) __get_dbe((x), (ptr), sizeof(*(ptr)))
0030
0031 struct __large_pstruct { unsigned long buf[100]; };
0032 #define __mp(x) (*(struct __large_pstruct *)(x))
0033
0034 #define __get_dbe(x, ptr, size) \
0035 ({ \
0036 long __gu_err; \
0037 __typeof__(*(ptr)) __gu_val; \
0038 unsigned long __gu_addr; \
0039 __asm__("":"=r" (__gu_val)); \
0040 __gu_addr = (unsigned long) (ptr); \
0041 __asm__("":"=r" (__gu_err)); \
0042 switch (size) { \
0043 case 1: __get_dbe_asm("lb"); break; \
0044 case 2: __get_dbe_asm("lh"); break; \
0045 case 4: __get_dbe_asm("lw"); break; \
0046 case 8: __get_dbe_asm("ld"); break; \
0047 default: __get_dbe_unknown(); break; \
0048 } \
0049 x = (__typeof__(*(ptr))) __gu_val; \
0050 __gu_err; \
0051 })
0052
0053 #define __get_dbe_asm(insn) \
0054 { \
0055 __asm__ __volatile__( \
0056 "1:\t" insn "\t%1,%2\n\t" \
0057 "move\t%0,$0\n" \
0058 "2:\n\t" \
0059 ".insn\n\t" \
0060 ".section\t.fixup,\"ax\"\n" \
0061 "3:\tli\t%0,%3\n\t" \
0062 "move\t%1,$0\n\t" \
0063 "j\t2b\n\t" \
0064 ".previous\n\t" \
0065 ".section\t__dbe_table,\"a\"\n\t" \
0066 __PA_ADDR "\t1b, 3b\n\t" \
0067 ".previous" \
0068 :"=r" (__gu_err), "=r" (__gu_val) \
0069 :"o" (__mp(__gu_addr)), "i" (-EFAULT)); \
0070 }
0071
0072 extern void __get_dbe_unknown(void);
0073
0074 #define __put_dbe(x, ptr, size) \
0075 ({ \
0076 long __pu_err; \
0077 __typeof__(*(ptr)) __pu_val; \
0078 long __pu_addr; \
0079 __pu_val = (x); \
0080 __pu_addr = (long) (ptr); \
0081 __asm__("":"=r" (__pu_err)); \
0082 switch (size) { \
0083 case 1: __put_dbe_asm("sb"); break; \
0084 case 2: __put_dbe_asm("sh"); break; \
0085 case 4: __put_dbe_asm("sw"); break; \
0086 case 8: __put_dbe_asm("sd"); break; \
0087 default: __put_dbe_unknown(); break; \
0088 } \
0089 __pu_err; \
0090 })
0091
0092 #define __put_dbe_asm(insn) \
0093 { \
0094 __asm__ __volatile__( \
0095 "1:\t" insn "\t%1,%2\n\t" \
0096 "move\t%0,$0\n" \
0097 "2:\n\t" \
0098 ".insn\n\t" \
0099 ".section\t.fixup,\"ax\"\n" \
0100 "3:\tli\t%0,%3\n\t" \
0101 "j\t2b\n\t" \
0102 ".previous\n\t" \
0103 ".section\t__dbe_table,\"a\"\n\t" \
0104 __PA_ADDR "\t1b, 3b\n\t" \
0105 ".previous" \
0106 : "=r" (__pu_err) \
0107 : "r" (__pu_val), "o" (__mp(__pu_addr)), "i" (-EFAULT)); \
0108 }
0109
0110 extern void __put_dbe_unknown(void);
0111
0112 extern unsigned long search_dbe_table(unsigned long addr);
0113
0114 #endif