1 /* 1 /* 2 * This file is subject to the terms and condi 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the mai 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 4 * for more details. 5 * 5 * 6 * Copyright (C) 2005 Thiemo Seufer 6 * Copyright (C) 2005 Thiemo Seufer 7 * Copyright (C) 2005 MIPS Technologies, Inc. 7 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. 8 * Author: Maciej W. Rozycki <macro@mips. 8 * Author: Maciej W. Rozycki <macro@mips.com> 9 */ 9 */ 10 10 11 11 12 #include <asm/addrspace.h> 12 #include <asm/addrspace.h> 13 #include <asm/bug.h> 13 #include <asm/bug.h> 14 #include <asm/cacheflush.h> 14 #include <asm/cacheflush.h> 15 15 16 #ifndef CKSEG2 16 #ifndef CKSEG2 17 #define CKSEG2 CKSSEG 17 #define CKSEG2 CKSSEG 18 #endif 18 #endif 19 #ifndef TO_PHYS_MASK 19 #ifndef TO_PHYS_MASK 20 #define TO_PHYS_MASK -1 20 #define TO_PHYS_MASK -1 21 #endif 21 #endif 22 22 23 /* 23 /* 24 * FUNC is executed in one of the uncached seg 24 * FUNC is executed in one of the uncached segments, depending on its 25 * original address as follows: 25 * original address as follows: 26 * 26 * 27 * 1. If the original address is in CKSEG0 or 27 * 1. If the original address is in CKSEG0 or CKSEG1, then the uncached 28 * segment used is CKSEG1. 28 * segment used is CKSEG1. 29 * 2. If the original address is in XKPHYS, th 29 * 2. If the original address is in XKPHYS, then the uncached segment 30 * used is XKPHYS(2). 30 * used is XKPHYS(2). 31 * 3. Otherwise it's a bug. 31 * 3. Otherwise it's a bug. 32 * 32 * 33 * The same remapping is done with the stack p 33 * The same remapping is done with the stack pointer. Stack handling 34 * works because we don't handle stack argumen 34 * works because we don't handle stack arguments or more complex return 35 * values, so we can avoid sharing the same st 35 * values, so we can avoid sharing the same stack area between a cached 36 * and the uncached mode. 36 * and the uncached mode. 37 */ 37 */ 38 unsigned long run_uncached(void *func) 38 unsigned long run_uncached(void *func) 39 { 39 { 40 register long ret __asm__("$2"); 40 register long ret __asm__("$2"); 41 long lfunc = (long)func, ufunc; 41 long lfunc = (long)func, ufunc; 42 long usp; 42 long usp; 43 long sp; 43 long sp; 44 44 45 __asm__("move %0, $sp" : "=r" (sp)); 45 __asm__("move %0, $sp" : "=r" (sp)); 46 46 47 if (sp >= (long)CKSEG0 && sp < (long)C 47 if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) 48 usp = CKSEG1ADDR(sp); 48 usp = CKSEG1ADDR(sp); 49 #ifdef CONFIG_64BIT 49 #ifdef CONFIG_64BIT 50 else if ((long long)sp >= (long long)P 50 else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0, 0) && 51 (long long)sp < (long long)PH 51 (long long)sp < (long long)PHYS_TO_XKPHYS(8, 0)) 52 usp = PHYS_TO_XKPHYS(K_CALG_UN 52 usp = PHYS_TO_XKPHYS(K_CALG_UNCACHED, 53 XKPHYS_TO 53 XKPHYS_TO_PHYS((long long)sp)); 54 #endif 54 #endif 55 else { 55 else { 56 BUG(); 56 BUG(); 57 usp = sp; 57 usp = sp; 58 } 58 } 59 if (lfunc >= (long)CKSEG0 && lfunc < ( 59 if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2) 60 ufunc = CKSEG1ADDR(lfunc); 60 ufunc = CKSEG1ADDR(lfunc); 61 #ifdef CONFIG_64BIT 61 #ifdef CONFIG_64BIT 62 else if ((long long)lfunc >= (long lon 62 else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0, 0) && 63 (long long)lfunc < (long long 63 (long long)lfunc < (long long)PHYS_TO_XKPHYS(8, 0)) 64 ufunc = PHYS_TO_XKPHYS(K_CALG_ 64 ufunc = PHYS_TO_XKPHYS(K_CALG_UNCACHED, 65 XKPHYS_ 65 XKPHYS_TO_PHYS((long long)lfunc)); 66 #endif 66 #endif 67 else { 67 else { 68 BUG(); 68 BUG(); 69 ufunc = lfunc; 69 ufunc = lfunc; 70 } 70 } 71 71 72 __asm__ __volatile__ ( 72 __asm__ __volatile__ ( 73 " move $16, $sp\n" 73 " move $16, $sp\n" 74 " move $sp, %1\n" 74 " move $sp, %1\n" 75 " jalr %2\n" 75 " jalr %2\n" 76 " move $sp, $16" 76 " move $sp, $16" 77 : "=r" (ret) 77 : "=r" (ret) 78 : "r" (usp), "r" (ufunc) 78 : "r" (usp), "r" (ufunc) 79 : "$16", "$31"); 79 : "$16", "$31"); 80 80 81 return ret; 81 return ret; 82 } 82 } 83 83
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.