1*819833afSPeter Tyser /* 2*819833afSPeter Tyser * This file is subject to the terms and conditions of the GNU General Public 3*819833afSPeter Tyser * License. See the file "COPYING" in the main directory of this archive 4*819833afSPeter Tyser * for more details. 5*819833afSPeter Tyser * 6*819833afSPeter Tyser * Copyright (C) 1994 - 1999 by Ralf Baechle 7*819833afSPeter Tyser * Copyright (C) 1996 by Paul M. Antoine 8*819833afSPeter Tyser * Copyright (C) 1994 - 1999 by Ralf Baechle 9*819833afSPeter Tyser * 10*819833afSPeter Tyser * Changed set_except_vector declaration to allow return of previous 11*819833afSPeter Tyser * vector address value - necessary for "borrowing" vectors. 12*819833afSPeter Tyser * 13*819833afSPeter Tyser * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com 14*819833afSPeter Tyser * Copyright (C) 2000 MIPS Technologies, Inc. 15*819833afSPeter Tyser */ 16*819833afSPeter Tyser #ifndef _ASM_SYSTEM_H 17*819833afSPeter Tyser #define _ASM_SYSTEM_H 18*819833afSPeter Tyser 19*819833afSPeter Tyser #include <linux/config.h> 20*819833afSPeter Tyser #include <asm/sgidefs.h> 21*819833afSPeter Tyser #include <asm/ptrace.h> 22*819833afSPeter Tyser #if 0 23*819833afSPeter Tyser #include <linux/kernel.h> 24*819833afSPeter Tyser #endif 25*819833afSPeter Tyser 26*819833afSPeter Tyser extern __inline__ void 27*819833afSPeter Tyser __sti(void) 28*819833afSPeter Tyser { 29*819833afSPeter Tyser __asm__ __volatile__( 30*819833afSPeter Tyser ".set\tpush\n\t" 31*819833afSPeter Tyser ".set\treorder\n\t" 32*819833afSPeter Tyser ".set\tnoat\n\t" 33*819833afSPeter Tyser "mfc0\t$1,$12\n\t" 34*819833afSPeter Tyser "ori\t$1,0x1f\n\t" 35*819833afSPeter Tyser "xori\t$1,0x1e\n\t" 36*819833afSPeter Tyser "mtc0\t$1,$12\n\t" 37*819833afSPeter Tyser ".set\tpop\n\t" 38*819833afSPeter Tyser : /* no outputs */ 39*819833afSPeter Tyser : /* no inputs */ 40*819833afSPeter Tyser : "$1", "memory"); 41*819833afSPeter Tyser } 42*819833afSPeter Tyser 43*819833afSPeter Tyser /* 44*819833afSPeter Tyser * For cli() we have to insert nops to make shure that the new value 45*819833afSPeter Tyser * has actually arrived in the status register before the end of this 46*819833afSPeter Tyser * macro. 47*819833afSPeter Tyser * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs 48*819833afSPeter Tyser * no nops at all. 49*819833afSPeter Tyser */ 50*819833afSPeter Tyser extern __inline__ void 51*819833afSPeter Tyser __cli(void) 52*819833afSPeter Tyser { 53*819833afSPeter Tyser __asm__ __volatile__( 54*819833afSPeter Tyser ".set\tpush\n\t" 55*819833afSPeter Tyser ".set\treorder\n\t" 56*819833afSPeter Tyser ".set\tnoat\n\t" 57*819833afSPeter Tyser "mfc0\t$1,$12\n\t" 58*819833afSPeter Tyser "ori\t$1,1\n\t" 59*819833afSPeter Tyser "xori\t$1,1\n\t" 60*819833afSPeter Tyser ".set\tnoreorder\n\t" 61*819833afSPeter Tyser "mtc0\t$1,$12\n\t" 62*819833afSPeter Tyser "nop\n\t" 63*819833afSPeter Tyser "nop\n\t" 64*819833afSPeter Tyser "nop\n\t" 65*819833afSPeter Tyser ".set\tpop\n\t" 66*819833afSPeter Tyser : /* no outputs */ 67*819833afSPeter Tyser : /* no inputs */ 68*819833afSPeter Tyser : "$1", "memory"); 69*819833afSPeter Tyser } 70*819833afSPeter Tyser 71*819833afSPeter Tyser #define __save_flags(x) \ 72*819833afSPeter Tyser __asm__ __volatile__( \ 73*819833afSPeter Tyser ".set\tpush\n\t" \ 74*819833afSPeter Tyser ".set\treorder\n\t" \ 75*819833afSPeter Tyser "mfc0\t%0,$12\n\t" \ 76*819833afSPeter Tyser ".set\tpop\n\t" \ 77*819833afSPeter Tyser : "=r" (x)) 78*819833afSPeter Tyser 79*819833afSPeter Tyser #define __save_and_cli(x) \ 80*819833afSPeter Tyser __asm__ __volatile__( \ 81*819833afSPeter Tyser ".set\tpush\n\t" \ 82*819833afSPeter Tyser ".set\treorder\n\t" \ 83*819833afSPeter Tyser ".set\tnoat\n\t" \ 84*819833afSPeter Tyser "mfc0\t%0,$12\n\t" \ 85*819833afSPeter Tyser "ori\t$1,%0,1\n\t" \ 86*819833afSPeter Tyser "xori\t$1,1\n\t" \ 87*819833afSPeter Tyser ".set\tnoreorder\n\t" \ 88*819833afSPeter Tyser "mtc0\t$1,$12\n\t" \ 89*819833afSPeter Tyser "nop\n\t" \ 90*819833afSPeter Tyser "nop\n\t" \ 91*819833afSPeter Tyser "nop\n\t" \ 92*819833afSPeter Tyser ".set\tpop\n\t" \ 93*819833afSPeter Tyser : "=r" (x) \ 94*819833afSPeter Tyser : /* no inputs */ \ 95*819833afSPeter Tyser : "$1", "memory") 96*819833afSPeter Tyser 97*819833afSPeter Tyser #define __restore_flags(flags) \ 98*819833afSPeter Tyser do { \ 99*819833afSPeter Tyser unsigned long __tmp1; \ 100*819833afSPeter Tyser \ 101*819833afSPeter Tyser __asm__ __volatile__( \ 102*819833afSPeter Tyser ".set\tnoreorder\t\t\t# __restore_flags\n\t" \ 103*819833afSPeter Tyser ".set\tnoat\n\t" \ 104*819833afSPeter Tyser "mfc0\t$1, $12\n\t" \ 105*819833afSPeter Tyser "andi\t%0, 1\n\t" \ 106*819833afSPeter Tyser "ori\t$1, 1\n\t" \ 107*819833afSPeter Tyser "xori\t$1, 1\n\t" \ 108*819833afSPeter Tyser "or\t%0, $1\n\t" \ 109*819833afSPeter Tyser "mtc0\t%0, $12\n\t" \ 110*819833afSPeter Tyser "nop\n\t" \ 111*819833afSPeter Tyser "nop\n\t" \ 112*819833afSPeter Tyser "nop\n\t" \ 113*819833afSPeter Tyser ".set\tat\n\t" \ 114*819833afSPeter Tyser ".set\treorder" \ 115*819833afSPeter Tyser : "=r" (__tmp1) \ 116*819833afSPeter Tyser : "0" (flags) \ 117*819833afSPeter Tyser : "$1", "memory"); \ 118*819833afSPeter Tyser } while(0) 119*819833afSPeter Tyser 120*819833afSPeter Tyser #ifdef CONFIG_SMP 121*819833afSPeter Tyser 122*819833afSPeter Tyser extern void __global_sti(void); 123*819833afSPeter Tyser extern void __global_cli(void); 124*819833afSPeter Tyser extern unsigned long __global_save_flags(void); 125*819833afSPeter Tyser extern void __global_restore_flags(unsigned long); 126*819833afSPeter Tyser # define sti() __global_sti() 127*819833afSPeter Tyser # define cli() __global_cli() 128*819833afSPeter Tyser # define save_flags(x) do { x = __global_save_flags(); } while (0) 129*819833afSPeter Tyser # define restore_flags(x) __global_restore_flags(x) 130*819833afSPeter Tyser # define save_and_cli(x) do { save_flags(x); cli(); } while(0) 131*819833afSPeter Tyser 132*819833afSPeter Tyser #else /* Single processor */ 133*819833afSPeter Tyser 134*819833afSPeter Tyser # define sti() __sti() 135*819833afSPeter Tyser # define cli() __cli() 136*819833afSPeter Tyser # define save_flags(x) __save_flags(x) 137*819833afSPeter Tyser # define save_and_cli(x) __save_and_cli(x) 138*819833afSPeter Tyser # define restore_flags(x) __restore_flags(x) 139*819833afSPeter Tyser 140*819833afSPeter Tyser #endif /* SMP */ 141*819833afSPeter Tyser 142*819833afSPeter Tyser /* For spinlocks etc */ 143*819833afSPeter Tyser #define local_irq_save(x) __save_and_cli(x); 144*819833afSPeter Tyser #define local_irq_restore(x) __restore_flags(x); 145*819833afSPeter Tyser #define local_irq_disable() __cli(); 146*819833afSPeter Tyser #define local_irq_enable() __sti(); 147*819833afSPeter Tyser 148*819833afSPeter Tyser /* 149*819833afSPeter Tyser * These are probably defined overly paranoid ... 150*819833afSPeter Tyser */ 151*819833afSPeter Tyser #ifdef CONFIG_CPU_HAS_WB 152*819833afSPeter Tyser 153*819833afSPeter Tyser #include <asm/wbflush.h> 154*819833afSPeter Tyser #define rmb() do { } while(0) 155*819833afSPeter Tyser #define wmb() wbflush() 156*819833afSPeter Tyser #define mb() wbflush() 157*819833afSPeter Tyser 158*819833afSPeter Tyser #else /* CONFIG_CPU_HAS_WB */ 159*819833afSPeter Tyser 160*819833afSPeter Tyser #define mb() \ 161*819833afSPeter Tyser __asm__ __volatile__( \ 162*819833afSPeter Tyser "# prevent instructions being moved around\n\t" \ 163*819833afSPeter Tyser ".set\tnoreorder\n\t" \ 164*819833afSPeter Tyser "# 8 nops to fool the R4400 pipeline\n\t" \ 165*819833afSPeter Tyser "nop;nop;nop;nop;nop;nop;nop;nop\n\t" \ 166*819833afSPeter Tyser ".set\treorder" \ 167*819833afSPeter Tyser : /* no output */ \ 168*819833afSPeter Tyser : /* no input */ \ 169*819833afSPeter Tyser : "memory") 170*819833afSPeter Tyser #define rmb() mb() 171*819833afSPeter Tyser #define wmb() mb() 172*819833afSPeter Tyser 173*819833afSPeter Tyser #endif /* CONFIG_CPU_HAS_WB */ 174*819833afSPeter Tyser 175*819833afSPeter Tyser #ifdef CONFIG_SMP 176*819833afSPeter Tyser #define smp_mb() mb() 177*819833afSPeter Tyser #define smp_rmb() rmb() 178*819833afSPeter Tyser #define smp_wmb() wmb() 179*819833afSPeter Tyser #else 180*819833afSPeter Tyser #define smp_mb() barrier() 181*819833afSPeter Tyser #define smp_rmb() barrier() 182*819833afSPeter Tyser #define smp_wmb() barrier() 183*819833afSPeter Tyser #endif 184*819833afSPeter Tyser 185*819833afSPeter Tyser #define set_mb(var, value) \ 186*819833afSPeter Tyser do { var = value; mb(); } while (0) 187*819833afSPeter Tyser 188*819833afSPeter Tyser #define set_wmb(var, value) \ 189*819833afSPeter Tyser do { var = value; wmb(); } while (0) 190*819833afSPeter Tyser 191*819833afSPeter Tyser #if !defined (_LANGUAGE_ASSEMBLY) 192*819833afSPeter Tyser /* 193*819833afSPeter Tyser * switch_to(n) should switch tasks to task nr n, first 194*819833afSPeter Tyser * checking that n isn't the current task, in which case it does nothing. 195*819833afSPeter Tyser */ 196*819833afSPeter Tyser #if 0 197*819833afSPeter Tyser extern asmlinkage void *resume(void *last, void *next); 198*819833afSPeter Tyser #endif 199*819833afSPeter Tyser #endif /* !defined (_LANGUAGE_ASSEMBLY) */ 200*819833afSPeter Tyser 201*819833afSPeter Tyser #define prepare_to_switch() do { } while(0) 202*819833afSPeter Tyser #define switch_to(prev,next,last) \ 203*819833afSPeter Tyser do { \ 204*819833afSPeter Tyser (last) = resume(prev, next); \ 205*819833afSPeter Tyser } while(0) 206*819833afSPeter Tyser 207*819833afSPeter Tyser /* 208*819833afSPeter Tyser * For 32 and 64 bit operands we can take advantage of ll and sc. 209*819833afSPeter Tyser * FIXME: This doesn't work for R3000 machines. 210*819833afSPeter Tyser */ 211*819833afSPeter Tyser extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val) 212*819833afSPeter Tyser { 213*819833afSPeter Tyser #ifdef CONFIG_CPU_HAS_LLSC 214*819833afSPeter Tyser unsigned long dummy; 215*819833afSPeter Tyser 216*819833afSPeter Tyser __asm__ __volatile__( 217*819833afSPeter Tyser ".set\tnoreorder\t\t\t# xchg_u32\n\t" 218*819833afSPeter Tyser ".set\tnoat\n\t" 219*819833afSPeter Tyser "ll\t%0, %3\n" 220*819833afSPeter Tyser "1:\tmove\t$1, %2\n\t" 221*819833afSPeter Tyser "sc\t$1, %1\n\t" 222*819833afSPeter Tyser "beqzl\t$1, 1b\n\t" 223*819833afSPeter Tyser " ll\t%0, %3\n\t" 224*819833afSPeter Tyser ".set\tat\n\t" 225*819833afSPeter Tyser ".set\treorder" 226*819833afSPeter Tyser : "=r" (val), "=o" (*m), "=r" (dummy) 227*819833afSPeter Tyser : "o" (*m), "2" (val) 228*819833afSPeter Tyser : "memory"); 229*819833afSPeter Tyser 230*819833afSPeter Tyser return val; 231*819833afSPeter Tyser #else 232*819833afSPeter Tyser unsigned long flags, retval; 233*819833afSPeter Tyser 234*819833afSPeter Tyser save_flags(flags); 235*819833afSPeter Tyser cli(); 236*819833afSPeter Tyser retval = *m; 237*819833afSPeter Tyser *m = val; 238*819833afSPeter Tyser restore_flags(flags); 239*819833afSPeter Tyser return retval; 240*819833afSPeter Tyser #endif /* Processor-dependent optimization */ 241*819833afSPeter Tyser } 242*819833afSPeter Tyser 243*819833afSPeter Tyser #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) 244*819833afSPeter Tyser #define tas(ptr) (xchg((ptr),1)) 245*819833afSPeter Tyser 246*819833afSPeter Tyser static __inline__ unsigned long 247*819833afSPeter Tyser __xchg(unsigned long x, volatile void * ptr, int size) 248*819833afSPeter Tyser { 249*819833afSPeter Tyser switch (size) { 250*819833afSPeter Tyser case 4: 251*819833afSPeter Tyser return xchg_u32(ptr, x); 252*819833afSPeter Tyser } 253*819833afSPeter Tyser return x; 254*819833afSPeter Tyser } 255*819833afSPeter Tyser 256*819833afSPeter Tyser extern void *set_except_vector(int n, void *addr); 257*819833afSPeter Tyser 258*819833afSPeter Tyser extern void __die(const char *, struct pt_regs *, const char *where, 259*819833afSPeter Tyser unsigned long line) __attribute__((noreturn)); 260*819833afSPeter Tyser extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, 261*819833afSPeter Tyser unsigned long line); 262*819833afSPeter Tyser 263*819833afSPeter Tyser #define die(msg, regs) \ 264*819833afSPeter Tyser __die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) 265*819833afSPeter Tyser #define die_if_kernel(msg, regs) \ 266*819833afSPeter Tyser __die_if_kernel(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) 267*819833afSPeter Tyser 268*819833afSPeter Tyser #endif /* _ASM_SYSTEM_H */ 269