Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
0007  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
0008  *
0009  * Protected memory access.  Used for everything that might take revenge
0010  * by sending a DBE error like accessing possibly non-existent memory or
0011  * devices.
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 /* _ASM_PACCESS_H */