2005-04-16 15:20:36 -07:00
/*
* 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>
2005-09-03 15:56:16 -07:00
# ifdef CONFIG_32BIT
2005-04-16 15:20:36 -07:00
# define __PA_ADDR ".word"
# endif
2005-09-03 15:56:16 -07:00
# ifdef CONFIG_64BIT
2005-04-16 15:20:36 -07:00
# define __PA_ADDR ".dword"
# endif
extern asmlinkage void handle_ibe ( void ) ;
extern asmlinkage void handle_dbe ( void ) ;
2007-10-11 23:46:15 +01:00
# define put_dbe(x, ptr) __put_dbe((x), (ptr), sizeof(*(ptr)))
# define get_dbe(x, ptr) __get_dbe((x), (ptr), sizeof(*(ptr)))
2005-04-16 15:20:36 -07:00
struct __large_pstruct { unsigned long buf [ 100 ] ; } ;
# define __mp(x) (*(struct __large_pstruct *)(x))
2007-10-11 23:46:15 +01:00
# define __get_dbe(x, ptr, size) \
2005-04-16 15:20:36 -07:00
( { \
long __gu_err ; \
2007-04-10 06:23:27 -04:00
__typeof__ ( * ( ptr ) ) __gu_val ; \
2005-04-16 15:20:36 -07:00
unsigned long __gu_addr ; \
__asm__ ( " " : " =r " ( __gu_val ) ) ; \
__gu_addr = ( unsigned 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) \
2005-03-04 19:36:51 +00:00
{ \
2005-04-16 15:20:36 -07:00
__asm__ __volatile__ ( \
" 1: \t " insn " \t %1,%2 \n \t " \
" move \t %0,$0 \n " \
" 2: \n \t " \
" .section \t .fixup, \" ax \" \n " \
" 3: \t li \t %0,%3 \n \t " \
" move \t %1,$0 \n \t " \
" j \t 2b \n \t " \
" .previous \n \t " \
" .section \t __dbe_table, \" a \" \n \t " \
__PA_ADDR " \t 1b, 3b \n \t " \
" .previous " \
: " =r " ( __gu_err ) , " =r " ( __gu_val ) \
: " o " ( __mp ( __gu_addr ) ) , " i " ( - EFAULT ) ) ; \
2005-03-04 19:36:51 +00:00
}
2005-04-16 15:20:36 -07:00
extern void __get_dbe_unknown ( void ) ;
2007-10-11 23:46:15 +01:00
# define __put_dbe(x, ptr, size) \
2005-04-16 15:20:36 -07:00
( { \
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) \
2005-03-04 19:36:51 +00:00
{ \
2005-04-16 15:20:36 -07:00
__asm__ __volatile__ ( \
" 1: \t " insn " \t %1,%2 \n \t " \
" move \t %0,$0 \n " \
" 2: \n \t " \
" .section \t .fixup, \" ax \" \n " \
" 3: \t li \t %0,%3 \n \t " \
" j \t 2b \n \t " \
" .previous \n \t " \
" .section \t __dbe_table, \" a \" \n \t " \
__PA_ADDR " \t 1b, 3b \n \t " \
" .previous " \
: " =r " ( __pu_err ) \
: " r " ( __pu_val ) , " o " ( __mp ( __pu_addr ) ) , " i " ( - EFAULT ) ) ; \
2005-03-04 19:36:51 +00:00
}
2005-04-16 15:20:36 -07:00
extern void __put_dbe_unknown ( void ) ;
extern unsigned long search_dbe_table ( unsigned long addr ) ;
# endif /* _ASM_PACCESS_H */