diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-20 23:50:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-20 23:50:27 +0000 |
commit | 72919904796333a20c6a5d5c380091b42e407aa9 (patch) | |
tree | 0d40300f31cfb7ff67e0e1ea98c1c1058f82d148 /include | |
parent | be8574a19cef3002c2d9041596bcf8fa3570d218 (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.h | 92 |
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 */ |