18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 38c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 48c2ecf20Sopenharmony_ci * for more details. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle 78c2ecf20Sopenharmony_ci * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Protected memory access. Used for everything that might take revenge 108c2ecf20Sopenharmony_ci * by sending a DBE error like accessing possibly non-existent memory or 118c2ecf20Sopenharmony_ci * devices. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#ifndef _ASM_PACCESS_H 148c2ecf20Sopenharmony_ci#define _ASM_PACCESS_H 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/errno.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#ifdef CONFIG_32BIT 198c2ecf20Sopenharmony_ci#define __PA_ADDR ".word" 208c2ecf20Sopenharmony_ci#endif 218c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 228c2ecf20Sopenharmony_ci#define __PA_ADDR ".dword" 238c2ecf20Sopenharmony_ci#endif 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciextern asmlinkage void handle_ibe(void); 268c2ecf20Sopenharmony_ciextern asmlinkage void handle_dbe(void); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define put_dbe(x, ptr) __put_dbe((x), (ptr), sizeof(*(ptr))) 298c2ecf20Sopenharmony_ci#define get_dbe(x, ptr) __get_dbe((x), (ptr), sizeof(*(ptr))) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistruct __large_pstruct { unsigned long buf[100]; }; 328c2ecf20Sopenharmony_ci#define __mp(x) (*(struct __large_pstruct *)(x)) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define __get_dbe(x, ptr, size) \ 358c2ecf20Sopenharmony_ci({ \ 368c2ecf20Sopenharmony_ci long __gu_err; \ 378c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __gu_val; \ 388c2ecf20Sopenharmony_ci unsigned long __gu_addr; \ 398c2ecf20Sopenharmony_ci __asm__("":"=r" (__gu_val)); \ 408c2ecf20Sopenharmony_ci __gu_addr = (unsigned long) (ptr); \ 418c2ecf20Sopenharmony_ci __asm__("":"=r" (__gu_err)); \ 428c2ecf20Sopenharmony_ci switch (size) { \ 438c2ecf20Sopenharmony_ci case 1: __get_dbe_asm("lb"); break; \ 448c2ecf20Sopenharmony_ci case 2: __get_dbe_asm("lh"); break; \ 458c2ecf20Sopenharmony_ci case 4: __get_dbe_asm("lw"); break; \ 468c2ecf20Sopenharmony_ci case 8: __get_dbe_asm("ld"); break; \ 478c2ecf20Sopenharmony_ci default: __get_dbe_unknown(); break; \ 488c2ecf20Sopenharmony_ci } \ 498c2ecf20Sopenharmony_ci x = (__typeof__(*(ptr))) __gu_val; \ 508c2ecf20Sopenharmony_ci __gu_err; \ 518c2ecf20Sopenharmony_ci}) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define __get_dbe_asm(insn) \ 548c2ecf20Sopenharmony_ci{ \ 558c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 568c2ecf20Sopenharmony_ci "1:\t" insn "\t%1,%2\n\t" \ 578c2ecf20Sopenharmony_ci "move\t%0,$0\n" \ 588c2ecf20Sopenharmony_ci "2:\n\t" \ 598c2ecf20Sopenharmony_ci ".insn\n\t" \ 608c2ecf20Sopenharmony_ci ".section\t.fixup,\"ax\"\n" \ 618c2ecf20Sopenharmony_ci "3:\tli\t%0,%3\n\t" \ 628c2ecf20Sopenharmony_ci "move\t%1,$0\n\t" \ 638c2ecf20Sopenharmony_ci "j\t2b\n\t" \ 648c2ecf20Sopenharmony_ci ".previous\n\t" \ 658c2ecf20Sopenharmony_ci ".section\t__dbe_table,\"a\"\n\t" \ 668c2ecf20Sopenharmony_ci __PA_ADDR "\t1b, 3b\n\t" \ 678c2ecf20Sopenharmony_ci ".previous" \ 688c2ecf20Sopenharmony_ci :"=r" (__gu_err), "=r" (__gu_val) \ 698c2ecf20Sopenharmony_ci :"o" (__mp(__gu_addr)), "i" (-EFAULT)); \ 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ciextern void __get_dbe_unknown(void); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define __put_dbe(x, ptr, size) \ 758c2ecf20Sopenharmony_ci({ \ 768c2ecf20Sopenharmony_ci long __pu_err; \ 778c2ecf20Sopenharmony_ci __typeof__(*(ptr)) __pu_val; \ 788c2ecf20Sopenharmony_ci long __pu_addr; \ 798c2ecf20Sopenharmony_ci __pu_val = (x); \ 808c2ecf20Sopenharmony_ci __pu_addr = (long) (ptr); \ 818c2ecf20Sopenharmony_ci __asm__("":"=r" (__pu_err)); \ 828c2ecf20Sopenharmony_ci switch (size) { \ 838c2ecf20Sopenharmony_ci case 1: __put_dbe_asm("sb"); break; \ 848c2ecf20Sopenharmony_ci case 2: __put_dbe_asm("sh"); break; \ 858c2ecf20Sopenharmony_ci case 4: __put_dbe_asm("sw"); break; \ 868c2ecf20Sopenharmony_ci case 8: __put_dbe_asm("sd"); break; \ 878c2ecf20Sopenharmony_ci default: __put_dbe_unknown(); break; \ 888c2ecf20Sopenharmony_ci } \ 898c2ecf20Sopenharmony_ci __pu_err; \ 908c2ecf20Sopenharmony_ci}) 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define __put_dbe_asm(insn) \ 938c2ecf20Sopenharmony_ci{ \ 948c2ecf20Sopenharmony_ci __asm__ __volatile__( \ 958c2ecf20Sopenharmony_ci "1:\t" insn "\t%1,%2\n\t" \ 968c2ecf20Sopenharmony_ci "move\t%0,$0\n" \ 978c2ecf20Sopenharmony_ci "2:\n\t" \ 988c2ecf20Sopenharmony_ci ".insn\n\t" \ 998c2ecf20Sopenharmony_ci ".section\t.fixup,\"ax\"\n" \ 1008c2ecf20Sopenharmony_ci "3:\tli\t%0,%3\n\t" \ 1018c2ecf20Sopenharmony_ci "j\t2b\n\t" \ 1028c2ecf20Sopenharmony_ci ".previous\n\t" \ 1038c2ecf20Sopenharmony_ci ".section\t__dbe_table,\"a\"\n\t" \ 1048c2ecf20Sopenharmony_ci __PA_ADDR "\t1b, 3b\n\t" \ 1058c2ecf20Sopenharmony_ci ".previous" \ 1068c2ecf20Sopenharmony_ci : "=r" (__pu_err) \ 1078c2ecf20Sopenharmony_ci : "r" (__pu_val), "o" (__mp(__pu_addr)), "i" (-EFAULT)); \ 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ciextern void __put_dbe_unknown(void); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciextern unsigned long search_dbe_table(unsigned long addr); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#endif /* _ASM_PACCESS_H */ 115