paccess.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
  7. * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8. *
  9. * Protected memory access. Used for everything that might take revenge
  10. * by sending a DBE error like accessing possibly non-existent memory or
  11. * devices.
  12. */
  13. #ifndef _ASM_PACCESS_H
  14. #define _ASM_PACCESS_H
  15. #include <linux/errno.h>
  16. #ifdef CONFIG_32BIT
  17. #define __PA_ADDR ".word"
  18. #endif
  19. #ifdef CONFIG_64BIT
  20. #define __PA_ADDR ".dword"
  21. #endif
  22. extern asmlinkage void handle_ibe(void);
  23. extern asmlinkage void handle_dbe(void);
  24. #define put_dbe(x, ptr) __put_dbe((x), (ptr), sizeof(*(ptr)))
  25. #define get_dbe(x, ptr) __get_dbe((x), (ptr), sizeof(*(ptr)))
  26. struct __large_pstruct { unsigned long buf[100]; };
  27. #define __mp(x) (*(struct __large_pstruct *)(x))
  28. #define __get_dbe(x, ptr, size) \
  29. ({ \
  30. long __gu_err; \
  31. __typeof__(*(ptr)) __gu_val; \
  32. unsigned long __gu_addr; \
  33. __asm__("":"=r" (__gu_val)); \
  34. __gu_addr = (unsigned long) (ptr); \
  35. __asm__("":"=r" (__gu_err)); \
  36. switch (size) { \
  37. case 1: __get_dbe_asm("lb"); break; \
  38. case 2: __get_dbe_asm("lh"); break; \
  39. case 4: __get_dbe_asm("lw"); break; \
  40. case 8: __get_dbe_asm("ld"); break; \
  41. default: __get_dbe_unknown(); break; \
  42. } \
  43. x = (__typeof__(*(ptr))) __gu_val; \
  44. __gu_err; \
  45. })
  46. #define __get_dbe_asm(insn) \
  47. { \
  48. __asm__ __volatile__( \
  49. "1:\t" insn "\t%1,%2\n\t" \
  50. "move\t%0,$0\n" \
  51. "2:\n\t" \
  52. ".insn\n\t" \
  53. ".section\t.fixup,\"ax\"\n" \
  54. "3:\tli\t%0,%3\n\t" \
  55. "move\t%1,$0\n\t" \
  56. "j\t2b\n\t" \
  57. ".previous\n\t" \
  58. ".section\t__dbe_table,\"a\"\n\t" \
  59. __PA_ADDR "\t1b, 3b\n\t" \
  60. ".previous" \
  61. :"=r" (__gu_err), "=r" (__gu_val) \
  62. :"o" (__mp(__gu_addr)), "i" (-EFAULT)); \
  63. }
  64. extern void __get_dbe_unknown(void);
  65. #define __put_dbe(x, ptr, size) \
  66. ({ \
  67. long __pu_err; \
  68. __typeof__(*(ptr)) __pu_val; \
  69. long __pu_addr; \
  70. __pu_val = (x); \
  71. __pu_addr = (long) (ptr); \
  72. __asm__("":"=r" (__pu_err)); \
  73. switch (size) { \
  74. case 1: __put_dbe_asm("sb"); break; \
  75. case 2: __put_dbe_asm("sh"); break; \
  76. case 4: __put_dbe_asm("sw"); break; \
  77. case 8: __put_dbe_asm("sd"); break; \
  78. default: __put_dbe_unknown(); break; \
  79. } \
  80. __pu_err; \
  81. })
  82. #define __put_dbe_asm(insn) \
  83. { \
  84. __asm__ __volatile__( \
  85. "1:\t" insn "\t%1,%2\n\t" \
  86. "move\t%0,$0\n" \
  87. "2:\n\t" \
  88. ".insn\n\t" \
  89. ".section\t.fixup,\"ax\"\n" \
  90. "3:\tli\t%0,%3\n\t" \
  91. "j\t2b\n\t" \
  92. ".previous\n\t" \
  93. ".section\t__dbe_table,\"a\"\n\t" \
  94. __PA_ADDR "\t1b, 3b\n\t" \
  95. ".previous" \
  96. : "=r" (__pu_err) \
  97. : "r" (__pu_val), "o" (__mp(__pu_addr)), "i" (-EFAULT)); \
  98. }
  99. extern void __put_dbe_unknown(void);
  100. extern unsigned long search_dbe_table(unsigned long addr);
  101. #endif /* _ASM_PACCESS_H */